Compare commits
46 Commits
niwinz-plu
...
superalex-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbb5c91acd | ||
|
|
5eba070a2c | ||
|
|
9e51fa198a | ||
|
|
f4e79af3cd | ||
|
|
3e758826fe | ||
|
|
2cf66c948d | ||
|
|
4ee908fc89 | ||
|
|
bdcf448f3f | ||
|
|
c58054d19c | ||
|
|
a7ab506c5c | ||
|
|
c7f644ab2a | ||
|
|
cb5cacbcee | ||
|
|
337cfc2d3e | ||
|
|
c2ee31e791 | ||
|
|
360937f613 | ||
|
|
f6d0414449 | ||
|
|
4d05827fa9 | ||
|
|
48fb9fa6ea | ||
|
|
c74cf3fa37 | ||
|
|
7c1ddd3d7d | ||
|
|
4965f6d859 | ||
|
|
a3cd90da7f | ||
|
|
2b130c7e52 | ||
|
|
c41b9214c5 | ||
|
|
fb80c8f45b | ||
|
|
009dc4485a | ||
|
|
b8f3bee3ac | ||
|
|
b28457860c | ||
|
|
23b268b414 | ||
|
|
32706a1460 | ||
|
|
cd4b9ddd47 | ||
|
|
f0e3f1a319 | ||
|
|
afb252f42e | ||
|
|
4185a7a6f3 | ||
|
|
0dda7bd9ee | ||
|
|
30106f8524 | ||
|
|
7ef16a2b69 | ||
|
|
71ec51919e | ||
|
|
1cb113dfeb | ||
|
|
b45aec13ab | ||
|
|
19592fadd8 | ||
|
|
0b2dfe7297 | ||
|
|
fe6fb0534c | ||
|
|
f2d09a6140 | ||
|
|
5ae2351e5a | ||
|
|
b5f4ce0a71 |
@@ -4,7 +4,7 @@
|
||||
"license": "MPL-2.0",
|
||||
"author": "Kaleidos INC",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.30.1+sha512.3590e550d5384caa39bd5c7c739f72270234b2f6059e13018f975c313b1eb9fefcc09714048765d4d9efe961382c312e624572c0420762bdc5d5940cdf9be73a",
|
||||
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -605,31 +605,31 @@
|
||||
add-undo-change-shape
|
||||
(fn [change-set id]
|
||||
(let [shape (get objects id)]
|
||||
(conj
|
||||
change-set
|
||||
{:type :add-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:parent-id (:parent-id shape)
|
||||
:frame-id (:frame-id shape)
|
||||
:index (cfh/get-position-on-parent objects id)
|
||||
:obj (cond-> shape
|
||||
(contains? shape :shapes)
|
||||
(assoc :shapes []))})))
|
||||
(cond-> change-set
|
||||
(some? shape)
|
||||
(conj {:type :add-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:parent-id (:parent-id shape)
|
||||
:frame-id (:frame-id shape)
|
||||
:index (cfh/get-position-on-parent objects id)
|
||||
:obj (cond-> shape
|
||||
(contains? shape :shapes)
|
||||
(assoc :shapes []))}))))
|
||||
|
||||
add-undo-change-parent
|
||||
(fn [change-set id]
|
||||
(let [shape (get objects id)
|
||||
prev-sibling (cfh/get-prev-sibling objects (:id shape))]
|
||||
(conj
|
||||
change-set
|
||||
{:type :mov-objects
|
||||
:page-id page-id
|
||||
:parent-id (:parent-id shape)
|
||||
:shapes [id]
|
||||
:after-shape prev-sibling
|
||||
:index 0
|
||||
:ignore-touched true})))]
|
||||
(cond-> change-set
|
||||
(some? shape)
|
||||
(conj {:type :mov-objects
|
||||
:page-id page-id
|
||||
:parent-id (:parent-id shape)
|
||||
:shapes [id]
|
||||
:after-shape prev-sibling
|
||||
:index 0
|
||||
:ignore-touched true}))))]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes #(reduce add-redo-change % ids))
|
||||
@@ -1150,3 +1150,24 @@
|
||||
[changes]
|
||||
(::page-id (meta changes)))
|
||||
|
||||
|
||||
(defn set-text-content
|
||||
[changes id content prev-content]
|
||||
(assert-page-id! changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
|
||||
redo-change
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id id
|
||||
:operations [{:type :set :attr :content :val content}]}
|
||||
|
||||
undo-change
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id id
|
||||
:operations [{:type :set :attr :content :val prev-content}]}]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj redo-change)
|
||||
(update :undo-changes conj undo-change))))
|
||||
|
||||
@@ -126,12 +126,6 @@ http {
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
|
||||
location /plugins {
|
||||
autoindex on;
|
||||
alias /home/penpot/penpot/plugins/dist/apps;
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
|
||||
location /mcp/ws {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"license": "MPL-2.0",
|
||||
"author": "Kaleidos INC",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.30.1+sha512.3590e550d5384caa39bd5c7c739f72270234b2f6059e13018f975c313b1eb9fefcc09714048765d4d9efe961382c312e624572c0420762bdc5d5940cdf9be73a",
|
||||
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/penpot/penpot"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"license": "MPL-2.0",
|
||||
"author": "Kaleidos INC",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.30.1+sha512.3590e550d5384caa39bd5c7c739f72270234b2f6059e13018f975c313b1eb9fefcc09714048765d4d9efe961382c312e624572c0420762bdc5d5940cdf9be73a",
|
||||
"packageManager": "pnpm@10.29.2+sha512.bef43fa759d91fd2da4b319a5a0d13ef7a45bb985a3d7342058470f9d2051a3ba8674e629672654686ef9443ad13a82da2beb9eeb3e0221c87b8154fff9d74b8",
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
],
|
||||
@@ -40,15 +40,16 @@
|
||||
"watch:app:libs": "node ./scripts/build-libs.js --watch",
|
||||
"watch:app:main": "clojure -M:dev:shadow-cljs watch main worker storybook",
|
||||
"clear:shadow-cache": "rm -rf .shadow-cljs",
|
||||
"clear:wasm": "cargo clean --manifest-path ../render-wasm/Cargo.toml",
|
||||
"watch": "exit 0",
|
||||
"watch:app": "pnpm run clear:shadow-cache && pnpm run build:wasm && concurrently --kill-others-on-fail \"pnpm run watch:app:assets\" \"pnpm run watch:app:main\" \"pnpm run watch:app:libs\"",
|
||||
"watch:app": "pnpm run clear:shadow-cache && pnpm run clear:wasm && pnpm run build:wasm && concurrently --kill-others-on-fail \"pnpm run watch:app:assets\" \"pnpm run watch:app:main\" \"pnpm run watch:app:libs\"",
|
||||
"watch:storybook": "pnpm run build:storybook:assets && concurrently --kill-others-on-fail \"storybook dev -p 6006 --no-open\" \"node ./scripts/watch-storybook.js\"",
|
||||
"postinstall": "(cd ../plugins/libs/plugins-runtime; pnpm install; pnpm run build)"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@penpot/draft-js": "workspace:./packages/draft-js",
|
||||
"@penpot/mousetrap": "workspace:./packages/mousetrap",
|
||||
"@penpot/plugins-runtime": "link:../plugins/libs/plugins-runtime",
|
||||
"@penpot/plugins-runtime": "link:../plugins/dist/plugins-runtime",
|
||||
"@penpot/svgo": "penpot/svgo#v3.2",
|
||||
"@penpot/text-editor": "workspace:./text-editor",
|
||||
"@penpot/tokenscript": "workspace:./packages/tokenscript",
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
[
|
||||
{
|
||||
"~:features": {
|
||||
"~#set": [
|
||||
"variants/v1",
|
||||
"layout/grid",
|
||||
"styles/v2",
|
||||
"fdata/pointer-map",
|
||||
"fdata/objects-map",
|
||||
"components/v2",
|
||||
"fdata/shape-data-type"
|
||||
]
|
||||
},
|
||||
"~:permissions": {
|
||||
"~:type": "~:membership",
|
||||
"~:is-owner": true,
|
||||
"~:is-admin": true,
|
||||
"~:can-edit": true
|
||||
},
|
||||
"~:name": "Default",
|
||||
"~:modified-at": "~m1713533116375",
|
||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f7920a",
|
||||
"~:created-at": "~m1713533116375",
|
||||
"~:is-default": true
|
||||
}
|
||||
]
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"~:email": "foo@example.com",
|
||||
"~:is-demo": false,
|
||||
"~:auth-backend": "penpot",
|
||||
"~:fullname": "Princesa Leia",
|
||||
"~:modified-at": "~m1713533116365",
|
||||
"~:is-active": true,
|
||||
"~:default-project-id": "~uc7ce0794-0992-8105-8004-38e630f7920b",
|
||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f29a9b",
|
||||
"~:is-muted": false,
|
||||
"~:default-team-id": "~uc7ce0794-0992-8105-8004-38e630f40f6d",
|
||||
"~:created-at": "~m1713533116365",
|
||||
"~:is-blocked": false,
|
||||
"~:props": {
|
||||
"~:nudge": {
|
||||
"~:big": 10,
|
||||
"~:small": 1
|
||||
},
|
||||
"~:v2-info-shown": true,
|
||||
"~:viewed-tutorial?": false,
|
||||
"~:viewed-walkthrough?": false,
|
||||
"~:onboarding-viewed": true,
|
||||
"~:builtin-templates-collapsed-status":
|
||||
true
|
||||
}
|
||||
}
|
||||
1161
frontend/playwright/data/render-wasm/get-solid-shadows.json
Normal file
2826
frontend/playwright/data/render-wasm/get-solid-strokes-shadows.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"~:file-id": "~u52c4e771-3853-8190-8007-9506c70e8100",
|
||||
"~:id": "~u4173a29d-4020-80b4-8007-96527ba9d8af",
|
||||
"~:created-at": "~m1771342236330",
|
||||
"~:modified-at": "~m1771342236330",
|
||||
"~:type": "fragment",
|
||||
"~:backend": "db",
|
||||
"~:data": {
|
||||
"~:id": "~uecb0cfd0-0f0b-81f7-8007-950628f9665b",
|
||||
"~:name": "Page 1",
|
||||
"~:objects": {
|
||||
"~#penpot/objects-map/v2": {
|
||||
"~ude9c6736-45ce-80a1-8007-950643da554d": "[\"~#shape\",[\"^ \",\"~:y\",383.99998939037323,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"R1\",\"~:width\",74,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",831.999992787838,\"~:y\",383.99998939037323]],[\"^<\",[\"^ \",\"~:x\",905.999992787838,\"~:y\",383.99998939037323]],[\"^<\",[\"^ \",\"~:x\",905.999992787838,\"~:y\",429.99998664855957]],[\"^<\",[\"^ \",\"~:x\",831.999992787838,\"~:y\",429.99998664855957]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~uecb0cfd0-0f0b-81f7-8007-950628f9665b\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~ude9c6736-45ce-80a1-8007-950643da554d\",\"~:parent-id\",\"~ude9c6736-45ce-80a1-8007-95063a202e52\",\"~:frame-id\",\"~ude9c6736-45ce-80a1-8007-95063a202e52\",\"~:strokes\",[],\"~:x\",831.999992787838,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",831.999992787838,\"~:y\",383.99998939037323,\"^8\",74,\"~:height\",45.99999725818634,\"~:x1\",831.999992787838,\"~:y1\",383.99998939037323,\"~:x2\",905.999992787838,\"~:y2\",429.99998664855957]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^K\",45.99999725818634,\"~:flip-y\",null]]",
|
||||
"~ude9c6736-45ce-80a1-8007-95065b4599ea": "[\"~#shape\",[\"^ \",\"~:y\",439.999969256975,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"R2\",\"~:width\",300.00007388362076,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",832.0000015918991,\"~:y\",439.99996925697496]],[\"^<\",[\"^ \",\"~:x\",1132.00007547552,\"~:y\",439.99996925697496]],[\"^<\",[\"^ \",\"~:x\",1132.00007547552,\"~:y\",589.9999658711585]],[\"^<\",[\"^ \",\"~:x\",832.0000015918991,\"~:y\",589.9999658711585]]],\"~:r2\",0,\"~:layout-item-h-sizing\",\"~:fix\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~uecb0cfd0-0f0b-81f7-8007-950628f9665b\",\"~:layout-item-v-sizing\",\"^?\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~ude9c6736-45ce-80a1-8007-95065b4599ea\",\"~:parent-id\",\"~ude9c6736-45ce-80a1-8007-95063a202e52\",\"~:frame-id\",\"~ude9c6736-45ce-80a1-8007-95063a202e52\",\"~:strokes\",[],\"~:x\",832.0000015918993,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",832.0000015918993,\"~:y\",439.999969256975,\"^8\",300.00007388362076,\"~:height\",149.9999966141835,\"~:x1\",832.0000015918993,\"~:y1\",439.999969256975,\"~:x2\",1132.0000754755201,\"~:y2\",589.9999658711586]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^N\",149.9999966141835,\"~:flip-y\",null]]",
|
||||
"~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]],\"~:page-id\",\"~uecb0cfd0-0f0b-81f7-8007-950628f9665b\",\"~: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,\"^I\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~ude9c6736-45ce-80a1-8007-95062aa41d6b\"]]]",
|
||||
"~ude9c6736-45ce-80a1-8007-95062aa41d6b": "[\"~#shape\",[\"^ \",\"~:y\",342.0000208153068,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",false,\"~:name\",\"A\",\"~:layout-align-items\",\"~:start\",\"~:width\",392.9999889135361,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",787.9999763965607,\"~:y\",342.0000208153068]],[\"^L\",[\"^ \",\"~:x\",1180.9999653100967,\"~:y\",342.0000208153068]],[\"^L\",[\"^ \",\"~:x\",1180.9999653100967,\"~:y\",704.000018450968]],[\"^L\",[\"^ \",\"~:x\",787.9999763965607,\"~:y\",704.000018450968]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~uecb0cfd0-0f0b-81f7-8007-950628f9665b\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:r3\",0,\"~:layout-justify-content\",\"^E\",\"~:r1\",0,\"~:id\",\"~ude9c6736-45ce-80a1-8007-95062aa41d6b\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",787.9999763965607,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",787.9999763965607,\"~:y\",342.0000208153068,\"^F\",392.9999889135361,\"~:height\",361.9999976356612,\"~:x1\",787.9999763965607,\"~:y1\",342.0000208153068,\"~:x2\",1180.9999653100967,\"~:y2\",704.000018450968]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^19\",361.9999976356612,\"~:flip-y\",null,\"~:shapes\",[\"~ude9c6736-45ce-80a1-8007-95062fafbb88\"]]]",
|
||||
"~ude9c6736-45ce-80a1-8007-95063a202e52": "[\"~#shape\",[\"^ \",\"~:y\",374.00001145409465,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",10,\"~:p2\",10,\"~:p3\",10,\"~:p4\",10],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"C\",\"~:layout-align-items\",\"~:start\",\"~:width\",320.00009969013945,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",821.9999915631233,\"~:y\",374.0000114540946]],[\"^L\",[\"^ \",\"~:x\",1142.0000912532628,\"~:y\",374.0000114540946]],[\"^L\",[\"^ \",\"~:x\",1142.0000912532628,\"~:y\",600.0000518384436]],[\"^L\",[\"^ \",\"~:x\",821.9999915631233,\"~:y\",600.0000518384436]]],\"~:r2\",0,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",10,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~uecb0cfd0-0f0b-81f7-8007-950628f9665b\",\"~:layout-item-v-sizing\",\"^O\",\"~:r3\",0,\"~:layout-justify-content\",\"^E\",\"~:r1\",0,\"~:id\",\"~ude9c6736-45ce-80a1-8007-95063a202e52\",\"~:parent-id\",\"~ude9c6736-45ce-80a1-8007-95062fafbb88\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~ude9c6736-45ce-80a1-8007-95062fafbb88\",\"~:strokes\",[[\"^ \",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-style\",\"~:solid\",\"~:stroke-color\",\"#000000\",\"~:stroke-opacity\",1,\"~:stroke-width\",1]],\"~:x\",821.9999915631233,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",821.9999915631233,\"~:y\",374.00001145409465,\"^F\",320.00009969013945,\"~:height\",226.000040384349,\"~:x1\",821.9999915631233,\"~:y1\",374.00001145409465,\"~:x2\",1142.0000912532628,\"~:y2\",600.0000518384436]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1A\",226.000040384349,\"~:flip-y\",null,\"~:shapes\",[\"~ude9c6736-45ce-80a1-8007-95065b4599ea\",\"~ude9c6736-45ce-80a1-8007-950643da554d\"]]]",
|
||||
"~ude9c6736-45ce-80a1-8007-95062fafbb88": "[\"~#shape\",[\"^ \",\"~:y\",342.0000083402533,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",31.999953508377075,\"~:p2\",34.000026052944804,\"~:p3\",31.999953508377075,\"~:p4\",34.000026052944804],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"B\",\"~:layout-align-items\",\"~:start\",\"~:width\",392.9999979687366,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",788.0000295450811,\"~:y\",342.00000834025326]],[\"^L\",[\"^ \",\"~:x\",1181.0000275138177,\"~:y\",342.00000834025326]],[\"^L\",[\"^ \",\"~:x\",1181.0000275138177,\"~:y\",631.9999659712]],[\"^L\",[\"^ \",\"~:x\",788.0000295450811,\"~:y\",631.9999659712]]],\"~:r2\",0,\"~:layout-item-h-sizing\",\"~:fill\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~uecb0cfd0-0f0b-81f7-8007-950628f9665b\",\"~:layout-item-v-sizing\",\"~:auto\",\"~:r3\",0,\"~:layout-justify-content\",\"^E\",\"~:r1\",0,\"~:id\",\"~ude9c6736-45ce-80a1-8007-95062fafbb88\",\"~:parent-id\",\"~ude9c6736-45ce-80a1-8007-95062aa41d6b\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~ude9c6736-45ce-80a1-8007-95062aa41d6b\",\"~:strokes\",[[\"^ \",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-style\",\"~:solid\",\"~:stroke-color\",\"#000000\",\"~:stroke-opacity\",1,\"~:stroke-width\",1]],\"~:x\",788.0000295450811,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",788.0000295450811,\"~:y\",342.0000083402533,\"^F\",392.9999979687366,\"~:height\",289.99995763094677,\"~:x1\",788.0000295450811,\"~:y1\",342.0000083402533,\"~:x2\",1181.0000275138177,\"~:y2\",631.9999659712]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1B\",289.99995763094677,\"~:flip-y\",null,\"~:shapes\",[\"~ude9c6736-45ce-80a1-8007-95063a202e52\"]]]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
131
frontend/playwright/data/workspace/get-file-13382.json
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"~:features": {
|
||||
"~#set": [
|
||||
"fdata/path-data",
|
||||
"design-tokens/v1",
|
||||
"variants/v1",
|
||||
"layout/grid",
|
||||
"fdata/pointer-map",
|
||||
"fdata/objects-map",
|
||||
"components/v2",
|
||||
"fdata/shape-data-type"
|
||||
]
|
||||
},
|
||||
"~:team-id": "~ud715d0a5-a44e-8056-8005-a79999e18b64",
|
||||
"~: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": "bug flex",
|
||||
"~:revn": 33,
|
||||
"~:modified-at": "~m1771342236324",
|
||||
"~:vern": 0,
|
||||
"~:id": "~u52c4e771-3853-8190-8007-9506c70e8100",
|
||||
"~: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",
|
||||
"0005-deprecate-image-type",
|
||||
"0006-fix-old-texts-fills",
|
||||
"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",
|
||||
"0013-clear-invalid-strokes-and-fills",
|
||||
"0014-fix-tokens-lib-duplicate-ids",
|
||||
"0014-clear-components-nil-objects",
|
||||
"0015-fix-text-attrs-blank-strings",
|
||||
"0015-clean-shadow-color",
|
||||
"0016-copy-fills-from-position-data-to-text-node"
|
||||
]
|
||||
},
|
||||
"~:version": 67,
|
||||
"~:project-id": "~u76eab896-accf-81a5-8007-2b264ebe7817",
|
||||
"~:created-at": "~m1771255281717",
|
||||
"~:backend": "legacy-db",
|
||||
"~:data": {
|
||||
"~:pages": [
|
||||
"~uecb0cfd0-0f0b-81f7-8007-950628f9665b"
|
||||
],
|
||||
"~:pages-index": {
|
||||
"~uecb0cfd0-0f0b-81f7-8007-950628f9665b": {
|
||||
"~#penpot/pointer": [
|
||||
"~u4173a29d-4020-80b4-8007-96527ba9d8af",
|
||||
{
|
||||
"~:created-at": "~m1771342236327"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"~:id": "~u52c4e771-3853-8190-8007-9506c70e8100",
|
||||
"~:options": {
|
||||
"~:components-v2": true,
|
||||
"~:base-font-size": "16px"
|
||||
}
|
||||
}
|
||||
}
|
||||
136
frontend/playwright/data/workspace/get-file-13385-2.json
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"~: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": "~u99e49e93-362f-80ef-8007-3450ea52c9a4",
|
||||
"~: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": "BUG 13385",
|
||||
"~:revn": 3,
|
||||
"~:modified-at": "~m1771254407745",
|
||||
"~:vern": 1173241426,
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-950361d24e43",
|
||||
"~: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",
|
||||
"0005-deprecate-image-type",
|
||||
"0006-fix-old-texts-fills",
|
||||
"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",
|
||||
"0013-clear-invalid-strokes-and-fills",
|
||||
"0014-fix-tokens-lib-duplicate-ids",
|
||||
"0014-clear-components-nil-objects",
|
||||
"0015-fix-text-attrs-blank-strings",
|
||||
"0015-clean-shadow-color",
|
||||
"0016-copy-fills-from-position-data-to-text-node"
|
||||
]
|
||||
},
|
||||
"~:version": 67,
|
||||
"~:project-id": "~ucd8f7672-e5d1-810f-8007-87e124eda82a",
|
||||
"~:created-at": "~m1771254391625",
|
||||
"~:backend": "legacy-db",
|
||||
"~:data": {
|
||||
"~:pages": [
|
||||
"~u3ea49ce0-9d99-8197-8007-950361d24e44"
|
||||
],
|
||||
"~:pages-index": {
|
||||
"~u3ea49ce0-9d99-8197-8007-950361d24e44": {
|
||||
"~: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\",[\"~ue0e81bed-4dc2-805c-8007-95036a4a3131\",\"~ue0e81bed-4dc2-805c-8007-95036c27428b\"]]]",
|
||||
"~ue0e81bed-4dc2-805c-8007-95036a4a3131": "[\"~#shape\",[\"^ \",\"~:y\",252,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",177,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",156,\"~:y\",252]],[\"^<\",[\"^ \",\"~:x\",333,\"~:y\",252]],[\"^<\",[\"^ \",\"~:x\",333,\"~:y\",389]],[\"^<\",[\"^ \",\"~:x\",156,\"~:y\",389]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~ue0e81bed-4dc2-805c-8007-95036a4a3131\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",156,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",156,\"~:y\",252,\"^8\",177,\"~:height\",137,\"~:x1\",156,\"~:y1\",252,\"~:x2\",333,\"~:y2\",389]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^J\",137,\"~:flip-y\",null]]",
|
||||
"~ue0e81bed-4dc2-805c-8007-95036c27428b": "[\"~#shape\",[\"^ \",\"~:y\",250,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Ellipse\",\"~:width\",148,\"~:type\",\"~:circle\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",362,\"~:y\",250]],[\"^<\",[\"^ \",\"~:x\",510,\"~:y\",250]],[\"^<\",[\"^ \",\"~:x\",510,\"~:y\",389]],[\"^<\",[\"^ \",\"~:x\",362,\"~:y\",389]]],\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~ue0e81bed-4dc2-805c-8007-95036c27428b\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",362,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",362,\"~:y\",250,\"^8\",148,\"~:height\",139,\"~:x1\",362,\"~:y1\",250,\"~:x2\",510,\"~:y2\",389]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^F\",139,\"~:flip-y\",null]]"
|
||||
}
|
||||
},
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-950361d24e44",
|
||||
"~:name": "Page 1"
|
||||
}
|
||||
},
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-950361d24e43",
|
||||
"~:options": {
|
||||
"~:components-v2": true,
|
||||
"~:base-font-size": "16px"
|
||||
}
|
||||
}
|
||||
}
|
||||
135
frontend/playwright/data/workspace/get-file-13385.json
Normal file
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"~: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": "~u99e49e93-362f-80ef-8007-3450ea52c9a4",
|
||||
"~: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": "BUG 13385",
|
||||
"~:revn": 2,
|
||||
"~:modified-at": "~m1771254464312",
|
||||
"~:vern": 0,
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-950361d24e43",
|
||||
"~: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",
|
||||
"0005-deprecate-image-type",
|
||||
"0006-fix-old-texts-fills",
|
||||
"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",
|
||||
"0013-clear-invalid-strokes-and-fills",
|
||||
"0014-fix-tokens-lib-duplicate-ids",
|
||||
"0014-clear-components-nil-objects",
|
||||
"0015-fix-text-attrs-blank-strings",
|
||||
"0015-clean-shadow-color",
|
||||
"0016-copy-fills-from-position-data-to-text-node"
|
||||
]
|
||||
},
|
||||
"~:version": 67,
|
||||
"~:project-id": "~ucd8f7672-e5d1-810f-8007-87e124eda82a",
|
||||
"~:created-at": "~m1771254391625",
|
||||
"~:backend": "legacy-db",
|
||||
"~:data": {
|
||||
"~:pages": [
|
||||
"~u3ea49ce0-9d99-8197-8007-950361d24e44"
|
||||
],
|
||||
"~:pages-index": {
|
||||
"~u3ea49ce0-9d99-8197-8007-950361d24e44": {
|
||||
"~: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\",[\"~ue0e81bed-4dc2-805c-8007-95036a4a3131\"]]]",
|
||||
"~ue0e81bed-4dc2-805c-8007-95036a4a3131": "[\"~#shape\",[\"^ \",\"~:y\",252,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",177,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",156,\"~:y\",252]],[\"^<\",[\"^ \",\"~:x\",333,\"~:y\",252]],[\"^<\",[\"^ \",\"~:x\",333,\"~:y\",389]],[\"^<\",[\"^ \",\"~:x\",156,\"~:y\",389]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~ue0e81bed-4dc2-805c-8007-95036a4a3131\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",156,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",156,\"~:y\",252,\"^8\",177,\"~:height\",137,\"~:x1\",156,\"~:y1\",252,\"~:x2\",333,\"~:y2\",389]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^J\",137,\"~:flip-y\",null]]"
|
||||
}
|
||||
},
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-950361d24e44",
|
||||
"~:name": "Page 1"
|
||||
}
|
||||
},
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-950361d24e43",
|
||||
"~:options": {
|
||||
"~:components-v2": true,
|
||||
"~:base-font-size": "16px"
|
||||
}
|
||||
}
|
||||
}
|
||||
135
frontend/playwright/data/workspace/get-file-13415.json
Normal file
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"~: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": "~u99e49e93-362f-80ef-8007-3450ea52c9a4",
|
||||
"~: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": "BUG 13415",
|
||||
"~:revn": 14,
|
||||
"~:modified-at": "~m1771334256704",
|
||||
"~:vern": 0,
|
||||
"~:id": "~u0472abff-2573-8186-8007-961793e53f45",
|
||||
"~: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",
|
||||
"0005-deprecate-image-type",
|
||||
"0006-fix-old-texts-fills",
|
||||
"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",
|
||||
"0013-clear-invalid-strokes-and-fills",
|
||||
"0014-fix-tokens-lib-duplicate-ids",
|
||||
"0014-clear-components-nil-objects",
|
||||
"0015-fix-text-attrs-blank-strings",
|
||||
"0015-clean-shadow-color",
|
||||
"0016-copy-fills-from-position-data-to-text-node"
|
||||
]
|
||||
},
|
||||
"~:version": 67,
|
||||
"~:project-id": "~ucd8f7672-e5d1-810f-8007-87e124eda82a",
|
||||
"~:created-at": "~m1771326794644",
|
||||
"~:backend": "legacy-db",
|
||||
"~:data": {
|
||||
"~:pages": [
|
||||
"~u0472abff-2573-8186-8007-961793e53f46"
|
||||
],
|
||||
"~:pages-index": {
|
||||
"~u0472abff-2573-8186-8007-961793e53f46": {
|
||||
"~: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\",[\"~uaef184da-e9c1-80f8-8007-961cf253d534\"]]]",
|
||||
"~uaef184da-e9c1-80f8-8007-961cf253d534": "[\"~#shape\",[\"^ \",\"~:y\",286,\"~:layout-grid-columns\",[[\"^ \",\"~:type\",\"~:flex\",\"~:value\",1],[\"^ \",\"^2\",\"^3\",\"^4\",1]],\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:grid\",\"~:hide-in-viewer\",false,\"~:name\",\"Board\",\"~:layout-align-items\",\"~:start\",\"~:width\",298,\"~:layout-grid-cells\",[\"^ \",\"~uaef184da-e9c1-80f8-8007-961cf50d67b4\",[\"^ \",\"~:justify-self\",\"~:auto\",\"~:column\",1,\"~:id\",\"~uaef184da-e9c1-80f8-8007-961cf50d67b4\",\"~:position\",\"^L\",\"~:column-span\",1,\"~:align-self\",\"^L\",\"~:row\",1,\"~:row-span\",1,\"~:shapes\",[]],\"~uaef184da-e9c1-80f8-8007-961cf50d67b5\",[\"^ \",\"^K\",\"^L\",\"^M\",2,\"^N\",\"~uaef184da-e9c1-80f8-8007-961cf50d67b5\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",1,\"^S\",1,\"^T\",[]],\"~uaef184da-e9c1-80f8-8007-961cf50d67b6\",[\"^ \",\"^K\",\"^L\",\"^M\",1,\"^N\",\"~uaef184da-e9c1-80f8-8007-961cf50d67b6\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",2,\"^S\",1,\"^T\",[]],\"~uaef184da-e9c1-80f8-8007-961cf50d67b7\",[\"^ \",\"^K\",\"^L\",\"^M\",2,\"^N\",\"~uaef184da-e9c1-80f8-8007-961cf50d67b7\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",2,\"^S\",1,\"^T\",[]]],\"~:layout-padding-type\",\"~:simple\",\"^2\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",322,\"~:y\",286]],[\"^10\",[\"^ \",\"~:x\",620,\"~:y\",286]],[\"^10\",[\"^ \",\"~:x\",620,\"~:y\",552]],[\"^10\",[\"^ \",\"~:x\",322,\"~:y\",552]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^>\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:layout-justify-content\",\"~:stretch\",\"~:r1\",0,\"^N\",\"~uaef184da-e9c1-80f8-8007-961cf253d534\",\"~:layout-justify-items\",\"^G\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-align-content\",\"^19\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",322,\"~:proportion\",1,\"~:r4\",0,\"~:layout-grid-rows\",[[\"^ \",\"^2\",\"^3\",\"^4\",1],[\"^ \",\"^2\",\"^3\",\"^4\",1]],\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",322,\"~:y\",286,\"^H\",298,\"~:height\",266,\"~:x1\",322,\"~:y1\",286,\"~:x2\",620,\"~:y2\",552]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:layout-grid-dir\",\"^R\",\"~:flip-x\",null,\"^1E\",266,\"~:flip-y\",null,\"^T\",[]]]"
|
||||
}
|
||||
},
|
||||
"~:id": "~u0472abff-2573-8186-8007-961793e53f46",
|
||||
"~:name": "Page 1"
|
||||
}
|
||||
},
|
||||
"~:id": "~u0472abff-2573-8186-8007-961793e53f45",
|
||||
"~:options": {
|
||||
"~:components-v2": true,
|
||||
"~:base-font-size": "16px"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"~:file-id": "~u3a4d7ec7-c391-8146-8007-9a05c41da6b9",
|
||||
"~:id": "~u3a4d7ec7-c391-8146-8007-9dd6c998fbc4",
|
||||
"~:created-at": "~m1771846681191",
|
||||
"~:modified-at": "~m1771846681191",
|
||||
"~:type": "fragment",
|
||||
"~:backend": "db",
|
||||
"~:data": {
|
||||
"~:id": "~u95b23c15-79f9-81ba-8007-99d81b5290dd",
|
||||
"~:name": "Page 1",
|
||||
"~: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]],\"~:page-id\",\"~u95b23c15-79f9-81ba-8007-99d81b5290dd\",\"~: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,\"^I\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~ucfb31a9c-83c2-806f-8007-9dbf43043bdf\"]]]",
|
||||
"~ucfb31a9c-83c2-806f-8007-9dbf43043be0": "[\"~#shape\",[\"^ \",\"~:y\",-218.99999605032087,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",5,\"~:p2\",5,\"~:p3\",5,\"~:p4\",5],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Container\",\"~:layout-align-items\",\"~:start\",\"~:width\",431.99994866329087,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",608.9999813066789,\"~:y\",-218.99999605032087]],[\"^J\",[\"^ \",\"~:x\",1040.9999299699698,\"~:y\",-218.99999605032087]],[\"^J\",[\"^ \",\"~:x\",1040.9999299699698,\"~:y\",-177.00001533586985]],[\"^J\",[\"^ \",\"~:x\",608.9999813066789,\"~:y\",-177.00001533586985]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:fill\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u95b23c15-79f9-81ba-8007-99d81b5290dd\",\"~:layout-item-v-sizing\",\"~:auto\",\"~:layout-justify-content\",\"^C\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be0\",\"~:parent-id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043bdf\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043bdf\",\"~:strokes\",[],\"~:x\",608.9999813066788,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",608.9999813066788,\"~:y\",-218.99999605032087,\"^D\",431.99994866329087,\"~:height\",41.99998071445103,\"~:x1\",608.9999813066788,\"~:y1\",-218.99999605032087,\"~:x2\",1040.9999299699698,\"~:y2\",-177.00001533586985]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ffc0cb\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1:\",41.99998071445103,\"~:flip-y\",null,\"~:shapes\",[\"~ucfb31a9c-83c2-806f-8007-9dbf43043be2\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be3\"]]]",
|
||||
"~ucfb31a9c-83c2-806f-8007-9dbf43043be2": "[\"~#shape\",[\"^ \",\"~:y\",-178.00000568505413,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",false,\"~:name\",\"show / hide me\",\"~:width\",99.98206911702209,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",614.0000002576337,\"~:y\",-178.00000568505413]],[\"^:\",[\"^ \",\"~:x\",713.9820693746558,\"~:y\",-178.00000568505413]],[\"^:\",[\"^ \",\"~:x\",713.9820693746558,\"~:y\",-148.0000135081636]],[\"^:\",[\"^ \",\"~:x\",614.0000002576337,\"~:y\",-148.0000135081636]]],\"~:r2\",0,\"~:layout-item-h-sizing\",\"~:fix\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:layout-item-v-sizing\",\"^=\",\"~:r3\",0,\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:r1\",0,\"~:hidden\",true,\"~:id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be2\",\"~:parent-id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be0\",\"~:frame-id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be0\",\"~:strokes\",[],\"~:x\",614.0000002576337,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",614.0000002576337,\"~:y\",-178.00000568505413,\"^6\",99.98206911702209,\"~:height\",29.999992176890544,\"~:x1\",614.0000002576337,\"~:y1\",-178.00000568505413,\"~:x2\",713.9820693746558,\"~:y2\",-148.0000135081636]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^P\",29.999992176890544,\"~:flip-y\",null]]",
|
||||
"~ucfb31a9c-83c2-806f-8007-9dbf43043be3": "[\"~#shape\",[\"^ \",\"~:y\",-213.99999587313152,\"~:hide-fill-on-export\",false,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Full width\",\"~:width\",422.00001200500014,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",613.9999939062393,\"~:y\",-213.99999587313152]],[\"^<\",[\"^ \",\"~:x\",1036.0000059112394,\"~:y\",-213.99999587313152]],[\"^<\",[\"^ \",\"~:x\",1036.0000059112394,\"~:y\",-182.00001303926604]],[\"^<\",[\"^ \",\"~:x\",613.9999939062393,\"~:y\",-182.00001303926604]]],\"~:r2\",8,\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:fix\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^4\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u95b23c15-79f9-81ba-8007-99d81b5290dd\",\"~:layout-item-v-sizing\",\"^@\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be3\",\"~:parent-id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be0\",\"~:frame-id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043be0\",\"~:strokes\",[],\"~:x\",613.9999939062393,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",613.9999939062393,\"~:y\",-213.99999587313152,\"^8\",422.00001200500014,\"~:height\",31.999982833865488,\"~:x1\",613.9999939062393,\"~:y1\",-213.99999587313152,\"~:x2\",1036.0000059112394,\"~:y2\",-182.00001303926604]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#212426\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^O\",31.999982833865488,\"~:flip-y\",null,\"~:shapes\",[]]]",
|
||||
"~ucfb31a9c-83c2-806f-8007-9dbf43043bdf": "[\"~#shape\",[\"^ \",\"~:y\",-228.99999763039506,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",10,\"~:p2\",10,\"~:p3\",10,\"~:p4\",10],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Parent\",\"~:layout-align-items\",\"~:start\",\"~:width\",451.999905143128,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",599.0000149607649,\"~:y\",-228.99999763039506]],[\"^J\",[\"^ \",\"~:x\",1050.999920103893,\"~:y\",-228.99999763039506]],[\"^J\",[\"^ \",\"~:x\",1050.999920103893,\"~:y\",-167.0000160450801]],[\"^J\",[\"^ \",\"~:x\",599.0000149607649,\"~:y\",-167.0000160450801]]],\"~:r2\",0,\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:fix\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",10,\"~:column-gap\",8],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u95b23c15-79f9-81ba-8007-99d81b5290dd\",\"~:layout-item-v-sizing\",\"~:auto\",\"~:r3\",0,\"~:layout-justify-content\",\"^C\",\"~:r1\",0,\"~:id\",\"~ucfb31a9c-83c2-806f-8007-9dbf43043bdf\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",599.0000149607649,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",599.0000149607649,\"~:y\",-228.99999763039506,\"^D\",451.999905143128,\"~:height\",61.99998158531497,\"~:x1\",599.0000149607649,\"~:y1\",-228.99999763039506,\"~:x2\",1050.999920103893,\"~:y2\",-167.0000160450801]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1:\",61.99998158531497,\"~:flip-y\",null,\"~:shapes\",[\"~ucfb31a9c-83c2-806f-8007-9dbf43043be0\"]]]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
131
frontend/playwright/data/workspace/get-file-13468.json
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"~:features": {
|
||||
"~#set": [
|
||||
"fdata/path-data",
|
||||
"design-tokens/v1",
|
||||
"variants/v1",
|
||||
"layout/grid",
|
||||
"fdata/pointer-map",
|
||||
"fdata/objects-map",
|
||||
"components/v2",
|
||||
"fdata/shape-data-type"
|
||||
]
|
||||
},
|
||||
"~:team-id": "~ud715d0a5-a44e-8056-8005-a79999e18b64",
|
||||
"~: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": "test-bug-flex",
|
||||
"~:revn": 114,
|
||||
"~:modified-at": "~m1771846681183",
|
||||
"~:vern": 0,
|
||||
"~:id": "~u3a4d7ec7-c391-8146-8007-9a05c41da6b9",
|
||||
"~: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",
|
||||
"0005-deprecate-image-type",
|
||||
"0006-fix-old-texts-fills",
|
||||
"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",
|
||||
"0013-clear-invalid-strokes-and-fills",
|
||||
"0014-fix-tokens-lib-duplicate-ids",
|
||||
"0014-clear-components-nil-objects",
|
||||
"0015-fix-text-attrs-blank-strings",
|
||||
"0015-clean-shadow-color",
|
||||
"0016-copy-fills-from-position-data-to-text-node"
|
||||
]
|
||||
},
|
||||
"~:version": 67,
|
||||
"~:project-id": "~u76eab896-accf-81a5-8007-2b264ebe7817",
|
||||
"~:created-at": "~m1771590560885",
|
||||
"~:backend": "legacy-db",
|
||||
"~:data": {
|
||||
"~:pages": [
|
||||
"~u95b23c15-79f9-81ba-8007-99d81b5290dd"
|
||||
],
|
||||
"~:pages-index": {
|
||||
"~u95b23c15-79f9-81ba-8007-99d81b5290dd": {
|
||||
"~#penpot/pointer": [
|
||||
"~u3a4d7ec7-c391-8146-8007-9dd6c998fbc4",
|
||||
{
|
||||
"~:created-at": "~m1771846681187"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"~:id": "~u3a4d7ec7-c391-8146-8007-9a05c41da6b9",
|
||||
"~:options": {
|
||||
"~:components-v2": true,
|
||||
"~:base-font-size": "16px"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-95037190405b",
|
||||
"~:label": "Version 000",
|
||||
"~:revn": 1,
|
||||
"~:version": 67,
|
||||
"~:created-at": "~m1771254407745",
|
||||
"~:modified-at": "~m1771254407745",
|
||||
"~:created-by": "user",
|
||||
"~:profile-id": "~u99e49e93-362f-80ef-8007-3450ea5204aa"
|
||||
},
|
||||
{
|
||||
"~:revn": 0,
|
||||
"~:modified-at": "~m1771254406526",
|
||||
"~:deleted-at": "~m1771340806524",
|
||||
"~:created-by": "system",
|
||||
"~:label": "internal/snapshot/0",
|
||||
"~:id": "~u3ea49ce0-9d99-8197-8007-9503705f8b9b",
|
||||
"~:profile-id": "~u99e49e93-362f-80ef-8007-3450ea5204aa",
|
||||
"~:version": 67,
|
||||
"~:created-at": "~m1771254406526"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"~:id": "~u99e49e93-362f-80ef-8007-3450ea5204aa",
|
||||
"~:email": "belen@example.com",
|
||||
"~:name": "Belén Albeza",
|
||||
"~:fullname": "Belén Albeza",
|
||||
"~:is-active": true
|
||||
}
|
||||
]
|
||||
18
frontend/playwright/data/workspace/update-file-13415.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"~:revn": 14,
|
||||
"~:lagged": [
|
||||
{
|
||||
"~:id": "~u0472abff-2573-8186-8007-96347d525f65",
|
||||
"~:revn": 15,
|
||||
"~:file-id": "~u0472abff-2573-8186-8007-961793e53f45",
|
||||
"~:session-id": "~uf25e6d2f-d10c-8021-8007-96344433f08d",
|
||||
"~:changes": [
|
||||
{
|
||||
"~:type": "~:del-obj",
|
||||
"~:page-id": "~u0472abff-2573-8186-8007-961793e53f46",
|
||||
"~:id": "~uaef184da-e9c1-80f8-8007-961cf253d534"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
export class BasePage {
|
||||
static async init(page) {
|
||||
await BasePage.mockConfigFlags(page, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks multiple RPC calls in a single call.
|
||||
*
|
||||
@@ -22,7 +26,7 @@ export class BasePage {
|
||||
* @param {*} options
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async mockRPC(page, path, jsonFilename, options) {
|
||||
static async mockRPC(page, path, jsonFilename = "", options = {}) {
|
||||
if (!page) {
|
||||
throw new TypeError("Invalid page argument. Must be a Playwright page.");
|
||||
}
|
||||
@@ -41,7 +45,7 @@ export class BasePage {
|
||||
return page.route(url, (route) =>
|
||||
route.fulfill({
|
||||
...interceptConfig,
|
||||
path: `playwright/data/${jsonFilename}`,
|
||||
path: jsonFilename ? `playwright/data/${jsonFilename}` : undefined,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,8 @@ import { MockWebSocketHelper } from "../../helpers/MockWebSocketHelper";
|
||||
import BasePage from "./BasePage";
|
||||
|
||||
export class BaseWebSocketPage extends BasePage {
|
||||
/**
|
||||
* This should be called on `test.beforeEach`.
|
||||
*
|
||||
* @param {Page} page
|
||||
* @returns
|
||||
*/
|
||||
static async initWebSockets(page) {
|
||||
static async init(page) {
|
||||
await super.init(page);
|
||||
await MockWebSocketHelper.init(page);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,54 +3,62 @@ import { BaseWebSocketPage } from "./BaseWebSocketPage";
|
||||
|
||||
export class DashboardPage extends BaseWebSocketPage {
|
||||
static async init(page) {
|
||||
await BaseWebSocketPage.initWebSockets(page);
|
||||
await super.init(page);
|
||||
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockConfigFlags(page, ["disable-onboarding"]);
|
||||
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-teams",
|
||||
"logged-in-user/get-teams-default.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-font-variants?team-id=*",
|
||||
"workspace/get-font-variants-empty.json",
|
||||
);
|
||||
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-projects?team-id=*",
|
||||
"logged-in-user/get-projects-default.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-team-members?team-id=*",
|
||||
"logged-in-user/get-team-members-your-penpot.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-team-users?team-id=*",
|
||||
"logged-in-user/get-team-users-single-user.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-unread-comment-threads?team-id=*",
|
||||
"logged-in-user/get-team-users-single-user.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-team-recent-files?team-id=*",
|
||||
"logged-in-user/get-team-recent-files-empty.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-profiles-for-file-comments",
|
||||
"workspace/get-profile-for-file-comments.json",
|
||||
);
|
||||
await BaseWebSocketPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-builtin-templates",
|
||||
"logged-in-user/get-built-in-templates-empty.json",
|
||||
);
|
||||
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in.json",
|
||||
);
|
||||
}
|
||||
|
||||
static anyTeamId = "c7ce0794-0992-8105-8004-38e630f40f6d";
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { BasePage } from "./BasePage";
|
||||
|
||||
export class LoginPage extends BasePage {
|
||||
static async init(page) {
|
||||
await super.init(page);
|
||||
}
|
||||
|
||||
constructor(page) {
|
||||
super(page);
|
||||
this.loginButton = page.getByRole("button", { name: "Continue" });
|
||||
|
||||
@@ -29,8 +29,13 @@ export class RegisterPage extends BasePage {
|
||||
);
|
||||
}
|
||||
|
||||
static async init(page) {
|
||||
await BasePage.init(page);
|
||||
}
|
||||
|
||||
static async initWithLoggedOutUser(page) {
|
||||
await this.mockRPC(page, "get-profile", "get-profile-anonymous.json");
|
||||
await BasePage.init(page);
|
||||
await BasePage.mockRPC(page, "get-profile", "get-profile-anonymous.json");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ import { DashboardPage } from "./DashboardPage";
|
||||
|
||||
export class SubscriptionProfilePage extends DashboardPage {
|
||||
static async init(page) {
|
||||
await DashboardPage.initWebSockets(page);
|
||||
await super.init(page);
|
||||
|
||||
await DashboardPage.mockRPC(
|
||||
await super.mockRPC(
|
||||
page,
|
||||
"get-subscription-usage",
|
||||
"subscription/get-subscription-usage.json",
|
||||
|
||||
@@ -4,16 +4,6 @@ export class ViewerPage extends BaseWebSocketPage {
|
||||
static anyFileId = "c7ce0794-0992-8105-8004-38f280443849";
|
||||
static anyPageId = "c7ce0794-0992-8105-8004-38f28044384a";
|
||||
|
||||
/**
|
||||
* This should be called on `test.beforeEach`.
|
||||
*
|
||||
* @param {Page} page
|
||||
* @returns
|
||||
*/
|
||||
static async init(page) {
|
||||
await BaseWebSocketPage.initWebSockets(page);
|
||||
}
|
||||
|
||||
async setupLoggedInUser() {
|
||||
await this.mockRPC(
|
||||
"get-profile",
|
||||
|
||||
@@ -35,8 +35,8 @@ export class WasmWorkspacePage extends WorkspacePage {
|
||||
return WasmWorkspacePage.mockConfigFlags(this.page, flags);
|
||||
}
|
||||
|
||||
constructor(page) {
|
||||
super(page);
|
||||
constructor(page, options) {
|
||||
super(page, options);
|
||||
this.canvas = page.getByTestId("canvas-wasm-shapes");
|
||||
}
|
||||
|
||||
@@ -54,6 +54,19 @@ export class WasmWorkspacePage extends WorkspacePage {
|
||||
await this.hideUI();
|
||||
}
|
||||
|
||||
async getRenderCount() {
|
||||
return this.page.evaluate(() => window.wasmRenderCount || 0);
|
||||
}
|
||||
|
||||
async waitForNextRender(previousCount = null) {
|
||||
const baseCount =
|
||||
previousCount === null ? await this.getRenderCount() : previousCount;
|
||||
await this.page.waitForFunction(
|
||||
(count) => (window.wasmRenderCount || 0) > count,
|
||||
baseCount,
|
||||
);
|
||||
}
|
||||
|
||||
async hideUI() {
|
||||
await this.page.keyboard.press("\\");
|
||||
await expect(this.pageName).not.toBeVisible();
|
||||
|
||||
@@ -35,45 +35,9 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
}
|
||||
|
||||
async waitForEditor() {
|
||||
return this.page.waitForSelector('[data-itype="editor"]');
|
||||
}
|
||||
|
||||
async waitForRoot() {
|
||||
return this.page.waitForSelector('[data-itype="root"]');
|
||||
}
|
||||
|
||||
async waitForParagraph(nth) {
|
||||
if (!nth) {
|
||||
return this.page.waitForSelector('[data-itype="paragraph"]');
|
||||
}
|
||||
return this.page.waitForSelector(
|
||||
`[data-itype="paragraph"]:nth-child(${nth})`,
|
||||
);
|
||||
}
|
||||
|
||||
async waitForParagraphStyle(nth, styleName) {
|
||||
const paragraph = await this.waitForParagraph(nth);
|
||||
return this.waitForStyle(paragraph, styleName);
|
||||
}
|
||||
|
||||
async waitForTextSpan(nth = 0) {
|
||||
if (!nth) {
|
||||
return this.page.waitForSelector('[data-itype="span"]');
|
||||
}
|
||||
return this.page.waitForSelector(
|
||||
`[data-itype="span"]:nth-child(${nth})`,
|
||||
);
|
||||
}
|
||||
|
||||
async waitForTextSpanContent(nth = 0) {
|
||||
const textSpan = await this.waitForTextSpan(nth);
|
||||
const textContent = await textSpan.textContent();
|
||||
return textContent;
|
||||
}
|
||||
|
||||
async waitForTextSpanStyle(nth, styleName) {
|
||||
const textSpan = await this.waitForTextSpan(nth);
|
||||
return this.waitForStyle(textSpan, styleName);
|
||||
const typographyInput =
|
||||
this.workspacePage.rightSidebar.getByLabel("Font Size");
|
||||
await expect(typographyInput).toBeVisible();
|
||||
}
|
||||
|
||||
async startEditing() {
|
||||
@@ -81,24 +45,27 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
return this.waitForEditor();
|
||||
}
|
||||
|
||||
stopEditing() {
|
||||
return this.page.keyboard.press("Escape");
|
||||
async stopEditing() {
|
||||
await this.page.keyboard.press("Escape");
|
||||
}
|
||||
|
||||
async moveToLeft(amount = 0) {
|
||||
for (let i = 0; i < amount; i++) {
|
||||
await this.page.keyboard.press("ArrowLeft");
|
||||
}
|
||||
await this.waitForIdle();
|
||||
}
|
||||
|
||||
async moveToRight(amount = 0) {
|
||||
for (let i = 0; i < amount; i++) {
|
||||
await this.page.keyboard.press("ArrowRight");
|
||||
}
|
||||
await this.waitForIdle();
|
||||
}
|
||||
|
||||
async moveFromStart(offset = 0) {
|
||||
await this.page.keyboard.press("ArrowLeft");
|
||||
await this.page.keyboard.press("Home");
|
||||
await this.waitForIdle();
|
||||
await this.moveToRight(offset);
|
||||
}
|
||||
|
||||
@@ -125,7 +92,7 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
await expect(locator).toBeVisible();
|
||||
await locator.focus();
|
||||
await locator.fill(`${newValue}`);
|
||||
await locator.blur();
|
||||
await this.page.keyboard.press("Enter");
|
||||
}
|
||||
|
||||
changeFontSize(newValue) {
|
||||
@@ -139,6 +106,10 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
changeLetterSpacing(newValue) {
|
||||
return this.changeNumericInput(this.letterSpacing, newValue);
|
||||
}
|
||||
|
||||
async waitForIdle() {
|
||||
await this.page.evaluate(() => new Promise((resolve) => globalThis.requestIdleCallback(resolve)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -148,9 +119,9 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
* @returns
|
||||
*/
|
||||
static async init(page) {
|
||||
await BaseWebSocketPage.initWebSockets(page);
|
||||
await super.init(page);
|
||||
|
||||
await BaseWebSocketPage.mockRPCs(page, {
|
||||
await super.mockRPCs(page, {
|
||||
"get-profile": "logged-in-user/get-profile-logged-in.json",
|
||||
"get-team-users?file-id=*":
|
||||
"logged-in-user/get-team-users-single-user.json",
|
||||
@@ -317,7 +288,6 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
body,
|
||||
}),
|
||||
);
|
||||
// await this.mockRPC(/get\-file\?/, jsonFile);
|
||||
}
|
||||
|
||||
async mockGetAsset(regex, asset) {
|
||||
@@ -391,10 +361,12 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
const timeToWait = options?.timeToWait ?? 100;
|
||||
await this.page.keyboard.press("T");
|
||||
await this.page.waitForTimeout(timeToWait);
|
||||
|
||||
const layersCountBefore = await this.layers.getByTestId("layer-row").count();
|
||||
await this.clickAndMove(x1, y1, x2, y2);
|
||||
await expect(this.page.getByTestId("text-editor")).toBeVisible();
|
||||
|
||||
if (initialText) {
|
||||
await this.waitForSelectedShapeName("Text");
|
||||
await this.page.keyboard.type(initialText);
|
||||
}
|
||||
}
|
||||
@@ -494,10 +466,23 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||
|
||||
async expectSelectedLayer(name) {
|
||||
await expect(
|
||||
this.layers
|
||||
.getByTestId("layer-row")
|
||||
.filter({ has: this.page.getByText(name) }),
|
||||
).toHaveClass(/selected/);
|
||||
this.layers.getByRole("checkbox", { name, checked: true }),
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
async getSelectedShapeName() {
|
||||
const selectedLayer = this.layers
|
||||
.getByRole("checkbox", { checked: true })
|
||||
.first();
|
||||
await selectedLayer.waitFor({ state: "visible" });
|
||||
return (await selectedLayer.innerText()).trim();
|
||||
}
|
||||
|
||||
async waitForSelectedShapeName(expectedName) {
|
||||
const selectedLayer = this.layers
|
||||
.getByRole("checkbox", { checked: true })
|
||||
.first();
|
||||
await expect(selectedLayer).toHaveText(expectedName);
|
||||
}
|
||||
|
||||
async expectHiddenToolbarOptions() {
|
||||
|
||||
@@ -243,6 +243,46 @@ test("Renders a file with a closed path shape with multiple segments using strok
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("Renders solid shadows after select all and zoom to selected", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WasmWorkspacePage(page);
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.mockGetFile("render-wasm/get-solid-shadows.json");
|
||||
|
||||
await workspace.goToWorkspace({
|
||||
id: "93113137-fe66-80fb-8007-99ca9fd96841",
|
||||
pageId: "93113137-fe66-80fb-8007-99ca9fd96842",
|
||||
});
|
||||
await workspace.waitForFirstRender();
|
||||
|
||||
await workspace.viewport.click();
|
||||
await page.keyboard.press("ControlOrMeta+A");
|
||||
const previousRenderCount = await workspace.getRenderCount();
|
||||
await page.keyboard.press("f");
|
||||
await workspace.waitForNextRender(previousRenderCount);
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("Renders strokes with solid shadows", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WasmWorkspacePage(page);
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.mockGetFile("render-wasm/get-solid-strokes-shadows.json");
|
||||
|
||||
await workspace.goToWorkspace({
|
||||
id: "93113137-fe66-80fb-8007-99cfd5cbf361",
|
||||
pageId: "93113137-fe66-80fb-8007-99cfd5cbf362",
|
||||
});
|
||||
await workspace.waitForFirstRender();
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("Renders a file with paths and svg attrs", async ({ page }) => {
|
||||
const workspace = new WasmWorkspacePage(page);
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -356,3 +396,39 @@ test("Renders shapes with multiple fills and blur", async ({
|
||||
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("Keeps component visible when focusing after creating it", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WasmWorkspacePage(page);
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-not-empty.json");
|
||||
await workspace.mockRPC(
|
||||
"update-file?id=*",
|
||||
"workspace/update-file-create-rect.json",
|
||||
);
|
||||
|
||||
await workspace.goToWorkspace({
|
||||
fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
|
||||
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375",
|
||||
});
|
||||
await workspace.waitForFirstRender();
|
||||
|
||||
await workspace.clickLayers();
|
||||
await workspace.clickLeafLayer("Rectangle");
|
||||
await page.keyboard.press("ControlOrMeta+k");
|
||||
|
||||
const componentLayer = workspace.layers
|
||||
.getByTestId("layer-row")
|
||||
.filter({ has: page.getByTestId("icon-component") })
|
||||
.first();
|
||||
await expect(componentLayer).toBeVisible();
|
||||
await componentLayer.click();
|
||||
|
||||
const previousRenderCount = await workspace.getRenderCount();
|
||||
await page.keyboard.press("f");
|
||||
await workspace.waitForNextRender(previousRenderCount);
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 348 KiB After Width: | Height: | Size: 348 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 140 KiB |
@@ -3,11 +3,6 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test.describe("Dashboard Deleted Page", () => {
|
||||
|
||||
@@ -3,11 +3,6 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test("BUG 10421 - Fix libraries context menu", async ({ page }) => {
|
||||
|
||||
@@ -3,11 +3,6 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test("BUG 12359 - Selected invitations count is not pluralized", async ({
|
||||
|
||||
@@ -3,11 +3,7 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-teams",
|
||||
|
||||
@@ -3,11 +3,6 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test("Dashboad page has title ", async ({ page }) => {
|
||||
|
||||
@@ -2,6 +2,8 @@ import { test, expect } from "@playwright/test";
|
||||
import { LoginPage } from "../pages/LoginPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await LoginPage.init(page);
|
||||
|
||||
const login = new LoginPage(page);
|
||||
await login.initWithLoggedOutUser();
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import OnboardingPage from "../pages/OnboardingPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockConfigFlags(page, ["enable-onboarding"]);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
|
||||
@@ -3,11 +3,6 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test("Navigate to penpot changelog from profile menu", async ({ page }) => {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import { Clipboard } from "../../helpers/Clipboard";
|
||||
import { WorkspacePage } from "../pages/WorkspacePage";
|
||||
|
||||
const timeToWait = 100;
|
||||
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
|
||||
|
||||
test.beforeEach(async ({ page, context }) => {
|
||||
await Clipboard.enable(context, Clipboard.Permission.ALL);
|
||||
|
||||
await WorkspacePage.init(page);
|
||||
await WorkspacePage.mockConfigFlags(page, ["enable-feature-text-editor-v2"]);
|
||||
await WasmWorkspacePage.init(page);
|
||||
await WasmWorkspacePage.mockConfigFlags(page, ["enable-feature-text-editor-v2"]);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ context }) => {
|
||||
@@ -17,39 +15,36 @@ test.afterEach(async ({ context }) => {
|
||||
|
||||
test("Create a new text shape", async ({ page }) => {
|
||||
const initialText = "Lorem ipsum";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.goToWorkspace();
|
||||
await workspace.createTextShape(190, 150, 300, 200, initialText);
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe(initialText);
|
||||
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await workspace.waitForSelectedShapeName(initialText);
|
||||
});
|
||||
|
||||
test("Create a new text shape from pasting text", async ({ page, context }) => {
|
||||
const textToPaste = "Lorem ipsum";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.mockRPC("update-file?id=*", "text-editor/update-file.json");
|
||||
await workspace.goToWorkspace();
|
||||
await workspace.moveButton.click();
|
||||
|
||||
await Clipboard.writeText(page, textToPaste);
|
||||
|
||||
await workspace.clickAt(190, 150);
|
||||
await workspace.paste("keyboard");
|
||||
|
||||
await page.waitForTimeout(timeToWait);
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe(textToPaste);
|
||||
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await expect(workspace.layers.getByText(textToPaste)).toBeVisible();
|
||||
});
|
||||
|
||||
test("Create a new text shape from pasting text using context menu", async ({
|
||||
@@ -57,27 +52,26 @@ test("Create a new text shape from pasting text using context menu", async ({
|
||||
context,
|
||||
}) => {
|
||||
const textToPaste = "Lorem ipsum";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.goToWorkspace();
|
||||
await workspace.moveButton.click();
|
||||
|
||||
await Clipboard.writeText(page, textToPaste);
|
||||
|
||||
await workspace.clickAt(190, 150);
|
||||
await workspace.paste("context-menu");
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe(textToPaste);
|
||||
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await expect(workspace.layers.getByText(textToPaste)).toBeVisible();
|
||||
});
|
||||
|
||||
test("Update an already created text shape by appending text", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -87,15 +81,14 @@ test("Update an already created text shape by appending text", async ({
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.moveFromEnd(0);
|
||||
await page.keyboard.type(" dolor sit amet");
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Lorem ipsum dolor sit amet");
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Lorem ipsum dolor sit amet");
|
||||
});
|
||||
|
||||
test("Update an already created text shape by prepending text", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -105,15 +98,14 @@ test("Update an already created text shape by prepending text", async ({
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.moveFromStart(0);
|
||||
await page.keyboard.type("Dolor sit amet ");
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Dolor sit amet Lorem ipsum");
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Dolor sit amet Lorem ipsum");
|
||||
});
|
||||
|
||||
test.skip("Update an already created text shape by inserting text in between", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -123,9 +115,8 @@ test.skip("Update an already created text shape by inserting text in between", a
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.moveFromStart(5);
|
||||
await page.keyboard.type(" dolor sit amet");
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Lorem dolor sit amet ipsum");
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Lorem dolor sit amet ipsum");
|
||||
});
|
||||
|
||||
test("Update a new text shape appending text by pasting text", async ({
|
||||
@@ -133,7 +124,7 @@ test("Update a new text shape appending text by pasting text", async ({
|
||||
context,
|
||||
}) => {
|
||||
const textToPaste = " dolor sit amet";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -146,9 +137,8 @@ test("Update a new text shape appending text by pasting text", async ({
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.moveFromEnd();
|
||||
await workspace.paste("keyboard");
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Lorem ipsum dolor sit amet");
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Lorem ipsum dolor sit amet");
|
||||
});
|
||||
|
||||
test.skip("Update a new text shape prepending text by pasting text", async ({
|
||||
@@ -156,7 +146,7 @@ test.skip("Update a new text shape prepending text by pasting text", async ({
|
||||
context,
|
||||
}) => {
|
||||
const textToPaste = "Dolor sit amet ";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -169,16 +159,17 @@ test.skip("Update a new text shape prepending text by pasting text", async ({
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.moveFromStart();
|
||||
await workspace.paste("keyboard");
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Dolor sit amet Lorem ipsum");
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("Update a new text shape replacing (starting) text with pasted text", async ({
|
||||
page,
|
||||
}) => {
|
||||
const textToPaste = "Dolor sit amet";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -192,17 +183,15 @@ test("Update a new text shape replacing (starting) text with pasted text", async
|
||||
|
||||
await workspace.paste("keyboard");
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Dolor sit amet ipsum");
|
||||
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Dolor sit amet ipsum");
|
||||
});
|
||||
|
||||
test("Update a new text shape replacing (ending) text with pasted text", async ({
|
||||
page,
|
||||
}) => {
|
||||
const textToPaste = "dolor sit amet";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -216,17 +205,15 @@ test("Update a new text shape replacing (ending) text with pasted text", async (
|
||||
|
||||
await workspace.paste("keyboard");
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Lorem dolor sit amet");
|
||||
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Lorem dolor sit amet");
|
||||
});
|
||||
|
||||
test("Update a new text shape replacing (in between) text with pasted text", async ({
|
||||
page,
|
||||
}) => {
|
||||
const textToPaste = "dolor sit amet";
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -240,16 +227,14 @@ test("Update a new text shape replacing (in between) text with pasted text", asy
|
||||
|
||||
await workspace.paste("keyboard");
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Lordolor sit ametsum");
|
||||
|
||||
await workspace.textEditor.stopEditing();
|
||||
await workspace.waitForSelectedShapeName("Lordolor sit ametsum");
|
||||
});
|
||||
|
||||
test("Update text font size selecting a part of it (starting)", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -260,18 +245,16 @@ test("Update text font size selecting a part of it (starting)", async ({
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.selectFromStart(5);
|
||||
await workspace.textEditor.changeFontSize(36);
|
||||
|
||||
const textContent1 = await workspace.textEditor.waitForTextSpanContent(1);
|
||||
expect(textContent1).toBe("Lorem");
|
||||
const textContent2 = await workspace.textEditor.waitForTextSpanContent(2);
|
||||
expect(textContent2).toBe(" ipsum");
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test.skip("Update text line height selecting a part of it (starting)", async ({
|
||||
test("Update text line height selecting a part of it (starting)", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -281,24 +264,17 @@ test.skip("Update text line height selecting a part of it (starting)", async ({
|
||||
await workspace.clickLeafLayer("Lorem ipsum");
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.selectFromStart(5);
|
||||
await workspace.textEditor.changeLineHeight(1.4);
|
||||
|
||||
const lineHeight = await workspace.textEditor.waitForParagraphStyle(
|
||||
1,
|
||||
"line-height",
|
||||
);
|
||||
expect(lineHeight).toBe("1.4");
|
||||
|
||||
const textContent = await workspace.textEditor.waitForTextSpanContent();
|
||||
expect(textContent).toBe("Lorem ipsum");
|
||||
|
||||
await workspace.textEditor.changeLineHeight(4.4);
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test.skip("Update text letter spacing selecting a part of it (starting)", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspace = new WorkspacePage(page, {
|
||||
const workspace = new WasmWorkspacePage(page, {
|
||||
textEditor: true,
|
||||
});
|
||||
await workspace.setupEmptyFile();
|
||||
@@ -309,16 +285,14 @@ test.skip("Update text letter spacing selecting a part of it (starting)", async
|
||||
await workspace.textEditor.startEditing();
|
||||
await workspace.textEditor.selectFromStart(5);
|
||||
await workspace.textEditor.changeLetterSpacing(10);
|
||||
|
||||
const textContent1 = await workspace.textEditor.waitForTextSpanContent(1);
|
||||
expect(textContent1).toBe("Lorem");
|
||||
const textContent2 = await workspace.textEditor.waitForTextSpanContent(2);
|
||||
expect(textContent2).toBe(" ipsum");
|
||||
await workspace.textEditor.stopEditing();
|
||||
|
||||
await workspace.hideUI();
|
||||
await expect(workspace.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("BUG 11552 - Apply styles to the current caret", async ({ page }) => {
|
||||
const workspace = new WorkspacePage(page);
|
||||
const workspace = new WasmWorkspacePage(page);
|
||||
await workspace.setupEmptyFile();
|
||||
await workspace.mockGetFile("text-editor/get-file-11552.json");
|
||||
await workspace.mockRPC(
|
||||
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -1,5 +1,5 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
|
||||
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
|
||||
import { BaseWebSocketPage } from "../pages/BaseWebSocketPage";
|
||||
import { Clipboard } from "../../helpers/Clipboard";
|
||||
|
||||
@@ -7,7 +7,7 @@ test.beforeEach(async ({ page, context }) => {
|
||||
await Clipboard.enable(context, Clipboard.Permission.ALL);
|
||||
|
||||
await WasmWorkspacePage.init(page);
|
||||
await BaseWebSocketPage.mockRPC(page, "get-teams", "get-teams-variants.json");
|
||||
await WasmWorkspacePage.mockConfigFlags(page, ["enable-feature-variants"]);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ context }) => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
|
||||
import { presenceFixture } from "../../data/workspace/ws-notifications";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await WasmWorkspacePage.init(page);
|
||||
@@ -106,9 +105,37 @@ test("BUG 11006 - Fix history panel shortcut", async ({ page }) => {
|
||||
|
||||
await workspacePage.goToWorkspace();
|
||||
|
||||
await page.keyboard.press("Control+Alt+h");
|
||||
await page.keyboard.press("ControlOrMeta+Alt+h");
|
||||
|
||||
await expect(
|
||||
workspacePage.rightSidebar.getByText("There are no versions yet"),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("BUG 13385 - Fix viewport not updating when restoring version", async ({ page }) => {
|
||||
const workspacePage = new WasmWorkspacePage(page);
|
||||
await workspacePage.setupEmptyFile();
|
||||
await workspacePage.mockGetFile("workspace/get-file-13385.json");
|
||||
await workspacePage.mockRPC("get-profiles-for-file-comments?file-id=*", "workspace/get-profiles-for-file-comments-13385.json");
|
||||
|
||||
// navigate to workspace and check that the circle shape is not there
|
||||
await workspacePage.goToWorkspace();
|
||||
await expect(workspacePage.layers.getByText("Ellipse")).not.toBeVisible();
|
||||
|
||||
// mock network requests to restore the version
|
||||
await workspacePage.mockGetFile("workspace/get-file-13385-2.json");
|
||||
await workspacePage.mockRPC("get-file-snapshots?file-id=*", "workspace/get-file-snapshots-13385.json");
|
||||
await workspacePage.mockRPC("restore-file-snapshot", "", {
|
||||
status: 204,
|
||||
});
|
||||
|
||||
// request to restore the version
|
||||
await workspacePage.rightSidebar.getByRole("button", { name: "History" }).click();
|
||||
await workspacePage.rightSidebar.getByRole("button", { name: "Open version menu" }).click();
|
||||
await workspacePage.rightSidebar.getByRole("button", { name: "Restore" }).click();
|
||||
// confirm modal
|
||||
await workspacePage.page.getByRole("button", { name: /Restore/i }).click();
|
||||
|
||||
// assert that the circle shape exists
|
||||
await expect(workspacePage.layers.getByText("Ellipse")).toBeVisible();
|
||||
});
|
||||
@@ -23,4 +23,63 @@ test("BUG 13305 - Fix resize board to fit content", async ({ page }) => {
|
||||
await expect(workspacePage.rightSidebar.getByTitle("Height").getByRole("textbox")).toHaveValue("630");
|
||||
await expect(workspacePage.rightSidebar.getByTitle("X axis").getByRole("textbox")).toHaveValue("110");
|
||||
await expect(workspacePage.rightSidebar.getByTitle("Y axis").getByRole("textbox")).toHaveValue("110");
|
||||
});
|
||||
});
|
||||
|
||||
test("BUG 13382 - Fix problem with flex layout", async ({ page }) => {
|
||||
const workspacePage = new WasmWorkspacePage(page);
|
||||
await workspacePage.setupEmptyFile();
|
||||
await workspacePage.mockGetFile("workspace/get-file-13382.json");
|
||||
|
||||
await workspacePage.mockRPC(
|
||||
"get-file-fragment?file-id=*&fragment-id=*",
|
||||
"workspace/get-file-13382-fragment.json",
|
||||
);
|
||||
|
||||
await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-empty.json");
|
||||
|
||||
await workspacePage.goToWorkspace({
|
||||
fileId: "52c4e771-3853-8190-8007-9506c70e8100",
|
||||
pageId: "ecb0cfd0-0f0b-81f7-8007-950628f9665b",
|
||||
});
|
||||
|
||||
await workspacePage.clickToggableLayer("A");
|
||||
await workspacePage.clickToggableLayer("B");
|
||||
await workspacePage.clickToggableLayer("C");
|
||||
await workspacePage.clickLeafLayer("R2");
|
||||
|
||||
const heightText = workspacePage.rightSidebar.getByTitle("Height").getByPlaceholder('--');
|
||||
await heightText.fill("200");
|
||||
await heightText.press("Enter");
|
||||
|
||||
await workspacePage.clickLeafLayer("B");
|
||||
await expect(workspacePage.rightSidebar.getByTitle("Height").getByRole("textbox")).toHaveValue("340");
|
||||
|
||||
});
|
||||
|
||||
test("BUG 13468 - Fix problem with flex propagation", async ({ page }) => {
|
||||
const workspacePage = new WasmWorkspacePage(page);
|
||||
await workspacePage.setupEmptyFile();
|
||||
await workspacePage.mockGetFile("workspace/get-file-13468.json");
|
||||
|
||||
await workspacePage.mockRPC(
|
||||
"get-file-fragment?file-id=*&fragment-id=*",
|
||||
"workspace/get-file-13468-fragment.json",
|
||||
);
|
||||
|
||||
await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-empty.json");
|
||||
|
||||
await workspacePage.goToWorkspace({
|
||||
fileId: "3a4d7ec7-c391-8146-8007-9a05c41da6b9",
|
||||
pageId: "95b23c15-79f9-81ba-8007-99d81b5290dd",
|
||||
});
|
||||
0
|
||||
await workspacePage.clickToggableLayer("Parent");
|
||||
await workspacePage.clickToggableLayer("Container");
|
||||
|
||||
await workspacePage.sidebar.getByRole('button', { name: 'Show' }).click();
|
||||
|
||||
await workspacePage.clickLeafLayer("Container");
|
||||
await expect(workspacePage.rightSidebar.getByTitle("Height").getByRole("textbox")).toHaveValue("76");
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -483,3 +483,25 @@ test("Bug 8371 - Flatten option is not visible in context menu", async ({
|
||||
.filter({ visible: true }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("BUG 13415 - Grid layout overlay is not removed when deleting a board", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspacePage = new WasmWorkspacePage(page);
|
||||
await workspacePage.setupEmptyFile(page);
|
||||
await workspacePage.mockGetFile("workspace/get-file-13415.json");
|
||||
await workspacePage.mockRPC(
|
||||
"update-file?id=*",
|
||||
"workspace/update-file-13415.json",
|
||||
);
|
||||
|
||||
await workspacePage.goToWorkspace();
|
||||
await workspacePage.clickLeafLayer("Board");
|
||||
|
||||
const currentRenderCount = await workspacePage.getRenderCount();
|
||||
await workspacePage.page.keyboard.press("Delete");
|
||||
|
||||
await workspacePage.waitForNextRender(currentRenderCount);
|
||||
await workspacePage.hideUI();
|
||||
await expect(workspacePage.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 9.3 KiB |
@@ -3,11 +3,6 @@ import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test("User goes to an empty dashboard", async ({ page }) => {
|
||||
|
||||
@@ -2,6 +2,8 @@ import { test, expect } from "@playwright/test";
|
||||
import { LoginPage } from "../pages/LoginPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await LoginPage.init(page);
|
||||
|
||||
const login = new LoginPage(page);
|
||||
await login.initWithLoggedOutUser();
|
||||
await login.page.goto("/#/auth/login");
|
||||
|
||||
4
frontend/pnpm-lock.yaml
generated
@@ -20,8 +20,8 @@ importers:
|
||||
specifier: workspace:./packages/mousetrap
|
||||
version: link:packages/mousetrap
|
||||
'@penpot/plugins-runtime':
|
||||
specifier: link:../plugins/libs/plugins-runtime
|
||||
version: link:../plugins/libs/plugins-runtime
|
||||
specifier: link:../plugins/dist/plugins-runtime
|
||||
version: link:../plugins/dist/plugins-runtime
|
||||
'@penpot/svgo':
|
||||
specifier: penpot/svgo#v3.2
|
||||
version: svgo@https://codeload.github.com/penpot/svgo/tar.gz/8c9b0e32e9cb5f106085260bd9375f3c91a5010b
|
||||
|
||||
@@ -39,14 +39,6 @@ rm -rf node_modules;
|
||||
WS_URI="/mcp/ws" pnpm run --filter "mcp-plugin" build:multi-user
|
||||
popd;
|
||||
|
||||
pushd ../plugins
|
||||
rm -rf node_modules;
|
||||
rm -rf dist/apps/;
|
||||
corepack install;
|
||||
pnpm -r install;
|
||||
pnpm run build:plugins;
|
||||
popd
|
||||
|
||||
pnpm run build:app:main $EXTRA_PARAMS;
|
||||
pnpm run build:app:libs;
|
||||
pnpm run build:app:assets;
|
||||
@@ -55,11 +47,6 @@ sed -i "s/\.\/render.js/.\/render.js?version=$VERSION_TAG/g" resources/public/js
|
||||
|
||||
rsync -avr resources/public/ target/dist/
|
||||
|
||||
|
||||
# Include all plugins on the bundle
|
||||
rsync -avr ../plugins/dist/apps/ target/dist/plugins/;
|
||||
|
||||
# Include the MCP plugin on the bundle
|
||||
mkdir -p target/dist/plugins/mcp;
|
||||
rsync -avr ../mcp/packages/plugin/dist/ target/dist/plugins/mcp/;
|
||||
|
||||
mkdir -p target/dist/plugins/mcp/;
|
||||
rsync -avr ../mcp/packages/plugin/dist/ target/dist/plugins/mcp/
|
||||
|
||||
@@ -66,22 +66,22 @@
|
||||
(update-in state [:workspace-local :open-plugins] (fnil disj #{}) id))))
|
||||
|
||||
(defn- load-plugin!
|
||||
[{:keys [plugin-id name version description host code icon permissions]}]
|
||||
[{:keys [plugin-id name description host code icon permissions]}]
|
||||
(try
|
||||
(st/emit! (save-current-plugin plugin-id)
|
||||
(reset-plugin-flags plugin-id))
|
||||
|
||||
(.ɵloadPlugin ^js ug/global
|
||||
#js {:pluginId plugin-id
|
||||
:name name
|
||||
:description description
|
||||
:version version
|
||||
:host host
|
||||
:code code
|
||||
:icon icon
|
||||
:permissions (apply array permissions)}
|
||||
(fn []
|
||||
(st/emit! (remove-current-plugin plugin-id))))
|
||||
(.ɵloadPlugin
|
||||
^js ug/global
|
||||
#js {:pluginId plugin-id
|
||||
:name name
|
||||
:description description
|
||||
:host host
|
||||
:code code
|
||||
:icon icon
|
||||
:permissions (apply array permissions)}
|
||||
(fn []
|
||||
(st/emit! (remove-current-plugin plugin-id))))
|
||||
|
||||
(catch :default e
|
||||
(st/emit! (remove-current-plugin plugin-id))
|
||||
|
||||
@@ -222,9 +222,16 @@
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc :thumbnails thumbnails)
|
||||
(update :files assoc file-id file)))))
|
||||
(let [pending-version-id (:workspace-pending-file-version-id state)
|
||||
state (-> state
|
||||
(assoc :thumbnails thumbnails)
|
||||
(update :files assoc file-id file)
|
||||
(dissoc :workspace-pending-file-version-id))]
|
||||
(cond-> state
|
||||
(some? pending-version-id)
|
||||
(assoc :workspace-file-version-id pending-version-id)
|
||||
(nil? pending-version-id)
|
||||
(dissoc :workspace-file-version-id))))))
|
||||
|
||||
(defn zoom-to-frame
|
||||
[]
|
||||
@@ -280,192 +287,197 @@
|
||||
(wasm.api/process-object shape))))))
|
||||
|
||||
(defn initialize-workspace
|
||||
[team-id file-id]
|
||||
(assert (uuid? team-id) "expected valud uuid for `team-id`")
|
||||
(assert (uuid? file-id) "expected valud uuid for `file-id`")
|
||||
([team-id file-id]
|
||||
(initialize-workspace team-id file-id nil))
|
||||
([team-id file-id version-id]
|
||||
(assert (uuid? team-id) "expected valud uuid for `team-id`")
|
||||
(assert (uuid? file-id) "expected valud uuid for `file-id`")
|
||||
|
||||
(ptk/reify ::initialize-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc :recent-colors (:recent-colors storage/user))
|
||||
(assoc :recent-fonts (:recent-fonts storage/user))
|
||||
(assoc :current-file-id file-id)
|
||||
(assoc :workspace-presence {})))
|
||||
(ptk/reify ::initialize-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc :recent-colors (:recent-colors storage/user))
|
||||
(assoc :recent-fonts (:recent-fonts storage/user))
|
||||
(assoc :current-file-id file-id)
|
||||
(assoc :workspace-presence {})
|
||||
;; Store pending version-id; bundle-fetched will set workspace-file-version-id
|
||||
;; when the new bundle is applied so the viewport re-inits with new data
|
||||
(assoc :workspace-pending-file-version-id version-id)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
||||
rparams (rt/get-params state)
|
||||
features (features/get-enabled-features state team-id)
|
||||
render-wasm? (contains? features "render-wasm/v1")]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
||||
rparams (rt/get-params state)
|
||||
features (features/get-enabled-features state team-id)
|
||||
render-wasm? (contains? features "render-wasm/v1")]
|
||||
|
||||
(log/debug :hint "initialize-workspace"
|
||||
:team-id (dm/str team-id)
|
||||
:file-id (dm/str file-id))
|
||||
(log/debug :hint "initialize-workspace"
|
||||
:team-id (dm/str team-id)
|
||||
:file-id (dm/str file-id))
|
||||
|
||||
(->> (rx/merge
|
||||
(rx/concat
|
||||
;; Fetch all essential data that should be loaded before the file
|
||||
(rx/merge
|
||||
(if ^boolean render-wasm?
|
||||
(->> (rx/from @wasm/module)
|
||||
(rx/filter true?)
|
||||
(rx/tap (fn [_]
|
||||
(let [event (ug/event "penpot:wasm:loaded")]
|
||||
(ug/dispatch! event))))
|
||||
(rx/ignore))
|
||||
(rx/empty))
|
||||
(->> (rx/merge
|
||||
(rx/concat
|
||||
;; Fetch all essential data that should be loaded before the file
|
||||
(rx/merge
|
||||
(if ^boolean render-wasm?
|
||||
(->> (rx/from @wasm/module)
|
||||
(rx/filter true?)
|
||||
(rx/tap (fn [_]
|
||||
(let [event (ug/event "penpot:wasm:loaded")]
|
||||
(ug/dispatch! event))))
|
||||
(rx/ignore))
|
||||
(rx/empty))
|
||||
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::df/fonts-loaded))
|
||||
(rx/take 1)
|
||||
(rx/ignore))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::df/fonts-loaded))
|
||||
(rx/take 1)
|
||||
(rx/ignore))
|
||||
|
||||
(rx/of (ntf/hide)
|
||||
(dcmt/retrieve-comment-threads file-id)
|
||||
(dcmt/fetch-profiles)
|
||||
(df/fetch-fonts team-id)))
|
||||
(rx/of (ntf/hide)
|
||||
(dcmt/retrieve-comment-threads file-id)
|
||||
(dcmt/fetch-profiles)
|
||||
(df/fetch-fonts team-id)))
|
||||
|
||||
;; Once the essential data is fetched, lets proceed to
|
||||
;; fetch teh file bunldle
|
||||
(rx/of (fetch-bundle file-id features)))
|
||||
;; Once the essential data is fetched, lets proceed to
|
||||
;; fetch teh file bunldle
|
||||
(rx/of (fetch-bundle file-id features)))
|
||||
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::bundle-fetched))
|
||||
(rx/take 1)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [file]}]
|
||||
(log/debug :hint "bundle fetched"
|
||||
:team-id (dm/str team-id)
|
||||
:file-id (dm/str file-id))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::bundle-fetched))
|
||||
(rx/take 1)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [file]}]
|
||||
(log/debug :hint "bundle fetched"
|
||||
:team-id (dm/str team-id)
|
||||
:file-id (dm/str file-id))
|
||||
|
||||
(rx/of (dpj/initialize-project (:project-id file))
|
||||
(dwn/initialize team-id file-id)
|
||||
(dwsl/initialize-shape-layout)
|
||||
(fetch-libraries file-id features)
|
||||
(-> (workspace-initialized file-id)
|
||||
(with-meta {:team-id team-id
|
||||
:file-id file-id}))))))
|
||||
(rx/of (dpj/initialize-project (:project-id file))
|
||||
(dwn/initialize team-id file-id)
|
||||
(dwsl/initialize-shape-layout)
|
||||
(fetch-libraries file-id features)
|
||||
(-> (workspace-initialized file-id)
|
||||
(with-meta {:team-id team-id
|
||||
:file-id file-id}))))))
|
||||
|
||||
;; Install dev perf observers once the workspace is ready
|
||||
(when (contains? cf/flags :perf-logs)
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-initialized))
|
||||
(rx/take 1)
|
||||
(rx/tap (fn [_] (perf/setup)))))
|
||||
;; Install dev perf observers once the workspace is ready
|
||||
(when (contains? cf/flags :perf-logs)
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-initialized))
|
||||
(rx/take 1)
|
||||
(rx/tap (fn [_] (perf/setup)))))
|
||||
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dps/persistence-notification))
|
||||
(rx/take 1)
|
||||
(rx/map dwc/set-workspace-visited))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dps/persistence-notification))
|
||||
(rx/take 1)
|
||||
(rx/map dwc/set-workspace-visited))
|
||||
|
||||
(when-let [component-id (some-> rparams :component-id uuid/parse)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-initialized))
|
||||
(rx/observe-on :async)
|
||||
(rx/take 1)
|
||||
(rx/map #(dwl/go-to-local-component :id component-id :update-layout? (:update-layout rparams)))))
|
||||
(when-let [component-id (some-> rparams :component-id uuid/parse)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-initialized))
|
||||
(rx/observe-on :async)
|
||||
(rx/take 1)
|
||||
(rx/map #(dwl/go-to-local-component :id component-id :update-layout? (:update-layout rparams)))))
|
||||
|
||||
(when (:board-id rparams)
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dwv/initialize-viewport))
|
||||
(rx/take 1)
|
||||
(rx/map zoom-to-frame)))
|
||||
(when (:board-id rparams)
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dwv/initialize-viewport))
|
||||
(rx/take 1)
|
||||
(rx/map zoom-to-frame)))
|
||||
|
||||
(when-let [comment-id (some-> rparams :comment-id uuid/parse)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-initialized))
|
||||
(rx/observe-on :async)
|
||||
(rx/take 1)
|
||||
(rx/map #(dwcm/navigate-to-comment-id comment-id))))
|
||||
(when-let [comment-id (some-> rparams :comment-id uuid/parse)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-initialized))
|
||||
(rx/observe-on :async)
|
||||
(rx/take 1)
|
||||
(rx/map #(dwcm/navigate-to-comment-id comment-id))))
|
||||
|
||||
(when render-wasm?
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [redo-changes]}]
|
||||
(let [added (->> redo-changes
|
||||
(filter #(= (:type %) :add-obj))
|
||||
(map :id))]
|
||||
(->> (rx/from added)
|
||||
(rx/map process-wasm-object)))))))
|
||||
(when render-wasm?
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [redo-changes]}]
|
||||
(let [added (->> redo-changes
|
||||
(filter #(= (:type %) :add-obj))
|
||||
(map :id))]
|
||||
(->> (rx/from added)
|
||||
(rx/map process-wasm-object)))))))
|
||||
|
||||
(when render-wasm?
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(and (= :local (:source %))
|
||||
(not (contains? (:tags %) :position-data))))
|
||||
(rx/filter (complement empty?)))
|
||||
(when render-wasm?
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(and (= :local (:source %))
|
||||
(not (contains? (:tags %) :position-data))))
|
||||
(rx/filter (complement empty?)))
|
||||
|
||||
notifier-s
|
||||
(rx/merge
|
||||
(->> local-commits-s (rx/debounce 1000))
|
||||
(->> stream (rx/filter dps/force-persist?)))
|
||||
notifier-s
|
||||
(rx/merge
|
||||
(->> local-commits-s (rx/debounce 1000))
|
||||
(->> stream (rx/filter dps/force-persist?)))
|
||||
|
||||
objects-s
|
||||
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
|
||||
objects-s
|
||||
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
|
||||
|
||||
current-page-id-s
|
||||
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
|
||||
current-page-id-s
|
||||
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
|
||||
|
||||
(->> local-commits-s
|
||||
(rx/buffer-until notifier-s)
|
||||
(rx/with-latest-from objects-s)
|
||||
(rx/map
|
||||
(fn [[commits objects]]
|
||||
(->> commits
|
||||
(mapcat :redo-changes)
|
||||
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
|
||||
(filter #(cfh/text-shape? objects (:id %)))
|
||||
(map #(vector
|
||||
(:id %)
|
||||
(wasm.api/calculate-position-data (get objects (:id %))))))))
|
||||
(->> local-commits-s
|
||||
(rx/buffer-until notifier-s)
|
||||
(rx/with-latest-from objects-s)
|
||||
(rx/map
|
||||
(fn [[commits objects]]
|
||||
(->> commits
|
||||
(mapcat :redo-changes)
|
||||
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
|
||||
(filter #(cfh/text-shape? objects (:id %)))
|
||||
(map #(vector
|
||||
(:id %)
|
||||
(wasm.api/calculate-position-data (get objects (:id %))))))))
|
||||
|
||||
(rx/with-latest-from current-page-id-s)
|
||||
(rx/map
|
||||
(fn [[text-position-data page-id]]
|
||||
(let [changes
|
||||
(->> text-position-data
|
||||
(mapv (fn [[id position-data]]
|
||||
{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations
|
||||
[{:type :set
|
||||
:attr :position-data
|
||||
:val position-data
|
||||
:ignore-touched true
|
||||
:ignore-geometry true}]})))]
|
||||
(when (d/not-empty? changes)
|
||||
(dch/commit-changes
|
||||
{:redo-changes changes :undo-changes []
|
||||
:save-undo? false
|
||||
:tags #{:position-data}})))))
|
||||
(rx/take-until stoper-s))))
|
||||
(rx/with-latest-from current-page-id-s)
|
||||
(rx/map
|
||||
(fn [[text-position-data page-id]]
|
||||
(let [changes
|
||||
(->> text-position-data
|
||||
(mapv (fn [[id position-data]]
|
||||
{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations
|
||||
[{:type :set
|
||||
:attr :position-data
|
||||
:val position-data
|
||||
:ignore-touched true
|
||||
:ignore-geometry true}]})))]
|
||||
(when (d/not-empty? changes)
|
||||
(dch/commit-changes
|
||||
{:redo-changes changes :undo-changes []
|
||||
:save-undo? false
|
||||
:tags #{:position-data}})))))
|
||||
(rx/take-until stoper-s))))
|
||||
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [save-undo? undo-changes redo-changes undo-group tags stack-undo?]}]
|
||||
(if (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes undo-changes
|
||||
:redo-changes redo-changes
|
||||
:undo-group undo-group
|
||||
:tags tags}]
|
||||
(rx/of (dwu/append-undo entry stack-undo?)))
|
||||
(rx/empty))))))
|
||||
(rx/take-until stoper-s))))
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [save-undo? undo-changes redo-changes undo-group tags stack-undo?]}]
|
||||
(if (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes undo-changes
|
||||
:redo-changes redo-changes
|
||||
:undo-group undo-group
|
||||
:tags tags}]
|
||||
(rx/of (dwu/append-undo entry stack-undo?)))
|
||||
(rx/empty))))))
|
||||
(rx/take-until stoper-s))))
|
||||
|
||||
ptk/EffectEvent
|
||||
(effect [_ _ _]
|
||||
(let [name (dm/str "workspace-" file-id)]
|
||||
(unchecked-set ug/global "name" name)))))
|
||||
ptk/EffectEvent
|
||||
(effect [_ _ _]
|
||||
(let [name (dm/str "workspace-" file-id)]
|
||||
(unchecked-set ug/global "name" name))))))
|
||||
|
||||
(defn finalize-workspace
|
||||
[_team-id file-id]
|
||||
|
||||
@@ -197,11 +197,12 @@
|
||||
objects (:objects page)
|
||||
|
||||
undo-id (or (:undo-id options) (js/Symbol))
|
||||
[all-parents changes] (-> (pcb/empty-changes it (:id page))
|
||||
(cls/generate-delete-shapes fdata page objects ids
|
||||
{:ignore-touched (:allow-altering-copies options)
|
||||
:undo-group (:undo-group options)
|
||||
:undo-id undo-id}))]
|
||||
[all-parents changes]
|
||||
(-> (pcb/empty-changes it (:id page))
|
||||
(cls/generate-delete-shapes fdata page objects ids
|
||||
{:ignore-touched (:allow-altering-copies options)
|
||||
:undo-group (:undo-group options)
|
||||
:undo-id undo-id}))]
|
||||
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dc/detach-comment-thread ids)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.attrs :as attrs]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
@@ -19,6 +20,7 @@
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.text :as txt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
@@ -916,11 +918,11 @@
|
||||
(update-in state [:workspace-text-modifier shape-id] {:position-data position-data}))))
|
||||
|
||||
(defn v2-update-text-shape-content
|
||||
[id content & {:keys [update-name? name finalize? save-undo?]
|
||||
:or {update-name? false name nil finalize? false save-undo? true}}]
|
||||
[id content & {:keys [update-name? name finalize? save-undo? original-content]
|
||||
:or {update-name? false name nil finalize? false save-undo? true original-content nil}}]
|
||||
(ptk/reify ::v2-update-text-shape-content
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(watch [it state _]
|
||||
(if (features/active-feature? state "render-wasm/v1")
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
@@ -950,11 +952,11 @@
|
||||
new-shape))
|
||||
{:save-undo? save-undo? :undo-group (when new-shape? id)})
|
||||
|
||||
(let [modifiers (dwwt/resize-wasm-text-modifiers shape content)
|
||||
options {:undo-group (when new-shape? id)}]
|
||||
(if (and (not= :fixed (:grow-type shape)) finalize?)
|
||||
(dwm/apply-wasm-modifiers modifiers options)
|
||||
(dwm/set-wasm-modifiers modifiers options))))
|
||||
(when-let [modifiers (dwwt/resize-wasm-text-modifiers shape content)]
|
||||
(let [options {:undo-group (when new-shape? id)}]
|
||||
(if (and (not= :fixed (:grow-type shape)) finalize?)
|
||||
(dwm/apply-wasm-modifiers modifiers options)
|
||||
(dwm/set-wasm-modifiers modifiers options)))))
|
||||
|
||||
(when finalize?
|
||||
(rx/concat
|
||||
@@ -970,7 +972,13 @@
|
||||
{:save-undo? false}))
|
||||
(dws/deselect-shape id)
|
||||
(dwsh/delete-shapes #{id})))
|
||||
(rx/of (dwt/finish-transform))))))
|
||||
(rx/of
|
||||
;; This commit is necesary for undo and component propagation
|
||||
;; on finalization
|
||||
(dch/commit-changes
|
||||
(-> (pcb/empty-changes it (:current-page-id state))
|
||||
(pcb/set-text-content id content original-content)))
|
||||
(dwt/finish-transform))))))
|
||||
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
(rx/take 1)
|
||||
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
|
||||
(rx/tap #(th/clear-queue!))
|
||||
(rx/map #(dw/initialize-workspace team-id file-id)))
|
||||
(rx/map #(dw/initialize-workspace team-id file-id id)))
|
||||
(case origin
|
||||
:version
|
||||
(rx/of (ptk/event ::ev/event {::ev/name "restore-pin-version"}))
|
||||
@@ -231,7 +231,7 @@
|
||||
(rx/filter #(or (nil? %) (= :saved %)))
|
||||
(rx/take 1)
|
||||
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
|
||||
(rx/map #(dw/initialize-workspace team-id file-id)))
|
||||
(rx/map #(dw/initialize-workspace team-id file-id id)))
|
||||
|
||||
(->> (rx/of 1)
|
||||
(rx/tap resolve)
|
||||
|
||||
@@ -27,27 +27,28 @@
|
||||
(resize-wasm-text-modifiers shape (:content shape)))
|
||||
|
||||
([{:keys [id points selrect grow-type] :as shape} content]
|
||||
(wasm.api/use-shape id)
|
||||
(wasm.api/set-shape-text-content id content)
|
||||
(wasm.api/set-shape-text-images id content)
|
||||
(when id
|
||||
(wasm.api/use-shape id)
|
||||
(wasm.api/set-shape-text-content id content)
|
||||
(wasm.api/set-shape-text-images id content)
|
||||
|
||||
(let [dimension (wasm.api/get-text-dimensions)
|
||||
width-scale (if (#{:fixed :auto-height} grow-type)
|
||||
1.0
|
||||
(/ (:width dimension) (:width selrect)))
|
||||
height-scale (if (= :fixed grow-type)
|
||||
1.0
|
||||
(/ (:height dimension) (:height selrect)))
|
||||
resize-v (gpt/point width-scale height-scale)
|
||||
origin (first points)]
|
||||
(let [dimension (wasm.api/get-text-dimensions)
|
||||
width-scale (if (#{:fixed :auto-height} grow-type)
|
||||
1.0
|
||||
(/ (:width dimension) (:width selrect)))
|
||||
height-scale (if (= :fixed grow-type)
|
||||
1.0
|
||||
(/ (:height dimension) (:height selrect)))
|
||||
resize-v (gpt/point width-scale height-scale)
|
||||
origin (first points)]
|
||||
|
||||
{id
|
||||
{:modifiers
|
||||
(ctm/resize-modifiers
|
||||
resize-v
|
||||
origin
|
||||
(:transform shape (gmt/matrix))
|
||||
(:transform-inverse shape (gmt/matrix)))}})))
|
||||
{id
|
||||
{:modifiers
|
||||
(ctm/resize-modifiers
|
||||
resize-v
|
||||
origin
|
||||
(:transform shape (gmt/matrix))
|
||||
(:transform-inverse shape (gmt/matrix)))}}))))
|
||||
|
||||
(defn resize-wasm-text
|
||||
"Resize a single text shape (auto-width/auto-height) by id.
|
||||
|
||||
@@ -256,6 +256,9 @@
|
||||
(def workspace-layout
|
||||
(l/derived :workspace-layout st/state))
|
||||
|
||||
(def workspace-file-version-id
|
||||
(l/derived :workspace-file-version-id st/state))
|
||||
|
||||
(def snap-pixel?
|
||||
(l/derived #(contains? % :snap-pixel-grid) workspace-layout))
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc search-bar*
|
||||
[{:keys [id class value placeholder icon-id auto-focus on-change on-clear on-submit children]}]
|
||||
[{:keys [id class value placeholder icon-id auto-focus on-change on-clear children]}]
|
||||
(let [handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
@@ -31,19 +31,12 @@
|
||||
|
||||
handle-key-down
|
||||
(mf/use-fn
|
||||
(mf/deps on-submit)
|
||||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)
|
||||
node (dom/get-target event)]
|
||||
(when ^boolean enter?
|
||||
(dom/blur! node)
|
||||
(when (fn? on-submit)
|
||||
(let [value (dom/get-target-val event)]
|
||||
(on-submit value event))))
|
||||
|
||||
(when ^boolean enter? (dom/blur! node))
|
||||
(when ^boolean esc? (dom/blur! node)))))]
|
||||
|
||||
[:span {:class (stl/css-case :search-box true
|
||||
:has-children (some? children))}
|
||||
children
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
(mf/defc workspace-content*
|
||||
{::mf/private true}
|
||||
[{:keys [file layout page wglobal]}]
|
||||
[{:keys [file layout page wglobal file-version-id]}]
|
||||
|
||||
(let [palete-size (mf/use-state nil)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
@@ -109,6 +109,7 @@
|
||||
:wglobal wglobal
|
||||
:selected selected
|
||||
:layout layout
|
||||
:file-version-id file-version-id
|
||||
:palete-size
|
||||
(when (and (or colorpalette? textpalette?) (not hide-ui?))
|
||||
@palete-size)}]]]
|
||||
@@ -168,7 +169,7 @@
|
||||
|
||||
(mf/defc workspace-inner*
|
||||
{::mf/private true}
|
||||
[{:keys [page-id file-id file layout wglobal]}]
|
||||
[{:keys [page-id file-id file layout wglobal file-version-id]}]
|
||||
(let [page-ref (mf/with-memo [file-id page-id]
|
||||
(make-page-ref file-id page-id))
|
||||
page (mf/deref page-ref)]
|
||||
@@ -187,7 +188,8 @@
|
||||
[:> workspace-content* {:file file
|
||||
:page page
|
||||
:wglobal wglobal
|
||||
:layout layout}]
|
||||
:layout layout
|
||||
:file-version-id file-version-id}]
|
||||
[:> workspace-loader*])))
|
||||
|
||||
(mf/defc workspace*
|
||||
@@ -199,6 +201,7 @@
|
||||
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
wglobal (mf/deref refs/workspace-global)
|
||||
file-version-id (mf/deref refs/workspace-file-version-id)
|
||||
|
||||
team-ref (mf/with-memo [team-id]
|
||||
(make-team-ref team-id))
|
||||
@@ -274,7 +277,8 @@
|
||||
:file-id file-id
|
||||
:file file
|
||||
:wglobal wglobal
|
||||
:layout layout}])
|
||||
:layout layout
|
||||
:file-version-id file-version-id}])
|
||||
(when (or (not (and file-loaded? page-id))
|
||||
;; in wasm renderer, extend the pixel loader until the first frame is rendered
|
||||
;; but do not apply it when switching pages
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.uri :as u]
|
||||
[app.config :as cfg]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.modal :as modal]
|
||||
@@ -25,7 +24,6 @@
|
||||
[app.plugins.register :as preg]
|
||||
[app.util.avatars :as avatars]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as global]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
@@ -35,19 +33,7 @@
|
||||
(def ^:private close-icon
|
||||
(deprecated-icon/icon-xref :close (stl/css :close-icon)))
|
||||
|
||||
(defn- normalize-plugin-url
|
||||
"Automatically appens manifest.json if the plugin-uri comes without it."
|
||||
[plugin-url]
|
||||
(if (str/ends-with? plugin-url "manifest.json")
|
||||
plugin-url
|
||||
(-> (u/uri plugin-url)
|
||||
(update :path (fn [path]
|
||||
(if (str/ends-with? path "/")
|
||||
(str path "manifest.json")
|
||||
(str path "/manifest.json"))))
|
||||
(str))))
|
||||
|
||||
(defn- icon-url
|
||||
(defn icon-url
|
||||
"Creates an sanitizes de icon URL to display"
|
||||
[host icon]
|
||||
(dm/str host
|
||||
@@ -108,49 +94,48 @@
|
||||
::mf/register-as :plugin-management}
|
||||
[]
|
||||
|
||||
(let [plugins-state* (mf/use-state #(preg/plugins-list))
|
||||
plugins-state (deref plugins-state*)
|
||||
(let [plugins-state* (mf/use-state #(preg/plugins-list))
|
||||
plugins-state (deref plugins-state*)
|
||||
|
||||
plugin-url* (mf/use-state "")
|
||||
plugin-url (deref plugin-url*)
|
||||
plugin-url* (mf/use-state "")
|
||||
plugin-url (deref plugin-url*)
|
||||
|
||||
input-status* (mf/use-state nil) ;; :error-url :error-manifest :success
|
||||
input-status (deref input-status*)
|
||||
fetching-manifest? (mf/use-state false)
|
||||
|
||||
error-url? (= :error-url input-status)
|
||||
input-status* (mf/use-state nil) ;; :error-url :error-manifest :success
|
||||
input-status @input-status*
|
||||
|
||||
error-url? (= :error-url input-status)
|
||||
error-manifest? (= :error-manifest input-status)
|
||||
error? (or error-url? error-manifest?)
|
||||
error? (or error-url? error-manifest?)
|
||||
|
||||
permissions (mf/deref refs/permissions)
|
||||
user-can-edit? (get permissions :can-edit)
|
||||
user-can-edit? (:can-edit (deref refs/permissions))
|
||||
|
||||
fetching-manifest?
|
||||
(mf/use-state false)
|
||||
|
||||
on-url-change
|
||||
handle-url-input
|
||||
(mf/use-fn
|
||||
(fn [value]
|
||||
(reset! input-status* nil)
|
||||
(reset! plugin-url* value)))
|
||||
|
||||
on-install
|
||||
handle-install-click
|
||||
(mf/use-fn
|
||||
(mf/deps plugins-state plugin-url)
|
||||
(fn []
|
||||
(reset! fetching-manifest? true)
|
||||
(->> (dp/fetch-manifest (normalize-plugin-url plugin-url))
|
||||
(->> (dp/fetch-manifest plugin-url)
|
||||
(rx/subs!
|
||||
(fn [plugin]
|
||||
(reset! fetching-manifest? false)
|
||||
(if plugin
|
||||
(do
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "install-plugin" :name (:name plugin) :url plugin-url}))
|
||||
(modal/show! :plugin-permissions
|
||||
{:plugin plugin
|
||||
:on-accept
|
||||
#(do
|
||||
(preg/install-plugin! plugin)
|
||||
(modal/show! :plugin-management {}))})
|
||||
(modal/show!
|
||||
:plugin-permissions
|
||||
{:plugin plugin
|
||||
:on-accept
|
||||
#(do
|
||||
(preg/install-plugin! plugin)
|
||||
(modal/show! :plugin-management {}))})
|
||||
(reset! input-status* :success)
|
||||
(reset! plugin-url* ""))
|
||||
;; Cannot get the manifest
|
||||
@@ -160,7 +145,7 @@
|
||||
(reset! fetching-manifest? false)
|
||||
(reset! input-status* :error-url))))))
|
||||
|
||||
on-open-plugin
|
||||
handle-open-plugin
|
||||
(mf/use-fn
|
||||
(fn [manifest]
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "start-plugin"
|
||||
@@ -170,7 +155,7 @@
|
||||
(dp/open-plugin! manifest user-can-edit?)
|
||||
(modal/hide!)))
|
||||
|
||||
on-remove-plugin
|
||||
handle-remove-plugin
|
||||
(mf/use-fn
|
||||
(mf/deps plugins-state)
|
||||
(fn [plugin-index]
|
||||
@@ -190,16 +175,14 @@
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :top-bar)}
|
||||
[:> search-bar* {:on-change on-url-change
|
||||
:on-submit on-install
|
||||
[:> search-bar* {:on-change handle-url-input
|
||||
:value plugin-url
|
||||
:placeholder (tr "workspace.plugins.search-placeholder")
|
||||
:class (stl/css-case :input-error error?)}]
|
||||
|
||||
[:button {:class (stl/css :primary-button)
|
||||
:disabled @fetching-manifest?
|
||||
:on-click on-install}
|
||||
(tr "workspace.plugins.install")]]
|
||||
:on-click handle-install-click} (tr "workspace.plugins.install")]]
|
||||
|
||||
(when error-url?
|
||||
[:div {:class (stl/css-case :info true :error error?)}
|
||||
@@ -237,11 +220,10 @@
|
||||
:index idx
|
||||
:manifest manifest
|
||||
:user-can-edit user-can-edit?
|
||||
:on-open-plugin on-open-plugin
|
||||
:on-remove-plugin on-remove-plugin}])]])]]]))
|
||||
:on-open-plugin handle-open-plugin
|
||||
:on-remove-plugin handle-remove-plugin}])]])]]]))
|
||||
|
||||
(mf/defc plugins-permission-list*
|
||||
{::mf/private true}
|
||||
(mf/defc plugins-permission-list
|
||||
[{:keys [permissions]}]
|
||||
[:div {:class (stl/css :permissions-list)}
|
||||
(cond
|
||||
@@ -309,45 +291,36 @@
|
||||
::mf/register-as :plugin-permissions}
|
||||
[{:keys [plugin on-accept on-close]}]
|
||||
|
||||
(let [host
|
||||
(:host plugin)
|
||||
(let [{:keys [host permissions]} plugin
|
||||
permissions (set permissions)
|
||||
|
||||
permissions
|
||||
(-> plugin :permissions set)
|
||||
|
||||
on-accept-dialog
|
||||
handle-accept-dialog
|
||||
(mf/use-fn
|
||||
(mf/deps on-accept)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (ev/event {::ev/name "allow-plugin-permissions"
|
||||
:host host
|
||||
:permissions (str/join ", " permissions)})
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "allow-plugin-permissions"
|
||||
:host host
|
||||
:permissions (->> permissions (str/join ", "))})
|
||||
(modal/hide))
|
||||
(when on-accept (on-accept))))
|
||||
|
||||
on-close-dialog
|
||||
handle-close-dialog
|
||||
(mf/use-fn
|
||||
(mf/deps on-close)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (ev/event {::ev/name "reject-plugin-permissions"
|
||||
:host host
|
||||
:permissions (str/join ", " permissions)})
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "reject-plugin-permissions"
|
||||
:host host
|
||||
:permissions (->> permissions (str/join ", "))})
|
||||
(modal/hide))
|
||||
(when on-close (on-close))))]
|
||||
|
||||
(mf/with-effect [on-accept-dialog]
|
||||
(.addEventListener ^js global/document "keydown" on-accept-dialog)
|
||||
#(.removeEventListener ^js global/document "keydown" on-accept-dialog))
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog :plugin-permissions)}
|
||||
[:button {:class (stl/css :close-btn) :on-click on-close-dialog} close-icon]
|
||||
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon]
|
||||
[:div {:class (stl/css :modal-title)} (tr "workspace.plugins.permissions.title" (str/upper (:name plugin)))]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:> plugins-permission-list* {:permissions permissions}]
|
||||
[:& plugins-permission-list {:permissions permissions}]
|
||||
|
||||
(when-not (contains? cfg/plugins-whitelist host)
|
||||
[:div {:class (stl/css :permissions-disclaimer)}
|
||||
@@ -359,13 +332,13 @@
|
||||
{:class (stl/css :cancel-button :button-expand)
|
||||
:type "button"
|
||||
:value (tr "ds.confirm-cancel")
|
||||
:on-click on-close-dialog}]
|
||||
:on-click handle-close-dialog}]
|
||||
|
||||
[:input
|
||||
{:class (stl/css :primary-button :button-expand)
|
||||
:type "button"
|
||||
:value (tr "ds.confirm-allow")
|
||||
:on-click on-accept-dialog}]]]]]))
|
||||
:on-click handle-accept-dialog}]]]]]))
|
||||
|
||||
|
||||
(mf/defc plugins-permissions-updated-dialog
|
||||
@@ -373,15 +346,11 @@
|
||||
::mf/register-as :plugin-permissions-update}
|
||||
[{:keys [plugin on-accept on-close]}]
|
||||
|
||||
(let [host
|
||||
(:host plugin)
|
||||
(let [{:keys [host permissions]} plugin
|
||||
permissions (set permissions)
|
||||
|
||||
permissions
|
||||
(-> plugin :permissions set)
|
||||
|
||||
on-accept-dialog
|
||||
handle-accept-dialog
|
||||
(mf/use-fn
|
||||
(mf/deps on-accept)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "allow-plugin-permissions"
|
||||
@@ -390,9 +359,8 @@
|
||||
(modal/hide))
|
||||
(when on-accept (on-accept))))
|
||||
|
||||
on-close-dialog
|
||||
handle-close-dialog
|
||||
(mf/use-fn
|
||||
(mf/deps on-close)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "reject-plugin-permissions"
|
||||
@@ -401,20 +369,16 @@
|
||||
(modal/hide))
|
||||
(when on-close (on-close))))]
|
||||
|
||||
(mf/with-effect [on-accept-dialog]
|
||||
(.addEventListener ^js global/document "keydown" on-accept-dialog)
|
||||
#(.removeEventListener ^js global/document "keydown" on-accept-dialog))
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog :plugin-permissions)}
|
||||
[:button {:class (stl/css :close-btn) :on-click on-close-dialog} close-icon]
|
||||
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon]
|
||||
[:div {:class (stl/css :modal-title)}
|
||||
(tr "workspace.plugins.permissions-update.title" (str/upper (:name plugin)))]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-paragraph)}
|
||||
(tr "workspace.plugins.permissions-update.warning")]
|
||||
[:> plugins-permission-list* {:permissions permissions}]]
|
||||
[:& plugins-permission-list {:permissions permissions}]]
|
||||
|
||||
[:div {:class (stl/css :modal-footer)}
|
||||
[:div {:class (stl/css :action-buttons)}
|
||||
@@ -422,13 +386,13 @@
|
||||
{:class (stl/css :cancel-button :button-expand)
|
||||
:type "button"
|
||||
:value (tr "ds.confirm-cancel")
|
||||
:on-click on-close-dialog}]
|
||||
:on-click handle-close-dialog}]
|
||||
|
||||
[:input
|
||||
{:class (stl/css :primary-button :button-expand)
|
||||
:type "button"
|
||||
:value (tr "ds.confirm-allow")
|
||||
:on-click on-accept-dialog}]]]]]))
|
||||
:on-click handle-accept-dialog}]]]]]))
|
||||
|
||||
|
||||
(mf/defc plugins-try-out-dialog
|
||||
@@ -438,31 +402,25 @@
|
||||
|
||||
(let [{:keys [icon host name]} plugin
|
||||
|
||||
on-accept-dialog
|
||||
handle-accept-dialog
|
||||
(mf/use-fn
|
||||
(mf/deps on-accept)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "try-out-accept"})
|
||||
(modal/hide))
|
||||
(when on-accept (on-accept))))
|
||||
|
||||
on-close-dialog
|
||||
handle-close-dialog
|
||||
(mf/use-fn
|
||||
(mf/deps on-close)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "try-out-cancel"})
|
||||
(modal/hide))
|
||||
(when on-close (on-close))))]
|
||||
|
||||
(mf/with-effect [on-accept-dialog]
|
||||
(.addEventListener ^js global/document "keydown" on-accept-dialog)
|
||||
#(.removeEventListener ^js global/document "keydown" on-accept-dialog))
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog :plugin-try-out)}
|
||||
[:button {:class (stl/css :close-btn) :on-click on-close-dialog} close-icon]
|
||||
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon]
|
||||
[:div {:class (stl/css :modal-title)}
|
||||
[:div {:class (stl/css :plugin-icon)}
|
||||
[:img {:src (if (some? icon)
|
||||
@@ -480,10 +438,10 @@
|
||||
{:class (stl/css :cancel-button :button-expand)
|
||||
:type "button"
|
||||
:value (tr "workspace.plugins.try-out.cancel")
|
||||
:on-click on-close-dialog}]
|
||||
:on-click handle-close-dialog}]
|
||||
|
||||
[:input
|
||||
{:class (stl/css :primary-button :button-expand)
|
||||
:type "button"
|
||||
:value (tr "workspace.plugins.try-out.try")
|
||||
:on-click on-accept-dialog}]]]]]))
|
||||
:on-click handle-accept-dialog}]]]]]))
|
||||
|
||||
@@ -118,7 +118,8 @@
|
||||
:update-name? update-name?
|
||||
:name generated-name
|
||||
:finalize? true
|
||||
:save-undo? false))))
|
||||
:save-undo? false
|
||||
:original-content original-content))))
|
||||
|
||||
(let [container-node (mf/ref-val container-ref)]
|
||||
(dom/set-style! container-node "opacity" 0)))
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
:on-click on-select-shape
|
||||
:on-context-menu on-context-menu
|
||||
:data-testid "layer-row"
|
||||
:role "checkbox"
|
||||
:aria-checked selected?
|
||||
:class (stl/css-case
|
||||
:layer-row true
|
||||
:highlight highlighted?
|
||||
|
||||
@@ -540,7 +540,7 @@
|
||||
[:values schema:layout-item-props-schema]
|
||||
[:applied-tokens [:maybe [:map-of :keyword :string]]]
|
||||
[:ids [::sm/vec ::sm/uuid]]
|
||||
[:v-sizing {:optional true} [:maybe [:= :fill]]]])
|
||||
[:v-sizing {:optional true} [:maybe [:enum :fill :fix :auto]]]])
|
||||
|
||||
(mf/defc layout-size-constraints*
|
||||
{::mf/private true
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
objects)))
|
||||
|
||||
(mf/defc viewport*
|
||||
[{:keys [selected wglobal wlocal layout file page palete-size]}]
|
||||
[{:keys [selected wglobal wlocal layout file page palete-size file-version-id]}]
|
||||
(let [;; When adding data from workspace-local revisit `app.main.ui.workspace` to check
|
||||
;; that the new parameter is sent
|
||||
{:keys [edit-path
|
||||
@@ -141,6 +141,7 @@
|
||||
|
||||
canvas-ref (mf/use-ref nil)
|
||||
text-editor-ref (mf/use-ref nil)
|
||||
last-file-version-id-ref (mf/use-ref nil)
|
||||
|
||||
;; STATE REFS
|
||||
disable-paste-ref (mf/use-ref false)
|
||||
@@ -223,8 +224,9 @@
|
||||
show-gradient-handlers? (= (count selected) 1)
|
||||
show-grids? (contains? layout :display-guides)
|
||||
|
||||
show-frame-outline? (= transform :move)
|
||||
show-frame-outline? (and (= transform :move) (not panning))
|
||||
show-outlines? (and (nil? transform)
|
||||
(not panning)
|
||||
(not edition)
|
||||
(not drawing-obj)
|
||||
(not (#{:comments :path :curve} drawing-tool)))
|
||||
@@ -344,11 +346,18 @@
|
||||
(when (and @canvas-init? preview-blend)
|
||||
(wasm.api/request-render "with-effect")))
|
||||
|
||||
(mf/with-effect [@canvas-init? zoom vbox background]
|
||||
(when (and @canvas-init? (not @initialized?))
|
||||
(wasm.api/clear-canvas-pixels)
|
||||
(wasm.api/initialize-viewport base-objects zoom vbox background)
|
||||
(reset! initialized? true)))
|
||||
(mf/with-effect [@canvas-init? file-version-id zoom vbox background]
|
||||
(when @canvas-init?
|
||||
(if (not @initialized?)
|
||||
(do
|
||||
(wasm.api/clear-canvas-pixels)
|
||||
(wasm.api/initialize-viewport base-objects zoom vbox background)
|
||||
(reset! initialized? true)
|
||||
(mf/set-ref-val! last-file-version-id-ref file-version-id))
|
||||
(when (and (some? file-version-id)
|
||||
(not= file-version-id (mf/ref-val last-file-version-id-ref)))
|
||||
(wasm.api/initialize-viewport base-objects zoom vbox background)
|
||||
(mf/set-ref-val! last-file-version-id-ref file-version-id)))))
|
||||
|
||||
(mf/with-effect [focus]
|
||||
(when (and @canvas-init? @initialized?)
|
||||
@@ -553,7 +562,7 @@
|
||||
:shift? @shift?}])
|
||||
|
||||
[:> widgets/frame-titles*
|
||||
{:objects (with-meta objects-modified nil)
|
||||
{:objects objects-modified
|
||||
:selected selected
|
||||
:zoom zoom
|
||||
:is-show-artboard-names show-artboard-names?
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
(d/without-nils
|
||||
{:plugin-id plugin-id
|
||||
:url (str plugin-url)
|
||||
:version vers
|
||||
:name name
|
||||
:description desc
|
||||
:host origin
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
[rumext.v2 :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(def caret-blink-interval-ms 250)
|
||||
|
||||
(defn- sync-wasm-text-editor-content!
|
||||
"Sync WASM text editor content back to the shape via the standard
|
||||
commit pipeline. Called after every text-modifying input."
|
||||
@@ -54,18 +56,17 @@
|
||||
(.focus node))
|
||||
js/undefined))
|
||||
|
||||
;; Animation loop for cursor blink
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(let [raf-id (atom nil)
|
||||
animate (fn animate []
|
||||
(when (text-editor/text-editor-is-active?)
|
||||
(wasm.api/request-render "cursor-blink")
|
||||
(reset! raf-id (js/requestAnimationFrame animate))))]
|
||||
(animate)
|
||||
(let [timeout-id (atom nil)
|
||||
schedule-blink (fn schedule-blink []
|
||||
(when (text-editor/text-editor-is-active?)
|
||||
(wasm.api/request-render "cursor-blink"))
|
||||
(reset! timeout-id (js/setTimeout schedule-blink caret-blink-interval-ms)))]
|
||||
(schedule-blink)
|
||||
(fn []
|
||||
(when @raf-id
|
||||
(js/cancelAnimationFrame @raf-id))))))
|
||||
(when @timeout-id
|
||||
(js/clearTimeout @timeout-id))))))
|
||||
|
||||
;; Document-level keydown handler for control keys
|
||||
(mf/use-effect
|
||||
|
||||
@@ -642,13 +642,15 @@ export class SelectionController extends EventTarget {
|
||||
} else {
|
||||
this.#anchorNode = anchorNode;
|
||||
this.#anchorOffset = anchorOffset;
|
||||
if (anchorNode === focusNode) {
|
||||
this.#focusNode = this.#anchorNode;
|
||||
this.#focusOffset = this.#anchorOffset;
|
||||
this.#focusNode = focusNode;
|
||||
this.#focusOffset = focusOffset;
|
||||
// setPosition() collapses the selection to a single caret. We must only use it
|
||||
// when anchorOffset === focusOffset. When both points are in the same node but
|
||||
// offsets differ (e.g. selecting "hola" in "hola adios"), we need setBaseAndExtent()
|
||||
// to preserve the range so we don't incorrectly collapse ranges and lose the selection.
|
||||
if (anchorNode === focusNode && anchorOffset === focusOffset) {
|
||||
this.#selection.setPosition(anchorNode, anchorOffset);
|
||||
} else {
|
||||
this.#focusNode = focusNode;
|
||||
this.#focusOffset = focusOffset;
|
||||
this.#selection.setBaseAndExtent(
|
||||
anchorNode,
|
||||
anchorOffset,
|
||||
|
||||
@@ -12,10 +12,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:application",
|
||||
"options": {
|
||||
"outputPath": {
|
||||
"base": "dist/apps/contrast-plugin",
|
||||
"browser": ""
|
||||
},
|
||||
"outputPath": "dist/apps/contrast-plugin",
|
||||
"index": "apps/contrast-plugin/src/index.html",
|
||||
"browser": "apps/contrast-plugin/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
@@ -23,7 +20,6 @@
|
||||
"assets": [
|
||||
"apps/contrast-plugin/src/_headers",
|
||||
"apps/contrast-plugin/src/favicon.ico",
|
||||
"apps/contrast-plugin/src/manifest.json",
|
||||
"apps/contrast-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -92,7 +88,6 @@
|
||||
"assets": [
|
||||
"apps/icons-plugin/src/_headers",
|
||||
"apps/icons-plugin/src/favicon.ico",
|
||||
"apps/icons-plugin/src/manifest.json",
|
||||
"apps/icons-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -161,7 +156,6 @@
|
||||
"assets": [
|
||||
"apps/lorem-ipsum-plugin/src/_headers",
|
||||
"apps/lorem-ipsum-plugin/src/favicon.ico",
|
||||
"apps/lorem-ipsum-plugin/src/manifest.json",
|
||||
"apps/lorem-ipsum-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -224,10 +218,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:application",
|
||||
"options": {
|
||||
"outputPath": {
|
||||
"base": "dist/apps/table-plugin",
|
||||
"browser": ""
|
||||
},
|
||||
"outputPath": "dist/apps/table-plugin",
|
||||
"index": "apps/table-plugin/src/index.html",
|
||||
"browser": "apps/table-plugin/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
@@ -235,7 +226,6 @@
|
||||
"assets": [
|
||||
"apps/table-plugin/src/_headers",
|
||||
"apps/table-plugin/src/favicon.ico",
|
||||
"apps/table-plugin/src/manifest.json",
|
||||
"apps/table-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -304,7 +294,6 @@
|
||||
"assets": [
|
||||
"apps/rename-layers-plugin/src/_headers",
|
||||
"apps/rename-layers-plugin/src/favicon.ico",
|
||||
"apps/rename-layers-plugin/src/manifest.json",
|
||||
"apps/rename-layers-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -367,10 +356,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:application",
|
||||
"options": {
|
||||
"outputPath": {
|
||||
"base": "dist/apps/colors-to-tokens-plugin",
|
||||
"browser": ""
|
||||
},
|
||||
"outputPath": "dist/apps/colors-to-tokens-plugin",
|
||||
"index": "apps/colors-to-tokens-plugin/src/index.html",
|
||||
"browser": "apps/colors-to-tokens-plugin/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
@@ -378,7 +364,6 @@
|
||||
"assets": [
|
||||
"apps/colors-to-tokens-plugin/src/_headers",
|
||||
"apps/colors-to-tokens-plugin/src/favicon.ico",
|
||||
"apps/colors-to-tokens-plugin/src/manifest.json",
|
||||
"apps/colors-to-tokens-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -448,7 +433,6 @@
|
||||
"tsConfig": "apps/poc-state-plugin/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/poc-state-plugin/src/favicon.ico",
|
||||
"apps/poc-state-plugin/src/manifest.json",
|
||||
"apps/poc-state-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
@@ -519,7 +503,6 @@
|
||||
"assets": [
|
||||
"apps/poc-tokens-plugin/src/_headers",
|
||||
"apps/poc-tokens-plugin/src/favicon.ico",
|
||||
"apps/poc-tokens-plugin/src/manifest.json",
|
||||
"apps/poc-tokens-plugin/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
"build": "ng build colors-to-tokens-plugin && pnpm run build:plugin",
|
||||
"build:dev": "ng build colors-to-tokens-plugin --configuration development",
|
||||
"build:plugin": "node ../../tools/scripts/build-plugin.mjs --plugin=colors-to-tokens-plugin",
|
||||
"watch": "node ../../tools/scripts/build-plugin.mjs --plugin=colors-to-tokens-plugin --watch",
|
||||
"build:plugin:watch": "node ../../tools/scripts/build-plugin.mjs --plugin=colors-to-tokens-plugin --watch",
|
||||
"serve": "ng serve colors-to-tokens-plugin",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run build:plugin:watch\" \"pnpm run serve\"",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideRouter, withHashLocation } from '@angular/router';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideRouter([], withHashLocation())],
|
||||
providers: [provideRouter([])],
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>colors-to-tokens-plugin</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "Colors to Tokens",
|
||||
"description": "Generate a design tokens file from a list of colors",
|
||||
"version": 2,
|
||||
"code": "assets/plugin.js",
|
||||
"icon": "assets/icon.png",
|
||||
"permissions": ["content:read", "library:read", "allow:downloads"]
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
"build": "ng build contrast-plugin && pnpm run build:plugin",
|
||||
"build:dev": "ng build contrast-plugin --configuration development",
|
||||
"build:plugin": "node ../../tools/scripts/build-plugin.mjs --plugin=contrast-plugin",
|
||||
"watch": "node ../../tools/scripts/build-plugin.mjs --plugin=contrast-plugin --watch",
|
||||
"build:plugin:watch": "node ../../tools/scripts/build-plugin.mjs --plugin=contrast-plugin --watch",
|
||||
"serve": "ng serve contrast-plugin",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run build:plugin:watch\" \"pnpm run serve\"",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideRouter, withHashLocation } from '@angular/router';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideRouter([], withHashLocation())],
|
||||
providers: [provideRouter([])],
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>contrast-plugin</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "Contrast",
|
||||
"description": "Measure contrast plugin",
|
||||
"version": 2,
|
||||
"code": "assets/plugin.js",
|
||||
"icon": "assets/icon.png",
|
||||
"permissions": ["content:read"]
|
||||
}
|
||||
@@ -5,10 +5,10 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build --emptyOutDir",
|
||||
"watch": "vite build --watch --mode development",
|
||||
"serve": "vite preview",
|
||||
"init": "concurrently --kill-others --names build,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"build": "vite build",
|
||||
"build:watch": "vite build --watch --mode development",
|
||||
"preview": "vite preview",
|
||||
"init": "concurrently --kill-others --names build,serve \"pnpm run build:watch\" \"pnpm run preview\"",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest"
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "Create Palette from library",
|
||||
"description": "Create a board with all the colors in the local library",
|
||||
"code": "plugin.js",
|
||||
"version": 2,
|
||||
"icon": "assets/icon.png",
|
||||
"permissions": ["content:read", "content:write", "library:read"]
|
||||
}
|
||||
@@ -5,11 +5,12 @@ import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
server: {
|
||||
port: 4202,
|
||||
port: 4305,
|
||||
host: '0.0.0.0',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4202,
|
||||
port: 4305,
|
||||
host: '0.0.0.0',
|
||||
},
|
||||
plugins: [tsconfigPaths()],
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Penpot plugin styles</title>
|
||||
<base href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="/src/styles.css" />
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"watch": "vite build --watch --mode development",
|
||||
"init": "concurrently --kill-others --names build,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"serve": "vite preview",
|
||||
"build:watch": "vite build --watch --mode development",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint ."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
server: {
|
||||
port: 4202,
|
||||
port: 4201,
|
||||
host: '0.0.0.0',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4202,
|
||||
port: 4201,
|
||||
host: '0.0.0.0',
|
||||
},
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>icons-plugin</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "Icons plugin",
|
||||
"version": 2,
|
||||
"code": "assets/plugin.js",
|
||||
"icon": "assets/icon.png",
|
||||
"description": "Create icons from the Feather Icons set",
|
||||
"permissions": ["content:read", "content:write"]
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
"build": "ng build lorem-ipsum-plugin && pnpm run build:plugin",
|
||||
"build:dev": "ng build lorem-ipsum-plugin --configuration development",
|
||||
"build:plugin": "node ../../tools/scripts/build-plugin.mjs --plugin=lorem-ipsum-plugin",
|
||||
"watch": "node ../../tools/scripts/build-plugin.mjs --plugin=lorem-ipsum-plugin --watch",
|
||||
"build:plugin:watch": "node ../../tools/scripts/build-plugin.mjs --plugin=lorem-ipsum-plugin --watch",
|
||||
"serve": "ng serve lorem-ipsum-plugin",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run build:plugin:watch\" \"pnpm run serve\"",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>lorem-ipsum-plugin</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "Lorem ipsum",
|
||||
"description": "Lorem ipsum text generator plugin",
|
||||
"version": 2,
|
||||
"code": "assets/plugin.js",
|
||||
"icon": "assets/icon.png",
|
||||
"permissions": ["content:read", "content:write"]
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
"build": "ng build poc-state-plugin && pnpm run build:plugin",
|
||||
"build:dev": "ng build poc-state-plugin --configuration development",
|
||||
"build:plugin": "node ../../tools/scripts/build-plugin.mjs --plugin=poc-state-plugin",
|
||||
"watch": "node ../../tools/scripts/build-plugin.mjs --plugin=poc-state-plugin --watch",
|
||||
"build:plugin:watch": "node ../../tools/scripts/build-plugin.mjs --plugin=poc-state-plugin --watch",
|
||||
"serve": "ng serve poc-state-plugin",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run build:plugin:watch\" \"pnpm run serve\"",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>poc-state-plugin</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "POC State Read",
|
||||
"description": "Sandbox plugin for plugins development",
|
||||
"version": 2,
|
||||
"code": "assets/plugin.js",
|
||||
"permissions": [
|
||||
"content:write",
|
||||
"library:write",
|
||||
"comment:write",
|
||||
"user:read",
|
||||
"allow:downloads",
|
||||
"allow:localstorage"
|
||||
]
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
"build": "ng build poc-tokens-plugin && pnpm run build:plugin",
|
||||
"build:dev": "ng build poc-tokens-plugin --configuration development",
|
||||
"build:plugin": "node ../../tools/scripts/build-plugin.mjs --plugin=poc-tokens-plugin",
|
||||
"watch": "node ../../tools/scripts/build-plugin.mjs --plugin=poc-tokens-plugin --watch",
|
||||
"build:plugin:watch": "node ../../tools/scripts/build-plugin.mjs --plugin=poc-tokens-plugin --watch",
|
||||
"serve": "ng serve poc-tokens-plugin",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run build:plugin:watch\" \"pnpm run serve\"",
|
||||
"lint": "eslint .",
|
||||
"test": "exit 0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Angular example plugin</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "Design tokens plugin POC",
|
||||
"description": "This is a plugin to try Design Tokens in Penpot API",
|
||||
"version": 2,
|
||||
"code": "assets/plugin.js",
|
||||
"permissions": [
|
||||
"page:read",
|
||||
"content:read",
|
||||
"file:read",
|
||||
"selection:read",
|
||||
"content:write",
|
||||
"library:read",
|
||||
"library:write"
|
||||
]
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
"build": "ng build rename-layers-plugin && pnpm run build:plugin",
|
||||
"build:dev": "ng build rename-layers-plugin --configuration development",
|
||||
"build:plugin": "node ../../tools/scripts/build-plugin.mjs --plugin=rename-layers-plugin",
|
||||
"watch": "node ../../tools/scripts/build-plugin.mjs --plugin=rename-layers-plugin --watch",
|
||||
"build:plugin:watch": "node ../../tools/scripts/build-plugin.mjs --plugin=rename-layers-plugin --watch",
|
||||
"serve": "ng serve rename-layers-plugin",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run watch\" \"pnpm run serve\"",
|
||||
"init": "concurrently --kill-others --names plugin,serve \"pnpm run build:plugin:watch\" \"pnpm run serve\"",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest"
|
||||
}
|
||||
|
||||