Compare commits

...

35 Commits

Author SHA1 Message Date
Eva Marco
9e2bd5c38c 🐛 Fix hover position of lock proportion tooltip 2025-10-16 10:52:49 +02:00
Eva Marco
24264e7d8a 🎉 Replace numeric inputs on layout menus (#7488)
* 🎉 Replace numeric inputs on layout menus

* 🎉 Add numeric inputs on gaps

* ♻️ Refactor scss file

* 🐛 Fix comments
2025-10-16 10:05:25 +02:00
Xaviju
5b77df997b 🐛 Remove color validation for non-color tokens in strokes (#7513) 2025-10-16 09:54:50 +02:00
Xaviju
968274096d 🐛 Fix visual glitch in transparent background for swatch component (#7509) 2025-10-16 09:54:33 +02:00
Alejandro Alonso
392e3ac34e Merge pull request #7507 from penpot/elenatorro-11974-fix-resize-on-blocked-shapes
🐛 Fix resize on blocked shapes from the viewport
2025-10-16 09:17:13 +02:00
Elena Torro
e8336a401e 🐛 Do not show resize controls when a selected shape is blocked 2025-10-16 06:43:34 +02:00
Elena Torro
18048a4b2e 🐛 Do not select a blocked frame when clicking its name 2025-10-16 06:42:45 +02:00
Elena Torro
e28d4eaff1 🐛 Do not allow to resize a shape that is blocked from the viewport 2025-10-16 06:42:45 +02:00
Alejandro Alonso
fae574796f Merge pull request #7512 from penpot/elenatorro-11963-change-font-styles-label
🌐 Add font-style label on workspace assets
2025-10-16 06:36:39 +02:00
Elena Torro
db59209b21 🌐 Add font-style label on workspace assets 2025-10-15 14:41:15 +02:00
Alejandro Alonso
a62f1fb46f Merge pull request #7505 from penpot/elenatorro-review-extrect
🔧 Fix extrect and selrect debug interactivity
2025-10-15 14:02:22 +02:00
Alejandro Alonso
ffd2aa03a9 Merge pull request #7510 from penpot/alotor-bugfix-pan-with-guides
🐛 Fix pan cursor not disabling viewport guides
2025-10-15 13:36:12 +02:00
Xaviju
f1ebcaf635 Add composite typography token to text panel (#7496) 2025-10-15 13:21:30 +02:00
alonso.torres
6a4d0f05bc 🐛 Fix pan cursor not disabling viewport guides 2025-10-15 13:02:56 +02:00
Alejandro Alonso
4d751c5acd Merge pull request #7504 from penpot/azazeln28-feat-webgl-error
🎉 Add debug and alert when WebGL is unsupported
2025-10-15 12:51:45 +02:00
Andrey Antukh
9a5efe8671 Merge remote-tracking branch 'origin/staging' into develop 2025-10-15 11:32:15 +02:00
Andrey Antukh
1f65e2f560 Merge branch 'staging' into develop 2025-10-15 11:22:03 +02:00
Alejandro Alonso
bf6874a96d Merge pull request #7460 from penpot/ladybenko-12205-cap-fills-text
 Cap the amount of text fills
2025-10-15 11:17:32 +02:00
Elena Torro
3c05067c99 🔧 Fix extrect and selrect debug interactivity 2025-10-15 10:10:24 +02:00
Aitor Moreno
bbb78904fb 🎉 Add debug and alert when WebGL is unsupported 2025-10-15 10:06:02 +02:00
Elena Torró
12e91751c3 🔧 Improve debugging UI (#7500) 2025-10-14 17:29:04 +02:00
David Barragán Merino
0f0c8466be 📎 Add bundle version to the metadata in S3 2025-10-14 16:30:31 +02:00
Belén Albeza
204d0dfb9d Add integration test to check fills limit in UI 2025-10-14 16:14:53 +02:00
Belén Albeza
e4a3fc3940 Limit the amount of text fills passed to wasm 2025-10-14 16:05:03 +02:00
Francis Santiago
29dc99deae 🔧 Replace ADD with COPY in Dockerfiles to fix hadolint warnings 2025-10-14 13:53:48 +02:00
alonso.torres
025f0d2fdb 🐛 Fix problem with tiles and transform 2025-10-14 12:51:48 +02:00
Eva Marco
045aa7c788 🎉 Add tokens to color selection (#7447)
* 🎉 Add tokens to color row

* 🎉 Add color-token to stroke input

* 🐛 Fix change token on multiselection with groups

* 🎉 Create token colors on selected-colors section

* ♻️ Fix comments
2025-10-14 11:17:14 +02:00
Andrey Antukh
0f3ca67773 🔧 Simplfy circleci workflow dependencies 2025-10-13 18:53:39 +02:00
Andrey Antukh
1c06c87acf 🔧 Add missing construction_worker to commit checker regex 2025-10-13 18:53:39 +02:00
Andrey Antukh
d532558bab Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 18:41:18 +02:00
Andrey Antukh
71ed845307 Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 16:35:53 +02:00
Andrey Antukh
dd35c82824 Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 15:19:07 +02:00
Xaviju
253605f6cc 🎉 Add text panel to inspect styles tab (#7413) 2025-10-13 14:20:55 +02:00
Xaviju
2548bec651 🐛 Fix visual glitch in background for swatch component (#7468) 2025-10-13 14:20:14 +02:00
Andrey Antukh
da5da00bd4 📚 Update changelog 2025-10-13 14:08:33 +02:00
91 changed files with 4641 additions and 3518 deletions

View File

@@ -57,6 +57,7 @@ jobs:
id: vars
run: |
echo "gh_ref=${{ inputs.gh_ref || github.ref_name }}" >> $GITHUB_OUTPUT
echo "bundle_version=$(git describe --tags --always)" >> $GITHUB_OUTPUT
- name: Build bundle
env:
@@ -76,7 +77,7 @@ jobs:
- name: Upload Penpot bundle to S3
run: |
aws s3 cp zips/penpot.zip s3://${{ secrets.S3_BUCKET }}/penpot-${{ steps.vars.outputs.gh_ref }}.zip
aws s3 cp zips/penpot.zip s3://${{ secrets.S3_BUCKET }}/penpot-${{ steps.vars.outputs.gh_ref }}.zip --metadata bundle-version=${{ steps.vars.outputs.bundle_version }}
- name: Notify Mattermost
if: failure()
@@ -86,4 +87,5 @@ jobs:
TEXT: |
❌ *[PENPOT] Error during the execution of the job*
📄 Triggered from ref: `${{ steps.vars.outputs.gh_ref }}`
Bundle version: `${{ steps.vars.outputs.bundle_version }}`
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}

View File

@@ -1,5 +1,20 @@
# CHANGELOG
## 2.12.0 (Unreleased)
### :boom: Breaking changes & Deprecations
### :rocket: Epics and highlights
### :heart: Community contributions (Thank you!)
### :sparkles: New features & Enhancements
### :bug: Bugs fixed
- Fix pan cursor not disabling viewport guides [Github #6985](https://github.com/penpot/penpot/issues/6985)
- Fix viewport resize on locked shapes [Taiga #11974](https://tree.taiga.io/project/penpot/issue/11974)
## 2.11.0 (Unreleased)
### :boom: Breaking changes & Deprecations

View File

@@ -34,7 +34,6 @@
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set (tht/get-tokens-lib file) "foo/bar"))
_ (prn "changes" changes)
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)

View File

@@ -128,7 +128,7 @@ COPY --from=build /opt/node /opt/node
COPY --from=penpotapp/imagemagick:7.1.2-0 /opt/imagick /opt/imagick
ARG BUNDLE_PATH="./bundle-backend/"
ADD --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/backend/
COPY --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/backend/
USER penpot:penpot
WORKDIR /opt/penpot/backend

View File

@@ -90,7 +90,7 @@ RUN set -eux; \
chown -R penpot:penpot /opt/penpot;
ARG BUNDLE_PATH="./bundle-exporter/"
ADD --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/exporter/
COPY --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/exporter/
WORKDIR /opt/penpot/exporter
USER penpot:penpot

View File

@@ -12,13 +12,13 @@ RUN set -ex; \
mkdir -p /etc/nginx/overrides/location.d/;
ARG BUNDLE_PATH="./bundle-frontend/"
ADD $BUNDLE_PATH /var/www/app/
ADD ./files/config.js /var/www/app/js/config.js
ADD ./files/nginx.conf.template /tmp/nginx.conf.template
ADD ./files/nginx-resolvers.conf.template /tmp/resolvers.conf.template
ADD ./files/nginx-mime.types /etc/nginx/mime.types
ADD ./files/nginx-external-locations.conf /etc/nginx/overrides/location.d/external-locations.conf
ADD ./files/nginx-entrypoint.sh /entrypoint.sh
COPY $BUNDLE_PATH /var/www/app/
COPY ./files/config.js /var/www/app/js/config.js
COPY ./files/nginx.conf.template /tmp/nginx.conf.template
COPY ./files/nginx-resolvers.conf.template /tmp/resolvers.conf.template
COPY ./files/nginx-mime.types /etc/nginx/mime.types
COPY ./files/nginx-external-locations.conf /etc/nginx/overrides/location.d/external-locations.conf
COPY ./files/nginx-entrypoint.sh /entrypoint.sh
RUN chown -R 1001:0 /var/cache/nginx; \
chmod -R g+w /var/cache/nginx; \

View File

@@ -217,7 +217,7 @@ repository:
```bash
# cd <repo>/frontend
yarn run validate-translations
yarn run translations
```
At Penpot core team we maintain manually the english and spanish .po files. All

View File

@@ -0,0 +1,132 @@
{
"~:features": {
"~#set": [
"fdata/path-data",
"plugins/runtime",
"design-tokens/v1",
"variants/v1",
"layout/grid",
"styles/v2",
"fdata/objects-map",
"render-wasm/v1",
"components/v2",
"fdata/shape-data-type"
]
},
"~:team-id": "~u3e5ffd68-2819-8084-8006-eb1c616a5afd",
"~:permissions": {
"~:type": "~:membership",
"~:is-owner": true,
"~:is-admin": true,
"~:can-edit": true,
"~:can-read": true,
"~:is-logged": true
},
"~:has-media-trimmed": false,
"~:comment-thread-seqn": 0,
"~:name": "Text fills",
"~:revn": 26,
"~:modified-at": "~m1760450987132",
"~:vern": 0,
"~:id": "~ub1ff3fdf-b491-812b-8006-f2ce3d29333a",
"~:is-shared": false,
"~:migrations": {
"~#ordered-set": [
"legacy-2",
"legacy-3",
"legacy-5",
"legacy-6",
"legacy-7",
"legacy-8",
"legacy-9",
"legacy-10",
"legacy-11",
"legacy-12",
"legacy-13",
"legacy-14",
"legacy-16",
"legacy-17",
"legacy-18",
"legacy-19",
"legacy-25",
"legacy-26",
"legacy-27",
"legacy-28",
"legacy-29",
"legacy-31",
"legacy-32",
"legacy-33",
"legacy-34",
"legacy-36",
"legacy-37",
"legacy-38",
"legacy-39",
"legacy-40",
"legacy-41",
"legacy-42",
"legacy-43",
"legacy-44",
"legacy-45",
"legacy-46",
"legacy-47",
"legacy-48",
"legacy-49",
"legacy-50",
"legacy-51",
"legacy-52",
"legacy-53",
"legacy-54",
"legacy-55",
"legacy-56",
"legacy-57",
"legacy-59",
"legacy-62",
"legacy-65",
"legacy-66",
"legacy-67",
"0001-remove-tokens-from-groups",
"0002-normalize-bool-content-v2",
"0002-clean-shape-interactions",
"0003-fix-root-shape",
"0003-convert-path-content-v2",
"0004-clean-shadow-color",
"0005-deprecate-image-type",
"0006-fix-old-texts-fills",
"0007-clear-invalid-strokes-and-fills-v2",
"0008-fix-library-colors-v4",
"0009-clean-library-colors",
"0009-add-partial-text-touched-flags",
"0010-fix-swap-slots-pointing-non-existent-shapes",
"0011-fix-invalid-text-touched-flags",
"0012-fix-position-data",
"0013-fix-component-path",
"0014-fix-tokens-lib-duplicate-ids"
]
},
"~:version": 67,
"~:project-id": "~u3e5ffd68-2819-8084-8006-eb1c616e69bf",
"~:created-at": "~m1760368824484",
"~:backend": "legacy-db",
"~:data": {
"~:pages": [
"~ub1ff3fdf-b491-812b-8006-f2ce3d29333b"
],
"~:pages-index": {
"~ub1ff3fdf-b491-812b-8006-f2ce3d29333b": {
"~:objects": {
"~#penpot/objects-map/v2": {
"~u00000000-0000-0000-0000-000000000000": "[\"~#shape\",[\"^ \",\"~:y\",0,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"Root Frame\",\"~:width\",0.01,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",0.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",0,\"~:proportion\",1.0,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",0.01,\"~:height\",0.01,\"~:x1\",0,\"~:y1\",0,\"~:x2\",0.01,\"~:y2\",0.01]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^H\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~u23b2a9cc-5d10-800a-8006-f2ce6354e75d\"]]]",
"~u23b2a9cc-5d10-800a-8006-f2ce6354e75d": "[\"~#shape\",[\"^ \",\"~:y\",540.9999842227844,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:key\",\"1tx250q8puw\",\"~:children\",[[\"^ \",\"^7\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"\",\"^;\",\"normal\",\"~:typography-ref-id\",null,\"~:text-transform\",\"none\",\"~:font-id\",\"sourcesanspro\",\"^8\",\"1c1skqx1y2p\",\"~:font-size\",\"36\",\"~:font-weight\",\"700\",\"~:typography-ref-file\",null,\"~:font-variant-id\",\"bold\",\"~:text-decoration\",\"none\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-opacity\",1],[\"^ \",\"^F\",\"#00ffc3\",\"^G\",1],[\"^ \",\"^F\",\"#d9ff00\",\"^G\",1],[\"^ \",\"^F\",\"#192b60\",\"^G\",1],[\"^ \",\"^F\",\"#7f9fff\",\"^G\",1],[\"^ \",\"^F\",\"#ff00ca\",\"^G\",1],[\"^ \",\"^F\",\"#003fff\",\"^G\",1]],\"~:font-family\",\"sourcesanspro\",\"~:text\",\"Lorem ipsum\"]],\"^<\",null,\"^=\",\"none\",\"~:text-align\",\"left\",\"^>\",\"sourcesanspro\",\"^8\",\"12a6vwimj9j\",\"^?\",\"0\",\"^@\",\"700\",\"^A\",null,\"~:text-direction\",\"ltr\",\"^7\",\"paragraph\",\"^B\",\"bold\",\"^C\",\"none\",\"^D\",\"0\",\"^E\",[[\"^ \",\"^F\",\"#000000\",\"^G\",1],[\"^ \",\"^F\",\"#00ffc3\",\"^G\",1],[\"^ \",\"^F\",\"#d9ff00\",\"^G\",1],[\"^ \",\"^F\",\"#192b60\",\"^G\",1],[\"^ \",\"^F\",\"#7f9fff\",\"^G\",1],[\"^ \",\"^F\",\"#ff00ca\",\"^G\",1],[\"^ \",\"^F\",\"#003fff\",\"^G\",1]],\"^H\",\"sourcesanspro\"]]]],\"~:vertical-align\",\"top\"],\"~:hide-in-viewer\",false,\"~:name\",\"Lorem ipsum\",\"~:width\",207.000004835394,\"^7\",\"^I\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",321.9999624852649,\"~:y\",540.9999842227845]],[\"^Q\",[\"^ \",\"~:x\",528.9999673206589,\"~:y\",540.9999842227845]],[\"^Q\",[\"^ \",\"~:x\",528.9999673206589,\"~:y\",583.9999821366218]],[\"^Q\",[\"^ \",\"~:x\",321.9999624852649,\"~:y\",583.9999821366218]]],\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~u23b2a9cc-5d10-800a-8006-f2ce6354e75d\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:x\",321.99996248526486,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",321.99996248526486,\"~:y\",540.9999842227844,\"^O\",207.000004835394,\"~:height\",42.99999791383732,\"~:x1\",321.99996248526486,\"~:y1\",540.9999842227844,\"~:x2\",528.9999673206589,\"~:y2\",583.9999821366217]],\"~:flip-x\",null,\"^X\",42.99999791383732,\"~:flip-y\",null]]"
}
},
"~:id": "~ub1ff3fdf-b491-812b-8006-f2ce3d29333b",
"~:name": "Page 1"
}
},
"~:id": "~ub1ff3fdf-b491-812b-8006-f2ce3d29333a",
"~:options": {
"~:components-v2": true,
"~:base-font-size": "16px"
}
}
}

View File

@@ -89,6 +89,38 @@ test.describe("Shape attributes", () => {
await expect(workspace.page.getByTestId("add-fill")).toBeDisabled();
});
test("Cannot add a new text fill when the limit has been reached", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
await workspace.mockConfigFlags(["enable-feature-render-wasm"]);
await workspace.setupEmptyFile();
await workspace.mockRPC(
/get\-file\?/,
"design/get-file-text-fills-limit.json",
);
await workspace.goToWorkspace({
fileId: "b1ff3fdf-b491-812b-8006-f2ce3d29333a",
pageId: "b1ff3fdf-b491-812b-8006-f2ce3d29333b",
});
await workspace.clickLeafLayer("Lorem ipsum");
await expect(
workspace.page.getByRole("button", { name: "Remove color" }),
).toHaveCount(7);
await workspace.page.getByRole("button", { name: "Add fill" }).click();
await expect(
workspace.page.getByRole("button", { name: "Remove color" }),
).toHaveCount(8);
await expect(
workspace.page.getByRole("button", { name: "Add fill" }),
).toBeDisabled();
});
});
test.describe("Multiple shapes attributes", () => {

View File

@@ -28,13 +28,29 @@ const setupFileWithAssets = async (workspace) => {
return { fileId, pageId };
};
test("Shows the workspace correctly for a blank file", async ({ page }) => {
const workspace = new WorkspacePage(page);
await workspace.setupEmptyFile();
test.describe("Viewport", () => {
test("Shows the workspace correctly for a blank file", async ({ page }) => {
const workspace = new WorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.goToWorkspace();
await workspace.goToWorkspace();
await expect(workspace.page).toHaveScreenshot();
await expect(workspace.page).toHaveScreenshot();
});
test("User creates a rectangle and locks it", async ({ page }) => {
const workspace = new WorkspacePage(page);
await workspace.setupEmptyFile(page);
await workspace.goToWorkspace();
await workspace.rectShapeButton.click();
await workspace.clickWithDragViewportAt(128, 128, 200, 100);
await workspace.clickLeafLayer("Rectangle");
await page.keyboard.press("Shift+Control+L");
await expect(workspace.page).toHaveScreenshot();
});
});
test.describe("Design tab", () => {
@@ -145,4 +161,4 @@ test.describe("Palette", () => {
workspace.palette.getByRole("button", { name: "#7798ff" }),
).toBeVisible();
});
});
});

View File

@@ -1137,16 +1137,20 @@
ref-id (:stroke-color-ref-id stroke)
colors (-> libraries
(get ref-file)
(get ref-id)
(get :data)
(ctl/get-colors))
shared? (contains? colors ref-id)
has-color? (:stroke-color stroke)
is-shared? (contains? colors ref-id)
has-color? (or (:stroke-color stroke)
(:stroke-color-gradient stroke))
attrs (cond-> (clr/stroke->color stroke)
(not (or is-shared? (= ref-file file-id)))
(dissoc :ref-id :ref-file))]
base-attrs (cond-> (clr/stroke->color stroke)
(not (or shared? (= ref-file file-id)))
(dissoc :ref-file :ref-id))
attrs (cond-> base-attrs
(:has-token-applied stroke)
(assoc :has-token-applied true
:token-name (:token-name stroke)))]
(when has-color?
{:attrs attrs
@@ -1154,7 +1158,25 @@
:shape-id (:shape-id stroke)
:index (:index stroke)})))
(defn- shadow->color-att
(defn- shadow->color-attr
"Given a stroke map enriched with :shape-id, :index, and optionally
:has-token-applied / :token-name, returns a color attribute map.
If :has-token-applied is true, adds token metadata to :attrs:
{:has-token-applied true
:token-name <token-name>}
Args:
- stroke: map with stroke info, including :shape-id and :index
- file-id: current file UUID
- libraries: map of shared color libraries
Returns:
A map like:
{:attrs {...color data...}
:prop :stroke
:shape-id <uuid>
:index <int>}"
[shadow file-id libraries]
(let [color (get shadow :color)
ref-file (get color :ref-file)
@@ -1202,6 +1224,24 @@
(map #(text->color-att % file-id libraries)))))
(defn- fill->color-att
"Given a fill map enriched with :shape-id, :index, and optionally
:has-token-applied / :token-name, returns a color attribute map.
If :has-token-applied is true, adds token metadata to :attrs:
{:has-token-applied true
:token-name <token-name>}
Args:
- fill: map with fill info, including :shape-id and :index
- file-id: current file UUID
- libraries: map of shared color libraries
Returns:
A map like:
{:attrs {...color data...}
:prop :fill
:shape-id <uuid>
:index <int>}"
[fill file-id libraries]
(let [ref-file (:fill-color-ref-file fill)
ref-id (:fill-color-ref-id fill)
@@ -1213,9 +1253,15 @@
shared? (contains? colors ref-id)
has-color? (or (:fill-color fill)
(:fill-color-gradient fill))
attrs (cond-> (types.fills/fill->color fill)
base-attrs (cond-> (types.fills/fill->color fill)
(not (or shared? (= ref-file file-id)))
(dissoc :ref-file :ref-id))]
(dissoc :ref-file :ref-id))
attrs (cond-> base-attrs
(:has-token-applied fill)
(assoc :has-token-applied true
:token-name (:token-name fill)))]
(when has-color?
{:attrs attrs
@@ -1224,21 +1270,55 @@
:index (:index fill)})))
(defn extract-all-colors
"Extracts color information from a list of shapes, including fills, strokes, and shadows.
If a shape has applied tokens of type :fill or :stroke-color, the first fill or stroke
will include extra attributes in its :attrs map:
{:has-token-applied true
:token-name <token-name>}
Args:
- shapes: vector of shape maps
- file-id: current file UUID
- libraries: map of shared color libraries
Returns:
A vector of color attribute maps with metadata for each shape."
[shapes file-id libraries]
(reduce
(fn [result shape]
(let [fill-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:fills shape))
stroke-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:strokes shape))
shadow-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:shadow shape))]
(let [applied-tokens (:applied-tokens shape)
applied-fill (get applied-tokens :fill)
applied-stroke (get applied-tokens :stroke-color)
fills (:fills shape)
strokes (:strokes shape)
shadows (:shadow shape)
shape-id (:id shape)
fills* (map-indexed
(fn [index fill]
(cond-> (assoc fill :shape-id shape-id :index index)
(and (zero? index) applied-fill)
(assoc :has-token-applied true
:token-name applied-fill)))
fills)
strokes* (map-indexed
(fn [index stroke]
(cond-> (assoc stroke :shape-id shape-id :index index)
(and (zero? index) applied-stroke)
(assoc :has-token-applied true
:token-name applied-stroke)))
strokes)
shadows* (map-indexed #(assoc %2 :shape-id shape-id :index %1) shadows)]
(if (= :text (:type shape))
(-> result
(into (keep #(stroke->color-att % file-id libraries)) stroke-obj)
(into (map #(shadow->color-att % file-id libraries)) shadow-obj)
(into (keep #(stroke->color-att % file-id libraries)) strokes*)
(into (map #(shadow->color-attr % file-id libraries)) shadows*)
(into (extract-text-colors shape file-id libraries)))
(-> result
(into (keep #(fill->color-att % file-id libraries)) fill-obj)
(into (keep #(stroke->color-att % file-id libraries)) stroke-obj)
(into (map #(shadow->color-att % file-id libraries)) shadow-obj)))))
(into (keep #(fill->color-att % file-id libraries)) fills*)
(into (keep #(stroke->color-att % file-id libraries)) strokes*)
(into (map #(shadow->color-attr % file-id libraries)) shadows*)))))
[]
shapes))

View File

@@ -273,76 +273,82 @@
ptk/WatchEvent
(watch [_ state stream]
(let [initial-position @ms/mouse-position
(if (:blocked shape)
(rx/empty)
(let [initial-position @ms/mouse-position
stopper (mse/drag-stopper stream)
layout (:workspace-layout state)
page-id (:current-page-id state)
focus (:workspace-focus-selected state)
zoom (dm/get-in state [:workspace-local :zoom] 1)
objects (dsh/lookup-page-objects state page-id)
shapes (map (d/getf objects) ids)
stopper (mse/drag-stopper stream)
layout (:workspace-layout state)
page-id (:current-page-id state)
focus (:workspace-focus-selected state)
zoom (dm/get-in state [:workspace-local :zoom] 1)
objects (dsh/lookup-page-objects state page-id)
shape-ids (filterv (comp not :blocked (d/getf objects)) ids)]
resize-events-stream
(->> ms/mouse-position
(rx/filter some?)
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-alt)
(rx/map normalize-proportion-lock)
(rx/switch-map
(fn [[point _ _ :as current]]
(->> (snap/closest-snap-point page-id shapes objects layout zoom focus point)
(rx/map #(conj current %)))))
(rx/map #(resize shape initial-position layout %))
(rx/share))
(if (empty? shape-ids)
(rx/empty)
(let [shapes (map (d/getf objects) shape-ids)
modifiers-stream
(if (features/active-feature? state "render-wasm/v1")
(rx/merge
(->> resize-events-stream
(rx/mapcat
(fn [modifiers]
(let [modif-tree (dwm/create-modif-tree ids modifiers)]
(rx/of
(dwm/set-wasm-modifiers
modif-tree
:ignore-constraints (contains? layout :scale-text))))))
(rx/take-until stopper))
resize-events-stream
(->> ms/mouse-position
(rx/filter some?)
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-alt)
(rx/map normalize-proportion-lock)
(rx/switch-map
(fn [[point _ _ :as current]]
(->> (snap/closest-snap-point page-id shapes objects layout zoom focus point)
(rx/map #(conj current %)))))
(rx/map #(resize shape initial-position layout %))
(rx/share))
modifiers-stream
(if (features/active-feature? state "render-wasm/v1")
(rx/merge
(->> resize-events-stream
(rx/mapcat
(fn [modifiers]
(let [modif-tree (dwm/create-modif-tree shape-ids modifiers)]
(rx/of
(dwm/set-wasm-modifiers
modif-tree
:ignore-constraints (contains? layout :scale-text))))))
(rx/take-until stopper))
;; The last event we need to use the old method so the elements are correctly positioned until
;; all the logic is implemented in wasm
(->> resize-events-stream
(rx/take-until stopper)
(rx/last)
(rx/map
#(dwm/apply-wasm-modifiers
(dwm/create-modif-tree ids %)
:ignore-constraints (contains? layout :scale-text)))))
(->> resize-events-stream
(rx/take-until stopper)
(rx/last)
(rx/map
#(dwm/apply-wasm-modifiers
(dwm/create-modif-tree shape-ids %)
:ignore-constraints (contains? layout :scale-text)))))
(->> resize-events-stream
(rx/mapcat
(fn [modifiers]
(let [modif-tree (dwm/create-modif-tree ids modifiers)]
(rx/of (dwm/set-modifiers modif-tree (contains? layout :scale-text))))))
(rx/take-until stopper)))]
(->> resize-events-stream
(rx/mapcat
(fn [modifiers]
(let [modif-tree (dwm/create-modif-tree shape-ids modifiers)]
(rx/of (dwm/set-modifiers modif-tree (contains? layout :scale-text))))))
(rx/take-until stopper)))]
(rx/concat
(rx/concat
;; This initial stream waits for some pixels to be move before making the resize
;; if you make a click in the border will not make a resize
(->> ms/mouse-position
(rx/map #(gpt/to-vec initial-position %))
(rx/map #(gpt/length %))
(rx/filter #(> % (/ 10 zoom)))
(rx/take 1)
(rx/take-until stopper)
(rx/mapcat (fn [] modifiers-stream)))
(->> ms/mouse-position
(rx/map #(gpt/to-vec initial-position %))
(rx/map #(gpt/length %))
(rx/filter #(> % (/ 10 zoom)))
(rx/take 1)
(rx/take-until stopper)
(rx/mapcat (fn [] modifiers-stream)))
(if (features/active-feature? state "render-wasm/v1")
(rx/of
(finish-transform))
(if (features/active-feature? state "render-wasm/v1")
(rx/of
(finish-transform))
(rx/of
(dwm/apply-modifiers)
(finish-transform)))))))))
(rx/of
(dwm/apply-modifiers)
(finish-transform))))))))))))
(defn trigger-bounding-box-cloaking
"Trigger the bounding box cloaking (with default timer of 1sec)

View File

@@ -20,13 +20,15 @@
[:icon
[:and :string [:fn #(contains? icon-list %)]]]
[:aria-label :string]
[:tooltip-placement {:optional true}
[:maybe [:enum "top" "bottom" "left" "right" "top-right" "bottom-right" "bottom-left" "top-left"]]]
[:variant {:optional true}
[:maybe [:enum "primary" "secondary" "ghost" "destructive" "action"]]]])
(mf/defc icon-button*
{::mf/schema schema:icon-button
::mf/memo true}
[{:keys [class icon icon-class variant aria-label children] :rest props}]
[{:keys [class icon icon-class variant aria-label children tooltip-placement] :rest props}]
(let [variant
(d/nilv variant "primary")
@@ -47,6 +49,7 @@
:aria-labelledby tooltip-id})]
[:> tooltip* {:content aria-label
:placement tooltip-placement
:id tooltip-id}
[:> :button props
[:> icon* {:icon-id icon :aria-hidden true :class icon-class}]

View File

@@ -25,6 +25,7 @@
[app.util.keyboard :as kbd]
[app.util.object :as obj]
[app.util.simple-math :as smt]
[app.util.timers :as ts]
[cuerdas.core :as str]
[goog.events :as events]
[rumext.v2 :as mf]
@@ -382,7 +383,11 @@
(reset! focused-id* nil)
(reset! is-open* false)
(reset! token-applied* name)
(apply-token value name)))
(apply-token value name)
(ts/schedule-on-idle
(fn []
(when token-wrapper-ref
(dom/focus! (mf/ref-val token-wrapper-ref)))))))
on-option-click
(mf/use-fn
@@ -416,14 +421,16 @@
(fn [event]
(let [target (dom/get-related-target event)
self-node (mf/ref-val wrapper-ref)]
(when-not (dom/is-child? self-node target)
(reset! filter-id* "")
(reset! focused-id* nil)
(reset! is-open* false)))
(when (mf/ref-val dirty-ref)
(apply-value (mf/ref-val raw-value*))
(when (fn? on-blur)
(on-blur event)))))
(apply-value (mf/ref-val raw-value*)))
(when (fn? on-blur)
(on-blur event))))
on-key-down
(mf/use-fn
@@ -560,9 +567,11 @@
(reset! token-applied* nil)
(reset! selected-id* nil)
(reset! focused-id* nil)
(dom/focus! (mf/ref-val ref))
(when on-detach
(on-detach token))))))
(on-detach token))
(ts/schedule-on-idle
(fn []
(dom/focus! (mf/ref-val ref))))))))
on-token-key-down
(mf/use-fn
@@ -656,6 +665,7 @@
:label label
:value token-value
:on-click open-dropdown-token
:on-focus on-focus
:on-token-key-down on-token-key-down
:disabled disabled
:on-blur on-blur

View File

@@ -27,13 +27,14 @@
[:on-click {:optional true} fn?]
[:on-token-key-down fn?]
[:on-blur {:optional true} fn?]
[:on-focus {:optional true} fn?]
[:detach-token fn?]])
(mf/defc token-field*
{::mf/schema schema:token-field}
[{:keys [id label value slot-start disabled
on-click on-token-key-down on-blur detach-token
token-wrapper-ref token-detach-btn-ref]}]
token-wrapper-ref token-detach-btn-ref on-focus]}]
(let [set-active? (some? id)
content (if set-active?
label
@@ -60,6 +61,7 @@
:on-key-down on-token-key-down
:ref token-wrapper-ref
:on-blur on-blur
:on-focus on-focus
:tab-index (if disabled -1 0)}
(when (some? slot-start) slot-start)

View File

@@ -93,6 +93,8 @@
image (:image background)
format (if id? "rounded" "square")
element-id (mf/use-id)
has-opacity? (and (some? (:color background))
(< (:opacity background) 1))
on-click
(mf/use-fn
(mf/deps background on-click)
@@ -124,19 +126,20 @@
[:> element-type props
(cond
(some? gradient-type)
[:span {:class (stl/css :swatch-gradient)
:style {:background-image (str (uc/gradient->css gradient-data) ", repeating-conic-gradient(lightgray 0% 25%, white 0% 50%)")}}]
[:div {:class (stl/css :swatch-gradient)
:style {:background-image (str (uc/gradient->css gradient-data) ", repeating-conic-gradient(lightgray 0% 25%, white 0% 50%)")}}]
(some? image)
(let [uri (cfg/resolve-file-media image)]
[:span {:class (stl/css :swatch-image)
:style {:background-image (str/ffmt "url(%)" uri)}}])
[:div {:class (stl/css :swatch-image)
:style {:background-image (str/ffmt "url(%)" uri)}}])
has-errors
[:span {:class (stl/css :swatch-error)}]
[:div {:class (stl/css :swatch-error)}]
:else
[:span {:class (stl/css :swatch-opacity)}
[:span {:class (stl/css :swatch-solid-side)
:style {:background (uc/color->background (assoc background :opacity 1))}}]
[:span {:class (stl/css :swatch-opacity-side)
:style {:background (uc/color->background background)}}]])]]))
[:div {:class (stl/css :swatch-opacity)}
[:div {:class (stl/css :swatch-solid-side)
:style {:background (uc/color->background (assoc background :opacity 1))}}]
[:div {:class (stl/css-case :swatch-opacity-side true
:swatch-opacity-side-transparency has-opacity?
:swatch-opacity-side-solid-color (not has-opacity?))
:style {"--solid-color-overlay" (str (uc/color->background background))}}]])]]))

View File

@@ -8,8 +8,14 @@
@use "ds/_sizes.scss" as *;
@use "ds/colors.scss" as *;
@property --solid-color-overlay {
syntax: "<color>";
inherits: false;
initial-value: rgba(0, 0, 0, 0);
}
.swatch {
--border-color: var(--color-accent-primary-muted);
--border-color: var(--color-background-quaternary);
--border-radius: #{$br-4};
--border-color-active: var(--color-foreground-primary);
--border-color-active-inset: var(--color-background-primary);
@@ -73,7 +79,8 @@
background: none;
&:hover {
border: 2px solid var(--border-color);
--border-color: var(--color-accent-primary-muted);
border-width: $b-2;
}
}
@@ -98,9 +105,25 @@
}
.swatch-opacity {
background: var(--checkerboard-background);
background-size: var(--checkerboard-size);
display: flex;
display: grid;
grid-template-columns: auto auto;
}
.swatch-opacity-side-transparency {
background-image:
/* solidcolour overlay */
/* checkerboard pattern */
linear-gradient(var(--solid-color-overlay), var(--solid-color-overlay)), var(--checkerboard-background);
background-size: cover, var(--checkerboard-size);
background-position: center, center;
background-repeat: no-repeat, repeat;
clip-path: inset(0 0 0 0 round 0 #{$br-4} #{$br-4} 0);
}
.swatch-opacity-side-solid-color {
background: var(--solid-color-overlay);
background-size: cover;
}
.swatch-solid-side,

View File

@@ -13,29 +13,18 @@
[app.common.types.fills :as types.fills]
[app.common.types.text :as types.text]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.copy-button :refer [copy-button*]]
[app.main.ui.components.title-bar :refer [inspect-title-bar*]]
[app.main.ui.formats :as fmt]
[app.main.ui.inspect.attributes.common :refer [color-row]]
[app.main.ui.inspect.common.typography :as ict]
[app.util.i18n :refer [tr]]
[cuerdas.core :as str]
[okulary.core :as l]
[rumext.v2 :as mf]))
(defn- has-text? [shape]
(:content shape))
(def ^:private file-typographies-ref
(l/derived (l/in [:viewer :file :data :typographies]) st/state))
(defn- make-typographies-library-ref [file-id]
(let [get-library
(fn [state]
(get-in state [:viewer-libraries file-id :data :typographies]))]
#(l/derived get-library st/state)))
(defn- copy-style-data
[style & properties]
(->> properties
@@ -44,24 +33,10 @@
(mf/defc typography-block
[{:keys [text style]}]
(let [typography-library-ref
(mf/use-memo
(mf/deps (:typography-ref-file style))
(make-typographies-library-ref (:typography-ref-file style)))
typography-library (mf/deref typography-library-ref)
;; FIXME: too many duplicate operations
file-typographies-viewer (mf/deref file-typographies-ref)
file-typographies-workspace (mf/deref refs/workspace-file-typography)
file-library-workspace (get (mf/deref refs/files) (:typography-ref-file style))
typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
color-format* (mf/use-state :hex)
(let [color-format* (mf/use-state :hex)
color-format (deref color-format*)
typography (or (get (or typography-library file-typographies-viewer file-typographies-workspace) (:typography-ref-id style)) typography-external-lib)]
typography (ict/get-typography style)]
[:div {:class (stl/css :attributes-content)}
(when (:fills style)

View File

@@ -0,0 +1,38 @@
;; 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.inspect.common.typography
(:require
[app.main.refs :as refs]
[app.main.store :as st]
[okulary.core :as l]
[rumext.v2 :as mf]))
(defn- make-typographies-library-ref
[file-id]
(let [get-library
(fn [state]
(get-in state [:viewer-libraries file-id :data :typographies]))]
#(l/derived get-library st/state)))
(def ^:private file-typographies-ref
(l/derived (l/in [:viewer :file :data :typographies]) st/state))
(defn get-typography
[style]
(let [typography-library-ref
(mf/use-memo
(mf/deps (:typography-ref-file style))
(make-typographies-library-ref (:typography-ref-file style)))
; FIXME: too many duplicate operations
typography-library (mf/deref typography-library-ref)
file-typographies-viewer (mf/deref file-typographies-ref)
file-typographies-workspace (mf/deref refs/workspace-file-typography)
file-library-workspace (get (mf/deref refs/files) (:typography-ref-file style))
typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
typography (or (get (or typography-library file-typographies-viewer file-typographies-workspace) (:typography-ref-id style)) typography-external-lib)]
typography))

View File

@@ -22,6 +22,7 @@
[app.main.ui.inspect.styles.panels.layout-element :refer [layout-element-panel*]]
[app.main.ui.inspect.styles.panels.stroke :refer [stroke-panel*]]
[app.main.ui.inspect.styles.panels.svg :refer [svg-panel*]]
[app.main.ui.inspect.styles.panels.text :refer [text-panel*]]
[app.main.ui.inspect.styles.panels.tokens-panel :refer [tokens-panel*]]
[app.main.ui.inspect.styles.panels.variants-panel :refer [variants-panel*]]
[app.main.ui.inspect.styles.panels.visibility :refer [visibility-panel*]]
@@ -71,6 +72,9 @@
(defn- has-blur? [shape]
(:blur shape))
(defn- has-text? [shape]
(:content shape))
(defn- get-shape-type
[shapes first-shape first-component]
(if (= (count shapes) 1)
@@ -195,6 +199,14 @@
[:> style-box* {:panel :blur}
[:> blur-panel* {:shapes shapes
:objects objects}]]))
:text
(let [shapes (filter has-text? shapes)]
(when (seq shapes)
[:> style-box* {:panel :text}
[:> text-panel* {:shapes shapes
:color-space color-space
:objects objects
:resolved-tokens resolved-active-tokens}]]))
;; DEFAULT WIP
[:> style-box* {:panel panel}
[:div color-space]])])]))

View File

@@ -47,7 +47,7 @@
;; Current token implementation on fills only supports one token per shape and has to be the first fill
;; This must be improved in the future
(defn- has-token?
(defn- has-color-token?
"Returns true if the resolved token matches the color and is the first fill (idx = 0)."
[resolved-token stroke-type idx]
(and (= (:resolved-value resolved-token) (:color stroke-type))
@@ -66,17 +66,17 @@
property-name (cmm/get-css-rule-humanized property)
property-value (css/get-css-property objects stroke property)
resolved-token (get-resolved-token property shape resolved-tokens)
has-token (has-token? resolved-token stroke-type idx)]
has-color-token (has-color-token? resolved-token stroke-type idx)]
(if (= property :border-color)
[:> color-properties-row* {:key (str idx property)
:term property-name
:color stroke-type
:token (when has-token resolved-token)
:token (when has-color-token resolved-token)
:format color-space
:copiable true}]
[:> properties-row* {:key (str idx property)
:term (d/name property-name)
:detail (dm/str value)
:token (when has-token resolved-token)
:token resolved-token
:property property-value
:copiable true}]))))])])

View File

@@ -30,9 +30,9 @@
:term (d/name sub-attr-key)
:detail (dm/str sub-attr-value)
:property property-value
:copiable false}]))
:copiable true}]))
[:> properties-row* {:key (dm/str "svg-property-" (d/name attr-key))
:term (d/name attr-key)
:detail (dm/str attr-value)
:property (dm/str attr-key ": " attr-value ";")
:copiable false}]))]])
:copiable true}]))]])

View File

@@ -0,0 +1,184 @@
;; 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.inspect.styles.panels.text
(:require-macros [app.main.style :as stl])
(:require
[app.common.types.fills :as types.fills]
[app.common.types.text :as txt]
[app.main.fonts :as fonts]
[app.main.ui.formats :as fmt]
[app.main.ui.inspect.common.typography :as ict]
[app.main.ui.inspect.styles.property-detail-copiable :refer [property-detail-copiable*]]
[app.main.ui.inspect.styles.rows.color-properties-row :refer [color-properties-row*]]
[app.main.ui.inspect.styles.rows.properties-row :refer [properties-row*]]
[app.util.timers :as tm]
[app.util.webapi :as wapi]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
(defn- get-applied-tokens-in-shape
[shape-tokens property]
(get shape-tokens property))
(defn- get-resolved-token
[property shape resolved-tokens]
(let [shape-tokens (:applied-tokens shape)
applied-tokens-in-shape (get-applied-tokens-in-shape shape-tokens property)
token (get resolved-tokens applied-tokens-in-shape)]
token))
(defn- get-style-text
[shape]
(->> (:content shape)
(txt/content->text+styles)
(remove (fn [[_ text]] (str/empty? (str/trim text))))
(mapv (fn [[style text]] (vector (merge (txt/get-default-text-attrs) style) text)))))
(mf/defc typography-name-block*
[{:keys [style]}]
(let [typography (ict/get-typography style)
property-value (:name typography)]
(when typography
[:> properties-row* {:term "Typography"
:detail (:name typography)
:property property-value
:copiable true}])))
(mf/defc typography-color-row*
[{:keys [fill shape resolved-tokens color-space]}]
(let [color (types.fills/fill->color fill)
resolved-token (get-resolved-token :fill shape resolved-tokens)]
[:> color-properties-row* {:term "Font Color"
:color color
:token resolved-token
:format color-space
:copiable true}]))
(mf/defc text-panel*
[{:keys [shapes _ resolved-tokens color-space]}]
[:div {:class (stl/css :text-panel)}
(for [shape shapes]
(let [style-text-blocks (get-style-text shape)
composite-typography-token (get-resolved-token :typography shape resolved-tokens)]
[:div {:key (:id shape) :class "text-shape"}
(for [[style text] style-text-blocks]
[:div {:key (:id shape) :class "text-properties"}
(when (:fills style)
(for [[idx fill] (map-indexed vector (:fills style))]
[:> typography-color-row* {:key idx
:fill fill
:shape shape
:resolved-tokens resolved-tokens
:color-space color-space}]))
;; Typography style
(when (and (not composite-typography-token)
(:typography-ref-id style))
[:> typography-name-block* {:style style}])
;; Composite Typography token
(when (and (not (:typography-ref-id style))
composite-typography-token)
[:> properties-row* {:term "Typography"
:detail (:name composite-typography-token)
:token composite-typography-token
:property (:name composite-typography-token)
:copiable true}])
(when (:font-id style)
(let [name (get (fonts/get-font-data (:font-id style)) :name)
resolved-token (get-resolved-token :font-family shape resolved-tokens)]
[:> properties-row* {:term "Font Family"
:detail name
:token resolved-token
:property (str "font-family: \"" name "\";")
:copiable true}]))
(when (:font-style style)
[:> properties-row* {:term "Font Style"
:detail (:font-style style)
:property (str "font-style: " (:font-style style) ";")
:copiable true}])
(when (:font-size style)
(let [font-size (fmt/format-pixels (:font-size style))
resolved-token (get-resolved-token :font-size shape resolved-tokens)]
[:> properties-row* {:term "Font Size"
:detail font-size
:token resolved-token
:property (str "font-size: " font-size ";")
:copiable true}]))
(when (:font-weight style)
(let [resolved-token (get-resolved-token :font-weight shape resolved-tokens)]
[:> properties-row* {:term "Font Weight"
:detail (:font-weight style)
:token resolved-token
:property (str "font-weight: " (:font-weight style) ";")
:copiable true}]))
(when (:line-height style)
(let [line-height (:line-height style)
resolved-token (get-resolved-token :line-height shape resolved-tokens)]
[:> properties-row* {:term "Line Height"
:detail (str line-height)
:token resolved-token
:property (str "line-height: " line-height ";")
:copiable true}]))
(when (:letter-spacing style)
(let [letter-spacing (fmt/format-pixels (:letter-spacing style))
resolved-token (get-resolved-token :letter-spacing shape resolved-tokens)]
[:> properties-row* {:term "Letter Spacing"
:detail letter-spacing
:token resolved-token
:property (str "letter-spacing: " letter-spacing ";")
:copiable true}]))
(when (:text-decoration style)
(let [resolved-token (get-resolved-token :text-decoration shape resolved-tokens)]
[:> properties-row* {:term "Text Decoration"
:detail (:text-decoration style)
:token resolved-token
:property (str "text-decoration: " (:text-decoration style) ";")
:copiable true}]))
(when (:text-transform style)
(let [resolved-token (get-resolved-token :text-case shape resolved-tokens)]
[:> properties-row* {:term "Text Transform"
:detail (:text-transform style)
:token resolved-token
:property (str "text-transform: " (:text-transform style) ";")
:copiable true}]))
(when text
(let [copied* (mf/use-state false)
copied (deref copied*)
text (str/trim text)
copy-text
(mf/use-fn
(mf/deps copied)
(fn []
(let [formatted-text (if (= (:text-transform style) "uppercase")
(.toUpperCase text)
text)]
(reset! copied* true)
(wapi/write-to-clipboard formatted-text)
(tm/schedule 1000 #(reset! copied* false)))))]
[:div {:class (stl/css :text-content-wrapper)}
[:> property-detail-copiable* {:copied copied
:on-click copy-text}
[:span {:class (stl/css :text-content)
:style {:font-family (:font-family style)
:font-weight (:font-weight style)
:text-transform (:text-transform style)
:letter-spacing (fmt/format-pixels (:letter-spacing style))
:font-style (:font-style style)}}
text]]]))])]))])

View File

@@ -0,0 +1,20 @@
// 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/_borders.scss" as *;
.text-content-wrapper {
--border-color: var(--color-background-quaternary);
--border-radius: ${$br-8};
border: $b-1 solid var(--border-color);
border-radius: var(--border-radius);
}
.text-content {
--detail-color: var(--color-foreground-secondary);
color: var(--detail-color);
}

View File

@@ -16,7 +16,6 @@
(def ^:private schema:property-detail-copiable
[:map
[:detail :string]
[:color {:optional true} :any] ;; color object with :color, :gradient or :image
[:token {:optional true} :any] ;; resolved token object
[:copied :boolean]
@@ -24,7 +23,7 @@
(mf/defc property-detail-copiable*
{::mf/schema schema:property-detail-copiable}
[{:keys [detail color token copied on-click]}]
[{:keys [color token copied on-click children]}]
[:button {:class (stl/css-case :property-detail-copiable true
:property-detail-copied copied
:property-detail-copiable-color (some? color))
@@ -45,7 +44,7 @@
color-library-name (get-in (or colors-library file-colors) [(:ref-id color) :name])
color (assoc color :name color-library-name)]
[:span {:class (stl/css :property-detail-text)} (:name color)])
[:span {:class (stl/css :property-detail-text)} detail]))
[:span {:class (stl/css :property-detail-text)} children]))
[:> icon* {:class (stl/css :property-detail-icon)
:icon-id (if copied i/tick i/clipboard)
:size "s"

View File

@@ -12,23 +12,6 @@
--detail-color: var(--color-foreground-primary);
--button-min-inline-size: #{$sz-154};
--button-min-block-size: #{$sz-36};
}
.property-detail-text {
color: var(--detail-color);
}
.property-detail-text-token {
@include use-typography("code-font");
--detail-color: var(--color-token-foreground);
line-height: 1.4;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.property-detail-copiable {
--button-border-radius: #{$br-4};
--button-background: none;
@@ -69,3 +52,17 @@
.property-detail-icon {
display: none;
}
.property-detail-text {
color: var(--detail-color);
}
.property-detail-text-token {
@include use-typography("code-font");
--detail-color: var(--color-token-foreground);
line-height: 1.4;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}

View File

@@ -101,18 +101,16 @@
[:div {:class (stl/css :tooltip-token-title)}
(tr "inspect.tabs.styles.token.resolved-value")]
[:div {:class (stl/css :tooltip-token-value)}
(:value token)]])}
[:> property-detail-copiable* {:detail formatted-color-value
:color color
(:resolved-value token)]])}
[:> property-detail-copiable* {:color color
:token token
:copied copied
:on-click copy-attr}]]
:on-click copy-attr} formatted-color-value]]
[:> property-detail-copiable* {:detail formatted-color-value
:color color
[:> property-detail-copiable* {:color color
:copied copied
:on-click copy-attr}])]]
:on-click copy-attr} formatted-color-value])]]
(when (:image color)
[:div {:class (stl/css :color-image-preview)}
[:div {:class (stl/css :color-image-preview-wrapper)}

View File

@@ -7,6 +7,7 @@
(ns app.main.ui.inspect.styles.rows.properties-row
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.main.ui.ds.tooltip :refer [tooltip*]]
[app.main.ui.inspect.styles.property-detail-copiable :refer [property-detail-copiable*]]
[app.util.i18n :refer [tr]]
@@ -26,7 +27,7 @@
(mf/defc properties-row*
{::mf/schema schema:properties-row}
[{:keys [class term detail token property copiable]}]
(let [copiable? (or copiable false)
(let [copiable? (d/nilv copiable false)
detail? (not (or (nil? detail) (str/blank? detail)))
detail (if detail? detail "-")
copied* (mf/use-state false)
@@ -51,12 +52,10 @@
:content #(mf/html
[:div {:class (stl/css :tooltip-token)}
[:div {:class (stl/css :tooltip-token-title)} (tr "inspect.tabs.styles.token.resolved-value")]
[:div {:class (stl/css :tooltip-token-value)} (:value token)]])}
[:> property-detail-copiable* {:detail detail
:token token
[:div {:class (stl/css :tooltip-token-value)} (if (= :typography (:type token)) (:name token) (:resolved-value token))]])}
[:> property-detail-copiable* {:token token
:copied copied
:on-click copy-attr}]]
[:> property-detail-copiable* {:detail detail
:copied copied
:on-click copy-attr}])
:on-click copy-attr} detail]]
[:> property-detail-copiable* {:copied copied
:on-click copy-attr} detail])
detail)]]))

View File

@@ -143,6 +143,7 @@
edit-grid?
[:& layout-container/grid-layout-edition
{:ids [edition]
:shapes shapes
:values (get objects edition)}]
(some? sp-panel)

View File

@@ -13,44 +13,93 @@
[app.main.data.workspace.tokens.application :as dwta]
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar*]]
[app.main.ui.hooks :as h]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row*]]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
(defn- prepare-colors
[shapes file-id libraries]
(let [data (into [] (remove nil? (dwc/extract-all-colors shapes file-id libraries)))
groups (d/group-by :attrs #(dissoc % :attrs) data)
all-colors (distinct (mapv :attrs data))
"Prepares and groups extracted color information from shapes.
Input:
- shapes: vector of shape maps
- file-id: current file UUID
- libraries: shared color libraries
tmp (group-by #(some? (:id %)) all-colors)
library-colors (get tmp true)
colors (get tmp false)]
Output:
{:groups explained below
:all-colors vector of all color maps (unique attrs)
:colors vector of normal colors (without ref-id or token)
:library-colors vector of colors linked to libraries (with ref-id)
:token-colors vector of colors linked to applied tokens
:tokens placeholder for future token data}
:groups structure
A map where:
- Each **key** is a color descriptor map representing a unique color instance.
Depending on the color type, it can contain:
• :color → hex string (e.g. \"#9f2929\")
• :opacity → numeric value between 0-1
• :ref-id and :ref-file → if the color comes from a library
• :token-name \"some-token\" → if the color
originates from an applied token
- Each **value** is a vector of one or more maps describing *where* that
color is used. Each entry corresponds to a specific shape and color
property in the document:
• :prop → the property type (:fill, :stroke, :shadow, etc.)
• :shape-id → the UUID of the shape using this color
• :index → index of the color in the shape's fill/stroke list
Example of groups:
{
{:color \"#9f2929\", :opacity 0.3, :token-name \"asd2\" :has-token-applied true}
[{:prop :fill, :shape-id #uuid \"d0231035-25c9-80d5-8006-eae4c3dff32e\", :index 0}]
{:color \"#1b54b6\", :opacity 1}
[{:prop :fill, :shape-id #uuid \"aab34f9a-98c1-801a-8006-eae5e8236f1b\", :index 0}]
}
This structure allows fast lookups of all shapes using the same visual color,
regardless of whether it comes from local fills, strokes or shadow-colors."
[shapes file-id libraries]
(let [data (into [] (remove nil?) (dwc/extract-all-colors shapes file-id libraries))
groups (d/group-by :attrs #(dissoc % :attrs) data)
;; Unique color attribute maps
all-colors (distinct (mapv :attrs data))
;; Split into: library colors, token colors, and plain colors
library-colors (filterv :ref-id all-colors)
token-colors (filterv :token-name all-colors)
colors (filterv #(and (nil? (:ref-id %))
(not (:token-name %)))
all-colors)]
{:groups groups
:all-colors all-colors
:colors colors
:token-colors token-colors
:library-colors library-colors}))
(def xf:map-shape-id
(map :shape-id))
(defn- generate-color-operations
(defn- retrieve-color-operations
[groups old-color prev-colors]
(let [old-color (-> old-color
(dissoc :name :path)
(d/without-nils))
prev-color (d/seek (partial get groups) prev-colors)
(let [old-color (-> old-color
(dissoc :name :path)
(d/without-nils))
prev-color (d/seek (partial get groups) prev-colors)
color-operations-old (get groups old-color)
color-operations-prev (get groups prev-colors)
color-operations (or color-operations-prev color-operations-old)
old-color (or prev-color old-color)]
old-color (or prev-color old-color)]
[color-operations old-color]))
(mf/defc color-selection-menu*
{::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]}
[{:keys [shapes file-id libraries]}]
(let [{:keys [groups library-colors colors]}
(let [{:keys [groups library-colors colors token-colors]}
(mf/with-memo [file-id shapes libraries]
(prepare-colors shapes file-id libraries))
@@ -63,21 +112,19 @@
expand-lib-color (mf/use-state false)
expand-color (mf/use-state false)
expand-token-color (mf/use-state false)
groups-ref (h/use-ref-value groups)
;; TODO: Review if this is still necessary.
prev-colors-ref (mf/use-ref nil)
on-change
(mf/use-fn
(fn [new-color old-color from-picker?]
(let [;; When dragging on the color picker sometimes all
;; the shapes hasn't updated the color to the prev
;; value so we need this extra calculation
groups (mf/ref-val groups-ref)
prev-colors (mf/ref-val prev-colors-ref)
[color-operations old-color] (generate-color-operations groups old-color prev-colors)]
(mf/deps groups)
(fn [old-color new-color from-picker?]
(let [prev-colors (mf/ref-val prev-colors-ref)
[color-operations old-color] (retrieve-color-operations groups old-color prev-colors)]
;; TODO: Review if this is still necessary.
(when from-picker?
(let [color (-> new-color
(dissoc :name :path)
@@ -85,7 +132,7 @@
(mf/set-ref-val! prev-colors-ref
(conj prev-colors color))))
(st/emit! (dwc/change-color-in-selected color-operations new-color old-color)))))
(st/emit! (dwc/change-color-in-selected color-operations new-color (dissoc old-color :token-name :has-token-applied))))))
on-open
(mf/use-fn #(mf/set-ref-val! prev-colors-ref []))
@@ -95,31 +142,52 @@
on-detach
(mf/use-fn
(mf/deps groups)
(fn [color]
(let [groups (mf/ref-val groups-ref)
color-operations (get groups color)
color' (dissoc color :id :file-id)]
(let [color-operations (get groups color)
color' (dissoc color :ref-id :ref-file)]
(st/emit! (dwc/change-color-in-selected color-operations color' color)))))
on-detach-token
(mf/use-fn
(mf/deps token-colors groups)
(fn [token]
(let [prev-colors (mf/ref-val prev-colors-ref)
token-color (some #(when (= (:token-name %) (:name token)) %) token-colors)
[color-operations _] (retrieve-color-operations groups token-color prev-colors)]
(doseq [op color-operations]
(let [attr (if (= (:prop op) :stroke)
#{:stroke-color}
#{:fill})
color (-> token-color
(dissoc :token-name :has-token-applied)
(d/without-nils))]
(mf/set-ref-val! prev-colors-ref
(conj prev-colors color))
(st/emit! (dwta/unapply-token {:attributes attr
:token token
:shape-ids [(:shape-id op)]})))))))
select-only
(mf/use-fn
(mf/deps groups)
(fn [color]
(let [groups (mf/ref-val groups-ref)
color-operations (get groups color)
(let [color-operations (get groups color)
ids (into (d/ordered-set) xf:map-shape-id color-operations)]
(st/emit! (dws/select-shapes ids)))))
on-token-change
(mf/use-fn
(mf/deps groups)
(fn [_ token old-color]
(let [groups (mf/ref-val groups-ref)
prev-colors (mf/ref-val prev-colors-ref)
(let [prev-colors (mf/ref-val prev-colors-ref)
resolved-value (:resolved-value token)
new-color (dwta/value->color resolved-value)
color (-> new-color
(dissoc :name :path)
(d/without-nils))
[color-operations _] (generate-color-operations groups old-color prev-colors)]
[color-operations _] (retrieve-color-operations groups old-color prev-colors)]
(mf/set-ref-val! prev-colors-ref
(conj prev-colors color))
(st/emit! (dwta/apply-token-on-selected color-operations token)))))]
@@ -135,22 +203,15 @@
(when open?
[:div {:class (stl/css :element-content)}
[:div {:class (stl/css :selected-color-group)}
;; The hidden color is to solve a problem with the color picker. When a color is changed
;; and is no longer a library color it disapears from the list of library colors. Because
;; we need to keep the color picker open we need to maintain that color. The easier way
;; is to render the color elements so even if the library color is no longer we have still
;; the component to change it from the color picker.
(let [lib-colors (cond->> library-colors (not @expand-lib-color) (take 3))
lib-colors (concat lib-colors colors)]
(for [[index color] (d/enumerate lib-colors)]
(let [library-colors-extract (cond->> library-colors (not @expand-lib-color) (take 3))]
(for [[index color] (d/enumerate library-colors-extract)]
[:> color-row*
{:key index
:color color
:index index
:hidden (not (:id color))
:on-detach on-detach
:on-detach #(on-detach color %)
:select-only select-only
:on-change #(on-change %1 color %2)
:on-change #(on-change color %1 %2)
:on-token-change #(on-token-change %1 %2 color)
:on-open on-open
:origin :color-selection
@@ -167,7 +228,7 @@
:color color
:index index
:select-only select-only
:on-change #(on-change %1 color %2)
:on-change #(on-change color %1 %2)
:origin :color-selection
:on-token-change #(on-token-change %1 %2 color)
:on-open on-open
@@ -176,4 +237,28 @@
(when (and (false? @expand-color) (< 3 (count colors)))
[:button {:class (stl/css :more-colors-btn)
:on-click #(reset! expand-color true)}
(tr "workspace.options.more-colors")])]])]))
(tr "workspace.options.more-colors")])]
[:div {:class (stl/css :selected-color-group)}
(let [token-color-extract (cond->> token-colors (not @expand-token-color) (take 3))]
(for [[index token-color] (d/enumerate token-color-extract)]
(let [color {:color (:color token-color)
:opacity (:opacity token-color)}]
[:> color-row*
{:key index
:color color
:index index
:select-only select-only
:on-change #(on-change token-color %1 %2)
:origin :color-selection
:applied-token (:token-name token-color)
:on-detach-token on-detach-token
:on-token-change #(on-token-change %1 %2 token-color)
:on-open on-open
:on-close on-close}])))
(when (and (false? @expand-token-color)
(< 3 (count token-colors)))
[:button {:class (stl/css :more-colors-btn)
:on-click #(reset! expand-token-color true)}
(tr "workspace.options.more-token-colors")])]])]))

View File

@@ -256,7 +256,9 @@
:on-remove on-remove
:disable-drag disable-drag?
:on-focus on-focus
:applied-token fill-token-applied
:applied-token (if (= index 0)
fill-token-applied
nil)
:on-token-change on-token-change
:origin :fill
:select-on-focus (not disable-drag?)

View File

@@ -11,19 +11,24 @@
[app.common.data.macros :as dm]
[app.common.math :as mth]
[app.common.types.shape.layout :as ctl]
[app.common.types.token :as tk]
[app.config :as cf]
[app.main.data.event :as-alias ev]
[app.main.data.workspace :as udw]
[app.main.data.workspace.grid-layout.editor :as dwge]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.tokens.application :as dwta]
[app.main.features :as features]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.numeric-input :as deprecated-input]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar*]]
[app.main.ui.context :as muc]
[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 :as i]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as h]
@@ -42,6 +47,44 @@
:column deprecated-icon/column
:column-reverse deprecated-icon/column-reverse))
(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)
input-type (cond
(some #{:p2 :p4} [name])
:horizontal-padding
(some #{:p1 :p3} [name])
:vertical-padding
:else
name)
tokens (mf/with-memo [tokens input-type]
(delay
(-> (deref tokens)
(select-keys (get tk/tokens-by-input input-type))
(not-empty))))
on-detach-attr
(mf/use-fn
(mf/deps on-detach name)
#(on-detach % name))
props (mf/spread-props props
{:placeholder (if (or (= :multiple (:applied-tokens values))
(= :multiple (get values name))
(nil? (get values name)))
(tr "settings.multiple")
"--")
:class (stl/css :numeric-input-measures)
:applied-token (get applied-tokens name)
:tokens tokens
:align align
:on-detach on-detach-attr
:value (get values name)})]
[:> numeric-input* props]))
;; FLEX COMPONENTS
(def layout-container-flex-attrs
@@ -296,10 +339,12 @@
[_event]
(select-padding false false false false))
(mf/defc simple-padding-selection
{::mf/props :obj}
[{:keys [value on-change]}]
(let [p1 (:p1 value)
(mf/defc simple-padding-selection*
[{:keys [value on-change shapes applied-tokens ids]}]
(let [token-numeric-inputs
(features/use-feature "tokens/numeric-input")
p1 (:p1 value)
p2 (:p2 value)
p3 (:p3 value)
p4 (:p4 value)
@@ -314,150 +359,296 @@
p2
nil)
applied-to-p1 (:p1 applied-tokens)
applied-to-p2 (:p2 applied-tokens)
applied-to-p3 (:p3 applied-tokens)
applied-to-p4 (:p4 applied-tokens)
applied-to-p1 (if (= applied-to-p1 applied-to-p3)
applied-to-p1
nil)
applied-to-p2 (if (= applied-to-p2 applied-to-p4)
applied-to-p2
nil)
on-change'
(mf/use-fn
(mf/deps on-change)
(fn [value event]
(let [attr (-> (dom/get-current-target event)
(dom/get-data "attr")
(keyword))]
(on-change :simple attr value event))))
(mf/deps on-change shapes)
(fn [value attr event]
(if (or (string? value) (int? value))
(on-change :simple attr value event)
(do
(let [resolved-value (:resolved-value (first value))]
(st/emit! (dwta/toggle-token {:token (first value)
:attrs #{attr}
:shapes shapes}))
(on-change :simple attr resolved-value event))))))
on-detach-token
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
on-focus
(mf/use-fn
(fn [event]
(let [attr (-> (dom/get-current-target event)
(dom/get-data "attr")
(keyword))]
(mf/deps select-padding)
(fn [attr event]
(case attr
:p1 (select-padding true false true false)
:p2 (select-padding false true false true))
(case attr
:p1 (select-padding true false true false)
:p2 (select-padding false true false true))
(dom/select-target event)))
(dom/select-target event))))]
on-focus-p1
(mf/use-fn (mf/deps on-focus) #(on-focus :p1))
on-focus-p2
(mf/use-fn (mf/deps on-focus) #(on-focus :p2))
on-p1-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p1))
on-p2-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p2))]
[:div {:class (stl/css :paddings-simple)}
[:div {:class (stl/css :padding-simple)
:title (tr "workspace.layout_grid.editor.padding.vertical")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-top-bottom]
[:> numeric-input*
{:class (stl/css :numeric-input)
:placeholder (tr "settings.multiple")
:aria-label (tr "workspace.layout_grid.editor.padding.vertical")
:data-attr "p1"
:on-change on-change'
:on-focus on-focus
:nillable true
:min 0
:value p1}]]
[:div {:class (stl/css :padding-simple)
:title (tr "workspace.layout_grid.editor.padding.horizontal")}
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-p1-change
:on-detach on-detach-token
:on-blur on-padding-blur
:on-focus on-focus-p1
:icon i/padding-top-bottom
:min 0
:name :p1
:property (tr "workspace.layout_grid.editor.padding.vertical")
:nillable true
:applied-tokens {:p1 applied-to-p1}
:values {:p1 p1}}]
[:span {:class (stl/css :icon)}
deprecated-icon/padding-left-right]
[:> numeric-input*
{:className (stl/css :numeric-input)
:placeholder (tr "settings.multiple")
:aria-label (tr "workspace.layout_grid.editor.padding.horizontal")
:data-attr "p2"
:on-change on-change'
:on-focus on-focus
:on-blur on-padding-blur
:min 0
:nillable true
:value p2}]]]))
[:div {:class (stl/css :padding-simple)
:title (tr "workspace.layout_grid.editor.padding.vertical")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-top-bottom]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input)
:placeholder (tr "settings.multiple")
:aria-label (tr "workspace.layout_grid.editor.padding.vertical")
:on-change on-p1-change
:on-focus on-focus-p1
:on-blur on-padding-blur
:nillable true
:min 0
:value p1}]])
(mf/defc multiple-padding-selection
{::mf/props :obj}
[{:keys [value on-change]}]
(let [p1 (:p1 value)
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-p2-change
:on-detach on-detach-token
:on-blur on-padding-blur
:on-focus on-focus-p2
:icon i/padding-left-right
:min 0
:name :p2
:property (tr "workspace.layout_grid.editor.padding.horizontal")
:nillable true
:applied-tokens {:p2 applied-to-p2}
:values {:p2 p2}}]
[:div {:class (stl/css :padding-simple)
:title (tr "workspace.layout_grid.editor.padding.horizontal")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-left-right]
[:> deprecated-input/numeric-input*
{:className (stl/css :numeric-input)
:placeholder (tr "settings.multiple")
:aria-label (tr "workspace.layout_grid.editor.padding.horizontal")
:on-change on-p2-change
:on-focus on-focus-p2
:on-blur on-padding-blur
:min 0
:nillable true
:value p2}]])]))
(mf/defc multiple-padding-selection*
[{:keys [value on-change shapes applied-tokens ids]}]
(let [token-numeric-inputs
(features/use-feature "tokens/numeric-input")
p1 (:p1 value)
p2 (:p2 value)
p3 (:p3 value)
p4 (:p4 value)
on-change'
(mf/use-fn
(mf/deps on-change)
(fn [value event]
(let [attr (-> (dom/get-current-target event)
(dom/get-data "attr")
(keyword))]
(on-change :multiple attr value event))))
(mf/deps on-change shapes)
(fn [value attr event]
(if (or (string? value) (int? value))
(on-change :multiple attr value event)
(do
(let [resolved-value (:resolved-value (first value))]
(st/emit! (dwta/toggle-token {:token (first value)
:attrs #{attr}
:shapes shapes}))
(on-change :multiple attr resolved-value event))))))
on-focus
(mf/use-fn
(fn [event]
(let [attr (-> (dom/get-current-target event)
(dom/get-data "attr")
(keyword))]
(mf/deps select-padding)
(fn [attr event]
(select-padding attr)
(dom/select-target event)))
(select-padding attr)
(dom/select-target event))))]
on-detach-token
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
on-p1-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p1))
on-p2-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p2))
on-p3-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p3))
on-p4-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p4))
on-focus-p1
(mf/use-fn (mf/deps on-focus) #(on-focus :p1))
on-focus-p2
(mf/use-fn (mf/deps on-focus) #(on-focus :p2))
on-focus-p3
(mf/use-fn (mf/deps on-focus) #(on-focus :p3))
on-focus-p4
(mf/use-fn (mf/deps on-focus) #(on-focus :p4))]
[:div {:class (stl/css :paddings-multiple)}
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.top")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-top]
[:> numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.top")
:data-attr "p1"
:on-change on-change'
:on-focus on-focus
:on-blur on-padding-blur
:min 0
:value p1}]]
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-p1-change
:on-detach on-detach-token
:on-blur on-padding-blur
:on-focus on-focus-p1
:icon i/padding-top
:min 0
:name :p1
:property (tr "workspace.layout_grid.editor.padding.top")
:applied-tokens applied-tokens
:values value}]
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.right")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-right]
[:> numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.right")
:data-attr "p2"
:on-change on-change'
:on-focus on-focus
:on-blur on-padding-blur
:min 0
:value p2}]]
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.top")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-top]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.top")
:data-attr "p1"
:on-change on-p1-change
:on-focus on-focus-p1
:on-blur on-padding-blur
:min 0
:value p1}]])
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.bottom")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-bottom]
[:> numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.bottom")
:data-attr "p3"
:on-change on-change'
:on-focus on-focus
:on-blur on-padding-blur
:min 0
:value p3}]]
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-p2-change
:on-detach on-detach-token
:on-blur on-padding-blur
:on-focus on-focus-p2
:icon i/padding-right
:min 0
:name :p2
:property (tr "workspace.layout_grid.editor.padding.right")
:applied-tokens applied-tokens
:values value}]
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.left")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-left]
[:> numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.left")
:data-attr "p4"
:on-change on-change'
:on-focus on-focus
:on-blur on-padding-blur
:min 0
:value p4}]]]))
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.right")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-right]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.right")
:data-attr "p2"
:on-change on-p2-change
:on-focus on-focus-p2
:on-blur on-padding-blur
:min 0
:value p2}]])
(mf/defc padding-section
{::mf/props :obj}
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-p3-change
:on-detach on-detach-token
:on-blur on-padding-blur
:on-focus on-focus-p3
:icon i/padding-bottom
:min 0
:name :p3
:property (tr "workspace.layout_grid.editor.padding.bottom")
:applied-tokens applied-tokens
:values value}]
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.bottom")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-bottom]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.bottom")
:data-attr "p3"
:on-change on-p3-change
:on-focus on-focus-p3
:on-blur on-padding-blur
:min 0
:value p3}]])
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-p4-change
:on-detach on-detach-token
:on-blur on-padding-blur
:on-focus on-focus-p4
:icon i/padding-left
:min 0
:name :p4
:property (tr "workspace.layout_grid.editor.padding.left")
:applied-tokens applied-tokens
:values value}]
[:div {:class (stl/css :padding-multiple)
:title (tr "workspace.layout_grid.editor.padding.left")}
[:span {:class (stl/css :icon)}
deprecated-icon/padding-left]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input)
:placeholder "--"
:aria-label (tr "workspace.layout_grid.editor.padding.left")
:data-attr "p4"
:on-change on-p4-change
:on-focus on-focus-p4
:on-blur on-padding-blur
:min 0
:value p4}]])]))
(mf/defc padding-section*
[{:keys [type on-type-change on-change] :as props}]
(let [on-type-change'
(mf/use-fn
@@ -479,10 +670,10 @@
[:div {:class (stl/css :padding-inputs)}
(cond
(= type :simple)
[:> simple-padding-selection props]
[:> simple-padding-selection* props]
(= type :multiple)
[:> multiple-padding-selection props])]
[:> multiple-padding-selection* props])]
[:button {:class (stl/css-case
:padding-toggle true
@@ -502,23 +693,20 @@
(st/emit! (udw/set-gap-selected value)))
(defn- on-gap-focus
[event]
(let [type (-> (dom/get-current-target event)
(dom/get-data "type")
(keyword))]
(select-gap! type)
(dom/select-target event)))
[type]
(select-gap! type))
(defn- on-gap-blur
[_event]
(select-gap! nil))
(mf/defc gap-section
{::mf/props :obj}
[{:keys [is-column wrap-type on-change value]
:or {wrap-type :none}
(mf/defc gap-section*
[{:keys [is-column wrap-type on-change value applied-tokens shapes ids]
:as props}]
(let [nowrap? (= :nowrap wrap-type)
(let [token-numeric-inputs
(features/use-feature "tokens/numeric-input")
nowrap? (= :nowrap wrap-type)
row-gap-disabled?
(and ^boolean nowrap?
@@ -530,12 +718,38 @@
on-change'
(mf/use-fn
(mf/deps on-change)
(fn [value event]
(let [target (dom/get-current-target event)
wrap-type (dom/get-data target "wrap-type")
type (keyword (dom/get-data target "type"))]
(on-change (= "nowrap" wrap-type) type value event))))]
(mf/deps on-change wrap-type)
(fn [value attr event]
(if (or (string? value) (int? value))
(on-change (= "nowrap" wrap-type) attr value event)
(do
(let [resolved-value (:resolved-value (first value))]
(st/emit! (dwta/toggle-token {:token (first value)
:attrs #{attr}
:shapes shapes}))
(on-change (= "nowrap" wrap-type) attr resolved-value event))))))
on-detach-token
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(prn ids)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
on-row-gap-change
(mf/use-fn (mf/deps on-change') #(on-change' % :row-gap))
on-column-gap-change
(mf/use-fn (mf/deps on-change') #(on-change' % :column-gap))
on-focus-row-gap
(mf/use-fn (mf/deps on-gap-focus) #(on-gap-focus :row-gap))
on-focus-column-gap
(mf/use-fn (mf/deps on-gap-focus) #(on-gap-focus :column-gap))]
(mf/with-effect []
;; on destroy component
@@ -544,43 +758,73 @@
[:div {:class (stl/css :gap-group)}
[:div {:class (stl/css-case
:row-gap true
:disabled row-gap-disabled?)
:title "Row gap"}
[:span {:class (stl/css :icon)} deprecated-icon/gap-vertical]
[:> numeric-input*
{:class (stl/css :numeric-input true)
:no-validate true
:placeholder "--"
:data-type "row-gap"
:data-wrap-type (d/name wrap-type)
:on-focus on-gap-focus
:on-change on-change'
:on-blur on-gap-blur
:nillable true
:min 0
:value (:row-gap value)
:disabled row-gap-disabled?}]]
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-row-gap-change
:on-detach on-detach-token
:on-focus on-focus-row-gap
:on-blur on-gap-blur
:icon i/gap-vertical
:nillable true
:min 0
:name :row-gap
:applied-tokens applied-tokens
:property "Row gap"
:values {:row-gap (:row-gap value)}
:disabled row-gap-disabled?}]
[:div {:class (stl/css-case
:column-gap true
:disabled col-gap-disabled?)
:title "Column gap"}
[:span {:class (stl/css :icon)} deprecated-icon/gap-horizontal]
[:> numeric-input*
{:class (stl/css :numeric-input true)
:no-validate true
:placeholder "--"
:data-type "column-gap"
:data-wrap-type (d/name wrap-type)
:on-focus on-gap-focus
:on-change on-change'
:on-blur on-gap-blur
:nillable true
:min 0
:value (:column-gap value)
:disabled col-gap-disabled?}]]]))
[:div {:class (stl/css-case
:row-gap true
:disabled row-gap-disabled?)
:title "Row gap"}
[:span {:class (stl/css :icon)} deprecated-icon/gap-vertical]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input true)
:no-validate true
:placeholder "--"
:data-type "row-gap"
:data-wrap-type (d/name wrap-type)
:on-focus on-focus-row-gap
:on-change on-change'
:on-blur on-gap-blur
:nillable true
:min 0
:value (:row-gap value)
:disabled row-gap-disabled?}]])
(if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-column-gap-change
:on-detach on-detach-token
:on-focus on-focus-column-gap
:on-blur on-gap-blur
:icon i/gap-horizontal
:nillable true
:min 0
:name :column-gap
:applied-tokens applied-tokens
:property "Column gap"
:values {:column-gap (:column-gap value)}
:disabled col-gap-disabled?}]
[:div {:class (stl/css-case
:column-gap true
:disabled col-gap-disabled?)
:title "Column gap"}
[:span {:class (stl/css :icon)} deprecated-icon/gap-horizontal]
[:> deprecated-input/numeric-input*
{:class (stl/css :numeric-input true)
:no-validate true
:placeholder "--"
:data-type "column-gap"
:data-wrap-type (d/name wrap-type)
:on-focus on-focus-column-gap
:on-change on-change'
:on-blur on-gap-blur
:nillable true
:min 0
:value (:column-gap value)
:disabled col-gap-disabled?}]])]))
;; GRID COMPONENTS
@@ -760,12 +1004,12 @@
(if is-column deprecated-icon/flex-vertical deprecated-icon/flex-horizontal)]
[:div {:class (stl/css :track-info-value)}
[:> numeric-input* {:no-validate true
:value (:value column)
:on-change #(set-column-value type index %)
:placeholder "--"
:min 0
:disabled (= :auto (:type column))}]]
[:> deprecated-input/numeric-input* {:no-validate true
:value (:value column)
:on-change #(set-column-value type index %)
:placeholder "--"
:min 0
:disabled (= :auto (:type column))}]]
[:div {:class (stl/css :track-info-unit)}
[:& select {:class (stl/css :track-info-unit-selector)
@@ -838,9 +1082,8 @@
(st/emit! (dom/open-new-window cf/grid-help-uri)))
(mf/defc layout-container-menu
{::mf/memo #{:ids :values :multiple}
::mf/props :obj}
[{:keys [ids values multiple]}]
{::mf/memo #{:ids :values :multiple :shapes :applied-tokens}}
[{:keys [ids values multiple shapes applied-tokens]}]
(let [;; Display
layout-type (:layout values)
has-layout? (some? layout-type)
@@ -920,14 +1163,16 @@
;; Gap
on-gap-change
(fn [multiple? type val]
(let [val (mth/finite val 0)]
(cond
^boolean multiple?
(st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}}))
(mf/use-fn
(mf/deps ids)
(fn [multiple? type val]
(let [val (mth/finite val 0)]
(cond
^boolean multiple?
(st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}}))
(some? type)
(st/emit! (dwsl/update-layout ids {:layout-gap {type val}})))))
(some? type)
(st/emit! (dwsl/update-layout ids {:layout-gap {type val}}))))))
;; Padding
on-padding-type-change
@@ -1091,15 +1336,20 @@
:value align-content
:on-change on-align-content-change}]])
[:div {:class (stl/css :forth-row)}
[:& gap-section {:is-column is-column
:wrap-type wrap-type
:on-change on-gap-change
:value (:layout-gap values)}]
[:& padding-section {:value (:layout-padding values)
:type (:layout-padding-type values)
:on-type-change on-padding-type-change
:on-change on-padding-change}]]]
[:> gap-section* {:is-column is-column
:wrap-type wrap-type
:on-change on-gap-change
:shapes shapes
:ids ids
:applied-tokens applied-tokens
:value (:layout-gap values)}]
[:> padding-section* {:value (:layout-padding values)
:type (:layout-padding-type values)
:on-type-change on-padding-type-change
:shapes shapes
:ids ids
:applied-tokens applied-tokens
:on-change on-padding-change}]]]
:grid
[:div {:class (stl/css :grid-layout-menu)}
@@ -1133,20 +1383,24 @@
:on-change on-row-justify-change}]]
[:div {:class (stl/css :gap-row)}
[:& gap-section {:on-change on-gap-change
:value (:layout-gap values)}]]
[:> gap-section* {:on-change on-gap-change
:shapes shapes
:ids ids
:applied-tokens applied-tokens
:value (:layout-gap values)}]]
[:div {:class (stl/css :padding-row)}
[:& padding-section {:value (:layout-padding values)
:type (:layout-padding-type values)
:on-type-change on-padding-type-change
:on-change on-padding-change}]]]
[:> padding-section* {:value (:layout-padding values)
:type (:layout-padding-type values)
:shapes shapes
:applied-tokens applied-tokens
:on-type-change on-padding-type-change
:on-change on-padding-change}]]]
nil))]))
(mf/defc grid-layout-edition
{::mf/memo #{:ids :values}
::mf/props :obj}
[{:keys [ids values]}]
{::mf/memo #{:ids :values :shapes :applied-tokens}}
[{:keys [ids values shapes applied-tokens]}]
(let [;; Gap
saved-grid-dir (:layout-grid-dir values)
@@ -1329,14 +1583,17 @@
:icon i/locate}]]
[:div {:class (stl/css :gap-row)}
[:& gap-section {:on-change on-gap-change
:value (:layout-gap values)}]]
[:> gap-section* {:on-change on-gap-change
:shapes shapes
:ids ids
:applied-tokens applied-tokens
:value (:layout-gap values)}]]
[:div {:class (stl/css :padding-row :padding-section)}
[:& padding-section {:value (:layout-padding values)
:type (:layout-padding-type values)
:on-type-change on-padding-type-change
:on-change on-padding-change}]]
[:> padding-section* {:value (:layout-padding values)
:type (:layout-padding-type values)
:on-type-change on-padding-type-change
:on-change on-padding-change}]]
[:div {:class (stl/css :grid-tracks-row)}
[:& grid-columns-row {:is-column true

View File

@@ -4,160 +4,180 @@
//
// Copyright (c) KALEIDOS INC
// TODO: When button replace remove this @use
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/_utils.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/_borders.scss" as *;
@use "ds/typography.scss" as t;
@use "ds/spacing.scss" as *;
@use "ds/mixins.scss" as *;
.element-set {
margin: 0;
.element-title {
.title-spacing-layout {
padding-left: deprecated.$s-2;
margin: 0;
}
}
.title-actions {
position: relative;
display: flex;
gap: deprecated.$s-4;
height: deprecated.$s-32;
padding: 0;
margin: 0;
.layout-options {
width: fit-content;
}
.layout-option {
white-space: nowrap;
}
}
.title-spacing-layout {
padding-inline-start: var(--sp-xxs);
margin: 0;
}
.title-actions {
position: relative;
display: flex;
gap: var(--sp-xs);
block-size: $sz-32;
padding: 0;
margin: 0;
}
.layout-options {
inline-size: fit-content;
}
.layout-option {
white-space: nowrap;
}
.flex-layout-menu {
display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
margin-block-end: var(--sp-s);
}
.first-row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
margin-block-end: var(--sp-m);
margin-block-start: var(--sp-xs);
}
.align-row {
grid-column: span 3;
}
.direction-row-flex {
grid-column: span 4;
}
// TODO: Replace this buttons with DS buttons
.wrap-button {
@extend .button-tertiary;
border-radius: $br-8;
block-size: $sz-32;
inline-size: $sz-32;
svg {
@extend .button-icon;
stroke: var(--color-foreground-secondary);
}
.flex-layout-menu {
display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
margin-bottom: deprecated.$s-8;
.first-row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
margin-bottom: deprecated.$s-12;
margin-top: deprecated.$s-4;
.align-row {
grid-column: span 3;
}
.direction-row-flex {
grid-column: span 4;
}
.wrap-button {
@extend .button-tertiary;
border-radius: deprecated.$br-8;
height: deprecated.$s-32;
width: deprecated.$s-32;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
&.selected {
@extend .button-icon-selected;
}
}
}
.second-row,
.third-row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
margin-bottom: deprecated.$s-12;
.align-content-row,
.justify-content-row {
grid-column: span 6;
}
}
.forth-row {
display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
gap: var(--sp-xs);
grid-column: 1 / -1;
}
.help-button-wrapper {
grid-column: 1 / -1;
display: flex;
flex-direction: row;
justify-content: space-between;
}
&.selected {
@extend .button-icon-selected;
}
}
.second-row,
.third-row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
margin-block-end: var(--sp-m);
}
.align-content-row,
.justify-content-row {
grid-column: span 6;
}
.forth-row {
/*
This element do not match the 8 column grid of sidebar
|___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each
|__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button.
We need to calculate the total width of each input block:
- 3.5 columns of the the base grid (--sp-xxxl)
- plus 3 inter-column gaps (3 * --sp-xs)
- minus half a gap (--sp-xs / 2) because the last spacing is shared
with the next block, keeping the overall visual rhythm consistent.
*/
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
display: grid;
grid-template-columns:
var(--input-width) /* first input block */
var(--input-width) /* second input block */
var(--sp-xxxl); /* action button */
gap: var(--sp-xs);
grid-column: 1 / -1;
}
.help-button-wrapper {
grid-column: 1 / -1;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.gap-group {
grid-column: span 3;
display: grid;
grid-template-columns: subgrid;
.column-gap {
@extend .input-element;
@include deprecated.bodySmallTypography;
&.disabled {
@extend .disabled-input;
}
}
.row-gap {
@extend .input-element;
@include deprecated.bodySmallTypography;
&.disabled {
@extend .disabled-input;
}
}
// TODO: Remove when activating token numeric inputs
.column-gap,
.row-gap {
@extend .input-element;
@include t.use-typography("body-small");
&.disabled {
@extend .disabled-input;
}
}
// TODO: Remove when activating token numeric inputs
.padding-simple,
.padding-multiple {
@include t.use-typography("body-small");
@extend .input-element;
}
.padding-group {
display: grid;
grid-column: span 3;
grid-template-columns: subgrid;
}
.padding-inputs {
grid-column: span 2;
display: grid;
grid-template-columns: subgrid;
.padding-inputs,
.paddings-simple {
grid-column: span 2;
display: grid;
grid-template-columns: subgrid;
}
.paddings-multiple {
display: grid;
grid-column: span 2;
grid-template-columns: subgrid;
gap: var(--sp-xs);
}
// TODO: Replace this buttons with DS buttons
.padding-toggle {
@extend .button-tertiary;
block-size: $sz-32;
inline-size: $sz-32;
border-radius: $br-8;
svg {
@extend .button-icon;
stroke: var(--color-foreground-secondary);
}
.paddings-simple {
display: grid;
grid-column: span 2;
grid-template-columns: subgrid;
.padding-simple {
@extend .input-element;
@include deprecated.bodySmallTypography;
}
}
.paddings-multiple {
display: grid;
grid-column: span 2;
grid-template-columns: subgrid;
gap: var(--sp-xs);
.padding-multiple {
@extend .input-element;
@include deprecated.bodySmallTypography;
}
}
.padding-toggle {
@extend .button-tertiary;
height: deprecated.$s-32;
width: deprecated.$s-32;
border-radius: deprecated.$br-8;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
&.selected {
@extend .button-icon-selected;
}
&.selected {
@extend .button-icon-selected;
}
}
@@ -165,78 +185,80 @@
display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
}
.edit-grid-wrapper,
.first-row,
.grid-layout-align,
.gap-row,
.padding-row {
grid-column: 1 / -1;
}
.edit-grid-wrapper,
.first-row,
.grid-layout-align,
.gap-row,
.padding-row {
grid-column: 1 / -1;
}
.first-row {
margin-bottom: deprecated.$s-8;
display: grid;
grid-template-columns: subgrid;
}
.first-row {
margin-block-end: var(--sp-s);
display: grid;
grid-template-columns: subgrid;
}
.grid-layout-align {
display: grid;
grid-template-columns: subgrid;
align-items: flex-start;
position: relative;
gap: var(--sp-xs);
.grid-layout-align {
display: grid;
grid-template-columns: subgrid;
align-items: flex-start;
position: relative;
gap: var(--sp-xs);
}
.locate-button {
grid-row: 1;
grid-column: 8;
}
}
.locate-button {
grid-row: 1;
grid-column: 8;
}
.grid-layout-menu-title {
flex: 1;
font-size: deprecated.$fs-11;
color: var(--title-foreground-color-hover);
grid-column: span 5;
}
.grid-layout-menu-title {
@include t.use-typography("headline-small");
flex: 1;
color: var(--color-foreground-primary);
grid-column: span 5;
}
.edit-mode-btn {
@extend .button-secondary;
@include deprecated.uppercaseTitleTipography;
width: 100%;
padding: deprecated.$s-8;
grid-column: span 7;
}
// TODO: Replace this buttons with DS buttons
.edit-mode-btn {
@extend .button-secondary;
@include t.use-typography("headline-small");
inline-size: 100%;
padding: var(--sp-s);
grid-column: span 7;
}
.exit-btn {
@extend .button-secondary;
@include deprecated.uppercaseTitleTipography;
padding: deprecated.$s-8 deprecated.$s-20;
grid-column: span 2;
}
// TODO: Replace this buttons with DS buttons
.exit-btn {
@extend .button-secondary;
@include t.use-typography("headline-small");
padding: var(--sp-s) var(--sp-xl);
grid-column: span 2;
}
.grid-tracks-info-container {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
gap: var(--sp-xs);
margin-top: deprecated.$s-4;
}
.grid-tracks-info-container {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
gap: var(--sp-xs);
margin-block-start: var(--sp-xs);
}
.padding-section {
margin-top: deprecated.$s-8;
}
.padding-section {
margin-block-start: var(--sp-s);
}
.grid-tracks-row {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
}
.grid-tracks-row {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
}
.edit-grid-wrapper {
display: grid;
grid-template-columns: subgrid;
}
.edit-grid-wrapper {
display: grid;
grid-template-columns: subgrid;
}
.track-info {
@@ -245,127 +267,155 @@
grid-template-columns: subgrid;
&.dnd-over-top {
border-top: deprecated.$s-2 solid var(--button-foreground-hover);
border-block-start: $b-2 solid var(--color-accent-primary);
}
&.dnd-over-bot {
border-bottom: deprecated.$s-2 solid var(--button-foreground-hover);
border-block-end: $b-2 solid var(--color-accent-primary);
}
}
.track-info-container {
display: flex;
grid-column: 1 / span 7;
}
.track-info-container {
display: flex;
grid-column: 1 / span 7;
}
.track-info-dir-icon {
cursor: pointer;
border-radius: deprecated.$br-8 0 0 deprecated.$br-8;
background-color: var(--input-background-color);
padding: 0 deprecated.$s-8;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
height: 100%;
}
&:hover svg {
stroke: var(--icon-foreground-hover);
}
// TODO: Replace this buttons with DS buttons
.track-info-dir-icon {
cursor: pointer;
border-radius: $br-8 0 0 $br-8;
background-color: var(--color-background-tertiary);
padding: 0 var(--sp-s);
svg {
@extend .button-icon;
stroke: var(--color-foreground-secondary);
block-size: 100%;
}
&:hover svg {
stroke: var(--color-foreground-primary);
}
}
.track-info-value {
@extend .input-element;
@include deprecated.bodySmallTypography;
border-radius: 0;
border-right: deprecated.$s-1 solid var(--panel-background-color);
}
.track-info-value {
@extend .input-element;
@include t.use-typography("body-small");
border-radius: 0;
border-inline-end: $b-1 solid var(--color-background-primary);
}
.track-info-unit-selector {
border-radius: 0 deprecated.$br-8 deprecated.$br-8 0;
width: deprecated.$s-96;
}
.track-info-unit-selector {
border-radius: 0 $br-8 $br-8 0;
inline-size: px2rem(96);
}
.grid-tracks {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
margin-top: deprecated.$s-8;
margin-block-start: var(--sp-s);
}
.grid-track-header {
@include deprecated.flexRow;
font-size: deprecated.$fs-12;
border-radius: deprecated.$br-8;
overflow: hidden;
background: var(--button-secondary-background-color-rest);
height: deprecated.$s-52;
grid-column: 1 / -1;
.grid-track-header {
@include t.use-typography("body-small");
display: flex;
align-items: center;
gap: var(--sp-xs);
border-radius: $br-8;
overflow: hidden;
background: var(--color-background-tertiary);
block-size: px2rem(52);
grid-column: 1 / -1;
}
.track-title {
display: grid;
flex-grow: 1;
padding: var(--sp-s);
gap: 0;
overflow: hidden;
}
.track-name {
color: var(--color-foreground-primary);
}
.track-detail {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
inline-size: 100%;
color: var(--color-foreground-secondary);
}
// TODO: Replace this buttons with DS buttons
.expand-icon {
@extend .button-secondary;
block-size: px2rem(52);
border-radius: $br-8 0 0 $br-8;
border-inline-end: $b-1 solid var(--color-background-primary);
svg {
@extend .button-icon;
stroke: var(--color-foreground-secondary);
fill: var(--color-foreground-secondary);
}
.track-title {
display: grid;
flex-grow: 1;
padding: deprecated.$s-8;
gap: 0;
overflow: hidden;
}
.track-name {
color: var(--color-foreground-primary);
}
.track-detail {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 100%;
color: var(--color-foreground-secondary);
}
.expand-icon {
@extend .button-secondary;
height: deprecated.$s-52;
border-radius: deprecated.$s-8 0 0 deprecated.$s-8;
border-right: deprecated.$s-1 solid var(--panel-background-color);
&:hover,
&:active {
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
fill: var(--icon-foreground);
}
&:hover,
&:active {
svg {
stroke: var(--button-foreground-hover);
fill: var(--button-foreground-hover);
}
}
}
.add-column {
@extend .button-tertiary;
height: deprecated.$s-52;
svg {
@extend .button-icon;
height: deprecated.$s-12;
width: deprecated.$s-12;
stroke: var(--icon-foreground);
fill: var(--icon-foreground);
stroke: var(--color-accent-primary);
fill: var(--color-accent-primary);
}
}
}
// TODO: Replace this buttons with DS buttons
.add-column {
@extend .button-tertiary;
block-size: px2rem(52);
svg {
display: flex;
justify-content: center;
align-items: center;
color: transparent;
fill: none;
stroke-width: px2rem(1);
block-size: $sz-12;
inline-size: $sz-12;
stroke: var(--color-foreground-secondary);
fill: var(--color-foreground-secondary);
}
}
.layout-options {
@extend .dropdown-wrapper;
@include deprecated.flexColumn;
right: var(--sp-s);
left: initial;
box-shadow: 0px 0px $sz-12 0px var(--color-shadow-dark);
position: absolute;
display: flex;
flex-direction: column;
inset-block-start: $sz-32;
inset-inline-start: initial;
inset-inline-end: var(--sp-s);
inline-size: 100%;
max-block-size: var(--menu-max-height, px2rem(300));
padding: var(--sp-xxs);
margin: 0;
margin-block-start: px2rem(1);
border-radius: $br-8;
z-index: var(--z-index-dropdown);
overflow-y: auto;
overflow-x: hidden;
background-color: var(--color-background-tertiary);
color: var(--color-foreground-primary);
border: $b-2 solid var(--color-background-quaternary);
gap: var(--sp-xs);
button {
@include deprecated.buttonStyle;
padding: deprecated.$s-8;
border: none;
background: none;
cursor: pointer;
padding: var(--sp-s);
color: var(--color-foreground-primary);
border-radius: deprecated.$br-6;
border-radius: $br-6;
&:hover {
background: var(--color-background-quaternary);
@@ -387,9 +437,27 @@
.gap-row,
.padding-row {
/*
This element do not match the 8 column grid of sidebar
|___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each
|__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button.
We need to calculate the total width of each input block:
- 3.5 columns of the the base grid (--sp-xxxl)
- plus 3 inter-column gaps (3 * --sp-xs)
- minus half a gap (--sp-xs / 2) because the last spacing is shared
with the next block, keeping the overall visual rhythm consistent.
*/
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
grid-template-columns:
var(--input-width) /* first input block */
var(--input-width) /* second input block */
var(--sp-xxxl); /* action button */
gap: var(--sp-xs);
}

View File

@@ -62,10 +62,27 @@
}
.margin-row {
/*
This element do not match the 8 column grid of sidebar
|___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each
|__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button.
We need to calculate the total width of each input block:
- 3.5 columns of the the base grid (--sp-xxxl)
- plus 3 inter-column gaps (3 * --sp-xs)
- minus half a gap (--sp-xs / 2) because the last spacing is shared
with the next block, keeping the overall visual rhythm consistent.
*/
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
display: grid;
// NOTE: this does not follow the 8-column grid and the size is not normalized,
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
grid-template-columns:
var(--input-width) /* first input block */
var(--input-width) /* second input block */
var(--sp-xxxl); /* action button */
gap: var(--sp-xs);
}
@@ -133,9 +150,27 @@
}
.advanced-options {
/*
This element do not match the 8 column grid of sidebar
|___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each
|__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button.
We need to calculate the total width of each input block:
- 3.5 columns of the the base grid (--sp-xxxl)
- plus 3 inter-column gaps (3 * --sp-xs)
- minus half a gap (--sp-xs / 2) because the last spacing is shared
with the next block, keeping the overall visual rhythm consistent.
*/
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
grid-template-columns:
var(--input-width) /* first input block */
var(--input-width) /* second input block */
var(--sp-xxxl); /* action button */
gap: var(--sp-xs);
}

View File

@@ -301,7 +301,7 @@
on-size-change
(mf/use-fn
(mf/deps ids)
(mf/deps ids shapes)
(fn [value attr]
(if (or (string? value) (int? value))
(do
@@ -528,6 +528,7 @@
:value (:height values)}]]])
[:> icon-button* {:variant "ghost"
:tooltip-placement "top-left"
:icon (if proportion-lock "lock" "unlock")
:class (stl/css-case :selected (true? proportion-lock))
:disabled (= proportion-lock :multiple)

View File

@@ -7,12 +7,29 @@
@use "refactor/common-refactor.scss" as deprecated;
.element-set {
/*
This element do not match the 8 column grid of sidebar
|___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each
|__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button.
We need to calculate the total width of each input block:
- 3.5 columns of the the base grid (--sp-xxxl)
- plus 3 inter-column gaps (3 * --sp-xs)
- minus half a gap (--sp-xs / 2) because the last spacing is shared
with the next block, keeping the overall visual rhythm consistent.
*/
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
display: grid;
margin-bottom: var(--sp-s);
// NOTE: this does not follow the 8-column grid and the size is not normalized,
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
grid-template-columns:
var(--input-width) /* first input block */
var(--input-width) /* second input block */
var(--sp-xxxl); /* action button */
gap: var(--sp-xs);
margin-bottom: var(--sp-s);
}
.presets {

View File

@@ -515,7 +515,7 @@
deprecated-icon/menu]]
[:div {:class (stl/css :info-row)}
[:span {:class (stl/css :info-label)} (tr "labels.variant")]
[:span {:class (stl/css :info-label)} (tr "workspace.assets.typography.font-style")]
[:span {:class (stl/css :info-content)} (:font-variant-id typography)]]
[:div {:class (stl/css :info-row)}

View File

@@ -69,9 +69,9 @@
(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 its already realized (not a delay),
(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 its already realized (not a delay),
;; we just use it directly.
active-tokens (if (delay? active-tokens)
@active-tokens
@@ -143,10 +143,10 @@
[{: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-detach-token
disable-drag on-focus on-blur select-only select-on-focus on-token-change applied-token]}]
(let [token-color (contains? cfg/flags :token-color)
libraries (mf/deref refs/files)
on-change (h/use-ref-callback on-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))
@@ -169,11 +169,12 @@
active-tokens* (mf/use-ctx ctx/active-tokens-by-type)
tokens (mf/with-memo [active-tokens* origin]
(delay
(-> (deref active-tokens*)
(select-keys (get tk/tokens-by-input origin))
(not-empty))))
tokens (mf/with-memo [active-tokens* origin]
(let [origin (if (= :color-selection origin) :fill origin)]
(delay
(-> (deref active-tokens*)
(select-keys (get tk/tokens-by-input origin))
(not-empty)))))
on-focus'
(mf/use-fn
@@ -205,9 +206,12 @@
handle-select
(mf/use-fn
(mf/deps select-only color)
(mf/deps select-only color applied-token)
(fn []
(select-only color)))
(let [color (if applied-token
(assoc color :has-token-applied true :token-name applied-token)
color)]
(select-only color))))
on-color-change
(mf/use-fn
@@ -233,7 +237,7 @@
open-modal
(mf/use-fn
(mf/deps disable-gradient disable-opacity disable-image disable-picker on-change on-close on-open tokens)
(mf/deps disable-gradient disable-opacity disable-image disable-picker on-change on-close on-open tokens index)
(fn [color pos tab]
(let [color (cond
has-multiple-colors
@@ -427,4 +431,4 @@
[:> icon-button* {:variant "ghost"
:aria-label (tr "settings.select-this-color")
:on-click handle-select
:icon i/move}])]))
:icon i/move}])]))

View File

@@ -127,7 +127,6 @@
stroke-style (or (:stroke-style stroke) :solid)
stroke-style-options
(mf/with-memo [stroke-style]
(d/concat-vec

View File

@@ -47,9 +47,27 @@
}
}
.stroke-caps-options {
/*
This element do not match the 8 column grid of sidebar
|___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each
|__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button.
We need to calculate the total width of each input block:
- 3.5 columns of the the base grid (--sp-xxxl)
- plus 3 inter-column gaps (3 * --sp-xs)
- minus half a gap (--sp-xs / 2) because the last spacing is shared
with the next block, keeping the overall visual rhythm consistent.
*/
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--sp-xxxl) var(--input-width);
grid-template-columns:
var(--input-width) /* first input block */
var(--input-width) /* second input block */
var(--sp-xxxl); /* action button */
gap: var(--sp-xs);
}

View File

@@ -97,6 +97,8 @@
{:type type
:ids [(:id shape)]
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -96,6 +96,8 @@
{:type type
:ids [(:id shape)]
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -115,6 +115,8 @@
[:& layout-container-menu
{:type shape-type
:ids ids
:shapes shapes
:applied-tokens applied-tokens
:values layout-container-values
:multiple false}]

View File

@@ -122,6 +122,8 @@
{:type type
:ids [(:id shape)]
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -408,7 +408,7 @@
[exports-ids exports-values]
(get-attrs shapes objects :exports)
[layout-container-ids layout-container-values]
[layout-container-ids layout-container-values layout-contianer-tokens]
(get-attrs shapes objects :layout-container)
[layout-item-ids layout-item-values {}]
@@ -461,6 +461,8 @@
{:type type
:ids layout-container-ids
:values layout-container-values
:applied-tokens layout-contianer-tokens
:shapes shapes
:multiple true}]
(when (or is-layout-child? has-flex-layout-container?)

View File

@@ -96,6 +96,8 @@
{:type type
:ids [(:id shape)]
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -96,6 +96,8 @@
{:type type
:ids ids
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -164,6 +164,8 @@
{:type type
:ids [(:id shape)]
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -129,14 +129,16 @@
[:> measures-menu*
{:ids ids
:type type
:applied-tokens applied-tokens
:values measure-values
:applied-tokens applied-tokens
:shapes shapes}]
[:& layout-container-menu
{:type type
:ids ids
:values layout-container-values
:applied-tokens applied-tokens
:shapes shapes
:multiple false}]
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)

View File

@@ -259,7 +259,7 @@
show-rulers? (and (contains? layout :rulers) (not hide-ui?))
disabled-guides? (or drawing-tool transform path-drawing? path-editing?)
disabled-guides? (or drawing-tool transform path-drawing? path-editing? @space? @mod?)
single-select? (= (count selected-shapes) 1)

View File

@@ -381,6 +381,7 @@
(and flip-y (not flip-x)))]
(when (and (not ^boolean read-only?)
(not (:blocked shape))
(not (or (= transform-type :move)
(= transform-type :rotate))))

View File

@@ -100,9 +100,9 @@
on-pointer-down
(mf/use-fn
(mf/deps (:id frame) on-frame-select workspace-read-only?)
(mf/deps (:id frame) on-frame-select workspace-read-only? blocked?)
(fn [event]
(when (dom/left-mouse? event)
(when (and (dom/left-mouse? event) (not blocked?))
(dom/prevent-default event)
(dom/stop-propagation event)
(on-frame-select event (:id frame)))))

View File

@@ -296,8 +296,9 @@
(->> wasm.api/module
(p/fmap (fn [ready?]
(when ready?
(reset! canvas-init? true)
(wasm.api/assign-canvas canvas)))))
(let [init? (wasm.api/init-canvas-context canvas)]
(reset! canvas-init? init?)
(when-not init? (js/alert "WebGL not supported")))))))
(fn []
(wasm.api/clear-canvas))))

View File

@@ -954,7 +954,7 @@
(h/call wasm/internal-module "_init_shapes_pool" total-shapes)
(set-objects base-objects)))
(def ^:private canvas-options
(def ^:private context-options
#js {:antialias false
:depth true
:stencil true
@@ -971,23 +971,30 @@
(dbg/enabled? :wasm-viewbox)
(bit-or 2r00000000000000000000000000000001)))
(defn assign-canvas
(defn set-canvas-size
[canvas]
(set! (.-width canvas) (* dpr (.-clientWidth ^js canvas)))
(set! (.-height canvas) (* dpr (.-clientHeight ^js canvas))))
(defn init-canvas-context
[canvas]
(let [gl (unchecked-get wasm/internal-module "GL")
flags (debug-flags)
context (.getContext ^js canvas "webgl2" canvas-options)
;; Register the context with emscripten
handle (.registerContext ^js gl context #js {"majorVersion" 2})]
(.makeContextCurrent ^js gl handle)
context-id (if (dbg/enabled? :wasm-gl-context-init-error) "fail" "webgl2")
context (.getContext ^js canvas context-id context-options)
context-init? (not (nil? context))]
(when-not (nil? context)
(let [handle (.registerContext ^js gl context #js {"majorVersion" 2})]
(.makeContextCurrent ^js gl handle)
;; Force the WEBGL_debug_renderer_info extension as emscripten does not enable it
(.getExtension context "WEBGL_debug_renderer_info")
;; Force the WEBGL_debug_renderer_info extension as emscripten does not enable it
(.getExtension context "WEBGL_debug_renderer_info")
;; Initialize Wasm Render Engine
(h/call wasm/internal-module "_init" (/ (.-width ^js canvas) dpr) (/ (.-height ^js canvas) dpr))
(h/call wasm/internal-module "_set_render_options" flags dpr))
(set! (.-width canvas) (* dpr (.-clientWidth ^js canvas)))
(set! (.-height canvas) (* dpr (.-clientHeight ^js canvas))))
;; Initialize Wasm Render Engine
(h/call wasm/internal-module "_init" (/ (.-width ^js canvas) dpr) (/ (.-height ^js canvas) dpr))
(h/call wasm/internal-module "_set_render_options" flags dpr)))
(set-canvas-size canvas)
context-init?))
(defn clear-canvas
[]

View File

@@ -17,6 +17,7 @@
(def ^:const PARAGRAPH-ATTR-U8-SIZE 44)
(def ^:const LEAF-ATTR-U8-SIZE 60)
(def ^:const MAX-TEXT-FILLS types.fills.impl/MAX-FILLS)
(defn- encode-text
"Into an UTF8 buffer. Returns an ArrayBuffer instance"
@@ -26,28 +27,27 @@
(defn- write-leaf-fills
[offset dview fills]
(reduce (fn [offset fill]
(let [opacity (get fill :fill-opacity 1.0)
color (get fill :fill-color)
gradient (get fill :fill-color-gradient)
image (get fill :fill-image)]
(let [new-ofset (reduce (fn [offset fill]
(let [opacity (get fill :fill-opacity 1.0)
color (get fill :fill-color)
gradient (get fill :fill-color-gradient)
image (get fill :fill-image)]
(cond
(some? color)
(types.fills.impl/write-solid-fill offset dview opacity color)
(cond
(some? color)
(types.fills.impl/write-solid-fill offset dview opacity color)
(some? gradient)
(types.fills.impl/write-gradient-fill offset dview opacity gradient)
(some? gradient)
(types.fills.impl/write-gradient-fill offset dview opacity gradient)
(some? image)
(types.fills.impl/write-image-fill offset dview opacity image))))
(some? image)
(types.fills.impl/write-image-fill offset dview opacity image))))
offset
fills))
offset
fills)
padding-fills (max 0 (- MAX-TEXT-FILLS (count fills)))]
(+ new-ofset (* padding-fills types.fills.impl/FILL-U8-SIZE))))
(defn- get-total-fills
[leaves]
(reduce #(+ %1 (count (:fills %2))) 0 leaves))
(defn- write-paragraph
[offset dview paragraph]
@@ -86,8 +86,7 @@
text-buffer (encode-text (get leaf :text))
text-length (mem/size text-buffer)
fills (get leaf :fills)
total-fills (count fills)
fills (take MAX-TEXT-FILLS (get leaf :fills))
font-variant-id
(get leaf :font-variant-id)
@@ -127,7 +126,7 @@
(mem/write-uuid dview (d/nilv font-variant-id uuid/zero))
(mem/write-i32 dview text-length)
(mem/write-i32 dview total-fills)
(mem/write-i32 dview (count fills))
(mem/assert-written offset LEAF-ATTR-U8-SIZE)
(write-leaf-fills dview fills))))
@@ -139,11 +138,9 @@
;; [<num-leaves> <paragraph_attributes> <leaves_attributes> <text>]
[leaves paragraph text]
(let [num-leaves (count leaves)
fills-size (* types.fills.impl/FILL-U8-SIZE
(get-total-fills leaves))
fills-size (* types.fills.impl/FILL-U8-SIZE MAX-TEXT-FILLS)
metadata-size (+ PARAGRAPH-ATTR-U8-SIZE
(* num-leaves LEAF-ATTR-U8-SIZE)
fills-size)
(* num-leaves (+ LEAF-ATTR-U8-SIZE fills-size)))
text-buffer (encode-text text)
text-size (mem/size text-buffer)

View File

@@ -96,9 +96,12 @@
;; Show some information about the WebGL context.
:gl-context
;; Show viewbox
;; Show viewbox.
:wasm-viewbox
;; Makes the GL context to fail on initialization.
:wasm-gl-context-init-error
;; Event times
:events-times})

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Alejandro Alonso <alejandro.alonso@kaleidos.net>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/penpot/frontend/"
"ar/>\n"
"Language-Team: Arabic "
"<https://hosted.weblate.org/projects/penpot/frontend/ar/>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -2832,6 +2832,9 @@ msgstr "أسلوب الخط"
msgid "workspace.assets.typography.font-size"
msgstr "الحجم"
msgid "workspace.assets.typography.font-style"
msgstr "نوع الخط"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "اذهب إلى تحرير نوع ملف المكتبة"
@@ -3826,7 +3829,7 @@ msgstr "أعلى"
msgid "workspace.options.more-colors"
msgstr "المزيد من الألوان"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "المزيد من ألوان المكتبة"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Aryiu <aryiu@users.noreply.hosted.weblate.org>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/penpot/frontend/"
"ca/>\n"
"Language-Team: Catalan "
"<https://hosted.weblate.org/projects/penpot/frontend/ca/>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -2790,6 +2790,9 @@ msgstr "Tipografia"
msgid "workspace.assets.typography.font-size"
msgstr "Mida"
msgid "workspace.assets.typography.font-style"
msgstr "Estil de la lletra"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Vés al fitxer de la biblioteca d'estils per a editar-lo"
@@ -3694,7 +3697,7 @@ msgstr "Dalt"
msgid "workspace.options.more-colors"
msgstr "Més colors"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Més llibreries de colors"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: \"Amerey.eu\" <info@amerey.eu>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/penpot/frontend/cs/"
">\n"
"Language-Team: Czech "
"<https://hosted.weblate.org/projects/penpot/frontend/cs/>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4278,6 +4278,9 @@ msgstr "Písmo"
msgid "workspace.assets.typography.font-size"
msgstr "Velikost"
msgid "workspace.assets.typography.font-style"
msgstr "Styl písma"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Chcete-li upravit, přejděte do souboru knihovny stylů"
@@ -5482,7 +5485,7 @@ msgstr "Nahoře"
msgid "workspace.options.more-colors"
msgstr "Více barev"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Více barev knihovny"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Marius <hi@mariusscheel.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/penpot/frontend/"
"de/>\n"
"Language-Team: German "
"<https://hosted.weblate.org/projects/penpot/frontend/de/>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4779,6 +4779,9 @@ msgstr "Schriftart"
msgid "workspace.assets.typography.font-size"
msgstr "Größe"
msgid "workspace.assets.typography.font-style"
msgstr "Schriftschnitt"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Wechseln Sie zur Stilbibliotheksdatei, um sie zu bearbeiten"
@@ -6060,7 +6063,7 @@ msgstr "Oben"
msgid "workspace.options.more-colors"
msgstr "Weitere Farben"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Weitere Bibliotheksfarben"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"Language-Team: Greek <https://hosted.weblate.org/projects/penpot/frontend/el/"
">\n"
"Language-Team: Greek "
"<https://hosted.weblate.org/projects/penpot/frontend/el/>\n"
"Language: el\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -1274,6 +1274,9 @@ msgstr "Γραμματοσειρά"
msgid "workspace.assets.typography.font-size"
msgstr "Μέγεθος"
msgid "workspace.assets.typography.font-style"
msgstr "Στυλ γραμματοσειράς"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Μεταβείτε στο αρχείο βιβλιοθήκης στυλ για επεξεργασία"

View File

@@ -5111,6 +5111,9 @@ msgstr "Font"
msgid "workspace.assets.typography.font-size"
msgstr "Size"
msgid "workspace.assets.typography.font-style"
msgstr "Font Style"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Go to style library file to edit"
@@ -6514,7 +6517,11 @@ msgstr "Top"
msgid "workspace.options.more-colors"
msgstr "More colors"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
msgid "workspace.options.more-token-colors"
msgstr "More color tokens"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "More library colors"

View File

@@ -5095,6 +5095,9 @@ msgstr "Fuente"
msgid "workspace.assets.typography.font-size"
msgstr "Tamaño"
msgid "workspace.assets.typography.font-style"
msgstr "Estilo de fuente"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Ir al archivo de la biblioteca del estilo para editar"
@@ -5467,8 +5470,8 @@ msgstr "Añadir"
#: src/app/main/ui/workspace/libraries.cljs:107, src/app/main/ui/workspace/libraries.cljs:133
msgid "workspace.libraries.colors"
msgid_plural "workspace.libraries.colors"
msgstr[0] "1 color"
msgid_plural "workspace.libraries.colors"
msgstr[0] "1 color"
msgstr[1] "%s colores"
#: src/app/main/ui/workspace/color_palette.cljs:147
@@ -5507,8 +5510,8 @@ msgstr "Guardar estilo de color"
#: src/app/main/ui/workspace/libraries.cljs:101, src/app/main/ui/workspace/libraries.cljs:125
msgid "workspace.libraries.components"
msgid_plural "workspace.libraries.components"
msgstr[0] "1 componente"
msgid_plural "workspace.libraries.components"
msgstr[0] "1 componente"
msgstr[1] "%s componentes"
#: src/app/main/ui/workspace/libraries.cljs:349
@@ -5533,8 +5536,8 @@ msgstr "Biblioteca del archivo"
#: src/app/main/ui/workspace/libraries.cljs:104, src/app/main/ui/workspace/libraries.cljs:129
msgid "workspace.libraries.graphics"
msgid_plural "workspace.libraries.graphics"
msgstr[0] "1 gráfico"
msgid_plural "workspace.libraries.graphics"
msgstr[0] "1 gráfico"
msgstr[1] "%s gráficos"
#: src/app/main/ui/workspace/libraries.cljs:316
@@ -5593,8 +5596,8 @@ msgstr "Desvincular todas las tipografías"
#: src/app/main/ui/workspace/libraries.cljs:110, src/app/main/ui/workspace/libraries.cljs:137
msgid "workspace.libraries.typography"
msgid_plural "workspace.libraries.typography"
msgstr[0] "1 tipografía"
msgid_plural "workspace.libraries.typography"
msgstr[0] "1 tipografía"
msgstr[1] "%s tipografías"
#: src/app/main/ui/workspace/libraries.cljs:354
@@ -6457,10 +6460,14 @@ msgstr "Arriba"
msgid "workspace.options.more-colors"
msgstr "Más colores"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Más colores de la biblioteca"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
msgid "workspace.options.more-token-colors"
msgstr "Más tokens de color"
#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:192
msgid "workspace.options.opacity"
msgstr "Opacidad"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Mikel Larreategi <mlarreategi@codesyntax.com>\n"
"Language-Team: Basque <https://hosted.weblate.org/projects/penpot/frontend/"
"eu/>\n"
"Language-Team: Basque "
"<https://hosted.weblate.org/projects/penpot/frontend/eu/>\n"
"Language: eu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -3130,6 +3130,9 @@ msgstr "Letra-tipoak"
msgid "workspace.assets.typography.font-size"
msgstr "Tamaina"
msgid "workspace.assets.typography.font-style"
msgstr "Letra-tipoaren estiloa"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Joan estilo liburutegiaren fitxategira editatzeko"
@@ -4082,7 +4085,7 @@ msgstr "Goian"
msgid "workspace.options.more-colors"
msgstr "Kolore gehiago"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Liburutegiko kolore gehiago"

View File

@@ -2282,6 +2282,9 @@ msgstr "فونت"
msgid "workspace.assets.typography.font-size"
msgstr "اندازه"
msgid "workspace.assets.typography.font-style"
msgstr "استایل فونت"
#: src/app/main/ui/dashboard/grid.cljs:217, src/app/main/ui/workspace/libraries.cljs:579, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:480, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:506, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:613, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:633
msgid "workspace.assets.typography.sample"
msgstr "مثال"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Pablo Alba <pablo.alba@kaleidos.net>\n"
"Language-Team: French <https://hosted.weblate.org/projects/penpot/frontend/"
"fr/>\n"
"Language-Team: French "
"<https://hosted.weblate.org/projects/penpot/frontend/fr/>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4887,6 +4887,9 @@ msgstr "Police"
msgid "workspace.assets.typography.font-size"
msgstr "Taille"
msgid "workspace.assets.typography.font-style"
msgstr "Style de police"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Accéder au fichier de bibliothèque de styles à modifier"
@@ -6202,7 +6205,7 @@ msgstr "En haut"
msgid "workspace.options.more-colors"
msgstr "Plus de couleurs"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Plus de couleurs de la bibliothèque"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Alejandro Alonso <alejandro.alonso@kaleidos.net>\n"
"Language-Team: Hausa <https://hosted.weblate.org/projects/penpot/frontend/ha/"
">\n"
"Language-Team: Hausa "
"<https://hosted.weblate.org/projects/penpot/frontend/ha/>\n"
"Language: ha\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -3388,6 +3388,9 @@ msgstr "tsarin haruffa"
msgid "workspace.assets.typography.font-size"
msgstr "girma"
msgid "workspace.assets.typography.font-style"
msgstr "tsarin salo"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "tafi zuwa salon dakin karatu don a tace"
@@ -4388,7 +4391,7 @@ msgstr "sama"
msgid "workspace.options.more-colors"
msgstr "kaloli masu yawa"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Ma'ajiyar kaloli masu yawa"

View File

@@ -2,14 +2,14 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
"Language-Team: Hebrew <https://hosted.weblate.org/projects/penpot/frontend/"
"he/>\n"
"Language-Team: Hebrew "
"<https://hosted.weblate.org/projects/penpot/frontend/he/>\n"
"Language: he\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : "
"((n > 10 && n % 10 == 0) ? 2 : 3));\n"
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && "
"n % 10 == 0) ? 2 : 3));\n"
"X-Generator: Weblate 5.14-dev\n"
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:153, src/app/main/ui/viewer/login.cljs:98
@@ -192,6 +192,16 @@ msgstr "דוא״ל עבודה"
msgid "branding-illustrations-marketing-pieces"
msgstr "…מיתוג, איורים, חומרים שיווקיים ועוד."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "האסימון הזה לא קיים או שנמחק."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"אין אסימוני צבע זמינים. נא לבדוק ערכות/ערכות עיצוב פעילות או להוסיף "
"אסימונים חדשים."
#: src/app/main/ui/comments.cljs:530
msgid "comments.mentions.not-found"
msgstr "לא נמצאו אנשים עבור @%s"
@@ -720,6 +730,22 @@ msgstr "הנתונים נשלחים לשרת (%s/%s)"
msgid "dashboard.import.progress.upload-media"
msgstr "נשלח קובץ: %s"
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "תימחקנה ההזמנות שמיועדות אל:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "תישלחנה מחדש ההזמנות שמיועדות אל:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "מחיקת הזמנות"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "שליחת הזמנות מחדש"
#: src/app/main/ui/dashboard/team.cljs:122, src/app/main/ui/dashboard/team.cljs:744
msgid "dashboard.invite-profile"
msgstr "הזמנת אנשים"
@@ -832,6 +858,14 @@ msgstr "פתיחת קובץ בלשונית חדשה"
msgid "dashboard.options"
msgstr "אפשרויות"
#: src/app/main/ui/dashboard/team.cljs:949
msgid "dashboard.order-invitations-by-role"
msgstr "סידור לפי תפקיד"
#: src/app/main/ui/dashboard/team.cljs:958
msgid "dashboard.order-invitations-by-status"
msgstr "סידור לפי מצב"
#: src/app/main/ui/settings/password.cljs:94, src/app/main/ui/settings/password.cljs:107
msgid "dashboard.password-change"
msgstr "החלפת סיסמה"
@@ -1827,6 +1861,38 @@ msgstr "מחושב"
msgid "inspect.tabs.info"
msgstr "מידע"
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
msgstr "העתקה ללוח הגזירים"
#: src/app/main/ui/inspect/styles/style_box.cljs:22
msgid "inspect.tabs.styles.panel.geometry"
msgstr "גודל ומקום"
#: src/app/main/ui/inspect/styles/style_box.cljs:59, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "החלפת חשיפת הלוח %s"
#: src/app/main/ui/inspect/styles/style_box.cljs:21
msgid "inspect.tabs.styles.panel.token"
msgstr "ערכות אסימונים וערכות עיצוב"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
msgid "inspect.tabs.styles.panel.tokens.active-sets"
msgstr "ערכות פעילות"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
msgid "inspect.tabs.styles.panel.tokens.active-themes"
msgstr "ערכות עיצוב פעילות"
#: src/app/main/ui/inspect/styles/style_box.cljs:20
msgid "inspect.tabs.styles.panel.variant"
msgstr "מאפייני הגוון"
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:53
msgid "inspect.tabs.styles.token.resolved-value"
msgstr "ערך פתור:"
#: src/app/main/ui/inspect/right_sidebar.cljs:165
msgid "inspect.tabs.switcher.label"
msgstr "פרטי שכבה"
@@ -1839,6 +1905,10 @@ msgstr "לסמן הכול כנקרא"
msgid "label.shortcuts"
msgstr "קיצורי דרך"
#: src/app/main/ui/dashboard/sidebar.cljs:1043
msgid "labels.about-penpot"
msgstr "על Penpot"
#: src/app/main/data/common.cljs:90, src/app/main/ui/dashboard/import.cljs:530
msgid "labels.accept"
msgstr "מקובל"
@@ -1894,6 +1964,10 @@ msgstr ""
msgid "labels.bad-gateway.main-message"
msgstr "שער גישה שגוי"
#: src/app/main/ui/inspect/styles/style_box.cljs:26
msgid "labels.blur"
msgstr "טשטוש"
#: src/app/main/data/common.cljs:129, src/app/main/ui/dashboard/change_owner.cljs:64, src/app/main/ui/dashboard/import.cljs:515, src/app/main/ui/dashboard/team.cljs:780, src/app/main/ui/dashboard/team.cljs:1122, src/app/main/ui/delete_shared.cljs:36, src/app/main/ui/exports/assets.cljs:162, src/app/main/ui/exports/files.cljs:191, src/app/main/ui/settings/access_tokens.cljs:175, src/app/main/ui/viewer/share_link.cljs:205, src/app/main/ui/workspace/sidebar/assets/groups.cljs:159, src/app/main/ui/workspace/tokens/export/modal.cljs:44, src/app/main/ui/workspace/tokens/import/modal.cljs:269, src/app/main/ui/workspace/tokens/management/create/form.cljs:632, src/app/main/ui/workspace/tokens/settings/menu.cljs:104, src/app/main/ui/workspace/tokens/themes/create_modal.cljs:228
msgid "labels.cancel"
msgstr "ביטול"
@@ -1910,6 +1984,10 @@ msgstr "סגירה"
msgid "labels.collapse"
msgstr "צמצום"
#: src/app/main/ui/workspace/colorpicker.cljs:427
msgid "labels.color"
msgstr "צבע"
#: src/app/main/ui/comments.cljs:913
msgid "labels.comment"
msgstr "הערה"
@@ -1926,6 +2004,10 @@ msgstr "הערות"
msgid "labels.community"
msgstr "קהילה"
#: src/app/main/ui/dashboard/sidebar.cljs:1030
msgid "labels.community-contributions"
msgstr "קהילה ותרומות"
#: src/app/main/ui/settings/password.cljs:91
msgid "labels.confirm-password"
msgstr "אישור סיסמה"
@@ -2064,6 +2146,10 @@ msgstr "המשוב נשלח"
msgid "labels.figma"
msgstr "Figma"
#: src/app/main/ui/inspect/styles/style_box.cljs:23
msgid "labels.fill"
msgstr "מילוי"
#: src/app/main/ui/dashboard/fonts.cljs:430
msgid "labels.font-family"
msgstr "משפחת גופנים"
@@ -2110,6 +2196,10 @@ msgstr "עיצוב גרפי"
msgid "labels.help-center"
msgstr "מרכז העזרה"
#: src/app/main/ui/dashboard/sidebar.cljs:1019
msgid "labels.help-learning"
msgstr "עזרה ולמידה"
#: src/app/main/ui/dashboard/templates.cljs:91
msgid "labels.hide"
msgstr "הסתרה"
@@ -2152,6 +2242,14 @@ msgstr "הזמנות"
msgid "labels.language"
msgstr "שפה"
#: src/app/main/ui/inspect/styles/style_box.cljs:28
msgid "labels.layout"
msgstr "פריסה"
#: src/app/main/ui/dashboard/sidebar.cljs:798
msgid "labels.learning-center"
msgstr "מרכז הלמידה"
#: src/app/main/ui/workspace/main_menu.cljs:168
msgid "labels.libraries-and-templates"
msgstr "ספריות ותבניות"
@@ -2294,6 +2392,14 @@ msgstr "סיסמה"
msgid "labels.pending-invitation"
msgstr "בהמתנה"
#: src/app/main/ui/dashboard/sidebar.cljs:878
msgid "labels.penpot-changelog"
msgstr "יומן השינויים של Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:804
msgid "labels.penpot-hub"
msgstr "המרכז של Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:751
msgid "labels.pinned-projects"
msgstr "מיזמים נעוצים"
@@ -2322,6 +2428,10 @@ msgstr "פרופיל"
msgid "labels.projects"
msgstr "מיזמים"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:644
msgid "labels.reference"
msgstr "הפניה"
#: src/app/main/data/common.cljs:83
msgid "labels.refresh"
msgstr "ריענון"
@@ -2372,6 +2482,10 @@ msgstr "תגובה חדשה"
msgid "labels.reply.thread"
msgstr "תגובה"
#: src/app/main/ui/dashboard/team.cljs:788
msgid "labels.resend"
msgstr "שליחה מחדש"
#: src/app/main/ui/dashboard/team.cljs:938
msgid "labels.resend-invitation"
msgstr "שליחת ההזמנה מחדש"
@@ -2428,6 +2542,10 @@ msgstr "סדרות"
msgid "labels.settings"
msgstr "הגדרות"
#: src/app/main/ui/inspect/styles/style_box.cljs:27
msgid "labels.shadow"
msgstr "צל"
#: src/app/main/ui/viewer/header.cljs:204
msgid "labels.share"
msgstr "שיתוף"
@@ -2476,10 +2594,22 @@ msgstr "התחלה"
msgid "labels.status"
msgstr "מצב"
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
msgid "labels.stroke"
msgstr "קו מתאר"
#: src/app/main/ui/onboarding/questions.cljs:87
msgid "labels.student-teacher"
msgstr "סטודנט/ית או מרצה"
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:107
msgid "labels.styles"
msgstr "סגנונות"
#: src/app/main/ui/inspect/styles/style_box.cljs:33
msgid "labels.svg"
msgstr "SVG"
#: src/app/main/ui/onboarding/questions.cljs:256
#, unused
msgid "labels.team-leader"
@@ -2490,6 +2620,10 @@ msgstr "מוביל או מובילת צוות"
msgid "labels.team-member"
msgstr "חבר או חברת צוות"
#: src/app/main/ui/inspect/styles/style_box.cljs:25
msgid "labels.text"
msgstr "טקסט"
#: src/app/main/ui/workspace/tokens/themes.cljs:36
msgid "labels.themes"
msgstr "ערכות עיצוב"
@@ -2498,6 +2632,10 @@ msgstr "ערכות עיצוב"
msgid "labels.tutorials"
msgstr "מדריכים"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1148
msgid "labels.typography"
msgstr "טיפוגרפיה"
#: src/app/main/data/workspace/tokens/errors.cljs:101
msgid "labels.unknown-error"
msgstr "שגיאה לא ידועה"
@@ -2530,6 +2668,14 @@ msgstr "העלאת גופנים משלך"
msgid "labels.uploading"
msgstr "מתבצעת העלאה…"
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:949, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:518
msgid "labels.variant"
msgstr "הגוון"
#: src/app/main/ui/dashboard/sidebar.cljs:872
msgid "labels.version-notes"
msgstr "הערות לגרסה %s"
#: src/app/main/ui/workspace/sidebar/sitemap.cljs:246
msgid "labels.view-only"
msgstr "תצוגה בלבד"
@@ -2538,6 +2684,10 @@ msgstr "תצוגה בלבד"
msgid "labels.viewer"
msgstr "מציג"
#: src/app/main/ui/inspect/styles/style_box.cljs:32
msgid "labels.visibility"
msgstr "חשיפה"
#: src/app/main/ui/dashboard/sidebar.cljs:441, src/app/main/ui/dashboard/team.cljs:103, src/app/main/ui/dashboard/team.cljs:113, src/app/main/ui/dashboard/team.cljs:1134
msgid "labels.webhooks"
msgstr "התליות"
@@ -3260,6 +3410,10 @@ msgstr "הפסקת תחזוקה: המערכת תושבת לעבודת תחזוק
msgid "notifications.by-code.upgrade-version"
msgstr "יש גרסה חדשה, נא לרענן את העמוד"
#: src/app/main/ui/dashboard/team.cljs:825
msgid "notifications.invitation-deleted"
msgstr "ההזמנה נמחקה בהצלחה"
#: src/app/main/ui/dashboard/team.cljs:170, src/app/main/ui/dashboard/team.cljs:867
msgid "notifications.invitation-email-sent"
msgstr "ההזמנה נשלחה בהצלחה"
@@ -3820,6 +3974,10 @@ msgstr "העתקת קישור ללוח הגזירים"
msgid "shortcuts.copy-props"
msgstr "העתקת מאפיינים"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
msgid "shortcuts.create-component-variant"
msgstr "יצירת רכיב / הגוון"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:98
msgid "shortcuts.create-new-project"
msgstr "יצירת חדש"
@@ -4374,6 +4532,12 @@ msgstr ""
"נא לשדרג כעת כדי לעמוד במכסת העורכים הנוכחית שלך. [להירשם "
"כעת.|target:self](%s)"
#: src/app/main/ui/dashboard/subscription.cljs:156
msgid "subscription.dashboard.unlimited-members-extra-editors-cta-text"
msgstr ""
"רק עורכים חדשים על פני הצוותים שבבעלותך מחושבים בחיובים העתידיים. 175$ "
"בחודש בלי תוספות עדיין חלים על 25+ עורכים."
#: src/app/main/ui/dashboard/subscription.cljs:152
msgid "subscription.dashboard.unlimited-members-extra-editors-cta-title"
msgstr "הזמנת אנשים תוך השתתפות בתוכנית הבלתי מוגבלת"
@@ -4532,6 +4696,7 @@ msgid "subscription.settings.sucess.dialog.title"
msgstr "התוכנית שלך היא %s!"
#: src/app/main/ui/settings/subscription.cljs:413
#, fuzzy
msgid "subscription.settings.support-us-since"
msgstr "תמכת בנו עם התוכנית הזאת מאז: %s"
@@ -4907,6 +5072,9 @@ msgstr "גופן"
msgid "workspace.assets.typography.font-size"
msgstr "גודל"
msgid "workspace.assets.typography.font-style"
msgstr "סגנון גופן"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "מעבר לקובץ ספריית סגנון כדי לערוך"
@@ -4935,6 +5103,18 @@ msgstr "התמרת טקסט"
msgid "workspace.assets.ungroup"
msgstr "פירוק קבוצה"
#: src/app/main/ui/workspace/colorpicker.cljs:431, src/app/main/ui/workspace/colorpicker.cljs:443
msgid "workspace.colorpicker.color-tokens"
msgstr "אסימוני צבע"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:464
msgid "workspace.component.swap.loop-error"
msgstr "אי אפשר לקנן את הרכיבים בתוך עצמם."
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:463
msgid "workspace.component.switch.loop-error-multi"
msgstr "לא ניתן לכבות/להדליק חלק מהעותקים. אי אפשר לקנן את הרכיבים בתוך עצמם."
#: src/app/main/ui/workspace/context_menu.cljs:794
msgid "workspace.context-menu.grid-cells.area"
msgstr "יצירת שטח"
@@ -5302,6 +5482,10 @@ msgstr "RGBA"
msgid "workspace.libraries.colors.save-color"
msgstr "שמירת סגנון צבע"
#: src/app/main/ui/workspace/libraries.cljs:349
msgid "workspace.libraries.connected-to"
msgstr "מחובר אל"
#: src/app/main/ui/workspace/libraries.cljs:404
msgid "workspace.libraries.empty.add-some"
msgstr "או להוסיף כמה מאלה לניסיון:"
@@ -6262,7 +6446,7 @@ msgstr "עליון"
msgid "workspace.options.more-colors"
msgstr "צבעים נוספים"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "צבעי ספרייה נוספים"
@@ -7201,6 +7385,10 @@ msgstr "בחירת תיקייה"
msgid "workspace.tokens.color"
msgstr "צבע"
#: src/app/main/data/workspace/tokens/errors.cljs:97
msgid "workspace.tokens.composite-line-height-needs-font-size"
msgstr "גובה השורה תלוי בגודל הגופן. יש להוסיף גודל גופן כדי לקבל את הערך הפתור."
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:53
msgid "workspace.tokens.create-new-theme"
msgstr "אפשר ליצור את ערכת העיצוב הראשונה שלך עכשיו."
@@ -7241,6 +7429,10 @@ msgstr "עריכת ערכת עיצוב"
msgid "workspace.tokens.edit-themes"
msgstr "עריכת ערכות עיצוב"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:551
msgid "workspace.tokens.edit-token"
msgstr "עריכת אסימון %s"
#: src/app/main/data/workspace/tokens/errors.cljs:41
msgid "workspace.tokens.empty-input"
msgstr "ערך האסימון לא יכול להישאר ריק"
@@ -7350,6 +7542,10 @@ msgstr ""
"הסדרה הזאת לא פעילה. יש להחליף את ערכת העיצוב או להפעיל את הסדרה הזאת כדי "
"לראות את השינויים באשנב"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:711
msgid "workspace.tokens.individual-tokens"
msgstr "להשתמש באסימונים עצמאיים"
#: src/app/main/data/workspace/tokens/errors.cljs:49
msgid "workspace.tokens.invalid-color"
msgstr "ערך צבע שגוי: %s"
@@ -7369,6 +7565,10 @@ msgstr ""
"שמות האסימונים יכולים להכיל אותיות וספרות מופרדים בתווי . ואסור שיתחילו "
"בדולר ($)."
#: src/app/main/data/workspace/tokens/errors.cljs:93
msgid "workspace.tokens.invalid-token-value-typography"
msgstr "ערך שגוי: חייב להפנות לאסימון טיפוגרפיה מרוכב."
#: src/app/main/data/workspace/tokens/errors.cljs:61, src/app/main/data/workspace/tokens/errors.cljs:73, src/app/main/data/workspace/tokens/errors.cljs:77
msgid "workspace.tokens.invalid-value"
msgstr "ערך אסימון שגוי: %s"
@@ -7389,6 +7589,10 @@ msgstr "ערכת עיצוב"
msgid "workspace.tokens.label.theme-placeholder"
msgstr "הוספת ערכת עיצוב (למשל: בהירה)"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1047
msgid "workspace.tokens.letter-spacing-value-enter-composite"
msgstr "הוספת ריווח תווים או {alias}"
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:220
msgid "workspace.tokens.margins"
msgstr "שוליים"
@@ -7458,6 +7662,7 @@ msgid "workspace.tokens.opacity-range"
msgstr "שקיפות צריכה להיות בין 0 ל־100% או 0 ו־1 (כלומר 50% או 0.5)."
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:120
#, fuzzy
msgid "workspace.tokens.original-value"
msgstr "ערך מקורי: %s"
@@ -7473,12 +7678,17 @@ msgstr "רדיוס"
msgid "workspace.tokens.ref-not-valid"
msgstr "ההפניה לא תקפה או שאינה באף סדרה פעילה"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:744
msgid "workspace.tokens.reference-composite"
msgstr "נא למלא כינוי לטיפוגרפיית אסימון"
#: src/app/main/ui/workspace/tokens/style_dictionary.cljs
#, unused
msgid "workspace.tokens.reference-error"
msgstr "שגיאות הפניה: "
#: src/app/main/data/workspace/tokens/warnings.cljs:15, src/app/main/data/workspace/tokens/warnings.cljs:19, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:56, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:84, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:100, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:41, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:46, src/app/main/ui/workspace/tokens/management/token_pill.cljs:121
#, fuzzy
msgid "workspace.tokens.resolved-value"
msgstr "ערך פתור: %s"
@@ -7546,6 +7756,7 @@ msgid "workspace.tokens.themes-list"
msgstr "רשימת ערכות עיצוב"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:608, src/app/main/ui/workspace/tokens/management/create/form.cljs:609
#, fuzzy
msgid "workspace.tokens.token-description"
msgstr "תיאור"
@@ -7601,6 +7812,10 @@ msgstr "הייבוא הצליח. חלק מהאסימונים לא נכללו."
msgid "workspace.tokens.unknown-token-type-section"
msgstr "הסוג %s לא נתמך (%s)\n"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:715
msgid "workspace.tokens.use-reference"
msgstr "להשתמש בהפניה"
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:131
msgid "workspace.tokens.value-not-valid"
msgstr "הערך לא תקף"
@@ -7944,212 +8159,3 @@ msgstr "גרסאות שנשמרו אוטומטית תישמרנה למשך %s י
#, unused
msgid "workspace.viewport.click-to-close-path"
msgstr "לחיצה תסגור את הנתיב"
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "האסימון הזה לא קיים או שנמחק."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"אין אסימוני צבע זמינים. נא לבדוק ערכות/ערכות עיצוב פעילות או להוסיף אסימונים "
"חדשים."
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "תימחקנה ההזמנות שמיועדות אל:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "תישלחנה מחדש ההזמנות שמיועדות אל:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "מחיקת הזמנות"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "שליחת הזמנות מחדש"
#: src/app/main/ui/dashboard/team.cljs:949
msgid "dashboard.order-invitations-by-role"
msgstr "סידור לפי תפקיד"
#: src/app/main/ui/dashboard/team.cljs:958
msgid "dashboard.order-invitations-by-status"
msgstr "סידור לפי מצב"
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
msgstr "העתקה ללוח הגזירים"
#: src/app/main/ui/inspect/styles/style_box.cljs:22
msgid "inspect.tabs.styles.panel.geometry"
msgstr "גודל ומקום"
#: src/app/main/ui/inspect/styles/style_box.cljs:59, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "החלפת חשיפת הלוח %s"
#: src/app/main/ui/inspect/styles/style_box.cljs:21
msgid "inspect.tabs.styles.panel.token"
msgstr "ערכות אסימונים וערכות עיצוב"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
msgid "inspect.tabs.styles.panel.tokens.active-sets"
msgstr "ערכות פעילות"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
msgid "inspect.tabs.styles.panel.tokens.active-themes"
msgstr "ערכות עיצוב פעילות"
#: src/app/main/ui/inspect/styles/style_box.cljs:20
msgid "inspect.tabs.styles.panel.variant"
msgstr "מאפייני הגוון"
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:53
msgid "inspect.tabs.styles.token.resolved-value"
msgstr "ערך פתור:"
#: src/app/main/ui/dashboard/sidebar.cljs:1043
msgid "labels.about-penpot"
msgstr "על Penpot"
#: src/app/main/ui/inspect/styles/style_box.cljs:26
msgid "labels.blur"
msgstr "טשטוש"
#: src/app/main/ui/workspace/colorpicker.cljs:427
msgid "labels.color"
msgstr "צבע"
#: src/app/main/ui/dashboard/sidebar.cljs:1030
msgid "labels.community-contributions"
msgstr "קהילה ותרומות"
#: src/app/main/ui/inspect/styles/style_box.cljs:23
msgid "labels.fill"
msgstr "מילוי"
#: src/app/main/ui/dashboard/sidebar.cljs:1019
msgid "labels.help-learning"
msgstr "עזרה ולמידה"
#: src/app/main/ui/inspect/styles/style_box.cljs:28
msgid "labels.layout"
msgstr "פריסה"
#: src/app/main/ui/dashboard/sidebar.cljs:798
msgid "labels.learning-center"
msgstr "מרכז הלמידה"
#: src/app/main/ui/dashboard/sidebar.cljs:878
msgid "labels.penpot-changelog"
msgstr "יומן השינויים של Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:804
msgid "labels.penpot-hub"
msgstr "המרכז של Penpot"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:644
msgid "labels.reference"
msgstr "הפניה"
#: src/app/main/ui/dashboard/team.cljs:788
msgid "labels.resend"
msgstr "שליחה מחדש"
#: src/app/main/ui/inspect/styles/style_box.cljs:27
msgid "labels.shadow"
msgstr "צל"
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
msgid "labels.stroke"
msgstr "קו מתאר"
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:107
msgid "labels.styles"
msgstr "סגנונות"
#: src/app/main/ui/inspect/styles/style_box.cljs:33
msgid "labels.svg"
msgstr "SVG"
#: src/app/main/ui/inspect/styles/style_box.cljs:25
msgid "labels.text"
msgstr "טקסט"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1148
msgid "labels.typography"
msgstr "טיפוגרפיה"
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:949, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:518
msgid "labels.variant"
msgstr "הגוון"
#: src/app/main/ui/dashboard/sidebar.cljs:872
msgid "labels.version-notes"
msgstr "הערות לגרסה %s"
#: src/app/main/ui/inspect/styles/style_box.cljs:32
msgid "labels.visibility"
msgstr "חשיפה"
#: src/app/main/ui/dashboard/team.cljs:825
msgid "notifications.invitation-deleted"
msgstr "ההזמנה נמחקה בהצלחה"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
msgid "shortcuts.create-component-variant"
msgstr "יצירת רכיב / הגוון"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:715
msgid "workspace.tokens.use-reference"
msgstr "להשתמש בהפניה"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:744
msgid "workspace.tokens.reference-composite"
msgstr "נא למלא כינוי לטיפוגרפיית אסימון"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1047
msgid "workspace.tokens.letter-spacing-value-enter-composite"
msgstr "הוספת ריווח תווים או {alias}"
#: src/app/main/data/workspace/tokens/errors.cljs:93
msgid "workspace.tokens.invalid-token-value-typography"
msgstr "ערך שגוי: חייב להפנות לאסימון טיפוגרפיה מרוכב."
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:711
msgid "workspace.tokens.individual-tokens"
msgstr "להשתמש באסימונים עצמאיים"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:551
msgid "workspace.tokens.edit-token"
msgstr "עריכת אסימון %s"
#: src/app/main/data/workspace/tokens/errors.cljs:97
msgid "workspace.tokens.composite-line-height-needs-font-size"
msgstr ""
"גובה השורה תלוי בגודל הגופן. יש להוסיף גודל גופן כדי לקבל את הערך הפתור."
#: src/app/main/ui/workspace/libraries.cljs:349
msgid "workspace.libraries.connected-to"
msgstr "מחובר אל"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:463
msgid "workspace.component.switch.loop-error-multi"
msgstr "לא ניתן לכבות/להדליק חלק מהעותקים. אי אפשר לקנן את הרכיבים בתוך עצמם."
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:464
msgid "workspace.component.swap.loop-error"
msgstr "אי אפשר לקנן את הרכיבים בתוך עצמם."
#: src/app/main/ui/workspace/colorpicker.cljs:431, src/app/main/ui/workspace/colorpicker.cljs:443
msgid "workspace.colorpicker.color-tokens"
msgstr "אסימוני צבע"
#: src/app/main/ui/dashboard/subscription.cljs:156
msgid "subscription.dashboard.unlimited-members-extra-editors-cta-text"
msgstr ""
"רק עורכים חדשים על פני הצוותים שבבעלותך מחושבים בחיובים העתידיים. 175$ בחודש "
"בלי תוספות עדיין חלים על 25+ עורכים."

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: VKing9 <vaibhavrathod2282@gmail.com>\n"
"Language-Team: Hindi <https://hosted.weblate.org/projects/penpot/frontend/hi/"
">\n"
"Language-Team: Hindi "
"<https://hosted.weblate.org/projects/penpot/frontend/hi/>\n"
"Language: hi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4754,6 +4754,9 @@ msgstr "फ़ॉन्ट"
msgid "workspace.assets.typography.font-size"
msgstr "आकार"
msgid "workspace.assets.typography.font-style"
msgstr "फ़ॉन्ट शैली"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "संपादन के लिए स्टाइल लाइब्रेरी फ़ाइल पर जाएँ"
@@ -6033,7 +6036,7 @@ msgstr "शीर्ष"
msgid "workspace.options.more-colors"
msgstr "और अधिक रंग"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "और लाइब्रेरी रंग"

View File

@@ -2,15 +2,14 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Zvonimir Juranko <zjuranko@gmail.com>\n"
"Language-Team: Croatian <https://hosted.weblate.org/projects/penpot/frontend/"
"hr/>\n"
"Language-Team: Croatian "
"<https://hosted.weblate.org/projects/penpot/frontend/hr/>\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural="
"(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? "
"1 : 2);\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.14-dev\n"
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:153, src/app/main/ui/viewer/login.cljs:98
@@ -4278,6 +4277,9 @@ msgstr "Font"
msgid "workspace.assets.typography.font-size"
msgstr "Veličina"
msgid "workspace.assets.typography.font-style"
msgstr "Stil fonta"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Idi na datoteku biblioteke stilova za uređivanje"
@@ -5494,7 +5496,7 @@ msgstr "Vrh"
msgid "workspace.options.more-colors"
msgstr "Više boja"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Više boja iz biblioteke"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Linerly <linerly@proton.me>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/penpot/"
"frontend/id/>\n"
"Language-Team: Indonesian "
"<https://hosted.weblate.org/projects/penpot/frontend/id/>\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4476,6 +4476,9 @@ msgstr "Fon"
msgid "workspace.assets.typography.font-size"
msgstr "Ukuran"
msgid "workspace.assets.typography.font-style"
msgstr "Gaya Fon"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Pergi ke berkas pustaka untuk menyunting"
@@ -5714,7 +5717,7 @@ msgstr "Atas"
msgid "workspace.options.more-colors"
msgstr "Lebih banyak warna"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Lebih banyak warna pustaka"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Nicola Bortoletto <nicola.bortoletto@live.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/penpot/frontend/"
"it/>\n"
"Language-Team: Italian "
"<https://hosted.weblate.org/projects/penpot/frontend/it/>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -201,6 +201,16 @@ msgstr "Email di lavoro"
msgid "branding-illustrations-marketing-pieces"
msgstr "…branding, illustrazione, materiali di marketing, etc."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "Questo token non esiste o è stato eliminato."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"Nessun token colore disponibile. Controlla i set o i temi attivi oppure "
"aggiungi nuovi token."
#: src/app/main/ui/comments.cljs:530
msgid "comments.mentions.not-found"
msgstr "Nessuna persona trovata per @%s"
@@ -750,6 +760,22 @@ msgstr "Caricamento dei dati sul server (%s/%s)"
msgid "dashboard.import.progress.upload-media"
msgstr "Caricamento file: %s"
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "Stai per eliminare gli inviti a:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "Stai per reinviare gli inviti a:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "Elimina inviti"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "Reinvia inviti"
#: src/app/main/ui/dashboard/team.cljs:122, src/app/main/ui/dashboard/team.cljs:744
msgid "dashboard.invite-profile"
msgstr "Invita nel team"
@@ -864,6 +890,14 @@ msgstr "Apri file in una nuova scheda"
msgid "dashboard.options"
msgstr "Opzioni"
#: src/app/main/ui/dashboard/team.cljs:949
msgid "dashboard.order-invitations-by-role"
msgstr "Ordina per ruolo"
#: src/app/main/ui/dashboard/team.cljs:958
msgid "dashboard.order-invitations-by-status"
msgstr "Ordina per stato"
#: src/app/main/ui/settings/password.cljs:94, src/app/main/ui/settings/password.cljs:107
msgid "dashboard.password-change"
msgstr "Cambia password"
@@ -1880,6 +1914,38 @@ msgstr "Calcolato"
msgid "inspect.tabs.info"
msgstr "Informazione"
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
msgstr "Copia negli appunti"
#: src/app/main/ui/inspect/styles/style_box.cljs:22
msgid "inspect.tabs.styles.panel.geometry"
msgstr "Dimensione e posizione"
#: src/app/main/ui/inspect/styles/style_box.cljs:59, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "Attiva/disattiva pannello %s"
#: src/app/main/ui/inspect/styles/style_box.cljs:21
msgid "inspect.tabs.styles.panel.token"
msgstr "Set di token e temi"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
msgid "inspect.tabs.styles.panel.tokens.active-sets"
msgstr "Set attivi"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
msgid "inspect.tabs.styles.panel.tokens.active-themes"
msgstr "Temi attivi"
#: src/app/main/ui/inspect/styles/style_box.cljs:20
msgid "inspect.tabs.styles.panel.variant"
msgstr "Proprietà delle varianti"
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:53
msgid "inspect.tabs.styles.token.resolved-value"
msgstr "Valore risolto:"
#: src/app/main/ui/inspect/right_sidebar.cljs:165
msgid "inspect.tabs.switcher.label"
msgstr "Informazioni livello"
@@ -1892,6 +1958,10 @@ msgstr "Contassegna tutto come letto"
msgid "label.shortcuts"
msgstr "Scorciatoie"
#: src/app/main/ui/dashboard/sidebar.cljs:1043
msgid "labels.about-penpot"
msgstr "Informazioni su Penpot"
#: src/app/main/data/common.cljs:90, src/app/main/ui/dashboard/import.cljs:530
msgid "labels.accept"
msgstr "Accetto"
@@ -1947,6 +2017,10 @@ msgstr ""
msgid "labels.bad-gateway.main-message"
msgstr "Gateway non corretto"
#: src/app/main/ui/inspect/styles/style_box.cljs:26
msgid "labels.blur"
msgstr "Sfocatura"
#: src/app/main/data/common.cljs:129, src/app/main/ui/dashboard/change_owner.cljs:64, src/app/main/ui/dashboard/import.cljs:515, src/app/main/ui/dashboard/team.cljs:780, src/app/main/ui/dashboard/team.cljs:1122, src/app/main/ui/delete_shared.cljs:36, src/app/main/ui/exports/assets.cljs:162, src/app/main/ui/exports/files.cljs:191, src/app/main/ui/settings/access_tokens.cljs:175, src/app/main/ui/viewer/share_link.cljs:205, src/app/main/ui/workspace/sidebar/assets/groups.cljs:159, src/app/main/ui/workspace/tokens/export/modal.cljs:44, src/app/main/ui/workspace/tokens/import/modal.cljs:269, src/app/main/ui/workspace/tokens/management/create/form.cljs:632, src/app/main/ui/workspace/tokens/settings/menu.cljs:104, src/app/main/ui/workspace/tokens/themes/create_modal.cljs:228
msgid "labels.cancel"
msgstr "Annulla"
@@ -1963,6 +2037,10 @@ msgstr "Chiudi"
msgid "labels.collapse"
msgstr "Comprimi"
#: src/app/main/ui/workspace/colorpicker.cljs:427
msgid "labels.color"
msgstr "Colore"
#: src/app/main/ui/comments.cljs:913
msgid "labels.comment"
msgstr "Commenta"
@@ -1979,6 +2057,10 @@ msgstr "Commenti"
msgid "labels.community"
msgstr "Community"
#: src/app/main/ui/dashboard/sidebar.cljs:1030
msgid "labels.community-contributions"
msgstr "Comunità e contributi"
#: src/app/main/ui/settings/password.cljs:91
msgid "labels.confirm-password"
msgstr "Conferma la password"
@@ -2117,6 +2199,10 @@ msgstr "Feedback inviato"
msgid "labels.figma"
msgstr "Figma"
#: src/app/main/ui/inspect/styles/style_box.cljs:23
msgid "labels.fill"
msgstr "Riempimento"
#: src/app/main/ui/dashboard/fonts.cljs:430
msgid "labels.font-family"
msgstr "Famiglia di caratteri"
@@ -2163,6 +2249,10 @@ msgstr "Graphic design"
msgid "labels.help-center"
msgstr "Supporto"
#: src/app/main/ui/dashboard/sidebar.cljs:1019
msgid "labels.help-learning"
msgstr "Aiuto e apprendimento"
#: src/app/main/ui/dashboard/templates.cljs:91
msgid "labels.hide"
msgstr "Nascondi"
@@ -2205,6 +2295,14 @@ msgstr "Inviti"
msgid "labels.language"
msgstr "Lingua"
#: src/app/main/ui/inspect/styles/style_box.cljs:28
msgid "labels.layout"
msgstr "Layout"
#: src/app/main/ui/dashboard/sidebar.cljs:798
msgid "labels.learning-center"
msgstr "Centro di apprendimento"
#: src/app/main/ui/workspace/main_menu.cljs:168
msgid "labels.libraries-and-templates"
msgstr "Librerie e modelli"
@@ -2341,6 +2439,14 @@ msgstr "Password"
msgid "labels.pending-invitation"
msgstr "In attesa"
#: src/app/main/ui/dashboard/sidebar.cljs:878
msgid "labels.penpot-changelog"
msgstr "Registro delle modifiche di Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:804
msgid "labels.penpot-hub"
msgstr "Hub di Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:751
msgid "labels.pinned-projects"
msgstr "Progetti in evidenza"
@@ -2369,6 +2475,10 @@ msgstr "Profilo"
msgid "labels.projects"
msgstr "Progetti"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:644
msgid "labels.reference"
msgstr "Riferimento"
#: src/app/main/data/common.cljs:83
msgid "labels.refresh"
msgstr "Ricarica"
@@ -2419,6 +2529,10 @@ msgstr "nuova risposta"
msgid "labels.reply.thread"
msgstr "Rispondi"
#: src/app/main/ui/dashboard/team.cljs:788
msgid "labels.resend"
msgstr "Reinvia"
#: src/app/main/ui/dashboard/team.cljs:938
msgid "labels.resend-invitation"
msgstr "Invia di nuovo l'invito"
@@ -2475,6 +2589,10 @@ msgstr "Set"
msgid "labels.settings"
msgstr "Configurazione"
#: src/app/main/ui/inspect/styles/style_box.cljs:27
msgid "labels.shadow"
msgstr "Ombra"
#: src/app/main/ui/viewer/header.cljs:204
msgid "labels.share"
msgstr "Condividi"
@@ -2523,10 +2641,22 @@ msgstr "Inizia"
msgid "labels.status"
msgstr "Stato"
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
msgid "labels.stroke"
msgstr "Traccia"
#: src/app/main/ui/onboarding/questions.cljs:87
msgid "labels.student-teacher"
msgstr "Studente o docente"
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:107
msgid "labels.styles"
msgstr "Stili"
#: src/app/main/ui/inspect/styles/style_box.cljs:33
msgid "labels.svg"
msgstr "SVG"
#: src/app/main/ui/onboarding/questions.cljs:256
#, unused
msgid "labels.team-leader"
@@ -2537,6 +2667,10 @@ msgstr "Capo del team"
msgid "labels.team-member"
msgstr "Membro del team"
#: src/app/main/ui/inspect/styles/style_box.cljs:25
msgid "labels.text"
msgstr "Testo"
#: src/app/main/ui/workspace/tokens/themes.cljs:36
msgid "labels.themes"
msgstr "Temi"
@@ -2545,6 +2679,10 @@ msgstr "Temi"
msgid "labels.tutorials"
msgstr "Tutorial"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1148
msgid "labels.typography"
msgstr "Tipografia"
#: src/app/main/data/workspace/tokens/errors.cljs:101
msgid "labels.unknown-error"
msgstr "Errore sconosciuto"
@@ -2577,6 +2715,14 @@ msgstr "Carica caratteri personalizzati"
msgid "labels.uploading"
msgstr "Caricamento…"
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:949, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:518
msgid "labels.variant"
msgstr "Variante"
#: src/app/main/ui/dashboard/sidebar.cljs:872
msgid "labels.version-notes"
msgstr "Note della versione %s"
#: src/app/main/ui/workspace/sidebar/sitemap.cljs:246
msgid "labels.view-only"
msgstr "Solo visualizzazione"
@@ -2585,6 +2731,10 @@ msgstr "Solo visualizzazione"
msgid "labels.viewer"
msgstr "Visualizzatore"
#: src/app/main/ui/inspect/styles/style_box.cljs:32
msgid "labels.visibility"
msgstr "Visibilità"
#: src/app/main/ui/dashboard/sidebar.cljs:441, src/app/main/ui/dashboard/team.cljs:103, src/app/main/ui/dashboard/team.cljs:113, src/app/main/ui/dashboard/team.cljs:1134
msgid "labels.webhooks"
msgstr "Webhook"
@@ -3314,6 +3464,10 @@ msgstr ""
msgid "notifications.by-code.upgrade-version"
msgstr "Una nuova versione è disponibile, si prega di ricaricare la pagina"
#: src/app/main/ui/dashboard/team.cljs:825
msgid "notifications.invitation-deleted"
msgstr "Invito eliminato con successo"
#: src/app/main/ui/dashboard/team.cljs:170, src/app/main/ui/dashboard/team.cljs:867
msgid "notifications.invitation-email-sent"
msgstr "Invito inviato con successo"
@@ -3881,6 +4035,10 @@ msgstr "Copia link negli appunti"
msgid "shortcuts.copy-props"
msgstr "Copia proprietà"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
msgid "shortcuts.create-component-variant"
msgstr "Crea componente / variante"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:98
msgid "shortcuts.create-new-project"
msgstr "Crea nuovo"
@@ -4992,6 +5150,9 @@ msgstr "Carattere"
msgid "workspace.assets.typography.font-size"
msgstr "Dimensione"
msgid "workspace.assets.typography.font-style"
msgstr "Stile del carattere"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Vai alla libreria dello stile del file per modificare"
@@ -5020,6 +5181,20 @@ msgstr "Trasforma testo"
msgid "workspace.assets.ungroup"
msgstr "Separa"
#: src/app/main/ui/workspace/colorpicker.cljs:431, src/app/main/ui/workspace/colorpicker.cljs:443
msgid "workspace.colorpicker.color-tokens"
msgstr "Token colore"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:464
msgid "workspace.component.swap.loop-error"
msgstr "I componenti non possono essere annidati dentro sé stessi."
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:463
msgid "workspace.component.switch.loop-error-multi"
msgstr ""
"Alcune copie non possono essere sostituite. I componenti non possono essere "
"annidati dentro sé stessi."
#: src/app/main/ui/workspace/context_menu.cljs:794
msgid "workspace.context-menu.grid-cells.area"
msgstr "Crea area"
@@ -5387,6 +5562,10 @@ msgstr "RGBA"
msgid "workspace.libraries.colors.save-color"
msgstr "Salva stile di colore"
#: src/app/main/ui/workspace/libraries.cljs:349
msgid "workspace.libraries.connected-to"
msgstr "Connesso a"
#: src/app/main/ui/workspace/libraries.cljs:404
msgid "workspace.libraries.empty.add-some"
msgstr "O aggiungi alcuni di questi per provare:"
@@ -6356,7 +6535,7 @@ msgstr "In alto"
msgid "workspace.options.more-colors"
msgstr "Più colori"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Più librerie colori"
@@ -7305,6 +7484,12 @@ msgstr "Scegli cartella"
msgid "workspace.tokens.color"
msgstr "Colore"
#: src/app/main/data/workspace/tokens/errors.cljs:97
msgid "workspace.tokens.composite-line-height-needs-font-size"
msgstr ""
"L'interlinea dipende dalla dimensione del carattere. Aggiungi una "
"dimensione carattere per ottenere il valore risolto."
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:53
msgid "workspace.tokens.create-new-theme"
msgstr "Crea ora il tuo prima tema."
@@ -7345,6 +7530,10 @@ msgstr "Modifica tema"
msgid "workspace.tokens.edit-themes"
msgstr "Modifica temi"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:551
msgid "workspace.tokens.edit-token"
msgstr "Modifica token %s"
#: src/app/main/data/workspace/tokens/errors.cljs:41
msgid "workspace.tokens.empty-input"
msgstr "Il valore del token non può essere vuoto"
@@ -7466,6 +7655,10 @@ msgstr ""
"Questo set non è attivo. Cambia tema o attiva questo set per vedere "
"modifiche nell'anteprima"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:711
msgid "workspace.tokens.individual-tokens"
msgstr "Utilizza token individuali"
#: src/app/main/data/workspace/tokens/errors.cljs:49
msgid "workspace.tokens.invalid-color"
msgstr "Valore colore invalido: %s"
@@ -7504,6 +7697,10 @@ msgstr ""
"Valore del token non valido: sono accettati solo none, underline e "
"strike-through"
#: src/app/main/data/workspace/tokens/errors.cljs:93
msgid "workspace.tokens.invalid-token-value-typography"
msgstr "Valore non valido: deve fare riferimento a un token tipografico composito."
#: src/app/main/data/workspace/tokens/errors.cljs:61, src/app/main/data/workspace/tokens/errors.cljs:73, src/app/main/data/workspace/tokens/errors.cljs:77
msgid "workspace.tokens.invalid-value"
msgstr "Valore token non valido: %s"
@@ -7524,6 +7721,14 @@ msgstr "Tema"
msgid "workspace.tokens.label.theme-placeholder"
msgstr "Aggiungi un tema (es. Chiaro)"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1047
msgid "workspace.tokens.letter-spacing-value-enter-composite"
msgstr "Aggiungi spaziatura tra lettere o {alias"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1043
msgid "workspace.tokens.line-height-value-enter"
msgstr "Inserisci interlinea — moltiplicatore, px, %, o {alias}"
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:220
msgid "workspace.tokens.margins"
msgstr "Margini"
@@ -7611,6 +7816,10 @@ msgstr "Raggio"
msgid "workspace.tokens.ref-not-valid"
msgstr "Il riferimento non è valido o non è presente in nessun set attivo"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:744
msgid "workspace.tokens.reference-composite"
msgstr "Inserisci un alias tipografico del token"
#: src/app/main/ui/workspace/tokens/style_dictionary.cljs
#, unused
msgid "workspace.tokens.reference-error"
@@ -7749,6 +7958,10 @@ msgstr ""
msgid "workspace.tokens.unknown-token-type-section"
msgstr "Il tipo '%s' non è supportato (%s)\n"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:715
msgid "workspace.tokens.use-reference"
msgstr "Utilizza un riferimento"
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:131
msgid "workspace.tokens.value-not-valid"
msgstr "Il valore non è valido"
@@ -8125,214 +8338,3 @@ msgstr "Clicca per chiudere il tracciato"
#~ msgid "onboarding.slide.1.desc1"
#~ msgstr "Crea interazioni complete per imitare al meglio il prodotto finale."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "Questo token non esiste o è stato eliminato."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"Nessun token colore disponibile. Controlla i set o i temi attivi oppure "
"aggiungi nuovi token."
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "Stai per eliminare gli inviti a:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "Stai per reinviare gli inviti a:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "Elimina inviti"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "Reinvia inviti"
#: src/app/main/ui/dashboard/team.cljs:949
msgid "dashboard.order-invitations-by-role"
msgstr "Ordina per ruolo"
#: src/app/main/ui/dashboard/team.cljs:958
msgid "dashboard.order-invitations-by-status"
msgstr "Ordina per stato"
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
msgstr "Copia negli appunti"
#: src/app/main/ui/inspect/styles/style_box.cljs:22
msgid "inspect.tabs.styles.panel.geometry"
msgstr "Dimensione e posizione"
#: src/app/main/ui/inspect/styles/style_box.cljs:59, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "Attiva/disattiva pannello %s"
#: src/app/main/ui/inspect/styles/style_box.cljs:21
msgid "inspect.tabs.styles.panel.token"
msgstr "Set di token e temi"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
msgid "inspect.tabs.styles.panel.tokens.active-sets"
msgstr "Set attivi"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
msgid "inspect.tabs.styles.panel.tokens.active-themes"
msgstr "Temi attivi"
#: src/app/main/ui/inspect/styles/style_box.cljs:20
msgid "inspect.tabs.styles.panel.variant"
msgstr "Proprietà delle varianti"
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:53
msgid "inspect.tabs.styles.token.resolved-value"
msgstr "Valore risolto:"
#: src/app/main/ui/dashboard/sidebar.cljs:1043
msgid "labels.about-penpot"
msgstr "Informazioni su Penpot"
#: src/app/main/ui/inspect/styles/style_box.cljs:26
msgid "labels.blur"
msgstr "Sfocatura"
#: src/app/main/ui/workspace/colorpicker.cljs:427
msgid "labels.color"
msgstr "Colore"
#: src/app/main/ui/dashboard/sidebar.cljs:1030
msgid "labels.community-contributions"
msgstr "Comunità e contributi"
#: src/app/main/ui/inspect/styles/style_box.cljs:23
msgid "labels.fill"
msgstr "Riempimento"
#: src/app/main/ui/dashboard/sidebar.cljs:1019
msgid "labels.help-learning"
msgstr "Aiuto e apprendimento"
#: src/app/main/ui/inspect/styles/style_box.cljs:28
msgid "labels.layout"
msgstr "Layout"
#: src/app/main/ui/dashboard/sidebar.cljs:798
msgid "labels.learning-center"
msgstr "Centro di apprendimento"
#: src/app/main/ui/dashboard/sidebar.cljs:878
msgid "labels.penpot-changelog"
msgstr "Registro delle modifiche di Penpot"
#: src/app/main/ui/dashboard/sidebar.cljs:804
msgid "labels.penpot-hub"
msgstr "Hub di Penpot"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:644
msgid "labels.reference"
msgstr "Riferimento"
#: src/app/main/ui/dashboard/team.cljs:788
msgid "labels.resend"
msgstr "Reinvia"
#: src/app/main/ui/inspect/styles/style_box.cljs:27
msgid "labels.shadow"
msgstr "Ombra"
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
msgid "labels.stroke"
msgstr "Traccia"
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:107
msgid "labels.styles"
msgstr "Stili"
#: src/app/main/ui/inspect/styles/style_box.cljs:33
msgid "labels.svg"
msgstr "SVG"
#: src/app/main/ui/inspect/styles/style_box.cljs:25
msgid "labels.text"
msgstr "Testo"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1148
msgid "labels.typography"
msgstr "Tipografia"
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:949, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:518
msgid "labels.variant"
msgstr "Variante"
#: src/app/main/ui/dashboard/sidebar.cljs:872
msgid "labels.version-notes"
msgstr "Note della versione %s"
#: src/app/main/ui/inspect/styles/style_box.cljs:32
msgid "labels.visibility"
msgstr "Visibilità"
#: src/app/main/ui/dashboard/team.cljs:825
msgid "notifications.invitation-deleted"
msgstr "Invito eliminato con successo"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
msgid "shortcuts.create-component-variant"
msgstr "Crea componente / variante"
#: src/app/main/ui/workspace/colorpicker.cljs:431, src/app/main/ui/workspace/colorpicker.cljs:443
msgid "workspace.colorpicker.color-tokens"
msgstr "Token colore"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:464
msgid "workspace.component.swap.loop-error"
msgstr "I componenti non possono essere annidati dentro sé stessi."
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:463
msgid "workspace.component.switch.loop-error-multi"
msgstr ""
"Alcune copie non possono essere sostituite. I componenti non possono essere "
"annidati dentro sé stessi."
#: src/app/main/ui/workspace/libraries.cljs:349
msgid "workspace.libraries.connected-to"
msgstr "Connesso a"
#: src/app/main/data/workspace/tokens/errors.cljs:97
msgid "workspace.tokens.composite-line-height-needs-font-size"
msgstr ""
"L'interlinea dipende dalla dimensione del carattere. Aggiungi una dimensione "
"carattere per ottenere il valore risolto."
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:551
msgid "workspace.tokens.edit-token"
msgstr "Modifica token %s"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:711
msgid "workspace.tokens.individual-tokens"
msgstr "Utilizza token individuali"
#: src/app/main/data/workspace/tokens/errors.cljs:93
msgid "workspace.tokens.invalid-token-value-typography"
msgstr ""
"Valore non valido: deve fare riferimento a un token tipografico composito."
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1047
msgid "workspace.tokens.letter-spacing-value-enter-composite"
msgstr "Aggiungi spaziatura tra lettere o {alias"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1043
msgid "workspace.tokens.line-height-value-enter"
msgstr "Inserisci interlinea — moltiplicatore, px, %, o {alias}"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:744
msgid "workspace.tokens.reference-composite"
msgstr "Inserisci un alias tipografico del token"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:715
msgid "workspace.tokens.use-reference"
msgstr "Utilizza un riferimento"

View File

@@ -2,15 +2,14 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Edgars Andersons <Edgars+Weblate@gaitenis.id.lv>\n"
"Language-Team: Latvian <https://hosted.weblate.org/projects/penpot/frontend/"
"lv/>\n"
"Language-Team: Latvian "
"<https://hosted.weblate.org/projects/penpot/frontend/lv/>\n"
"Language: lv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural="
"(n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19) ? 0 : "
"((n % 10 == 1 && n % 100 != 11) ? 1 : 2);\n"
"Plural-Forms: nplurals=3; plural=(n % 10 == 0 || n % 100 >= 11 && n % 100 "
"<= 19) ? 0 : ((n % 10 == 1 && n % 100 != 11) ? 1 : 2);\n"
"X-Generator: Weblate 5.14-dev\n"
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:153, src/app/main/ui/viewer/login.cljs:98
@@ -204,6 +203,16 @@ msgstr "Darba e-pasta adrese"
msgid "branding-illustrations-marketing-pieces"
msgstr "... zīmolrades, ilustrācijām, mārketinga materiāliem utt."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "Šī tekstvienība nepastāv vai ir izdzēsta."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"Nav pieejama neviena krāsu tekstvienība. Jāpārbauda izmantotās "
"kopas/izskati vai jāpievieno jaunas tekstvienības."
#: src/app/main/ui/comments.cljs:530
msgid "comments.mentions.not-found"
msgstr "Netika atrasts neviens cilvēks @%s"
@@ -747,6 +756,22 @@ msgstr "Augšupielādē datus serverī (%s/%s)"
msgid "dashboard.import.progress.upload-media"
msgstr "Augšupielādē datni: %s"
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "Tu grasies izdzēst uzaicinājumus:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "Tu grasies atkārtoti nosūtīt uzaicinājumus:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "Izdzēst uzaicinājumus"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "Atkārtoti nosūtīt uzaicinājumus"
#: src/app/main/ui/dashboard/team.cljs:122, src/app/main/ui/dashboard/team.cljs:744
msgid "dashboard.invite-profile"
msgstr "Uzaicināt personas"
@@ -4895,6 +4920,9 @@ msgstr "Fonti"
msgid "workspace.assets.typography.font-size"
msgstr "Izmērs"
msgid "workspace.assets.typography.font-style"
msgstr "Fonta stils"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Doties uz stilu bibliotēkas datni, lai labotu"
@@ -6243,7 +6271,7 @@ msgstr "Augša"
msgid "workspace.options.more-colors"
msgstr "Vairāk krāsu"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Vairāk bibliotēkas krāsu"
@@ -7864,29 +7892,3 @@ msgstr "Automātiski saglabātas versijas tiks paturētas %s dienas."
#, unused
msgid "workspace.viewport.click-to-close-path"
msgstr "Jānoklikšķina, lai aizvērtu ceļu"
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "Šī tekstvienība nepastāv vai ir izdzēsta."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"Nav pieejama neviena krāsu tekstvienība. Jāpārbauda izmantotās kopas/izskati "
"vai jāpievieno jaunas tekstvienības."
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "Tu grasies izdzēst uzaicinājumus:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "Tu grasies atkārtoti nosūtīt uzaicinājumus:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "Izdzēst uzaicinājumus"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "Atkārtoti nosūtīt uzaicinājumus"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/penpot/"
"frontend/nb_NO/>\n"
"Language-Team: Norwegian Bokmål "
"<https://hosted.weblate.org/projects/penpot/frontend/nb_NO/>\n"
"Language: nb_NO\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -597,6 +597,9 @@ msgstr "Skrift"
msgid "workspace.assets.typography.font-size"
msgstr "Størrelse"
msgid "workspace.assets.typography.font-style"
msgstr "Skriftstil"
#: src/app/main/ui/workspace/main_menu.cljs:361
msgid "workspace.header.menu.show-rules"
msgstr "Vis regler"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Stephan Paternotte <stephan@paternottes.net>\n"
"Language-Team: Dutch <https://hosted.weblate.org/projects/penpot/frontend/nl/"
">\n"
"Language-Team: Dutch "
"<https://hosted.weblate.org/projects/penpot/frontend/nl/>\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -199,6 +199,16 @@ msgstr "Werk e-mail"
msgid "branding-illustrations-marketing-pieces"
msgstr "…branding, illustraties, marketingstukken, etc."
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "Dit token bestaat niet of is verwijderd."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"Geen beschikbare kleurentokens. Controleer actieve sets/thema's of voeg "
"nieuwe tokens toe."
#: src/app/main/ui/comments.cljs:530
msgid "comments.mentions.not-found"
msgstr "Geen mensen gevonden voor @%s"
@@ -747,6 +757,22 @@ msgstr "Gegevens uploaden naar server (%s/%s)"
msgid "dashboard.import.progress.upload-media"
msgstr "Bestand aan het uploaden: %s"
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "Je gaat de uitnodigingen verwijderen op:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "Je gaat de uitnodigingen opnieuw versturen:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "Uitnodigingen verwijderen"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "Uitnodigingen opnieuw versturen"
#: src/app/main/ui/dashboard/team.cljs:122, src/app/main/ui/dashboard/team.cljs:744
msgid "dashboard.invite-profile"
msgstr "Nodig mensen uit"
@@ -863,6 +889,14 @@ msgstr "Bestand openen in een nieuw tabblad"
msgid "dashboard.options"
msgstr "Opties"
#: src/app/main/ui/dashboard/team.cljs:949
msgid "dashboard.order-invitations-by-role"
msgstr "Sortering op rol"
#: src/app/main/ui/dashboard/team.cljs:958
msgid "dashboard.order-invitations-by-status"
msgstr "Sortering op status"
#: src/app/main/ui/settings/password.cljs:94, src/app/main/ui/settings/password.cljs:107
msgid "dashboard.password-change"
msgstr "Verander wachtwoord"
@@ -1885,6 +1919,38 @@ msgstr "Berekend"
msgid "inspect.tabs.info"
msgstr "Informatie"
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
msgstr "Kopiëren naar klembord"
#: src/app/main/ui/inspect/styles/style_box.cljs:22
msgid "inspect.tabs.styles.panel.geometry"
msgstr "Grootte & positie"
#: src/app/main/ui/inspect/styles/style_box.cljs:59, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "Paneel &s wisselen"
#: src/app/main/ui/inspect/styles/style_box.cljs:21
msgid "inspect.tabs.styles.panel.token"
msgstr "Tokens & thema's"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
msgid "inspect.tabs.styles.panel.tokens.active-sets"
msgstr "Actieve verzamelingen"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
msgid "inspect.tabs.styles.panel.tokens.active-themes"
msgstr "Actieve thema's"
#: src/app/main/ui/inspect/styles/style_box.cljs:20
msgid "inspect.tabs.styles.panel.variant"
msgstr "Variant eigenschappen"
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:53
msgid "inspect.tabs.styles.token.resolved-value"
msgstr "Opgeloste waarde:"
#: src/app/main/ui/inspect/right_sidebar.cljs:165
msgid "inspect.tabs.switcher.label"
msgstr "Laaginfo"
@@ -1897,6 +1963,10 @@ msgstr "Alles als gelezen markeren"
msgid "label.shortcuts"
msgstr "Sneltoetsen"
#: src/app/main/ui/dashboard/sidebar.cljs:1043
msgid "labels.about-penpot"
msgstr "Over Penpot"
#: src/app/main/data/common.cljs:90, src/app/main/ui/dashboard/import.cljs:530
msgid "labels.accept"
msgstr "Accepteren"
@@ -1952,6 +2022,10 @@ msgstr ""
msgid "labels.bad-gateway.main-message"
msgstr "Bad Gateway"
#: src/app/main/ui/inspect/styles/style_box.cljs:26
msgid "labels.blur"
msgstr "Vervagen"
#: src/app/main/data/common.cljs:129, src/app/main/ui/dashboard/change_owner.cljs:64, src/app/main/ui/dashboard/import.cljs:515, src/app/main/ui/dashboard/team.cljs:780, src/app/main/ui/dashboard/team.cljs:1122, src/app/main/ui/delete_shared.cljs:36, src/app/main/ui/exports/assets.cljs:162, src/app/main/ui/exports/files.cljs:191, src/app/main/ui/settings/access_tokens.cljs:175, src/app/main/ui/viewer/share_link.cljs:205, src/app/main/ui/workspace/sidebar/assets/groups.cljs:159, src/app/main/ui/workspace/tokens/export/modal.cljs:44, src/app/main/ui/workspace/tokens/import/modal.cljs:269, src/app/main/ui/workspace/tokens/management/create/form.cljs:632, src/app/main/ui/workspace/tokens/settings/menu.cljs:104, src/app/main/ui/workspace/tokens/themes/create_modal.cljs:228
msgid "labels.cancel"
msgstr "Annuleren"
@@ -1968,6 +2042,10 @@ msgstr "Sluiten"
msgid "labels.collapse"
msgstr "Samenvouwen"
#: src/app/main/ui/workspace/colorpicker.cljs:427
msgid "labels.color"
msgstr "Kleur"
#: src/app/main/ui/comments.cljs:913
msgid "labels.comment"
msgstr "Commentaar"
@@ -1984,6 +2062,10 @@ msgstr "Commentaar"
msgid "labels.community"
msgstr "Gemeenschap"
#: src/app/main/ui/dashboard/sidebar.cljs:1030
msgid "labels.community-contributions"
msgstr "Gemeenschap & bijdragen"
#: src/app/main/ui/settings/password.cljs:91
msgid "labels.confirm-password"
msgstr "Wachtwoord bevestigen"
@@ -2122,6 +2204,10 @@ msgstr "Feedback verstuurd"
msgid "labels.figma"
msgstr "Figma"
#: src/app/main/ui/inspect/styles/style_box.cljs:23
msgid "labels.fill"
msgstr "Vullen"
#: src/app/main/ui/dashboard/fonts.cljs:430
msgid "labels.font-family"
msgstr "Lettertype-familie"
@@ -2168,6 +2254,10 @@ msgstr "Grafisch ontwerp"
msgid "labels.help-center"
msgstr "Helpcentrum"
#: src/app/main/ui/dashboard/sidebar.cljs:1019
msgid "labels.help-learning"
msgstr "Hulp & studie"
#: src/app/main/ui/dashboard/templates.cljs:91
msgid "labels.hide"
msgstr "Verbergen"
@@ -2210,6 +2300,14 @@ msgstr "Uitnodigingen"
msgid "labels.language"
msgstr "Taal"
#: src/app/main/ui/inspect/styles/style_box.cljs:28
msgid "labels.layout"
msgstr "Opmaak"
#: src/app/main/ui/dashboard/sidebar.cljs:798
msgid "labels.learning-center"
msgstr "Studiecentrum"
#: src/app/main/ui/workspace/main_menu.cljs:168
msgid "labels.libraries-and-templates"
msgstr "Bibliotheken en sjablonen"
@@ -2346,6 +2444,14 @@ msgstr "Wachtwoord"
msgid "labels.pending-invitation"
msgstr "In behandeling"
#: src/app/main/ui/dashboard/sidebar.cljs:878
msgid "labels.penpot-changelog"
msgstr "Penpot wijzigingen"
#: src/app/main/ui/dashboard/sidebar.cljs:804
msgid "labels.penpot-hub"
msgstr "Penpot-hub"
#: src/app/main/ui/dashboard/sidebar.cljs:751
msgid "labels.pinned-projects"
msgstr "Vastgemaakte projecten"
@@ -2374,6 +2480,10 @@ msgstr "Profiel"
msgid "labels.projects"
msgstr "Projecten"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:644
msgid "labels.reference"
msgstr "Referentie"
#: src/app/main/data/common.cljs:83
msgid "labels.refresh"
msgstr "Vernieuwen"
@@ -2424,6 +2534,10 @@ msgstr "nieuwe reactie"
msgid "labels.reply.thread"
msgstr "Reageren"
#: src/app/main/ui/dashboard/team.cljs:788
msgid "labels.resend"
msgstr "Opnieuw versturen"
#: src/app/main/ui/dashboard/team.cljs:938
msgid "labels.resend-invitation"
msgstr "Uitnodiging opnieuw versturen"
@@ -2480,6 +2594,10 @@ msgstr "Verzamelingen"
msgid "labels.settings"
msgstr "Instellingen"
#: src/app/main/ui/inspect/styles/style_box.cljs:27
msgid "labels.shadow"
msgstr "Schaduw"
#: src/app/main/ui/viewer/header.cljs:204
msgid "labels.share"
msgstr "Delen"
@@ -2528,10 +2646,22 @@ msgstr "Starten"
msgid "labels.status"
msgstr "Status"
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
msgid "labels.stroke"
msgstr "Streek"
#: src/app/main/ui/onboarding/questions.cljs:87
msgid "labels.student-teacher"
msgstr "Student of docent"
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:107
msgid "labels.styles"
msgstr "Stijlen"
#: src/app/main/ui/inspect/styles/style_box.cljs:33
msgid "labels.svg"
msgstr "SVG"
#: src/app/main/ui/onboarding/questions.cljs:256
#, unused
msgid "labels.team-leader"
@@ -2542,6 +2672,10 @@ msgstr "Teamleider"
msgid "labels.team-member"
msgstr "Teamlid"
#: src/app/main/ui/inspect/styles/style_box.cljs:25
msgid "labels.text"
msgstr "Tekst"
#: src/app/main/ui/workspace/tokens/themes.cljs:36
msgid "labels.themes"
msgstr "Thema's"
@@ -2550,6 +2684,10 @@ msgstr "Thema's"
msgid "labels.tutorials"
msgstr "Introductie"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1148
msgid "labels.typography"
msgstr "Typografie"
#: src/app/main/data/workspace/tokens/errors.cljs:101
msgid "labels.unknown-error"
msgstr "Onbekende fout"
@@ -2582,6 +2720,14 @@ msgstr "Eigen lettertypen uploaden"
msgid "labels.uploading"
msgstr "Uploaden…"
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:949, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:518
msgid "labels.variant"
msgstr "Variant"
#: src/app/main/ui/dashboard/sidebar.cljs:872
msgid "labels.version-notes"
msgstr "Versie %s opmerkingen"
#: src/app/main/ui/workspace/sidebar/sitemap.cljs:246
msgid "labels.view-only"
msgstr "ALLEEN BEKIJKEN"
@@ -2590,6 +2736,10 @@ msgstr "ALLEEN BEKIJKEN"
msgid "labels.viewer"
msgstr "Kijker"
#: src/app/main/ui/inspect/styles/style_box.cljs:32
msgid "labels.visibility"
msgstr "Zichtbaarheid"
#: src/app/main/ui/dashboard/sidebar.cljs:441, src/app/main/ui/dashboard/team.cljs:103, src/app/main/ui/dashboard/team.cljs:113, src/app/main/ui/dashboard/team.cljs:1134
msgid "labels.webhooks"
msgstr "Webhooks"
@@ -3335,6 +3485,10 @@ msgstr ""
msgid "notifications.by-code.upgrade-version"
msgstr "Er is een nieuwe versie beschikbaar, vernieuw de pagina"
#: src/app/main/ui/dashboard/team.cljs:825
msgid "notifications.invitation-deleted"
msgstr "Uitnodiging met succes verwijderd"
#: src/app/main/ui/dashboard/team.cljs:170, src/app/main/ui/dashboard/team.cljs:867
msgid "notifications.invitation-email-sent"
msgstr "Uitnodiging succesvol verstuurd"
@@ -3903,6 +4057,10 @@ msgstr "Link naar klembord kopiëren"
msgid "shortcuts.copy-props"
msgstr "Eigenschappen kopiëren"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
msgid "shortcuts.create-component-variant"
msgstr "Component/variant aanmaken"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:98
msgid "shortcuts.create-new-project"
msgstr "Nieuw project aanmaken"
@@ -4634,6 +4792,7 @@ msgid "subscription.settings.sucess.dialog.title"
msgstr "Je bent %s!"
#: src/app/main/ui/settings/subscription.cljs:413
#, fuzzy
msgid "subscription.settings.support-us-since"
msgstr "Je hebt ons gesteund met dit abonnement sinds: %s"
@@ -5009,6 +5168,9 @@ msgstr "Lettertype"
msgid "workspace.assets.typography.font-size"
msgstr "Grootte"
msgid "workspace.assets.typography.font-style"
msgstr "Lettertype-stijl"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Ga naar het stijl-bibliotheekbestand om te bewerken"
@@ -5037,6 +5199,20 @@ msgstr "Tekst transformeren"
msgid "workspace.assets.ungroup"
msgstr "Groep opheffen"
#: src/app/main/ui/workspace/colorpicker.cljs:431, src/app/main/ui/workspace/colorpicker.cljs:443
msgid "workspace.colorpicker.color-tokens"
msgstr "Kleurtokens"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:464
msgid "workspace.component.swap.loop-error"
msgstr "Componenten kunnen niet in zichzelf worden genest."
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:463
msgid "workspace.component.switch.loop-error-multi"
msgstr ""
"Sommige exemplaren konden niet worden verwisseld. Componenten kunnen niet "
"in zichzelf worden genest."
#: src/app/main/ui/workspace/context_menu.cljs:794
msgid "workspace.context-menu.grid-cells.area"
msgstr "Gebied aanmaken"
@@ -5404,6 +5580,10 @@ msgstr "RGBA"
msgid "workspace.libraries.colors.save-color"
msgstr "Kleurstijl opslaan"
#: src/app/main/ui/workspace/libraries.cljs:349
msgid "workspace.libraries.connected-to"
msgstr "Verbonden met"
#: src/app/main/ui/workspace/libraries.cljs:404
msgid "workspace.libraries.empty.add-some"
msgstr "Of voeg er enkele toe om te proberen:"
@@ -6369,7 +6549,7 @@ msgstr "Bovenkant"
msgid "workspace.options.more-colors"
msgstr "Meer kleuren"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Meer bibliotheekkleuren"
@@ -7314,6 +7494,12 @@ msgstr "Map kiezen"
msgid "workspace.tokens.color"
msgstr "Kleur"
#: src/app/main/data/workspace/tokens/errors.cljs:97
msgid "workspace.tokens.composite-line-height-needs-font-size"
msgstr ""
"Regelafstand is afhankelijk van de lettergrootte. Voeg een lettergrootte "
"toe om de opgeloste waarde te verkrijgen."
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:53
msgid "workspace.tokens.create-new-theme"
msgstr "Maak nu je eerste thema aan."
@@ -7354,6 +7540,10 @@ msgstr "Thema bewerken"
msgid "workspace.tokens.edit-themes"
msgstr "Thema's bewerken"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:551
msgid "workspace.tokens.edit-token"
msgstr "%s token bewerken"
#: src/app/main/data/workspace/tokens/errors.cljs:41
msgid "workspace.tokens.empty-input"
msgstr "De tokenwaarde mag niet leeg zijn"
@@ -7396,6 +7586,10 @@ msgstr ""
"Fout bij instellen van lettertype gewicht/stijl. Deze lettertypestijl "
"bestaat niet in het huidige lettertype"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1024, src/app/main/ui/workspace/tokens/management/create/form.cljs:1039
msgid "workspace.tokens.font-weight-value-enter"
msgstr "Voer een waarde in (300, vet, normaal cursief...) of een {alias}"
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:228
msgid "workspace.tokens.gaps"
msgstr "Tussenruimtes"
@@ -7471,6 +7665,10 @@ msgstr ""
"Deze verzameling is niet ingeschakeld. Verander het thema of activeer deze "
"verzameling om wijzigingen in de viewport te zien"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:711
msgid "workspace.tokens.individual-tokens"
msgstr "Individuele tokens gebruiken"
#: src/app/main/data/workspace/tokens/errors.cljs:49
msgid "workspace.tokens.invalid-color"
msgstr "Ongeldige kleurwaarde: %s"
@@ -7509,6 +7707,10 @@ msgstr ""
"Ongeldige tokenwaarde: alleen none, underline en strike-through zijn "
"toegestaan"
#: src/app/main/data/workspace/tokens/errors.cljs:93
msgid "workspace.tokens.invalid-token-value-typography"
msgstr "Ongeldige waarde: moet verwijzen naar een samengesteld typografietoken."
#: src/app/main/data/workspace/tokens/errors.cljs:61, src/app/main/data/workspace/tokens/errors.cljs:73, src/app/main/data/workspace/tokens/errors.cljs:77
msgid "workspace.tokens.invalid-value"
msgstr "Ongeldige tokenwaarde: %s"
@@ -7529,6 +7731,14 @@ msgstr "Thema"
msgid "workspace.tokens.label.theme-placeholder"
msgstr "Een thema toevoegen (bijv. Licht)"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1047
msgid "workspace.tokens.letter-spacing-value-enter-composite"
msgstr "Letterafstand of {alias} toevoegen"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1043
msgid "workspace.tokens.line-height-value-enter"
msgstr "Voer de regelafstand in — vermenigvuldigingsfactor, px, % of {alias}"
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:220
msgid "workspace.tokens.margins"
msgstr "Marges"
@@ -7598,6 +7808,7 @@ msgid "workspace.tokens.opacity-range"
msgstr "De dekking moet tussen 0 en 100% of 0 en 1 zijn (bijv. 50% of 0,5)."
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:120
#, fuzzy
msgid "workspace.tokens.original-value"
msgstr "Oorspronkelijke waarde: %s"
@@ -7613,12 +7824,17 @@ msgstr "Radius"
msgid "workspace.tokens.ref-not-valid"
msgstr "Referentie is niet geldig of zit niet in een actieve verzameling"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:744
msgid "workspace.tokens.reference-composite"
msgstr "Voer een alias voor tokentypografie in"
#: src/app/main/ui/workspace/tokens/style_dictionary.cljs
#, unused
msgid "workspace.tokens.reference-error"
msgstr "Referentie fouten: "
#: src/app/main/data/workspace/tokens/warnings.cljs:15, src/app/main/data/workspace/tokens/warnings.cljs:19, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:56, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:84, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:100, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:41, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:46, src/app/main/ui/workspace/tokens/management/token_pill.cljs:121
#, fuzzy
msgid "workspace.tokens.resolved-value"
msgstr "Opgeloste waarde: %s"
@@ -7694,6 +7910,7 @@ msgid "workspace.tokens.themes-list"
msgstr "Lijst met thema's"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:608, src/app/main/ui/workspace/tokens/management/create/form.cljs:609
#, fuzzy
msgid "workspace.tokens.token-description"
msgstr "Beschrijving"
@@ -7749,6 +7966,10 @@ msgstr "Importeren was succesvol. Sommige tokens zijn niet inbegrepen."
msgid "workspace.tokens.unknown-token-type-section"
msgstr "Typ '%s' wordt niet ondersteund (%s)\n"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:715
msgid "workspace.tokens.use-reference"
msgstr "Referentie gebruiken"
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:131
msgid "workspace.tokens.value-not-valid"
msgstr "De waarde is niet geldig"
@@ -8096,217 +8317,3 @@ msgstr "Automatisch opgeslagen versies worden %s dagen bewaard."
#, unused
msgid "workspace.viewport.click-to-close-path"
msgstr "Klik om het pad te sluiten"
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
msgid "color-row.token-color-row.deleted-token"
msgstr "Dit token bestaat niet of is verwijderd."
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
msgid "color-token.empty-state"
msgstr ""
"Geen beschikbare kleurentokens. Controleer actieve sets/thema's of voeg "
"nieuwe tokens toe."
#: src/app/main/ui/dashboard/team.cljs:765
msgid "dashboard.invitation-modal.delete"
msgstr "Je gaat de uitnodigingen verwijderen op:"
#: src/app/main/ui/dashboard/team.cljs:766
msgid "dashboard.invitation-modal.resend"
msgstr "Je gaat de uitnodigingen opnieuw versturen:"
#: src/app/main/ui/dashboard/team.cljs:756
msgid "dashboard.invitation-modal.title.delete-invitations"
msgstr "Uitnodigingen verwijderen"
#: src/app/main/ui/dashboard/team.cljs:757
msgid "dashboard.invitation-modal.title.resend-invitations"
msgstr "Uitnodigingen opnieuw versturen"
#: src/app/main/ui/dashboard/team.cljs:949
msgid "dashboard.order-invitations-by-role"
msgstr "Sortering op rol"
#: src/app/main/ui/dashboard/team.cljs:958
msgid "dashboard.order-invitations-by-status"
msgstr "Sortering op status"
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
msgstr "Kopiëren naar klembord"
#: src/app/main/ui/inspect/styles/style_box.cljs:22
msgid "inspect.tabs.styles.panel.geometry"
msgstr "Grootte & positie"
#: src/app/main/ui/inspect/styles/style_box.cljs:59, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "Paneel &s wisselen"
#: src/app/main/ui/inspect/styles/style_box.cljs:21
msgid "inspect.tabs.styles.panel.token"
msgstr "Tokens & thema's"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
msgid "inspect.tabs.styles.panel.tokens.active-sets"
msgstr "Actieve verzamelingen"
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
msgid "inspect.tabs.styles.panel.tokens.active-themes"
msgstr "Actieve thema's"
#: src/app/main/ui/inspect/styles/style_box.cljs:20
msgid "inspect.tabs.styles.panel.variant"
msgstr "Variant eigenschappen"
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:53
msgid "inspect.tabs.styles.token.resolved-value"
msgstr "Opgeloste waarde:"
#: src/app/main/ui/dashboard/sidebar.cljs:1043
msgid "labels.about-penpot"
msgstr "Over Penpot"
#: src/app/main/ui/inspect/styles/style_box.cljs:26
msgid "labels.blur"
msgstr "Vervagen"
#: src/app/main/ui/workspace/colorpicker.cljs:427
msgid "labels.color"
msgstr "Kleur"
#: src/app/main/ui/dashboard/sidebar.cljs:1030
msgid "labels.community-contributions"
msgstr "Gemeenschap & bijdragen"
#: src/app/main/ui/inspect/styles/style_box.cljs:23
msgid "labels.fill"
msgstr "Vullen"
#: src/app/main/ui/dashboard/sidebar.cljs:1019
msgid "labels.help-learning"
msgstr "Hulp & studie"
#: src/app/main/ui/inspect/styles/style_box.cljs:28
msgid "labels.layout"
msgstr "Opmaak"
#: src/app/main/ui/dashboard/sidebar.cljs:798
msgid "labels.learning-center"
msgstr "Studiecentrum"
#: src/app/main/ui/dashboard/sidebar.cljs:878
msgid "labels.penpot-changelog"
msgstr "Penpot wijzigingen"
#: src/app/main/ui/dashboard/sidebar.cljs:804
msgid "labels.penpot-hub"
msgstr "Penpot-hub"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:644
msgid "labels.reference"
msgstr "Referentie"
#: src/app/main/ui/dashboard/team.cljs:788
msgid "labels.resend"
msgstr "Opnieuw versturen"
#: src/app/main/ui/inspect/styles/style_box.cljs:27
msgid "labels.shadow"
msgstr "Schaduw"
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
msgid "labels.stroke"
msgstr "Streek"
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:107
msgid "labels.styles"
msgstr "Stijlen"
#: src/app/main/ui/inspect/styles/style_box.cljs:33
msgid "labels.svg"
msgstr "SVG"
#: src/app/main/ui/inspect/styles/style_box.cljs:25
msgid "labels.text"
msgstr "Tekst"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1148
msgid "labels.typography"
msgstr "Typografie"
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:949, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:518
msgid "labels.variant"
msgstr "Variant"
#: src/app/main/ui/dashboard/sidebar.cljs:872
msgid "labels.version-notes"
msgstr "Versie %s opmerkingen"
#: src/app/main/ui/inspect/styles/style_box.cljs:32
msgid "labels.visibility"
msgstr "Zichtbaarheid"
#: src/app/main/ui/dashboard/team.cljs:825
msgid "notifications.invitation-deleted"
msgstr "Uitnodiging met succes verwijderd"
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
msgid "shortcuts.create-component-variant"
msgstr "Component/variant aanmaken"
#: src/app/main/ui/workspace/colorpicker.cljs:431, src/app/main/ui/workspace/colorpicker.cljs:443
msgid "workspace.colorpicker.color-tokens"
msgstr "Kleurtokens"
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:464
msgid "workspace.component.swap.loop-error"
msgstr "Componenten kunnen niet in zichzelf worden genest."
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:463
msgid "workspace.component.switch.loop-error-multi"
msgstr ""
"Sommige exemplaren konden niet worden verwisseld. Componenten kunnen niet in "
"zichzelf worden genest."
#: src/app/main/ui/workspace/libraries.cljs:349
msgid "workspace.libraries.connected-to"
msgstr "Verbonden met"
#: src/app/main/data/workspace/tokens/errors.cljs:97
msgid "workspace.tokens.composite-line-height-needs-font-size"
msgstr ""
"Regelafstand is afhankelijk van de lettergrootte. Voeg een lettergrootte toe "
"om de opgeloste waarde te verkrijgen."
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:551
msgid "workspace.tokens.edit-token"
msgstr "%s token bewerken"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1024, src/app/main/ui/workspace/tokens/management/create/form.cljs:1039
msgid "workspace.tokens.font-weight-value-enter"
msgstr "Voer een waarde in (300, vet, normaal cursief...) of een {alias}"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:711
msgid "workspace.tokens.individual-tokens"
msgstr "Individuele tokens gebruiken"
#: src/app/main/data/workspace/tokens/errors.cljs:93
msgid "workspace.tokens.invalid-token-value-typography"
msgstr "Ongeldige waarde: moet verwijzen naar een samengesteld typografietoken."
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1047
msgid "workspace.tokens.letter-spacing-value-enter-composite"
msgstr "Letterafstand of {alias} toevoegen"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1043
msgid "workspace.tokens.line-height-value-enter"
msgstr "Voer de regelafstand in — vermenigvuldigingsfactor, px, % of {alias}"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:744
msgid "workspace.tokens.reference-composite"
msgstr "Voer een alias voor tokentypografie in"
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:715
msgid "workspace.tokens.use-reference"
msgstr "Referentie gebruiken"

View File

@@ -2,14 +2,14 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Radek Sawicki <radek@sqrc.pl>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/penpot/frontend/"
"pl/>\n"
"Language-Team: Polish "
"<https://hosted.weblate.org/projects/penpot/frontend/pl/>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural="
"(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && "
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.14-dev\n"
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:153, src/app/main/ui/viewer/login.cljs:98
@@ -3067,6 +3067,9 @@ msgstr "Czcionka"
msgid "workspace.assets.typography.font-size"
msgstr "Rozmiar"
msgid "workspace.assets.typography.font-style"
msgstr "Styl czcionki"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Przejdź do pliku biblioteki stylów, żeby edytować"
@@ -3998,7 +4001,7 @@ msgstr "Góra"
msgid "workspace.options.more-colors"
msgstr "Więcej kolorów"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Więcej kolorów z biblioteki"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Hugo Figueira <hugo.figueira7@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"penpot/frontend/pt_BR/>\n"
"Language-Team: Portuguese (Brazil) "
"<https://hosted.weblate.org/projects/penpot/frontend/pt_BR/>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -3504,6 +3504,9 @@ msgstr "Fonte"
msgid "workspace.assets.typography.font-size"
msgstr "Tamanho"
msgid "workspace.assets.typography.font-style"
msgstr "Estilo da fonte"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Ir para biblioteca de estilo para editar"
@@ -4428,7 +4431,7 @@ msgstr "Topo"
msgid "workspace.options.more-colors"
msgstr "Mais cores"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Mais cores da biblioteca"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Dário <dariogomes@gmail.com>\n"
"Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/"
"penpot/frontend/pt_PT/>\n"
"Language-Team: Portuguese (Portugal) "
"<https://hosted.weblate.org/projects/penpot/frontend/pt_PT/>\n"
"Language: pt_PT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4326,6 +4326,9 @@ msgstr "Fonte"
msgid "workspace.assets.typography.font-size"
msgstr "Tamanho"
msgid "workspace.assets.typography.font-style"
msgstr "Estilo da Fonte"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Ir para ficheiro da biblioteca de estilos para editar"
@@ -5499,7 +5502,7 @@ msgstr "Topo"
msgid "workspace.options.more-colors"
msgstr "Mais cores"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Mais bibliotecas de cor"

View File

@@ -2,14 +2,14 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: AlexTECPlayz <alextec70@outlook.com>\n"
"Language-Team: Romanian <https://hosted.weblate.org/projects/penpot/frontend/"
"ro/>\n"
"Language-Team: Romanian "
"<https://hosted.weblate.org/projects/penpot/frontend/ro/>\n"
"Language: ro\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : "
"(n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2;\n"
"X-Generator: Weblate 5.14-dev\n"
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:153, src/app/main/ui/viewer/login.cljs:98
@@ -3606,6 +3606,9 @@ msgstr "Font"
msgid "workspace.assets.typography.font-size"
msgstr "Dimensiune"
msgid "workspace.assets.typography.font-style"
msgstr "Stil Font"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Editează fişierul în Colecţia de stiluri"
@@ -4607,7 +4610,7 @@ msgstr "Sus"
msgid "workspace.options.more-colors"
msgstr "Mai multe culori"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Mai multe culori de bibliotecă"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Vint Prox <vintprox@envs.net>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/penpot/frontend/"
"ru/>\n"
"Language-Team: Russian "
"<https://hosted.weblate.org/projects/penpot/frontend/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -3964,6 +3964,9 @@ msgstr "Шрифт"
msgid "workspace.assets.typography.font-size"
msgstr "Размер"
msgid "workspace.assets.typography.font-style"
msgstr "Шрифт"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Перейти к файлу библиотеки стилей для редактирования"
@@ -5097,7 +5100,7 @@ msgstr "Сверху"
msgid "workspace.options.more-colors"
msgstr "Больше цветов"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Больше цветов библиотеки"

View File

@@ -2,15 +2,14 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Црнобог <68vuletic@gmail.com>\n"
"Language-Team: Serbian <https://hosted.weblate.org/projects/penpot/frontend/"
"sr/>\n"
"Language-Team: Serbian "
"<https://hosted.weblate.org/projects/penpot/frontend/sr/>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural="
"(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? "
"1 : 2);\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.14-dev\n"
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:153, src/app/main/ui/viewer/login.cljs:98
@@ -3803,6 +3802,9 @@ msgstr "Фонт"
msgid "workspace.assets.typography.font-size"
msgstr "Величина"
msgid "workspace.assets.typography.font-style"
msgstr "Стил фонта"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Идите на датотеку библиотеке стилова да бисте је уредили"
@@ -4932,7 +4934,7 @@ msgstr "Врх"
msgid "workspace.options.more-colors"
msgstr "Више боја"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Више боја библиотеке"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Henrik Allberg <henrik@thexorb.com>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/penpot/frontend/"
"sv/>\n"
"Language-Team: Swedish "
"<https://hosted.weblate.org/projects/penpot/frontend/sv/>\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4269,6 +4269,9 @@ msgstr "Teckensnitt"
msgid "workspace.assets.typography.font-size"
msgstr "Storlek"
msgid "workspace.assets.typography.font-style"
msgstr "Teckensnitt"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Gå till stilbibliotek fil för att redigera"
@@ -5480,7 +5483,7 @@ msgstr "Topp"
msgid "workspace.options.more-colors"
msgstr "Fler färger"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Fler biblioteksfärger"

View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Denys Kisil <ossenjoyer@proton.me>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/penpot/"
"frontend/ukr_UA/>\n"
"Language-Team: Ukrainian "
"<https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/>\n"
"Language: ukr_UA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4852,6 +4852,9 @@ msgstr "Шрифт"
msgid "workspace.assets.typography.font-size"
msgstr "Розмір"
msgid "workspace.assets.typography.font-style"
msgstr "Стиль шрифта"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "Перейти до файлу бібліотеки стилів для редагування"
@@ -6166,7 +6169,7 @@ msgstr "Згори"
msgid "workspace.options.more-colors"
msgstr "Більше кольорів"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Більше кольорів бібліотеки"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Alejandro Alonso <alejandro.alonso@kaleidos.net>\n"
"Language-Team: Yoruba <https://hosted.weblate.org/projects/penpot/frontend/"
"yo/>\n"
"Language-Team: Yoruba "
"<https://hosted.weblate.org/projects/penpot/frontend/yo/>\n"
"Language: yo\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -3179,6 +3179,9 @@ msgstr "Fonti"
msgid "workspace.assets.typography.font-size"
msgstr "Iwon"
msgid "workspace.assets.typography.font-style"
msgstr "Àrà Fọ́ǹtì"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:530
msgid "workspace.assets.typography.letter-spacing"
msgstr "Aaye leta"
@@ -4112,7 +4115,7 @@ msgstr "Òkè"
msgid "workspace.options.more-colors"
msgstr "Àwọn àwọ̀ púpọ̀ sí i"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "Àwọn yàrá àwọ̀ púpọ̀ sí I"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"Language-Team: Chinese (Simplified Han script) <https://hosted.weblate.org/"
"projects/penpot/frontend/zh_Hans/>\n"
"Language-Team: Chinese (Simplified Han script) "
"<https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4711,6 +4711,9 @@ msgstr "字体"
msgid "workspace.assets.typography.font-size"
msgstr "尺寸"
msgid "workspace.assets.typography.font-style"
msgstr "文字风格"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "前往样式库文件进行编辑"
@@ -6014,7 +6017,7 @@ msgstr "顶部"
msgid "workspace.options.more-colors"
msgstr "更多颜色"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "更多共享库颜色"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
"Last-Translator: william chen <william.fromtw@gmail.com>\n"
"Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/"
"projects/penpot/frontend/zh_Hant/>\n"
"Language-Team: Chinese (Traditional Han script) "
"<https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/>\n"
"Language: zh_Hant\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -4105,6 +4105,9 @@ msgstr "字型"
msgid "workspace.assets.typography.font-size"
msgstr "尺寸"
msgid "workspace.assets.typography.font-style"
msgstr "字體樣式"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:540
msgid "workspace.assets.typography.go-to-edit"
msgstr "前往樣式圖庫檔案進行編輯"
@@ -5319,7 +5322,7 @@ msgstr "上"
msgid "workspace.options.more-colors"
msgstr "更多顏色"
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
msgid "workspace.options.more-lib-colors"
msgstr "更多圖層顏色"

View File

@@ -422,15 +422,6 @@ impl RenderState {
rect,
self.background_color,
);
if self.options.is_debug_visible() {
debug::render_workspace_current_tile(
self,
"".to_string(),
self.current_tile.unwrap(),
rect,
);
}
}
pub fn apply_drawing_to_render_canvas(&mut self, shape: Option<&Shape>) {
@@ -814,6 +805,12 @@ impl RenderState {
// bools::debug_render_bool_paths(self, shape, shapes, modifiers, structure);
}
};
if self.options.is_debug_visible() {
let shape_selrect_bounds = self.get_shape_selrect_bounds(&shape);
debug::render_debug_shape(self, Some(shape_selrect_bounds), None);
}
if apply_to_current_surface {
self.apply_drawing_to_render_canvas(Some(&shape));
}
@@ -871,6 +868,10 @@ impl RenderState {
canvas.draw_image(snapshot, (0, 0), Some(&skia::Paint::default()));
canvas.restore();
if self.options.is_debug_visible() {
debug::render(self);
}
ui::render(self, shapes, modifiers, structure);
debug::render_wasm_label(self);
@@ -913,7 +914,8 @@ impl RenderState {
);
}
debug::render_debug_tiles_for_viewbox(self);
// FIXME - review debug
// debug::render_debug_tiles_for_viewbox(self);
performance::begin_measure!("tile_cache");
self.pending_tiles.update(&self.tile_viewbox);
@@ -1103,6 +1105,33 @@ impl RenderState {
)
}
pub fn get_rect_bounds(&mut self, rect: skia::Rect) -> Rect {
let scale = self.get_scale();
let offset_x = self.viewbox.area.left * scale;
let offset_y = self.viewbox.area.top * scale;
Rect::from_xywh(
(rect.left * scale) - offset_x,
(rect.top * scale) - offset_y,
rect.width() * scale,
rect.height() * scale,
)
}
pub fn get_shape_selrect_bounds(&mut self, shape: &Shape) -> Rect {
let rect = shape.selrect();
self.get_rect_bounds(rect)
}
pub fn get_shape_extrect_bounds(
&mut self,
shape: &Shape,
tree: &ShapesPool,
modifiers: &HashMap<Uuid, Matrix>,
) -> Rect {
let rect = shape.extrect(tree, modifiers);
self.get_rect_bounds(rect)
}
pub fn get_aligned_tile_bounds(&mut self, tile: tiles::Tile) -> Rect {
let scale = self.get_scale();
let start_tile_x =
@@ -1253,11 +1282,7 @@ impl RenderState {
}
if !node_render_state.is_root() {
let mut transformed_element: Cow<Shape> = Cow::Borrowed(element);
if let Some(modifier) = modifiers.get(&node_id) {
transformed_element.to_mut().apply_transform(modifier);
}
let transformed_element: Cow<Shape> = Cow::Borrowed(element);
let is_visible = transformed_element
.extrect(tree, modifiers)
@@ -1270,13 +1295,9 @@ impl RenderState {
);
if self.options.is_debug_visible() {
debug::render_debug_shape(
self,
&transformed_element,
is_visible,
tree,
modifiers,
);
let shape_extrect_bounds =
self.get_shape_extrect_bounds(&transformed_element, tree, modifiers);
debug::render_debug_shape(self, None, Some(shape_extrect_bounds));
}
if !is_visible {
@@ -1549,6 +1570,15 @@ impl RenderState {
let tile_rect = self.get_current_tile_bounds();
if !is_empty {
self.apply_render_to_final_canvas(tile_rect);
if self.options.is_debug_visible() {
debug::render_workspace_current_tile(
self,
"".to_string(),
current_tile,
tile_rect,
);
}
} else {
self.surfaces.apply_mut(SurfaceId::Target as u32, |s| {
let mut paint = skia::Paint::default();

View File

@@ -1,13 +1,5 @@
use crate::shapes::Shape;
use crate::state::ShapesPool;
use crate::uuid::Uuid;
use crate::math::Matrix;
use skia_safe::{self as skia, Rect};
use std::collections::HashMap;
use super::{tiles, RenderState, SurfaceId};
use skia_safe::{self as skia, Rect};
#[cfg(target_arch = "wasm32")]
use crate::run_script;
@@ -23,10 +15,11 @@ fn get_debug_rect(rect: Rect) -> Rect {
)
}
#[allow(dead_code)]
fn render_debug_view(render_state: &mut RenderState) {
let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke);
paint.set_color(skia::Color::from_rgb(255, 0, 255));
paint.set_color(skia::Color::GREEN);
paint.set_stroke_width(1.);
let rect = get_debug_rect(render_state.viewbox.area);
@@ -36,6 +29,7 @@ fn render_debug_view(render_state: &mut RenderState) {
.draw_rect(rect, &paint);
}
#[allow(dead_code)]
pub fn render_debug_cache_surface(render_state: &mut RenderState) {
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
canvas.save();
@@ -50,7 +44,7 @@ pub fn render_wasm_label(render_state: &mut RenderState) {
let canvas = render_state.surfaces.canvas(SurfaceId::Target);
let skia::ISize { width, height } = canvas.base_layer_size();
let mut paint = skia::Paint::default();
paint.set_color(skia::Color::from_argb(100, 0, 0, 0));
paint.set_color(skia::Color::GRAY);
let str = if render_state.options.is_debug_visible() {
"WASM RENDERER (DEBUG)"
@@ -64,36 +58,12 @@ pub fn render_wasm_label(render_state: &mut RenderState) {
canvas.draw_str(str, p, debug_font, &paint);
}
pub fn render_debug_shape(
render_state: &mut RenderState,
element: &Shape,
intersected: bool,
shapes_pool: &ShapesPool,
modifiers: &HashMap<Uuid, Matrix>,
) {
let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke);
paint.set_color(if intersected {
skia::Color::from_rgb(255, 255, 0)
} else {
skia::Color::from_rgb(0, 255, 255)
});
paint.set_stroke_width(1.);
let rect = get_debug_rect(element.extrect(shapes_pool, modifiers));
render_state
.surfaces
.canvas(SurfaceId::Debug)
.draw_rect(rect, &paint);
}
#[allow(dead_code)]
pub fn render_debug_tiles_for_viewbox(render_state: &mut RenderState) {
let tiles::TileRect(sx, sy, ex, ey) = render_state.tile_viewbox.interest_rect;
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke);
paint.set_color(skia::Color::from_rgb(255, 0, 127));
paint.set_stroke_width(1.);
paint.set_color(skia::Color::RED);
let str_rect = format!("{} {} {} {}", sx, sy, ex, ey);
let debug_font = render_state.fonts.debug_font();
@@ -101,12 +71,13 @@ pub fn render_debug_tiles_for_viewbox(render_state: &mut RenderState) {
}
// Renders the tiles in the viewbox
#[allow(dead_code)]
pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
let scale = render_state.get_scale();
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke);
paint.set_color(skia::Color::from_rgb(255, 0, 127));
paint.set_color(skia::Color::MAGENTA);
paint.set_stroke_width(1.);
let tile_size = tiles::get_tile_size(scale);
@@ -130,42 +101,7 @@ pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
let p = skia::Point::new(debug_rect.x(), debug_rect.y() - 1.);
let str = format!("{}:{}", x, y);
let debug_font = render_state.fonts.debug_font();
canvas.draw_str(str, p, debug_font, &paint);
canvas.draw_rect(debug_rect, &paint);
}
}
}
pub fn render_debug_tiles(render_state: &mut RenderState) {
let scale = render_state.get_scale();
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke);
paint.set_color(skia::Color::from_rgb(127, 0, 255));
paint.set_stroke_width(1.);
let tile_size = tiles::get_tile_size(scale);
let tiles::TileRect(sx, sy, ex, ey) =
tiles::get_tiles_for_rect(render_state.viewbox.area, tile_size);
for y in sy..=ey {
for x in sx..=ex {
let tile = tiles::Tile(x, y);
let shape_count = render_state.tiles.get_shapes_at(tile).iter().len();
if shape_count == 0 {
continue;
}
let rect = Rect::from_xywh(
x as f32 * tile_size,
y as f32 * tile_size,
tile_size,
tile_size,
);
let debug_rect = get_debug_rect(rect);
let p = skia::Point::new(debug_rect.x(), debug_rect.y() - 1.);
let str = format!("{}:{} {}", x, y, shape_count);
let debug_font = render_state.fonts.debug_font();
paint.set_style(skia::PaintStyle::Fill);
canvas.draw_str(str, p, debug_font, &paint);
canvas.draw_rect(debug_rect, &paint);
}
@@ -173,10 +109,15 @@ pub fn render_debug_tiles(render_state: &mut RenderState) {
}
pub fn render(render_state: &mut RenderState) {
render_debug_view(render_state);
render_debug_viewbox_tiles(render_state);
render_debug_tiles(render_state);
render_debug_cache_surface(render_state);
// DEBUG VIEWBOX - green rect - buggy?
// render_debug_view(render_state);
// DEBUG VIEWBOX TILES - magenta - buggy?
// render_debug_viewbox_tiles(render_state);
// DEBUG CACHE SURFACE - noisy - ?
// render_debug_cache_surface(render_state);
render_state.surfaces.draw_into(
SurfaceId::Debug,
SurfaceId::Target,
@@ -184,6 +125,48 @@ pub fn render(render_state: &mut RenderState) {
);
}
pub fn render_workspace_current_tile(
render_state: &mut RenderState,
prefix: String,
tile: tiles::Tile,
rect: skia::Rect,
) {
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
let mut p = skia::Paint::default();
p.set_stroke_width(2.);
p.set_style(skia::PaintStyle::Stroke);
canvas.draw_rect(rect, &p);
let tile_position_origin = skia::Point::new(rect.x() + 10., rect.y() + 20.);
p.set_style(skia::PaintStyle::Fill);
let str = format!("{prefix} {}:{}", tile.0, tile.1);
let mut debug_font = render_state.fonts.debug_font().clone();
debug_font.set_size(16.);
canvas.draw_str(str, tile_position_origin, &debug_font, &p);
}
pub fn render_debug_shape(
render_state: &mut RenderState,
shape_selrect: Option<skia::Rect>,
shape_extrect: Option<skia::Rect>,
) {
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke);
paint.set_color(skia::Color::RED);
paint.set_stroke_width(1.);
if let Some(rect) = shape_selrect {
canvas.draw_rect(rect, &paint);
}
if let Some(rect) = shape_extrect {
paint.set_color(skia::Color::BLUE);
canvas.draw_rect(rect, &paint);
}
}
#[cfg(target_arch = "wasm32")]
#[allow(dead_code)]
pub fn console_debug_surface(render_state: &mut RenderState, id: SurfaceId) {
@@ -208,22 +191,3 @@ pub fn console_debug_surface_rect(render_state: &mut RenderState, id: SurfaceId,
run_script!(format!("console.log('%c ', 'font-size: 1px; background: url(data:image/png;base64,{base64_image}) no-repeat; padding: 100px; background-size: contain;')"))
}
}
pub fn render_workspace_current_tile(
render_state: &mut RenderState,
prefix: String,
tile: tiles::Tile,
rect: skia::Rect,
) {
let canvas = render_state.surfaces.canvas(SurfaceId::Target);
let mut p = skia::Paint::default();
p.set_stroke_width(1.);
p.set_style(skia::PaintStyle::Stroke);
canvas.draw_rect(rect, &p);
let point = skia::Point::new(rect.x() + 10., rect.y() + 20.);
p.set_stroke_width(1.);
let str = format!("{prefix} {}:{}", tile.0, tile.1);
let debug_font = render_state.fonts.debug_font();
canvas.draw_str(str, point, debug_font, &p);
}

View File

@@ -742,14 +742,15 @@ impl Shape {
shapes_pool: &ShapesPool,
modifiers: &HashMap<Uuid, Matrix>,
) -> math::Rect {
let shape = self.transformed(modifiers.get(&self.id));
let mut max_stroke: f32 = 0.;
let is_open = if let Type::Path(p) = &self.shape_type {
let is_open = if let Type::Path(p) = &shape.shape_type {
p.is_open()
} else {
false
};
for stroke in self.strokes.iter() {
for stroke in shape.strokes.iter() {
let width = match stroke.render_kind(is_open) {
StrokeKind::Inner => 0.,
StrokeKind::Center => stroke.width / 2.,
@@ -758,11 +759,11 @@ impl Shape {
max_stroke = max_stroke.max(width);
}
let mut rect = if let Some(path) = self.get_skia_path() {
let mut rect = if let Some(path) = shape.get_skia_path() {
path.compute_tight_bounds()
.with_outset((max_stroke, max_stroke))
} else {
let mut bounds_rect = self.bounds().to_rect();
let mut bounds_rect = shape.bounds().to_rect();
let mut stroke_rect = bounds_rect;
stroke_rect.left -= max_stroke;
stroke_rect.right += max_stroke;
@@ -773,13 +774,13 @@ impl Shape {
bounds_rect
};
if let Type::Text(text_content) = &self.shape_type {
if let Type::Text(text_content) = &shape.shape_type {
let (width, height) = text_content.visual_bounds();
rect.right = rect.left + width;
rect.bottom = rect.top + height;
}
for shadow in self.shadows.iter() {
for shadow in shape.shadows.iter() {
if !shadow.hidden() {
let (x, y) = shadow.offset;
let mut shadow_rect = rect;
@@ -797,7 +798,7 @@ impl Shape {
}
}
if let Some(blur) = self.blur {
if let Some(blur) = shape.blur {
if !blur.hidden {
rect.left -= blur.value;
rect.top -= blur.value;
@@ -808,14 +809,14 @@ impl Shape {
// For groups and frames without clipping, extend the bounding rectangle to include all nested shapes
// This ensures that these containers properly encompass their content
let include_children = match &self.shape_type {
let include_children = match &shape.shape_type {
Type::Group(_) => true,
Type::Frame(_) => !self.clip_content,
Type::Frame(_) => !shape.clip_content,
_ => false,
};
if include_children {
for child_id in self.children_ids(false) {
for child_id in shape.children_ids(false) {
if let Some(child_shape) = shapes_pool.get(&child_id) {
// Create a copy of the child shape to apply any transformations
let mut transformed_element: Cow<Shape> = Cow::Borrowed(child_shape);
@@ -1116,11 +1117,11 @@ impl Shape {
}
pub fn transformed(&self, transform: Option<&Matrix>) -> Self {
let mut shape = self.clone();
let mut shape: Cow<Shape> = Cow::Borrowed(self);
if let Some(transform) = transform {
shape.apply_transform(transform);
shape.to_mut().apply_transform(transform);
}
shape
shape.into_owned()
}
pub fn is_absolute(&self) -> bool {

View File

@@ -1,6 +1,6 @@
use macros::ToJs;
use super::fonts::RawFontStyle;
use super::{fills::RawFillData, fonts::RawFontStyle};
use crate::math::{Matrix, Point};
use crate::mem;
use crate::shapes::{
@@ -9,10 +9,11 @@ use crate::shapes::{
use crate::utils::{uuid_from_u32, uuid_from_u32_quartet};
use crate::{with_current_shape, with_current_shape_mut, with_state_mut, STATE};
const RAW_LEAF_DATA_SIZE: usize = std::mem::size_of::<RawTextLeafAttrs>();
pub const RAW_LEAF_FILLS_SIZE: usize = 160;
const RAW_LEAF_DATA_SIZE: usize = std::mem::size_of::<RawTextLeaf>();
const RAW_PARAGRAPH_DATA_SIZE: usize = std::mem::size_of::<RawParagraphData>();
const MAX_TEXT_FILLS: usize = 8;
#[derive(Debug, PartialEq, Clone, Copy, ToJs)]
#[repr(u8)]
pub enum RawTextAlign {
@@ -121,10 +122,9 @@ impl TryFrom<&[u8]> for RawParagraphData {
}
}
// FIXME: Merge this struct with RawTextLeaf once we cap the amount of fills a text shape has
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct RawTextLeafAttrs {
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RawTextLeaf {
font_style: RawFontStyle,
text_decoration: RawTextDecoration,
text_transform: RawTextTransform,
@@ -136,55 +136,24 @@ pub struct RawTextLeafAttrs {
font_family: [u8; 4],
font_variant_id: [u32; 4], // TODO: maybe add RawUUID type
text_length: u32,
fill_count: u32, // FIXME: we should cap the amount of fills a text shape has
fill_count: u32,
fills: [RawFillData; MAX_TEXT_FILLS],
}
impl From<[u8; RAW_LEAF_DATA_SIZE]> for RawTextLeafAttrs {
impl From<[u8; RAW_LEAF_DATA_SIZE]> for RawTextLeaf {
fn from(bytes: [u8; RAW_LEAF_DATA_SIZE]) -> Self {
unsafe { std::mem::transmute(bytes) }
}
}
impl TryFrom<&[u8]> for RawTextLeafAttrs {
impl TryFrom<&[u8]> for RawTextLeaf {
type Error = String;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let data: [u8; RAW_LEAF_DATA_SIZE] = bytes
.get(0..RAW_LEAF_DATA_SIZE)
.and_then(|slice| slice.try_into().ok())
.ok_or("Invalid text leaf data".to_string())?;
Ok(RawTextLeafAttrs::from(data))
}
}
#[allow(dead_code)]
#[repr(C)]
#[derive(Debug, Clone)]
pub struct RawTextLeaf {
attrs: RawTextLeafAttrs,
raw_fills: Vec<u8>, // FIXME: remove this once we cap the amount of fills a text shape has
}
impl TryFrom<&[u8]> for RawTextLeaf {
// TODO: use a proper error type
type Error = String;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let raw_attrs: RawTextLeafAttrs = RawTextLeafAttrs::try_from(bytes)?;
let total_fills = raw_attrs.fill_count as usize;
// Use checked_mul to prevent overflow
let fills_size = total_fills
.checked_mul(RAW_LEAF_FILLS_SIZE)
.ok_or("Overflow occurred while calculating fills size")?;
let fills_start = RAW_LEAF_DATA_SIZE;
let fills_end = fills_start + fills_size;
let raw_fills = &bytes[fills_start..fills_end];
Ok(Self {
attrs: raw_attrs,
raw_fills: raw_fills.to_vec(),
})
Ok(RawTextLeaf::from(data))
}
}
@@ -193,23 +162,28 @@ impl From<RawTextLeaf> for shapes::TextLeaf {
let text = String::default();
let font_family = shapes::FontFamily::new(
uuid_from_u32(value.attrs.font_id),
value.attrs.font_weight as u32,
value.attrs.font_style.into(),
uuid_from_u32(value.font_id),
value.font_weight as u32,
value.font_style.into(),
);
let fills =
super::fills::parse_fills_from_bytes(&value.raw_fills, value.attrs.fill_count as usize);
let fills = value
.fills
.into_iter()
.take(value.fill_count as usize)
.map(|fill| fill.into())
.collect();
Self::new(
text,
font_family,
value.attrs.font_size,
value.attrs.letter_spacing,
value.attrs.text_decoration.into(),
value.attrs.text_transform.into(),
value.attrs.text_direction.into(),
value.attrs.font_weight,
uuid_from_u32(value.attrs.font_variant_id),
value.font_size,
value.letter_spacing,
value.text_decoration.into(),
value.text_transform.into(),
value.text_direction.into(),
value.font_weight,
uuid_from_u32(value.font_variant_id),
fills,
)
}
@@ -233,11 +207,8 @@ impl TryFrom<&Vec<u8>> for RawParagraph {
let mut raw_text_leaves: Vec<RawTextLeaf> = Vec::new();
for _ in 0..attrs.leaf_count {
let text_leaf = RawTextLeaf::try_from(&bytes[offset..])?;
let leaf_size =
RAW_LEAF_DATA_SIZE + (text_leaf.attrs.fill_count as usize * RAW_LEAF_FILLS_SIZE);
offset += leaf_size;
let text_leaf = RawTextLeaf::try_from(&bytes[offset..(offset + RAW_LEAF_DATA_SIZE)])?;
offset += RAW_LEAF_DATA_SIZE;
raw_text_leaves.push(text_leaf);
}
@@ -260,7 +231,7 @@ impl From<RawParagraph> for shapes::Paragraph {
let mut offset = 0;
for raw_leaf in value.leaves.into_iter() {
let delta = raw_leaf.attrs.text_length as usize;
let delta = raw_leaf.text_length as usize;
let text_buffer = &value.text_buffer[offset..offset + delta];
let mut leaf = shapes::TextLeaf::from(raw_leaf);