mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
🎉 Show tokens on color inputs (#7377)
* 🎉 Add tokens to color row * 🎉 Add color-token to stroke input * 🐛 FIx change token on multiselection with groups * 🔧 Add config flag * 🐛 Fix comments
This commit is contained in:
@@ -534,4 +534,6 @@
|
|||||||
:sided-margins #{:spacing :dimensions}
|
:sided-margins #{:spacing :dimensions}
|
||||||
:line-height #{:line-height :number}
|
:line-height #{:line-height :number}
|
||||||
:font-size #{:font-size}
|
:font-size #{:font-size}
|
||||||
:letter-spacing #{:letter-spacing}})
|
:letter-spacing #{:letter-spacing}
|
||||||
|
:fill #{:color}
|
||||||
|
:stroke-color #{:color}})
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ test("Create a LINEAR gradient", async ({ page }) => {
|
|||||||
await expect(inputOpacityGlobal).toHaveValue("50");
|
await expect(inputOpacityGlobal).toHaveValue("50");
|
||||||
await expect(inputOpacityGlobal).toBeVisible();
|
await expect(inputOpacityGlobal).toBeVisible();
|
||||||
|
|
||||||
await expect(workspacePage.page.getByText("Linear gradient")).toBeVisible();
|
await expect(workspacePage.page.getByText("Linear gradient").nth(1)).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Create a RADIAL gradient", async ({ page }) => {
|
test("Create a RADIAL gradient", async ({ page }) => {
|
||||||
@@ -175,7 +175,7 @@ test("Create a RADIAL gradient", async ({ page }) => {
|
|||||||
await expect(inputOpacityGlobal).toHaveValue("50");
|
await expect(inputOpacityGlobal).toHaveValue("50");
|
||||||
await expect(inputOpacityGlobal).toBeVisible();
|
await expect(inputOpacityGlobal).toBeVisible();
|
||||||
|
|
||||||
await expect(workspacePage.page.getByText("Radial gradient")).toBeVisible();
|
await expect(workspacePage.page.getByText("Radial gradient").nth(1)).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Gradient stops limit", async ({ page }) => {
|
test("Gradient stops limit", async ({ page }) => {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const setupTokensFile = async (page, options = {}) => {
|
|||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
const workspacePage = new WorkspacePage(page);
|
||||||
if (flags.length) {
|
if (flags.length > 0) {
|
||||||
await workspacePage.mockConfigFlags(flags);
|
await workspacePage.mockConfigFlags(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,7 +879,10 @@ test.describe("Tokens: Themes modal", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.describe("Tokens: Apply token", () => {
|
test.describe("Tokens: Apply token", () => {
|
||||||
test("User applies color token to a shape", async ({ page }) => {
|
// When deleting the "enable-token-color" flag, permanently remove this test.
|
||||||
|
test("User applies color token to a shape without tokens on design-tab", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
||||||
await setupTokensFile(page);
|
await setupTokensFile(page);
|
||||||
|
|
||||||
@@ -909,6 +912,35 @@ test.describe("Tokens: Themes modal", () => {
|
|||||||
await expect(inputColor).toHaveValue("000000");
|
await expect(inputColor).toHaveValue("000000");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("User applies color token to a shape", async ({ page }) => {
|
||||||
|
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
||||||
|
await setupTokensFile(page, { flags: ["enable-token-color"] });
|
||||||
|
|
||||||
|
await page.getByRole("tab", { name: "Layers" }).click();
|
||||||
|
|
||||||
|
await workspacePage.layers
|
||||||
|
.getByTestId("layer-row")
|
||||||
|
.filter({ hasText: "Button" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
||||||
|
await tokensTabButton.click();
|
||||||
|
|
||||||
|
await tokensSidebar
|
||||||
|
.getByRole("button")
|
||||||
|
.filter({ hasText: "Color" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await tokensSidebar
|
||||||
|
.getByRole("button", { name: "colors.black" })
|
||||||
|
.click({ button: "right" });
|
||||||
|
await tokenContextMenuForToken.getByText("Fill").click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
workspacePage.page.getByLabel("Name: colors.black"),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
test("User applies typography token to a text shape", async ({ page }) => {
|
test("User applies typography token to a text shape", async ({ page }) => {
|
||||||
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
||||||
await setupTypographyTokensFile(page);
|
await setupTypographyTokensFile(page);
|
||||||
@@ -1024,9 +1056,7 @@ test.describe("Tokens: Themes modal", () => {
|
|||||||
await expect(letterSpacingField).toHaveValue(
|
await expect(letterSpacingField).toHaveValue(
|
||||||
originalValues.letterSpacing,
|
originalValues.letterSpacing,
|
||||||
);
|
);
|
||||||
await expect(lineHeightField).toHaveValue(
|
await expect(lineHeightField).toHaveValue(originalValues.lineHeight);
|
||||||
originalValues.lineHeight,
|
|
||||||
);
|
|
||||||
await expect(textCaseField).toHaveValue(originalValues.textCase);
|
await expect(textCaseField).toHaveValue(originalValues.textCase);
|
||||||
await expect(textDecorationField).toHaveValue(
|
await expect(textDecorationField).toHaveValue(
|
||||||
originalValues.textDecoration,
|
originalValues.textDecoration,
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
cursor: grab;
|
cursor: grab;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: calc(100% + var(--sp-m));
|
block-size: calc(100% + var(--sp-m));
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
left: var(--reorder-left-position, calc(-1 * var(--sp-l)));
|
inset-inline-start: var(--reorder-left-position, -11px);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(-1 * (var(--sp-m) / 2));
|
inset-block-start: calc(-1 * (var(--sp-m) / 2));
|
||||||
z-index: var(--z-index-panels);
|
z-index: var(--z-index-panels);
|
||||||
}
|
}
|
||||||
|
|
||||||
.reorder-icon {
|
.reorder-icon {
|
||||||
height: var(--sp-l);
|
block-size: var(--sp-l);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
visibility: var(--reorder-icon-visibility, hidden);
|
visibility: var(--reorder-icon-visibility, hidden);
|
||||||
--icon-stroke-color: var(--color-foreground-secondary);
|
--icon-stroke-color: var(--color-foreground-secondary);
|
||||||
@@ -28,15 +28,15 @@
|
|||||||
border-color: var(--color-accent-primary);
|
border-color: var(--color-accent-primary);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
inline-size: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reorder-separator-top {
|
.reorder-separator-top {
|
||||||
display: var(--reorder-top-display, none);
|
display: var(--reorder-top-display, none);
|
||||||
top: calc(-1 * var(--sp-xxs));
|
inset-block-start: calc(-1 * var(--sp-xxs));
|
||||||
}
|
}
|
||||||
|
|
||||||
.reorder-separator-bottom {
|
.reorder-separator-bottom {
|
||||||
display: var(--reorder-bottom-display, none);
|
display: var(--reorder-bottom-display, none);
|
||||||
bottom: calc(-1 * var(--sp-xxs));
|
inset-block-end: calc(-1 * var(--sp-xxs));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ $sz-32: px2rem(32);
|
|||||||
$sz-36: px2rem(36);
|
$sz-36: px2rem(36);
|
||||||
$sz-40: px2rem(40);
|
$sz-40: px2rem(40);
|
||||||
$sz-48: px2rem(48);
|
$sz-48: px2rem(48);
|
||||||
$sz-80: px2rem(80);
|
|
||||||
$sz-88: px2rem(88);
|
$sz-88: px2rem(88);
|
||||||
$sz-120: px2rem(120);
|
$sz-120: px2rem(120);
|
||||||
$sz-154: px2rem(154);
|
$sz-154: px2rem(154);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) KALEIDOS INC
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "ds/_utils.scss" as *;
|
||||||
|
|
||||||
@keyframes line-pencil {
|
@keyframes line-pencil {
|
||||||
0% {
|
0% {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
@@ -44,8 +46,8 @@
|
|||||||
// Tips container
|
// Tips container
|
||||||
.tips-container {
|
.tips-container {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
min-width: var(--sp-600);
|
min-width: px2rem(600);
|
||||||
max-width: var(--sp-800);
|
max-width: px2rem(800);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--sp-s);
|
gap: var(--sp-s);
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ $_sp-16: px2rem(16);
|
|||||||
$_sp-20: px2rem(20);
|
$_sp-20: px2rem(20);
|
||||||
$_sp-24: px2rem(24);
|
$_sp-24: px2rem(24);
|
||||||
$_sp-32: px2rem(32);
|
$_sp-32: px2rem(32);
|
||||||
$_sp-600: px2rem(600);
|
|
||||||
$_sp-800: px2rem(800);
|
|
||||||
|
|
||||||
:global(:root) {
|
:global(:root) {
|
||||||
--sp-xxs: #{$_sp-2};
|
--sp-xxs: #{$_sp-2};
|
||||||
@@ -26,6 +24,4 @@ $_sp-800: px2rem(800);
|
|||||||
--sp-xl: #{$_sp-20};
|
--sp-xl: #{$_sp-20};
|
||||||
--sp-xxl: #{$_sp-24};
|
--sp-xxl: #{$_sp-24};
|
||||||
--sp-xxxl: #{$_sp-32};
|
--sp-xxxl: #{$_sp-32};
|
||||||
--sp-600: #{$_sp-600};
|
|
||||||
--sp-800: #{$_sp-800};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,11 +63,12 @@
|
|||||||
[:class {:optional true} :string]
|
[:class {:optional true} :string]
|
||||||
[:size {:optional true} [:enum "small" "medium" "large"]]
|
[:size {:optional true} [:enum "small" "medium" "large"]]
|
||||||
[:active {:optional true} ::sm/boolean]
|
[:active {:optional true} ::sm/boolean]
|
||||||
|
[:has-errors {:optional true} [:maybe ::sm/boolean]]
|
||||||
[:on-click {:optional true} ::sm/fn]])
|
[:on-click {:optional true} ::sm/fn]])
|
||||||
|
|
||||||
(mf/defc swatch*
|
(mf/defc swatch*
|
||||||
{::mf/schema (sm/schema schema:swatch)}
|
{::mf/schema (sm/schema schema:swatch)}
|
||||||
[{:keys [background on-click size active class tooltip-content]
|
[{:keys [background on-click size active class tooltip-content has-errors]
|
||||||
:rest props}]
|
:rest props}]
|
||||||
(let [;; NOTE: this code is only relevant for storybook, because
|
(let [;; NOTE: this code is only relevant for storybook, because
|
||||||
;; storybook is unable to pass in a comfortable way a complex
|
;; storybook is unable to pass in a comfortable way a complex
|
||||||
@@ -92,6 +93,12 @@
|
|||||||
image (:image background)
|
image (:image background)
|
||||||
format (if id? "rounded" "square")
|
format (if id? "rounded" "square")
|
||||||
element-id (mf/use-id)
|
element-id (mf/use-id)
|
||||||
|
on-click
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps background on-click)
|
||||||
|
(fn [event]
|
||||||
|
(when (fn? on-click)
|
||||||
|
(^function on-click background event))))
|
||||||
|
|
||||||
class
|
class
|
||||||
(dm/str class " " (stl/css-case
|
(dm/str class " " (stl/css-case
|
||||||
@@ -124,6 +131,8 @@
|
|||||||
(let [uri (cfg/resolve-file-media image)]
|
(let [uri (cfg/resolve-file-media image)]
|
||||||
[:span {:class (stl/css :swatch-image)
|
[:span {:class (stl/css :swatch-image)
|
||||||
:style {:background-image (str/ffmt "url(%)" uri)}}])
|
:style {:background-image (str/ffmt "url(%)" uri)}}])
|
||||||
|
has-errors
|
||||||
|
[:span {:class (stl/css :swatch-error)}]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[:span {:class (stl/css :swatch-opacity)}
|
[:span {:class (stl/css :swatch-opacity)}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
border: $b-1 solid var(--border-color);
|
border: $b-1 solid var(--border-color);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
--border-color: var(--color-accent-primary);
|
--border-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
@@ -109,3 +108,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.swatch-error {
|
||||||
|
background: var(--color-background-primary);
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,7 +47,8 @@
|
|||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]
|
||||||
|
[rumext.v2.util :as mfu]))
|
||||||
|
|
||||||
;; --- Refs
|
;; --- Refs
|
||||||
|
|
||||||
@@ -93,13 +94,13 @@
|
|||||||
(dom/set-css-property! node "--saturation-grad-to" (format-hsl hsl-to)))))
|
(dom/set-css-property! node "--saturation-grad-to" (format-hsl hsl-to)))))
|
||||||
|
|
||||||
(mf/defc colorpicker
|
(mf/defc colorpicker
|
||||||
[{:keys [data disable-gradient disable-opacity disable-image on-change on-accept origin combined-tokens color-origin on-token-change]}]
|
[{:keys [data disable-gradient disable-opacity disable-image on-change on-accept origin combined-tokens color-origin on-token-change tab]}]
|
||||||
(let [state (mf/deref refs/colorpicker)
|
(let [state (mf/deref refs/colorpicker)
|
||||||
node-ref (mf/use-ref)
|
node-ref (mf/use-ref)
|
||||||
|
|
||||||
should-update? (mf/use-var true)
|
should-update? (mf/use-var true)
|
||||||
token-color (contains? cfg/flags :token-color)
|
token-color (contains? cfg/flags :token-color)
|
||||||
color-style* (mf/use-state :direct-color)
|
color-style* (mf/use-state (d/nilv tab :direct-color))
|
||||||
color-style (deref color-style*)
|
color-style (deref color-style*)
|
||||||
toggle-token-color
|
toggle-token-color
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -364,7 +365,7 @@
|
|||||||
:icon i/hsva
|
:icon i/hsva
|
||||||
:id "hsva"}])
|
:id "hsva"}])
|
||||||
|
|
||||||
show-tokens? (contains? #{:fill :stroke :color-selection} color-origin)]
|
show-tokens? (contains? #{:fill :stroke-color :color-selection} color-origin)]
|
||||||
|
|
||||||
;; Initialize colorpicker state
|
;; Initialize colorpicker state
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
@@ -726,12 +727,16 @@
|
|||||||
color-origin
|
color-origin
|
||||||
on-token-change
|
on-token-change
|
||||||
on-close
|
on-close
|
||||||
|
tab
|
||||||
on-accept]}]
|
on-accept]}]
|
||||||
(let [vport (mf/deref viewport)
|
(let [vport (mf/deref viewport)
|
||||||
dirty? (mf/use-var false)
|
dirty? (mf/use-var false)
|
||||||
last-change (mf/use-var nil)
|
last-change (mf/use-var nil)
|
||||||
position (d/nilv position :left)
|
position (d/nilv position :left)
|
||||||
style (calculate-position vport position x y (some? (:gradient data)))
|
style (calculate-position vport position x y (some? (:gradient data)))
|
||||||
|
active-tokens (if (object? active-tokens)
|
||||||
|
(mfu/bean active-tokens)
|
||||||
|
active-tokens)
|
||||||
|
|
||||||
on-change'
|
on-change'
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -752,6 +757,10 @@
|
|||||||
(some-> tokens-lib
|
(some-> tokens-lib
|
||||||
(ctob/get-active-themes-set-names)))
|
(ctob/get-active-themes-set-names)))
|
||||||
|
|
||||||
|
active-tokens (if (delay? active-tokens)
|
||||||
|
@active-tokens
|
||||||
|
active-tokens)
|
||||||
|
|
||||||
color-tokens (:color active-tokens)
|
color-tokens (:color active-tokens)
|
||||||
|
|
||||||
grouped-tokens-by-set
|
grouped-tokens-by-set
|
||||||
@@ -783,5 +792,6 @@
|
|||||||
:on-token-change on-token-change
|
:on-token-change on-token-change
|
||||||
:on-change on-change'
|
:on-change on-change'
|
||||||
:origin origin
|
:origin origin
|
||||||
|
:tab tab
|
||||||
:color-origin color-origin
|
:color-origin color-origin
|
||||||
:on-accept on-accept}]]))
|
:on-accept on-accept}]]))
|
||||||
|
|||||||
@@ -135,24 +135,11 @@
|
|||||||
|
|
||||||
on-token-pill-click
|
on-token-pill-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps selected-shapes selected color-origin)
|
(mf/deps selected-shapes)
|
||||||
(fn [event token]
|
(fn [event token]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when (seq selected-shapes)
|
(when (seq selected-shapes)
|
||||||
(if (= :color-selection color-origin)
|
(on-token-change event token))))
|
||||||
(on-token-change event token)
|
|
||||||
(let [attributes (if (= color-origin :stroke) #{:stroke-color} #{:fill})
|
|
||||||
shape-ids (into #{} (map :id selected-shapes))]
|
|
||||||
(if (or
|
|
||||||
(and (= (:name token) has-stroke-tokens?) (= color-origin :stroke))
|
|
||||||
(and (= (:name token) has-color-tokens?) (= color-origin :fill)))
|
|
||||||
(st/emit! (dwta/unapply-token {:attributes attributes
|
|
||||||
:token token
|
|
||||||
:shape-ids shape-ids}))
|
|
||||||
(st/emit! (dwta/apply-token {:shape-ids shape-ids
|
|
||||||
:attributes attributes
|
|
||||||
:token token
|
|
||||||
:on-update-shape dwta/update-fill-stroke}))))))))
|
|
||||||
|
|
||||||
create-token-on-set
|
create-token-on-set
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
(str/join ", ")
|
(str/join ", ")
|
||||||
(str/ffmt "linear-gradient(90deg, %1)")))
|
(str/ffmt "linear-gradient(90deg, %1)")))
|
||||||
|
|
||||||
|
(defn- stop->hex-color
|
||||||
|
[stop]
|
||||||
|
(select-keys stop [:color :opacity]))
|
||||||
|
|
||||||
(mf/defc stop-input-row*
|
(mf/defc stop-input-row*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [stop
|
[{:keys [stop
|
||||||
@@ -156,7 +160,7 @@
|
|||||||
[:> color-row*
|
[:> color-row*
|
||||||
{:disable-gradient true
|
{:disable-gradient true
|
||||||
:disable-picker true
|
:disable-picker true
|
||||||
:color stop
|
:color (stop->hex-color stop)
|
||||||
:index index
|
:index index
|
||||||
:origin :gradient
|
:origin :gradient
|
||||||
:on-change handle-change-stop-color
|
:on-change handle-change-stop-color
|
||||||
|
|||||||
@@ -454,7 +454,7 @@
|
|||||||
.sample-library-button {
|
.sample-library-button {
|
||||||
@include t.use-typography("headline-small");
|
@include t.use-typography("headline-small");
|
||||||
height: $sz-32;
|
height: $sz-32;
|
||||||
width: $sz-80;
|
width: px2rem(80);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-radius: $br-8;
|
border-radius: $br-8;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
(mf/defc single-shape-options*
|
(mf/defc single-shape-options*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [shape page-id file-id libraries] :as props}]
|
[{:keys [shape page-id file-id libraries] :rest props}]
|
||||||
(let [shape-type (dm/get-prop shape :type)
|
(let [shape-type (dm/get-prop shape :type)
|
||||||
shape-id (dm/get-prop shape :id)
|
shape-id (dm/get-prop shape :id)
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@
|
|||||||
color-operations (get groups color)
|
color-operations (get groups color)
|
||||||
ids (into (d/ordered-set) xf:map-shape-id color-operations)]
|
ids (into (d/ordered-set) xf:map-shape-id color-operations)]
|
||||||
(st/emit! (dws/select-shapes ids)))))
|
(st/emit! (dws/select-shapes ids)))))
|
||||||
|
|
||||||
on-token-change
|
on-token-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [_ token old-color]
|
(fn [_ token old-color]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
[app.config :as cfg]
|
[app.config :as cfg]
|
||||||
[app.main.data.workspace :as udw]
|
[app.main.data.workspace :as udw]
|
||||||
[app.main.data.workspace.colors :as dc]
|
[app.main.data.workspace.colors :as dc]
|
||||||
|
[app.main.data.workspace.tokens.application :as dwta]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
@@ -68,16 +69,24 @@
|
|||||||
n-vals (unchecked-get n-props "values")
|
n-vals (unchecked-get n-props "values")
|
||||||
o-fills (get o-vals :fills)
|
o-fills (get o-vals :fills)
|
||||||
n-fills (get n-vals :fills)
|
n-fills (get n-vals :fills)
|
||||||
|
o-objects (get o-vals :objects)
|
||||||
|
n-objects (get n-vals :objects)
|
||||||
|
o-applied-tokens (get o-vals :applied-tokens)
|
||||||
|
n-applied-tokens (get n-vals :applied-tokens)
|
||||||
o-hide (get o-vals :hide-fill-on-export)
|
o-hide (get o-vals :hide-fill-on-export)
|
||||||
n-hide (get n-vals :hide-fill-on-export)]
|
n-hide (get n-vals :hide-fill-on-export)]
|
||||||
(and (identical? o-hide n-hide)
|
(and (identical? o-hide n-hide)
|
||||||
(identical? o-fills n-fills)))))
|
(identical? o-applied-tokens n-applied-tokens)
|
||||||
|
(identical? o-fills n-fills)
|
||||||
|
(identical? o-objects n-objects)))))
|
||||||
|
|
||||||
(mf/defc fill-menu*
|
(mf/defc fill-menu*
|
||||||
{::mf/wrap [#(mf/memo' % check-props)]}
|
{::mf/wrap [#(mf/memo' % check-props)]}
|
||||||
[{:keys [ids type values]}]
|
[{:keys [ids type values applied-tokens shapes objects]}]
|
||||||
|
|
||||||
(let [fills (get values :fills)
|
(let [fills (get values :fills)
|
||||||
hide-on-export (get values :hide-fill-on-export false)
|
hide-on-export (get values :hide-fill-on-export false)
|
||||||
|
fill-token-applied (:fill applied-tokens)
|
||||||
|
|
||||||
^boolean
|
^boolean
|
||||||
multiple? (= :multiple fills)
|
multiple? (= :multiple fills)
|
||||||
@@ -172,7 +181,37 @@
|
|||||||
#(reset! disable-drag* true))
|
#(reset! disable-drag* true))
|
||||||
|
|
||||||
on-blur
|
on-blur
|
||||||
(mf/use-fn #(reset! disable-drag* false))]
|
(mf/use-fn #(reset! disable-drag* false))
|
||||||
|
|
||||||
|
on-token-change
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps shapes objects)
|
||||||
|
(fn [_ token]
|
||||||
|
(let [expanded-shapes
|
||||||
|
(if (= 1 (count shapes))
|
||||||
|
(let [shape (first shapes)]
|
||||||
|
(if (= (:type shape) :group)
|
||||||
|
(keep objects (:shapes shape))
|
||||||
|
[shape]))
|
||||||
|
|
||||||
|
(mapcat (fn [shape]
|
||||||
|
(if (= (:type shape) :group)
|
||||||
|
(keep objects (:shapes shape))
|
||||||
|
[shape]))
|
||||||
|
shapes))]
|
||||||
|
|
||||||
|
(st/emit!
|
||||||
|
(dwta/toggle-token {:token token
|
||||||
|
:attrs #{:fill}
|
||||||
|
:shapes expanded-shapes})))))
|
||||||
|
|
||||||
|
on-detach-token
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps ids)
|
||||||
|
(fn [token]
|
||||||
|
(st/emit! (dwta/unapply-token {:attributes #{:fill}
|
||||||
|
:token token
|
||||||
|
:shape-ids ids}))))]
|
||||||
|
|
||||||
(mf/with-layout-effect [hide-on-export]
|
(mf/with-layout-effect [hide-on-export]
|
||||||
(when-let [checkbox (mf/ref-val checkbox-ref)]
|
(when-let [checkbox (mf/ref-val checkbox-ref)]
|
||||||
@@ -223,9 +262,12 @@
|
|||||||
:on-change on-change
|
:on-change on-change
|
||||||
:on-reorder on-reorder
|
:on-reorder on-reorder
|
||||||
:on-detach on-detach
|
:on-detach on-detach
|
||||||
|
:on-detach-token on-detach-token
|
||||||
:on-remove on-remove
|
:on-remove on-remove
|
||||||
:disable-drag disable-drag?
|
:disable-drag disable-drag?
|
||||||
:on-focus on-focus
|
:on-focus on-focus
|
||||||
|
:applied-token fill-token-applied
|
||||||
|
:on-token-change on-token-change
|
||||||
:origin :fill
|
:origin :fill
|
||||||
:select-on-focus (not disable-drag?)
|
:select-on-focus (not disable-drag?)
|
||||||
:on-blur on-blur}]))])
|
:on-blur on-blur}]))])
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
[app.common.types.stroke :as cts]
|
[app.common.types.stroke :as cts]
|
||||||
[app.main.data.workspace :as udw]
|
[app.main.data.workspace :as udw]
|
||||||
[app.main.data.workspace.colors :as dc]
|
[app.main.data.workspace.colors :as dc]
|
||||||
|
[app.main.data.workspace.tokens.application :as dwta]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
@@ -37,8 +38,8 @@
|
|||||||
:stroke-cap-end])
|
:stroke-cap-end])
|
||||||
|
|
||||||
(mf/defc stroke-menu
|
(mf/defc stroke-menu
|
||||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps"]))]}
|
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps" "applied-tokens" "shapes" "objects"]))]}
|
||||||
[{:keys [ids type values show-caps disable-stroke-style] :as props}]
|
[{:keys [ids type values show-caps disable-stroke-style applied-tokens shapes objects] :as props}]
|
||||||
(let [label (case type
|
(let [label (case type
|
||||||
:multiple (tr "workspace.options.selection-stroke")
|
:multiple (tr "workspace.options.selection-stroke")
|
||||||
:group (tr "workspace.options.group-stroke")
|
:group (tr "workspace.options.group-stroke")
|
||||||
@@ -167,7 +168,14 @@
|
|||||||
(reset! disable-drag true))
|
(reset! disable-drag true))
|
||||||
|
|
||||||
on-blur (fn [_]
|
on-blur (fn [_]
|
||||||
(reset! disable-drag false))]
|
(reset! disable-drag false))
|
||||||
|
on-detach-token
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps ids)
|
||||||
|
(fn [token attrs]
|
||||||
|
(st/emit! (dwta/unapply-token {:attributes attrs
|
||||||
|
:token token
|
||||||
|
:shape-ids ids}))))]
|
||||||
|
|
||||||
[:div {:class (stl/css :element-set)}
|
[:div {:class (stl/css :element-set)}
|
||||||
[:div {:class (stl/css :element-title)}
|
[:div {:class (stl/css :element-title)}
|
||||||
@@ -201,6 +209,8 @@
|
|||||||
:stroke value
|
:stroke value
|
||||||
:title (tr "workspace.options.stroke-color")
|
:title (tr "workspace.options.stroke-color")
|
||||||
:index index
|
:index index
|
||||||
|
:shapes shapes
|
||||||
|
:objects objects
|
||||||
:show-caps show-caps
|
:show-caps show-caps
|
||||||
:on-color-change on-color-change
|
:on-color-change on-color-change
|
||||||
:on-color-detach on-color-detach
|
:on-color-detach on-color-detach
|
||||||
@@ -212,6 +222,8 @@
|
|||||||
:on-stroke-cap-start-change on-stroke-cap-start-change
|
:on-stroke-cap-start-change on-stroke-cap-start-change
|
||||||
:on-stroke-cap-end-change on-stroke-cap-end-change
|
:on-stroke-cap-end-change on-stroke-cap-end-change
|
||||||
:on-stroke-cap-switch on-stroke-cap-switch
|
:on-stroke-cap-switch on-stroke-cap-switch
|
||||||
|
:applied-tokens applied-tokens
|
||||||
|
:on-detach-token on-detach-token
|
||||||
:on-remove on-remove
|
:on-remove on-remove
|
||||||
:on-reorder (handle-reorder index)
|
:on-reorder (handle-reorder index)
|
||||||
:disable-drag disable-drag
|
:disable-drag disable-drag
|
||||||
|
|||||||
@@ -11,28 +11,27 @@
|
|||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.types.color :as clr]
|
[app.common.types.color :as clr]
|
||||||
[app.common.types.shape.attrs :refer [default-color]]
|
[app.common.types.shape.attrs :refer [default-color]]
|
||||||
|
[app.common.types.token :as tk]
|
||||||
|
[app.config :as cfg]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.workspace.colors :as dwc]
|
[app.main.data.workspace.colors :as dwc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.color-bullet :as cb]
|
|
||||||
[app.main.ui.components.color-input :refer [color-input*]]
|
[app.main.ui.components.color-input :refer [color-input*]]
|
||||||
[app.main.ui.components.numeric-input :refer [numeric-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.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||||
|
[app.main.ui.ds.tooltip.tooltip :refer [tooltip*]]
|
||||||
|
[app.main.ui.ds.utilities.swatch :refer [swatch*]]
|
||||||
[app.main.ui.formats :as fmt]
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.hooks :as h]
|
[app.main.ui.hooks :as h]
|
||||||
[app.main.ui.icons :as deprecated-icon]
|
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def ^:private detach-icon
|
|
||||||
(deprecated-icon/icon-xref :detach (stl/css :detach-icon)))
|
|
||||||
|
|
||||||
(defn opacity->string
|
(defn opacity->string
|
||||||
[opacity]
|
[opacity]
|
||||||
(if (= opacity :multiple)
|
(if (= opacity :multiple)
|
||||||
@@ -42,45 +41,139 @@
|
|||||||
(* 100)
|
(* 100)
|
||||||
(fmt/format-number)))))
|
(fmt/format-number)))))
|
||||||
|
|
||||||
(defn remove-multiple
|
(mf/defc color-info-wrapper*
|
||||||
[v]
|
{::mf/private true}
|
||||||
(if (= v :multiple) nil v))
|
[{:keys [color class handle-click-color children select-on-focus opacity on-focus on-blur on-opacity-change]}]
|
||||||
|
[:div {:class (stl/css :color-info)}
|
||||||
|
[:div {:class class}
|
||||||
|
[:div {:class (stl/css :color-bullet-wrapper)}
|
||||||
|
[:> swatch* {:background color
|
||||||
|
:on-click handle-click-color
|
||||||
|
:size "small"}]]
|
||||||
|
children]
|
||||||
|
(when opacity
|
||||||
|
[:div {:class (stl/css :opacity-element-wrapper)}
|
||||||
|
[:span {:class (stl/css :icon-text)} "%"]
|
||||||
|
[:> numeric-input* {:value (-> color :opacity opacity->string)
|
||||||
|
:class (stl/css :opacity-input)
|
||||||
|
:placeholder "--"
|
||||||
|
:select-on-focus select-on-focus
|
||||||
|
:on-focus on-focus
|
||||||
|
:on-blur on-blur
|
||||||
|
:on-change on-opacity-change
|
||||||
|
:data-testid "opacity-input"
|
||||||
|
:default 100
|
||||||
|
:min 0
|
||||||
|
:max 100}]])])
|
||||||
|
|
||||||
|
(mf/defc color-token-row*
|
||||||
|
{::mf/private true}
|
||||||
|
[{:keys [active-tokens color-token color on-swatch-click-token detach-token open-modal-from-token]}]
|
||||||
|
(let [;; `active-tokens` may be provided as a `delay` (lazy computation).
|
||||||
|
;; In that case we must deref it (`@active-tokens`) to force evaluation
|
||||||
|
;; and obtain the actual value. If it’s already realized (not a delay),
|
||||||
|
;; we just use it directly.
|
||||||
|
active-tokens (if (delay? active-tokens)
|
||||||
|
@active-tokens
|
||||||
|
active-tokens)
|
||||||
|
|
||||||
|
color-tokens (:color active-tokens)
|
||||||
|
|
||||||
|
token (some #(when (= (:name %) color-token) %) color-tokens)
|
||||||
|
|
||||||
|
on-detach-token
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps detach-token token)
|
||||||
|
#(detach-token token))
|
||||||
|
|
||||||
|
has-errors (some? (:errors token))
|
||||||
|
token-name (:name token)
|
||||||
|
resolved (:resolved-value token)
|
||||||
|
not-active (and (some? active-tokens) (nil? token))
|
||||||
|
id (dm/str (:id token) "-name")
|
||||||
|
swatch-tooltip-content (cond
|
||||||
|
not-active
|
||||||
|
(tr "ds.inputs.token-field.no-active-token-option")
|
||||||
|
has-errors
|
||||||
|
(tr "color-row.token-color-row.deleted-token")
|
||||||
|
:else
|
||||||
|
(tr "workspace.tokens.resolved-value" resolved))
|
||||||
|
name-tooltip-content (cond
|
||||||
|
not-active
|
||||||
|
(tr "ds.inputs.token-field.no-active-token-option")
|
||||||
|
has-errors
|
||||||
|
(tr "color-row.token-color-row.deleted-token")
|
||||||
|
:else
|
||||||
|
(mf/html
|
||||||
|
[:div
|
||||||
|
[:span (dm/str (tr "workspace.tokens.token-name") ": ")]
|
||||||
|
[:span {:class (stl/css :token-name-tooltip)} color-token]]))]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :color-info)}
|
||||||
|
[:div {:class (stl/css-case :token-color-wrapper true
|
||||||
|
:token-color-with-errors has-errors
|
||||||
|
:token-color-not-active not-active)}
|
||||||
|
[:div {:class (stl/css :color-bullet-wrapper)}
|
||||||
|
(when (or has-errors not-active)
|
||||||
|
[:div {:class (stl/css :error-dot)}])
|
||||||
|
[:> swatch* {:background color
|
||||||
|
:tooltip-content swatch-tooltip-content
|
||||||
|
:on-click on-swatch-click-token
|
||||||
|
:has-errors (or has-errors not-active)
|
||||||
|
:size "small"}]]
|
||||||
|
[:> tooltip* {:content name-tooltip-content
|
||||||
|
:id id
|
||||||
|
:class (stl/css :token-tooltip)}
|
||||||
|
[:div {:class (stl/css :token-name)
|
||||||
|
:aria-labelledby id}
|
||||||
|
(or token-name color-token)]]
|
||||||
|
[:div {:class (stl/css :token-actions)}
|
||||||
|
[:> icon-button*
|
||||||
|
{:variant "action"
|
||||||
|
:aria-label (tr "ds.inputs.token-field.detach-token")
|
||||||
|
:on-click on-detach-token
|
||||||
|
:icon i/detach}]
|
||||||
|
[:> icon-button*
|
||||||
|
{:variant "action"
|
||||||
|
:aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown")
|
||||||
|
:on-click open-modal-from-token
|
||||||
|
:icon i/tokens}]]]]))
|
||||||
|
|
||||||
(mf/defc color-row*
|
(mf/defc color-row*
|
||||||
[{:keys [index color class disable-gradient disable-opacity disable-image disable-picker hidden
|
[{:keys [index color class disable-gradient disable-opacity disable-image disable-picker hidden
|
||||||
on-change on-reorder on-detach on-open on-close on-remove origin
|
on-change on-reorder on-detach on-open on-close on-remove origin on-detach-token
|
||||||
disable-drag on-focus on-blur select-only select-on-focus on-token-change]}]
|
disable-drag on-focus on-blur select-only select-on-focus on-token-change applied-token]}]
|
||||||
(let [libraries (mf/deref refs/files)
|
(let [token-color (contains? cfg/flags :token-color)
|
||||||
|
libraries (mf/deref refs/files)
|
||||||
on-change (h/use-ref-callback on-change)
|
on-change (h/use-ref-callback on-change)
|
||||||
on-token-change (h/use-ref-callback on-token-change)
|
on-token-change (h/use-ref-callback on-token-change)
|
||||||
|
color-without-hash (mf/use-memo
|
||||||
|
(mf/deps color)
|
||||||
|
#(-> color :color clr/remove-hash))
|
||||||
|
|
||||||
file-id (or (:ref-file color) (:file-id color))
|
file-id (or (:ref-file color) (:file-id color))
|
||||||
color-id (or (:ref-id color) (:id color))
|
color-id (or (:ref-id color) (:id color))
|
||||||
src-colors (dm/get-in libraries [file-id :data :colors])
|
src-colors (dm/get-in libraries [file-id :data :colors])
|
||||||
color-name (dm/get-in src-colors [color-id :name])
|
color-name (dm/get-in src-colors [color-id :name])
|
||||||
|
|
||||||
multiple-colors? (uc/multiple? color)
|
has-multiple-colors (uc/multiple? color)
|
||||||
library-color? (and (or (:id color) (:ref-id color)) color-name (not multiple-colors?))
|
library-color? (and (or (:id color) (:ref-id color)) color-name (not has-multiple-colors))
|
||||||
gradient-color? (and (not multiple-colors?)
|
gradient-color? (and (not has-multiple-colors)
|
||||||
(:gradient color)
|
(:gradient color)
|
||||||
(dm/get-in color [:gradient :type]))
|
(dm/get-in color [:gradient :type]))
|
||||||
image-color? (and (not multiple-colors?)
|
image-color? (and (not has-multiple-colors)
|
||||||
(:image color))
|
(:image color))
|
||||||
|
|
||||||
editing-text* (mf/use-state false)
|
editing-text* (mf/use-state false)
|
||||||
editing-text? (deref editing-text*)
|
is-editing-text (deref editing-text*)
|
||||||
|
|
||||||
class (if (some? class) (dm/str class " ") "")
|
|
||||||
|
|
||||||
active-tokens* (mf/use-ctx ctx/active-tokens-by-type)
|
active-tokens* (mf/use-ctx ctx/active-tokens-by-type)
|
||||||
active-tokens (if active-tokens*
|
|
||||||
@active-tokens*
|
|
||||||
{})
|
|
||||||
|
|
||||||
opacity?
|
tokens (mf/with-memo [active-tokens* origin]
|
||||||
(and (not multiple-colors?)
|
(delay
|
||||||
(not library-color?)
|
(-> (deref active-tokens*)
|
||||||
(not disable-opacity))
|
(select-keys (get tk/tokens-by-input origin))
|
||||||
|
(not-empty))))
|
||||||
|
|
||||||
on-focus'
|
on-focus'
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -138,12 +231,12 @@
|
|||||||
(st/emit! (dwc/add-recent-color color)
|
(st/emit! (dwc/add-recent-color color)
|
||||||
(on-change color index)))))
|
(on-change color index)))))
|
||||||
|
|
||||||
handle-click-color
|
open-modal
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps disable-gradient disable-opacity disable-image disable-picker on-change on-close on-open active-tokens)
|
(mf/deps disable-gradient disable-opacity disable-image disable-picker on-change on-close on-open tokens)
|
||||||
(fn [color event]
|
(fn [color pos tab]
|
||||||
(let [color (cond
|
(let [color (cond
|
||||||
multiple-colors?
|
has-multiple-colors
|
||||||
{:color default-color
|
{:color default-color
|
||||||
:opacity 1}
|
:opacity 1}
|
||||||
|
|
||||||
@@ -152,13 +245,8 @@
|
|||||||
|
|
||||||
:else
|
:else
|
||||||
color)
|
color)
|
||||||
|
props {:x (:x pos)
|
||||||
cpos (dom/get-client-position event)
|
:y (:y pos)
|
||||||
x (dm/get-prop cpos :x)
|
|
||||||
y (dm/get-prop cpos :y)
|
|
||||||
|
|
||||||
props {:x x
|
|
||||||
:y y
|
|
||||||
:disable-gradient disable-gradient
|
:disable-gradient disable-gradient
|
||||||
:disable-opacity disable-opacity
|
:disable-opacity disable-opacity
|
||||||
:disable-image disable-image
|
:disable-image disable-image
|
||||||
@@ -168,8 +256,9 @@
|
|||||||
:on-close (fn [value opacity id file-id]
|
:on-close (fn [value opacity id file-id]
|
||||||
(when on-close
|
(when on-close
|
||||||
(on-close value opacity id file-id)))
|
(on-close value opacity id file-id)))
|
||||||
:active-tokens active-tokens
|
:active-tokens tokens
|
||||||
:color-origin origin
|
:color-origin origin
|
||||||
|
:tab tab
|
||||||
:origin :sidebar
|
:origin :sidebar
|
||||||
:data color}]
|
:data color}]
|
||||||
|
|
||||||
@@ -179,6 +268,38 @@
|
|||||||
(when-not disable-picker
|
(when-not disable-picker
|
||||||
(modal/show! :colorpicker props)))))
|
(modal/show! :colorpicker props)))))
|
||||||
|
|
||||||
|
handle-click-color
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps open-modal)
|
||||||
|
(fn [color event]
|
||||||
|
(let [cpos (dom/get-client-position event)]
|
||||||
|
(open-modal color cpos nil))))
|
||||||
|
|
||||||
|
open-modal-from-token
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps open-modal color)
|
||||||
|
(fn [event]
|
||||||
|
(let [cpos (dom/get-client-position event)
|
||||||
|
x (:x cpos)
|
||||||
|
y (:y cpos)
|
||||||
|
pos {:x (- x 215)
|
||||||
|
:y y}]
|
||||||
|
(open-modal color pos :token-color))))
|
||||||
|
|
||||||
|
on-swatch-click-token
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps open-modal)
|
||||||
|
(fn [color event]
|
||||||
|
(let [cpos (dom/get-client-position event)]
|
||||||
|
(open-modal color cpos :token-color))))
|
||||||
|
|
||||||
|
detach-token
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-detach-token)
|
||||||
|
(fn [token]
|
||||||
|
(when on-detach-token
|
||||||
|
(on-detach-token token))))
|
||||||
|
|
||||||
on-remove'
|
on-remove'
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps index)
|
(mf/deps index)
|
||||||
@@ -207,88 +328,95 @@
|
|||||||
:name (str "Color row" index)})
|
:name (str "Color row" index)})
|
||||||
[nil nil])
|
[nil nil])
|
||||||
|
|
||||||
|
|
||||||
row-class
|
row-class
|
||||||
(stl/css-case :color-data true
|
(stl/css-case :color-data true
|
||||||
:hidden hidden
|
:hidden hidden
|
||||||
:dnd-over-top (= (:over dprops) :top)
|
:dnd-over-top (= (:over dprops) :top)
|
||||||
:dnd-over-bot (= (:over dprops) :bot))]
|
:dnd-over-bot (= (:over dprops) :bot))]
|
||||||
|
|
||||||
|
|
||||||
(mf/with-effect [color prev-color disable-picker]
|
(mf/with-effect [color prev-color disable-picker]
|
||||||
(when (and (not disable-picker) (not= prev-color color))
|
(when (and (not disable-picker) (not= prev-color color))
|
||||||
(modal/update-props! :colorpicker {:data (parse-color color)})))
|
(modal/update-props! :colorpicker {:data (parse-color color)})))
|
||||||
|
|
||||||
[:div {:class [class row-class]}
|
[:div {:class [class row-class]}
|
||||||
|
|
||||||
;; Drag handler
|
;; Drag handler
|
||||||
(when (some? on-reorder)
|
(when (some? on-reorder)
|
||||||
[:> reorder-handler* {:ref dref}])
|
[:> reorder-handler* {:ref dref}])
|
||||||
|
|
||||||
[:div {:class (stl/css :color-info)}
|
|
||||||
[:div {:class (stl/css-case :color-name-wrapper true
|
|
||||||
:no-opacity (or disable-opacity
|
|
||||||
(not opacity?))
|
|
||||||
:library-name-wrapper library-color?
|
|
||||||
:editing editing-text?
|
|
||||||
:gradient-name-wrapper gradient-color?)}
|
|
||||||
[:div {:class (stl/css :color-bullet-wrapper)}
|
|
||||||
[:& cb/color-bullet {:color (cond-> color
|
|
||||||
(nil? color-name) (dissoc :ref-id :ref-file))
|
|
||||||
:mini true
|
|
||||||
:on-click handle-click-color}]]
|
|
||||||
(cond
|
(cond
|
||||||
;; Rendering a color with ID
|
(and token-color applied-token)
|
||||||
|
[:> color-token-row* {:active-tokens tokens
|
||||||
|
:color-token applied-token
|
||||||
|
:color (dissoc color :ref-id :ref-file)
|
||||||
|
:on-swatch-click-token on-swatch-click-token
|
||||||
|
:detach-token detach-token
|
||||||
|
:open-modal-from-token open-modal-from-token}]
|
||||||
|
|
||||||
library-color?
|
library-color?
|
||||||
|
[:> color-info-wrapper* {:class (stl/css-case :color-name-wrapper true
|
||||||
|
:library-name-wrapper true)
|
||||||
|
:handle-click-color handle-click-color
|
||||||
|
:color color}
|
||||||
[:*
|
[:*
|
||||||
[:div {:class (stl/css :color-name)
|
[:div {:class (stl/css :color-name)
|
||||||
:title (str color-name)}
|
:title (str color-name)}
|
||||||
|
|
||||||
(str color-name)]
|
(str color-name)]
|
||||||
(when on-detach
|
[:> icon-button*
|
||||||
[:button
|
{:variant "ghost"
|
||||||
{:class (stl/css :detach-btn)
|
:class (stl/css :detach-btn)
|
||||||
:title (tr "settings.detach")
|
:aria-label (tr "settings.detach")
|
||||||
:on-click detach-value}
|
:on-click detach-value
|
||||||
detach-icon])]
|
:icon i/detach}]]]
|
||||||
|
|
||||||
;; Rendering a gradient
|
|
||||||
gradient-color?
|
gradient-color?
|
||||||
|
[:> color-info-wrapper* {:class (stl/css-case :color-name-wrapper true
|
||||||
|
:no-opacity disable-opacity
|
||||||
|
:gradient-name-wrapper true)
|
||||||
|
:handle-click-color handle-click-color
|
||||||
|
:color color
|
||||||
|
:opacity true
|
||||||
|
:select-on-focus select-on-focus
|
||||||
|
:on-focus on-focus'
|
||||||
|
:on-blur on-blur'
|
||||||
|
:on-opacity-change on-opacity-change}
|
||||||
[:div {:class (stl/css :color-name)}
|
[:div {:class (stl/css :color-name)}
|
||||||
(uc/gradient-type->string (dm/get-in color [:gradient :type]))]
|
(uc/gradient-type->string (dm/get-in color [:gradient :type]))]]
|
||||||
|
|
||||||
;; Rendering an image
|
|
||||||
image-color?
|
image-color?
|
||||||
|
[:> color-info-wrapper* {:class (stl/css-case :color-name-wrapper true
|
||||||
|
:no-opacity disable-opacity)
|
||||||
|
:handle-click-color handle-click-color
|
||||||
|
:color color
|
||||||
|
:opacity true
|
||||||
|
:select-on-focus select-on-focus
|
||||||
|
:on-focus on-focus'
|
||||||
|
:on-blur on-blur'
|
||||||
|
:on-opacity-change on-opacity-change}
|
||||||
[:div {:class (stl/css :color-name)}
|
[:div {:class (stl/css :color-name)}
|
||||||
(tr "media.image")]
|
(tr "media.image")]]
|
||||||
|
|
||||||
;; Rendering a plain color
|
|
||||||
:else
|
:else
|
||||||
|
[:> color-info-wrapper* {:class (stl/css-case :color-name-wrapper true
|
||||||
|
:no-opacity (or disable-opacity
|
||||||
|
has-multiple-colors)
|
||||||
|
:editing is-editing-text)
|
||||||
|
:handle-click-color handle-click-color
|
||||||
|
:color color
|
||||||
|
:opacity true
|
||||||
|
:select-on-focus select-on-focus
|
||||||
|
:on-focus on-focus'
|
||||||
|
:on-blur on-blur'
|
||||||
|
:on-opacity-change on-opacity-change}
|
||||||
|
|
||||||
[:span {:class (stl/css :color-input-wrapper)}
|
[:span {:class (stl/css :color-input-wrapper)}
|
||||||
[:> color-input* {:value (if multiple-colors?
|
[:> color-input* {:value (if has-multiple-colors
|
||||||
""
|
""
|
||||||
(-> color :color clr/remove-hash))
|
color-without-hash)
|
||||||
:placeholder (tr "settings.multiple")
|
:placeholder (tr "settings.multiple")
|
||||||
:data-index index
|
:data-index index
|
||||||
:class (stl/css :color-input)
|
:class (stl/css :color-input)
|
||||||
:on-focus on-focus'
|
:on-focus on-focus'
|
||||||
:on-blur on-blur'
|
:on-blur on-blur'
|
||||||
:on-change on-color-change}]])]
|
:on-change on-color-change}]]])
|
||||||
|
|
||||||
(when opacity?
|
|
||||||
[:div {:class (stl/css :opacity-element-wrapper)}
|
|
||||||
[:span {:class (stl/css :icon-text)} "%"]
|
|
||||||
[:> numeric-input* {:value (-> color :opacity opacity->string)
|
|
||||||
:class (stl/css :opacity-input)
|
|
||||||
:placeholder "--"
|
|
||||||
:select-on-focus select-on-focus
|
|
||||||
:on-focus on-focus'
|
|
||||||
:on-blur on-blur'
|
|
||||||
:on-change on-opacity-change
|
|
||||||
:data-testid "opacity-input"
|
|
||||||
:default 100
|
|
||||||
:min 0
|
|
||||||
:max 100}]])]
|
|
||||||
|
|
||||||
(when (some? on-remove)
|
(when (some? on-remove)
|
||||||
[:> icon-button* {:variant "ghost"
|
[:> icon-button* {:variant "ghost"
|
||||||
@@ -300,4 +428,3 @@
|
|||||||
:aria-label (tr "settings.select-this-color")
|
:aria-label (tr "settings.select-this-color")
|
||||||
:on-click handle-select
|
:on-click handle-select
|
||||||
:icon i/move}])]))
|
:icon i/move}])]))
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,18 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) KALEIDOS INC
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
@use "refactor/common-refactor.scss" as deprecated;
|
@use "ds/typography.scss" as t;
|
||||||
|
@use "ds/_sizes.scss" as *;
|
||||||
|
@use "ds/_borders.scss" as *;
|
||||||
|
@use "ds/mixins.scss" as *;
|
||||||
|
@use "ds/_utils.scss" as *;
|
||||||
|
|
||||||
.color-data {
|
.color-data {
|
||||||
@include deprecated.flexRow;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--sp-xs);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
--reorder-left-position: calc(-1 * var(--sp-m) - var(--sp-xxs));
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
--reorder-icon-visibility: visible;
|
--reorder-icon-visibility: visible;
|
||||||
}
|
}
|
||||||
@@ -34,156 +37,289 @@
|
|||||||
--detach-icon-foreground-color: none;
|
--detach-icon-foreground-color: none;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
flex: 1;
|
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: deprecated.$s-2;
|
flex: 1;
|
||||||
border-radius: deprecated.$s-8;
|
gap: var(--sp-xxs);
|
||||||
background-color: var(--input-details-color);
|
block-size: $sz-32;
|
||||||
height: deprecated.$s-32;
|
border-radius: $br-8;
|
||||||
|
background-color: var(--color-background-primary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
--detach-icon-foreground-color: var(--input-foreground-color-active);
|
--detach-icon-foreground-color: var(--color-foreground-primary);
|
||||||
|
|
||||||
.detach-btn,
|
|
||||||
.select-btn {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-name-wrapper {
|
.color-name-wrapper {
|
||||||
@extend .input-element;
|
--color-name-wrapper-background-color: var(--color-background-tertiary);
|
||||||
@include deprecated.bodySmallTypography;
|
--color-name-wrapper-foreground-color: var(--color-foreground-primary);
|
||||||
|
--color-name-wrapper-boder-color: var(--color-background-tertiary);
|
||||||
|
@include t.use-typography("body-small");
|
||||||
|
@include textEllipsis;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
width: 100%;
|
gap: var(--sp-xs);
|
||||||
min-width: 0;
|
block-size: $sz-32;
|
||||||
border-radius: deprecated.$br-8 0 0 deprecated.$br-8;
|
min-inline-size: 0;
|
||||||
|
inline-size: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-inline-end: 0;
|
margin-inline-end: 0;
|
||||||
gap: deprecated.$s-4;
|
border: $b-1 solid var(--color-name-wrapper-boder-color);
|
||||||
|
border-radius: $br-8;
|
||||||
|
background-color: var(--color-name-wrapper-background-color);
|
||||||
|
color: var(--color-name-wrapper-foreground-color);
|
||||||
|
border-radius: $br-8 0 0 $br-8;
|
||||||
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
input {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.color-bullet-wrapper {
|
|
||||||
height: deprecated.$s-28;
|
|
||||||
padding: 0 deprecated.$s-2 0 deprecated.$s-8;
|
|
||||||
border-radius: deprecated.$br-8 0 0 deprecated.$br-8;
|
|
||||||
background-color: transparent;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
&:hover {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.color-name {
|
|
||||||
@include deprecated.bodySmallTypography;
|
|
||||||
@include deprecated.textEllipsis;
|
|
||||||
padding-inline: deprecated.$s-6;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
color: var(--input-foreground-color-active);
|
|
||||||
}
|
|
||||||
.detach-btn {
|
|
||||||
@extend .button-tertiary;
|
|
||||||
height: deprecated.$s-28;
|
|
||||||
width: deprecated.$s-28;
|
|
||||||
margin-inline-start: auto;
|
|
||||||
border-radius: 0 deprecated.$br-8 deprecated.$br-8 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.detach-icon {
|
|
||||||
@extend .button-icon;
|
|
||||||
stroke: var(--detach-icon-foreground-color);
|
|
||||||
}
|
|
||||||
.color-input-wrapper {
|
|
||||||
@include deprecated.bodySmallTypography;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: deprecated.$s-28;
|
|
||||||
padding: 0 deprecated.$s-0;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
flex-grow: 1;
|
|
||||||
background-color: var(--input-background-color);
|
|
||||||
color: var(--input-foreground-color);
|
|
||||||
border-radius: deprecated.$br-0;
|
|
||||||
}
|
|
||||||
&.no-opacity {
|
&.no-opacity {
|
||||||
border-radius: deprecated.$br-8;
|
border-radius: $br-8;
|
||||||
.color-input-wrapper {
|
.color-input-wrapper {
|
||||||
border-radius: deprecated.$br-8;
|
border-radius: $br-8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
--detach-icon-foreground-color: var(--input-foreground-color-active);
|
--detach-icon-foreground-color: var(--input-foreground-color-active);
|
||||||
|
--color-name-wrapper-background-color: var(--color-background-quaternary);
|
||||||
|
--color-name-wrapper-boder-color: var(--color-background-quaternary);
|
||||||
|
|
||||||
background-color: var(--input-background-color-hover);
|
|
||||||
border: deprecated.$s-1 solid var(--input-border-color-hover);
|
|
||||||
.color-bullet-wrapper,
|
|
||||||
.color-name,
|
|
||||||
.detach-btn,
|
|
||||||
.color-input-wrapper {
|
|
||||||
background-color: var(--input-background-color-hover);
|
|
||||||
}
|
|
||||||
.detach-btn {
|
.detach-btn {
|
||||||
display: flex;
|
display: grid;
|
||||||
}
|
}
|
||||||
&.editing {
|
&.editing {
|
||||||
background-color: var(--input-background-color-active);
|
--color-name-wrapper-background-color: var(--color-background-primary);
|
||||||
.color-bullet-wrapper,
|
}
|
||||||
.color-name,
|
|
||||||
.detach-btn,
|
&:focus,
|
||||||
|
&:focus-within {
|
||||||
|
--color-name-wrapper-background-color: var(--color-background-tertiary);
|
||||||
|
--color-name-wrapper-boder-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:focus-within {
|
||||||
|
--color-name-wrapper-background-color: var(--color-background-tertiary);
|
||||||
|
--color-name-wrapper-boder-color: var(--color-accent-primary);
|
||||||
|
&:hover {
|
||||||
|
--color-name-wrapper-background-color: var(--color-background-quaternary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.editing {
|
||||||
|
--color-name-wrapper-background-color: var(--color-background-primary);
|
||||||
|
&:hover {
|
||||||
|
--color-name-wrapper-boder-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detach-btn {
|
||||||
|
display: none;
|
||||||
|
background: var(--color-name-wrapper-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
.color-input-wrapper {
|
.color-input-wrapper {
|
||||||
background-color: var(--input-background-color-active);
|
@include t.use-typography("body-small");
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
block-size: $sz-28;
|
||||||
|
inline-size: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: var(--color-name-wrapper-background-color);
|
||||||
|
color: var(--color-name-wrapper-foreground-color);
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-name {
|
||||||
|
@include t.use-typography("body-small");
|
||||||
|
@include textEllipsis;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-inline: px2rem(6);
|
||||||
|
border-radius: $br-8;
|
||||||
|
color: var(--color-name-wrapper-foreground-color);
|
||||||
}
|
}
|
||||||
&:focus,
|
|
||||||
&:focus-within {
|
.color-bullet-wrapper {
|
||||||
background-color: var(--input-background-color-focus);
|
display: flex;
|
||||||
border: deprecated.$s-1 solid var(--input-border-color-focus);
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
block-size: $sz-28;
|
||||||
|
padding: 0 var(--sp-xxs) 0 var(--sp-s);
|
||||||
|
border-radius: $br-8 0 0 $br-8;
|
||||||
|
background-color: transparent;
|
||||||
|
&:hover {
|
||||||
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus,
|
.color-input {
|
||||||
&:focus-within {
|
@include textEllipsis;
|
||||||
background-color: var(--input-background-color-focus);
|
border: none;
|
||||||
border: deprecated.$s-1 solid var(--input-border-color-focus);
|
background: none;
|
||||||
&:hover {
|
outline: none;
|
||||||
background-color: var(--input-background-color-hover);
|
block-size: $sz-28;
|
||||||
border: deprecated.$s-1 solid var(--input-border-color-focus);
|
inline-size: 100%;
|
||||||
}
|
flex-grow: 1;
|
||||||
}
|
margin: var(--sp-xxs) 0;
|
||||||
|
padding: 0 0 0 px2rem(6);
|
||||||
&.editing {
|
border-radius: $br-8;
|
||||||
background-color: var(--input-background-color-active);
|
color: var(--input-foreground-color-active);
|
||||||
&:hover {
|
&[disabled] {
|
||||||
border: deprecated.$s-1 solid var(--input-border-color-active);
|
opacity: 0.5;
|
||||||
}
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.library-name-wrapper {
|
.library-name-wrapper {
|
||||||
border-radius: deprecated.$br-8;
|
border-radius: $br-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opacity-element-wrapper {
|
.opacity-element-wrapper {
|
||||||
@extend .input-element;
|
--opacity-input-background-color: var(--color-background-tertiary);
|
||||||
@include deprecated.bodySmallTypography;
|
--opacity-input-boder-color: var(--color-background-tertiary);
|
||||||
width: deprecated.$s-60;
|
|
||||||
border-radius: 0 deprecated.$br-8 deprecated.$br-8 0;
|
@include t.use-typography("body-small");
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
block-size: $sz-32;
|
||||||
|
inline-size: px2rem(60);
|
||||||
|
border-radius: 0 $br-8 $br-8 0;
|
||||||
|
border: $b-1 solid var(--opacity-input-boder-color);
|
||||||
|
background-color: var(--opacity-input-background-color);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--opacity-input-background-color: var(--color-background-quaternary);
|
||||||
|
--opacity-input-boder-color: var(--color-background-quaternary);
|
||||||
|
|
||||||
|
.detach-btn {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
&.editing {
|
||||||
|
--opacity-input-background-color: var(--color-background-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:focus-within {
|
||||||
|
--opacity-input-background-color: var(--color-background-tertiary);
|
||||||
|
--opacity-input-boder-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:focus-within {
|
||||||
|
--opacity-input-background-color: var(--color-background-tertiary);
|
||||||
|
--opacity-input-boder-color: var(--color-accent-primary);
|
||||||
|
&:hover {
|
||||||
|
--opacity-input-background-color: var(--color-background-quaternary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.editing {
|
||||||
|
--opacity-input-background-color: var(--color-background-primary);
|
||||||
|
&:hover {
|
||||||
|
--opacity-input-boder-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.opacity-input {
|
.opacity-input {
|
||||||
|
@include textEllipsis;
|
||||||
|
block-size: $sz-28;
|
||||||
|
min-inline-size: $sz-28;
|
||||||
|
flex-grow: 1;
|
||||||
|
inline-size: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 0 deprecated.$br-8 deprecated.$br-8 0;
|
border-radius: 0 $br-8 $br-8 0;
|
||||||
min-width: deprecated.$s-28;
|
border: none;
|
||||||
|
background: none;
|
||||||
|
outline: none;
|
||||||
|
margin: var(--sp-xxs) 0;
|
||||||
|
padding: 0 0 0 px2rem(6);
|
||||||
|
color: var(--color-foreground-primary);
|
||||||
|
&[disabled] {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon-text {
|
.icon-text {
|
||||||
@include deprecated.flexCenter;
|
display: flex;
|
||||||
height: deprecated.$s-32;
|
justify-content: center;
|
||||||
margin-inline-end: deprecated.$s-4;
|
align-items: center;
|
||||||
margin-block-start: deprecated.$s-2;
|
block-size: $sz-32;
|
||||||
|
margin-inline-end: var(--sp-xs);
|
||||||
|
margin-block-start: var(--sp-xxs);
|
||||||
|
color: var(--color-foreground-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOKEN ROW
|
||||||
|
|
||||||
|
.token-color-wrapper {
|
||||||
|
--token-color-wrapper-background-color: var(--color-background-tertiary);
|
||||||
|
--token-color-wrapper-foreground-color: var(--color-token-foreground);
|
||||||
|
--token-color-wrapper-border-color: var(--color-token-border);
|
||||||
|
--token-actions-display: none;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr auto;
|
||||||
|
gap: var(--sp-xs);
|
||||||
|
block-size: $sz-32;
|
||||||
|
min-inline-size: 0;
|
||||||
|
inline-size: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin-inline-end: 0;
|
||||||
|
background: var(--token-color-wrapper-background-color);
|
||||||
|
border: $b-1 solid var(--token-color-wrapper-border-color);
|
||||||
|
border-radius: $br-8;
|
||||||
|
&:hover {
|
||||||
|
--token-color-wrapper-background-color: var(--color-token-background);
|
||||||
|
--token-color-wrapper-foreground-color: var(--color-foreground-primary);
|
||||||
|
--token-color-wrapper-border-color: var(--color-token-background);
|
||||||
|
--token-actions-display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.token-color-with-errors,
|
||||||
|
.token-color-not-active {
|
||||||
|
--token-color-wrapper-background-color: var(--color-background-primary);
|
||||||
|
--token-color-wrapper-foreground-color: var(--color-foreground-secondary);
|
||||||
|
--token-color-wrapper-border-color: var(--color-token-border);
|
||||||
|
&:hover {
|
||||||
|
--token-color-wrapper-background-color: var(--color-background-primary);
|
||||||
|
--token-color-wrapper-foreground-color: var(--color-foreground-secondary);
|
||||||
|
--token-color-wrapper-border-color: var(--color-token-background);
|
||||||
|
--token-actions-display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-name {
|
||||||
|
@include t.use-typography("body-small");
|
||||||
|
@include textEllipsis;
|
||||||
|
color: var(--token-color-wrapper-foreground-color);
|
||||||
|
block-size: $sz-32;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-name-tooltip {
|
||||||
|
color: var(--color-foreground-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-actions {
|
||||||
|
display: var(--token-actions-display);
|
||||||
|
justify-self: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-dot {
|
||||||
|
inline-size: px2rem(4);
|
||||||
|
block-size: px2rem(4);
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--color-foreground-error);
|
||||||
|
margin-inline-start: var(--sp-xs);
|
||||||
|
position: absolute;
|
||||||
|
inset-inline-end: px2rem(1);
|
||||||
|
inset-block-start: px2rem(5);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
(: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.main.data.workspace.tokens.application :as dwta]
|
||||||
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.numeric-input :refer [numeric-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]]
|
||||||
@@ -37,8 +39,12 @@
|
|||||||
disable-drag
|
disable-drag
|
||||||
on-focus
|
on-focus
|
||||||
on-blur
|
on-blur
|
||||||
|
applied-tokens
|
||||||
|
on-detach-token
|
||||||
disable-stroke-style
|
disable-stroke-style
|
||||||
select-on-focus]}]
|
select-on-focus
|
||||||
|
shapes
|
||||||
|
objects]}]
|
||||||
|
|
||||||
(let [on-drop
|
(let [on-drop
|
||||||
(fn [_ data]
|
(fn [_ data]
|
||||||
@@ -55,27 +61,29 @@
|
|||||||
:name (str "Border row" index)})
|
:name (str "Border row" index)})
|
||||||
[nil nil])
|
[nil nil])
|
||||||
|
|
||||||
|
stroke-color-token (:stroke-color applied-tokens)
|
||||||
|
|
||||||
on-color-change-refactor
|
on-color-change-refactor
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-color-change)
|
(mf/deps index on-color-change)
|
||||||
(fn [color]
|
(fn [color]
|
||||||
(on-color-change index color)))
|
(on-color-change index color)))
|
||||||
|
|
||||||
on-color-detach
|
on-color-detach
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-color-detach)
|
(mf/deps index on-color-detach)
|
||||||
(fn [color]
|
(fn [color]
|
||||||
(on-color-detach index color)))
|
(on-color-detach index color)))
|
||||||
|
|
||||||
on-remove
|
on-remove
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-remove)
|
(mf/deps index on-remove)
|
||||||
#(on-remove index))
|
#(on-remove index))
|
||||||
|
|
||||||
stroke-width (:stroke-width stroke)
|
stroke-width (:stroke-width stroke)
|
||||||
|
|
||||||
on-width-change
|
on-width-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-width-change)
|
(mf/deps index on-stroke-width-change)
|
||||||
#(on-stroke-width-change index %))
|
#(on-stroke-width-change index %))
|
||||||
|
|
||||||
@@ -91,12 +99,35 @@
|
|||||||
{:value :outer :label (tr "workspace.options.stroke.outer")}]))
|
{:value :outer :label (tr "workspace.options.stroke.outer")}]))
|
||||||
|
|
||||||
on-alignment-change
|
on-alignment-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-alignment-change)
|
(mf/deps index on-stroke-alignment-change)
|
||||||
#(on-stroke-alignment-change index (keyword %)))
|
#(on-stroke-alignment-change index (keyword %)))
|
||||||
|
|
||||||
|
on-token-change
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps shapes objects)
|
||||||
|
(fn [_ token]
|
||||||
|
(let [expanded-shapes
|
||||||
|
(if (= 1 (count shapes))
|
||||||
|
(let [shape (first shapes)]
|
||||||
|
(if (= (:type shape) :group)
|
||||||
|
(keep objects (:shapes shape))
|
||||||
|
[shape]))
|
||||||
|
|
||||||
|
(mapcat (fn [shape]
|
||||||
|
(if (= (:type shape) :group)
|
||||||
|
(keep objects (:shapes shape))
|
||||||
|
[shape]))
|
||||||
|
shapes))]
|
||||||
|
|
||||||
|
(st/emit!
|
||||||
|
(dwta/toggle-token {:token token
|
||||||
|
:attrs #{:stroke-color}
|
||||||
|
:shapes expanded-shapes})))))
|
||||||
|
|
||||||
stroke-style (or (:stroke-style stroke) :solid)
|
stroke-style (or (:stroke-style stroke) :solid)
|
||||||
|
|
||||||
|
|
||||||
stroke-style-options
|
stroke-style-options
|
||||||
(mf/with-memo [stroke-style]
|
(mf/with-memo [stroke-style]
|
||||||
(d/concat-vec
|
(d/concat-vec
|
||||||
@@ -108,20 +139,26 @@
|
|||||||
{:value :mixed :label (tr "workspace.options.stroke.mixed")}]))
|
{:value :mixed :label (tr "workspace.options.stroke.mixed")}]))
|
||||||
|
|
||||||
on-style-change
|
on-style-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-style-change)
|
(mf/deps index on-stroke-style-change)
|
||||||
#(on-stroke-style-change index (keyword %)))
|
#(on-stroke-style-change index (keyword %)))
|
||||||
|
|
||||||
on-caps-start-change
|
on-caps-start-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-cap-start-change)
|
(mf/deps index on-stroke-cap-start-change)
|
||||||
#(on-stroke-cap-start-change index (keyword %)))
|
#(on-stroke-cap-start-change index (keyword %)))
|
||||||
|
|
||||||
on-caps-end-change
|
on-caps-end-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-cap-end-change)
|
(mf/deps index on-stroke-cap-end-change)
|
||||||
#(on-stroke-cap-end-change index (keyword %)))
|
#(on-stroke-cap-end-change index (keyword %)))
|
||||||
|
|
||||||
|
on-detach-token-color
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-detach-token)
|
||||||
|
(fn [token]
|
||||||
|
(on-detach-token token #{:stroke-color})))
|
||||||
|
|
||||||
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
|
||||||
@@ -135,7 +172,7 @@
|
|||||||
{:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared}]
|
{:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared}]
|
||||||
|
|
||||||
on-cap-switch
|
on-cap-switch
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-cap-switch)
|
(mf/deps index on-stroke-cap-switch)
|
||||||
#(on-stroke-cap-switch index))]
|
#(on-stroke-cap-switch index))]
|
||||||
|
|
||||||
@@ -156,8 +193,11 @@
|
|||||||
:on-detach on-color-detach
|
:on-detach on-color-detach
|
||||||
:on-remove on-remove
|
:on-remove on-remove
|
||||||
:disable-drag disable-drag
|
:disable-drag disable-drag
|
||||||
|
:applied-token stroke-color-token
|
||||||
|
:on-detach-token on-detach-token-color
|
||||||
|
:on-token-change on-token-change
|
||||||
:on-focus on-focus
|
:on-focus on-focus
|
||||||
:origin :stroke
|
:origin :stroke-color
|
||||||
:select-on-focus select-on-focus
|
:select-on-focus select-on-focus
|
||||||
:on-blur on-blur}]
|
:on-blur on-blur}]
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
shapes (mf/with-memo [shape] [shape])
|
shapes (mf/with-memo [shape] [shape])
|
||||||
|
|
||||||
applied-tokens
|
applied-tokens
|
||||||
(get shape :applied-tokens)
|
(when (seq (get shape :applied-tokens))
|
||||||
|
(get shape :applied-tokens))
|
||||||
|
|
||||||
measure-values
|
measure-values
|
||||||
(select-keys shape measure-attrs)
|
(select-keys shape measure-attrs)
|
||||||
@@ -120,12 +121,16 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values shape}]
|
:values shape
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:show-caps true
|
:show-caps true
|
||||||
:values stroke-values}]
|
:values stroke-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
||||||
[:& blur-menu {:ids ids
|
[:& blur-menu {:ids ids
|
||||||
|
|||||||
@@ -120,10 +120,15 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values shape}]
|
:values shape
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values stroke-values}]
|
:values stroke-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
||||||
[:& blur-menu {:ids ids
|
[:& blur-menu {:ids ids
|
||||||
:values (select-keys shape [:blur])}]
|
:values (select-keys shape [:blur])}]
|
||||||
|
|||||||
@@ -143,11 +143,15 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type shape-type
|
:type shape-type
|
||||||
:values shape}]
|
:values shape
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type shape-type
|
:type shape-type
|
||||||
:values stroke-values}]
|
:values stroke-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
[:> color-selection-menu* {:type shape-type
|
[:> color-selection-menu* {:type shape-type
|
||||||
:shapes shapes-with-children
|
:shapes shapes-with-children
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
[constraint-ids constraint-values]
|
[constraint-ids constraint-values]
|
||||||
(get-attrs shapes objects :constraint)
|
(get-attrs shapes objects :constraint)
|
||||||
|
|
||||||
[fill-ids fill-values]
|
[fill-ids fill-values fill-tokens]
|
||||||
(get-attrs shapes objects :fill)
|
(get-attrs shapes objects :fill)
|
||||||
|
|
||||||
[shadow-ids]
|
[shadow-ids]
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
[blur-ids blur-values]
|
[blur-ids blur-values]
|
||||||
(get-attrs shapes objects :blur)
|
(get-attrs shapes objects :blur)
|
||||||
|
|
||||||
[stroke-ids stroke-values]
|
[stroke-ids stroke-values stroke-tokens]
|
||||||
(get-attrs shapes objects :stroke)
|
(get-attrs shapes objects :stroke)
|
||||||
|
|
||||||
[text-ids text-values]
|
[text-ids text-values]
|
||||||
@@ -143,10 +143,21 @@
|
|||||||
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
|
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
|
||||||
|
|
||||||
(when-not (empty? fill-ids)
|
(when-not (empty? fill-ids)
|
||||||
[:> fill/fill-menu* {:type type :ids fill-ids :values fill-values}])
|
[:> fill/fill-menu*
|
||||||
|
{:type type
|
||||||
|
:ids fill-ids
|
||||||
|
:values fill-values
|
||||||
|
:shapes shapes
|
||||||
|
:objects objects
|
||||||
|
:applied-tokens fill-tokens}])
|
||||||
|
|
||||||
(when-not (empty? stroke-ids)
|
(when-not (empty? stroke-ids)
|
||||||
[:& stroke-menu {:type type :ids stroke-ids :values stroke-values}])
|
[:& stroke-menu {:type type
|
||||||
|
:ids stroke-ids
|
||||||
|
:values stroke-values
|
||||||
|
:shapes shapes
|
||||||
|
:objects objects
|
||||||
|
:applied-tokens stroke-tokens}])
|
||||||
|
|
||||||
[:> color-selection-menu*
|
[:> color-selection-menu*
|
||||||
{:type type
|
{:type type
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
[app.common.types.shape.attrs :refer [editable-attrs]]
|
[app.common.types.shape.attrs :refer [editable-attrs]]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.common.types.text :as txt]
|
[app.common.types.text :as txt]
|
||||||
|
[app.common.types.token :as tt]
|
||||||
[app.common.weak :as weak]
|
[app.common.weak :as weak]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
|
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
|
||||||
@@ -211,18 +212,34 @@
|
|||||||
(= attr-group :blur) (attrs/get-attrs-multi [v1 v2] attrs blur-eq blur-sel)
|
(= attr-group :blur) (attrs/get-attrs-multi [v1 v2] attrs blur-eq blur-sel)
|
||||||
:else (attrs/get-attrs-multi [v1 v2] attrs)))
|
:else (attrs/get-attrs-multi [v1 v2] attrs)))
|
||||||
|
|
||||||
merge-token-values
|
merge-attr
|
||||||
(fn [acc keys attrs]
|
(fn [acc applied-tokens t-attr]
|
||||||
(reduce
|
"Merges a single token attribute (`t-attr`) into the accumulator map.
|
||||||
(fn [accum key]
|
- If the attribute is not present, associates it with the new value.
|
||||||
(let [new-val (get attrs key)
|
- If the existing value equals the new value, keeps the accumulator unchanged.
|
||||||
existing (get accum key ::not-found)]
|
- If there is a conflict, sets the value to `:multiple`."
|
||||||
|
(let [new-val (get applied-tokens t-attr)
|
||||||
|
existing (get acc t-attr ::not-found)]
|
||||||
(cond
|
(cond
|
||||||
(= existing ::not-found) (assoc accum key new-val)
|
(= existing ::not-found) (assoc acc t-attr new-val)
|
||||||
(= existing new-val) accum
|
(= existing new-val) acc
|
||||||
:else (assoc accum key :multiple))))
|
:else (assoc acc t-attr :multiple))))
|
||||||
acc
|
|
||||||
keys))
|
merge-shape-attr
|
||||||
|
(fn [acc applied-tokens shape-attr]
|
||||||
|
"Merges all token attributes derived from a single shape attribute
|
||||||
|
into the accumulator map using `merge-attr`."
|
||||||
|
(let [token-attrs (tt/shape-attr->token-attrs shape-attr)]
|
||||||
|
(reduce #(merge-attr %1 applied-tokens %2) acc token-attrs)))
|
||||||
|
|
||||||
|
merge-token-values
|
||||||
|
(fn [acc shape-attrs applied-tokens]
|
||||||
|
"Merges token values across all shape attributes.
|
||||||
|
For each shape attribute, its corresponding token attributes are merged
|
||||||
|
into the accumulator. If applied tokens are empty, the accumulator is returned unchanged."
|
||||||
|
(if (seq applied-tokens)
|
||||||
|
(reduce #(merge-shape-attr %1 applied-tokens %2) acc shape-attrs)
|
||||||
|
acc))
|
||||||
|
|
||||||
extract-attrs
|
extract-attrs
|
||||||
(fn [[ids values token-acc] {:keys [id type applied-tokens] :as shape}]
|
(fn [[ids values token-acc] {:keys [id type applied-tokens] :as shape}]
|
||||||
@@ -263,8 +280,8 @@
|
|||||||
|
|
||||||
:children
|
:children
|
||||||
(let [children (->> (:shapes shape []) (map #(get objects %)))
|
(let [children (->> (:shapes shape []) (map #(get objects %)))
|
||||||
[new-ids new-values] (get-attrs* children objects attr-group)]
|
[new-ids new-values tokens] (get-attrs* children objects attr-group)]
|
||||||
[(d/concat-vec ids new-ids) (merge-attrs values new-values) {}])
|
[(d/concat-vec ids new-ids) (merge-attrs values new-values) tokens])
|
||||||
|
|
||||||
[])))]
|
[])))]
|
||||||
|
|
||||||
@@ -376,7 +393,7 @@
|
|||||||
[constraint-ids constraint-values]
|
[constraint-ids constraint-values]
|
||||||
(get-attrs shapes objects :constraint)
|
(get-attrs shapes objects :constraint)
|
||||||
|
|
||||||
[fill-ids fill-values]
|
[fill-ids fill-values fill-tokens]
|
||||||
(get-attrs shapes objects :fill)
|
(get-attrs shapes objects :fill)
|
||||||
|
|
||||||
[shadow-ids shadow-values]
|
[shadow-ids shadow-values]
|
||||||
@@ -385,7 +402,7 @@
|
|||||||
[blur-ids blur-values]
|
[blur-ids blur-values]
|
||||||
(get-attrs shapes objects :blur)
|
(get-attrs shapes objects :blur)
|
||||||
|
|
||||||
[stroke-ids stroke-values]
|
[stroke-ids stroke-values stroke-tokens]
|
||||||
(get-attrs shapes objects :stroke)
|
(get-attrs shapes objects :stroke)
|
||||||
|
|
||||||
[exports-ids exports-values]
|
[exports-ids exports-values]
|
||||||
@@ -463,14 +480,22 @@
|
|||||||
[:& ot/text-menu {:type type :ids text-ids :values text-values}])
|
[:& ot/text-menu {:type type :ids text-ids :values text-values}])
|
||||||
|
|
||||||
(when-not (empty? fill-ids)
|
(when-not (empty? fill-ids)
|
||||||
[:> fill/fill-menu* {:type type :ids fill-ids :values fill-values}])
|
[:> fill/fill-menu* {:type type
|
||||||
|
:ids fill-ids
|
||||||
|
:values fill-values
|
||||||
|
:shapes shapes
|
||||||
|
:objects objects
|
||||||
|
:applied-tokens fill-tokens}])
|
||||||
|
|
||||||
(when-not (empty? stroke-ids)
|
(when-not (empty? stroke-ids)
|
||||||
[:& stroke-menu {:type type
|
[:& stroke-menu {:type type
|
||||||
:ids stroke-ids
|
:ids stroke-ids
|
||||||
:show-caps show-caps?
|
:show-caps show-caps?
|
||||||
:values stroke-values
|
:values stroke-values
|
||||||
:disable-stroke-style has-text?}])
|
:shapes shapes
|
||||||
|
:objects objects
|
||||||
|
:disable-stroke-style has-text?
|
||||||
|
:applied-tokens stroke-tokens}])
|
||||||
|
|
||||||
(when-not (empty? shapes)
|
(when-not (empty? shapes)
|
||||||
[:> color-selection-menu*
|
[:> color-selection-menu*
|
||||||
|
|||||||
@@ -120,12 +120,16 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values shape}]
|
:values shape
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:show-caps true
|
:show-caps true
|
||||||
:values stroke-values}]
|
:values stroke-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
||||||
[:& blur-menu {:ids ids
|
[:& blur-menu {:ids ids
|
||||||
:values (select-keys shape [:blur])}]
|
:values (select-keys shape [:blur])}]
|
||||||
|
|||||||
@@ -120,11 +120,15 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values shape}]
|
:shapes shapes
|
||||||
|
:values shape
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values stroke-values}]
|
:shapes shapes
|
||||||
|
:values stroke-values
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
||||||
|
|
||||||
|
|||||||
@@ -188,11 +188,15 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values fill-values}]
|
:values fill-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values stroke-values}]
|
:values stroke-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
|
||||||
|
|
||||||
|
|||||||
@@ -173,12 +173,16 @@
|
|||||||
[:> fill/fill-menu*
|
[:> fill/fill-menu*
|
||||||
{:ids ids
|
{:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values fill-values}]
|
:values fill-values
|
||||||
|
:shapes shapes
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
[:& stroke-menu {:ids ids
|
[:& stroke-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:values stroke-values
|
:values stroke-values
|
||||||
:disable-stroke-style true}]
|
:shapes shapes
|
||||||
|
:disable-stroke-style true
|
||||||
|
:applied-tokens applied-tokens}]
|
||||||
|
|
||||||
(when (= :multiple (:fills fill-values))
|
(when (= :multiple (:fills fill-values))
|
||||||
[:> color-selection-menu*
|
[:> color-selection-menu*
|
||||||
|
|||||||
@@ -1184,7 +1184,11 @@ msgstr "Detach token"
|
|||||||
|
|
||||||
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:39
|
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:39
|
||||||
msgid "ds.inputs.token-field.no-active-token-option"
|
msgid "ds.inputs.token-field.no-active-token-option"
|
||||||
msgstr "This token is not available in any active set or theme."
|
msgstr "This token is not in any active set or has an invalid value."
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
|
||||||
|
msgid "color-row.token-color-row.deleted-token"
|
||||||
|
msgstr "This token does not exists or has been deleted."
|
||||||
|
|
||||||
#: src/app/main/data/auth.cljs:314
|
#: src/app/main/data/auth.cljs:314
|
||||||
msgid "errors.auth-provider-not-allowed"
|
msgid "errors.auth-provider-not-allowed"
|
||||||
|
|||||||
@@ -1196,7 +1196,11 @@ msgstr "Desvincular token"
|
|||||||
|
|
||||||
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:39
|
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:39
|
||||||
msgid "ds.inputs.token-field.no-active-token-option"
|
msgid "ds.inputs.token-field.no-active-token-option"
|
||||||
msgstr "Este token no está disponible en ningún set ni tema activo."
|
msgstr "Este token no está disponible en ningún set o tiene un valor inválido."
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
|
||||||
|
msgid "color-row.token-color-row.deleted-token"
|
||||||
|
msgstr "Este token no existe o ha sido borrado."
|
||||||
|
|
||||||
#: src/app/main/data/auth.cljs:314
|
#: src/app/main/data/auth.cljs:314
|
||||||
msgid "errors.auth-provider-not-allowed"
|
msgid "errors.auth-provider-not-allowed"
|
||||||
|
|||||||
Reference in New Issue
Block a user