3948 Commits

Author SHA1 Message Date
Eva Marco
5a7ba7ee7e
🐛 Fix multiple selection on shapes with token applied to stroke-color (#9110)
*  Remove the need to navigate to page for deletion operation

* 🐛 Fix multiple selection with applied-tokens on stroke-color

* 🐛 Fix button position on page header

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-24 09:47:44 +02:00
Alejandro Alonso
7532bf411c Merge remote-tracking branch 'origin/develop' into develop 2026-04-24 09:32:35 +02:00
Alejandro Alonso
984d292ab2 Merge remote-tracking branch 'origin/staging' into develop 2026-04-24 09:29:24 +02:00
wdeveloper16
50bee5e176
Add clipboard:read/write permissions to plugin system (#6980) (#9053)
*  Add clipboard:read/write permissions to plugin system (#6980)

* 🔧 Fix prettier formatting in clipboard permission files

---------

Co-authored-by: wdeveloper16 <wdeveloer16@protonmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-24 09:07:58 +02:00
Andrey Antukh
7135782e7d Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-24 08:19:47 +02:00
wdeveloper16
e280168de9
Add read-only preview mode for saved versions (#7622) (#8976)
*  Add read-only preview mode for saved versions (#7622)

* 🔧 Address review feedback on version preview (#7622)

* 🐛 Fix version preview for WASM renderer (#7622)

* 🐛 Fix stylelint color-named and color-function-notation in preview banner (#7622)

* 🐛 Fix invalid-arity call to initialize-workspace in exit-preview (#7622)

* 🐛 Fix unclosed defn paren in exit-preview (#7622)

* ♻️ Refactor version preview/restore flow

Separate enter-preview and enter-restore flows with dedicated dialogs
instead of a persistent banner. Removes preview-banner component in favor
of inline actions dialog. Uses backup/restore pattern for exit-preview
instead of full workspace reinitialization. Adds analytics events for
preview/restore actions.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

*  Extract on-name-input-focus as namespace-level private function

The callback had no dependencies on component-local state or props,
making it a pure function that can be hoisted to a defn-. This avoids
recreating the same callback identity on every render of version-entry*.

*  Extract extract-id-from-event helper to deduplicate snapshot callbacks

Three callbacks in snapshot-entry* shared the same DOM extraction logic
(get current target, read data-id, parse UUID). Extracted into a private
defn- to remove the duplication and simplify each callback.

*  Extract pure state-update callbacks from versions-toolbox* to namespace level

Eight callbacks that only emit fixed Potok events with no meaningful
deps were hoisted out of the component as defn- functions:

- on-create-version
- on-edit-version
- on-cancel-version-edition
- on-rename-version
- on-delete-version
- on-pin-version
- on-lock-version
- on-unlock-version

These no longer need mf/use-fn wrappers since namespace-level functions
have stable identity across renders, avoiding unnecessary callback
recreation on each render cycle.

*  Rename filter parameter to filter-value in on-change-filter to avoid core shadowing

The parameter name 'filter' shadowed clojure.core/filter within the
function scope. Renamed to 'filter-value' for clarity and to prevent
potential bugs if core/filter were needed in future changes.

* 🔧 Fix linter warnings and errors across version-related namespaces

frontend/src/app/main/ui/workspace.cljs:
- Remove unused requires: app.common.data, app.main.data.notifications,
  app.main.data.workspace.versions

frontend/src/app/main/data/workspace/versions.cljs:
- Remove unused require: app.common.uuid
- Fix duplicate reify type: enter-restore used ::restore-version
  (same as the private restore-version fn), renamed to ::enter-restore
- Remove unused bindings: state in enter-restore, team-id in
  exit-preview and restore-version-from-plugin

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Signed-off-by: wdeveloper16 <wdeveloer16@protonmail.com>
Co-authored-by: wdeveloper16 <wdeveloer16@protonmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-24 08:13:16 +02:00
Eva Marco
0c60db56a2
🐛 Fix multiselection error with typography texts (#9071)
* 🐛 Ensure typography-ref attrs are always present and fix nil encoding

Add :typography-ref-file and :typography-ref-id (both defaulting to nil)
to default-text-attrs so these keys are always present in text node maps,
whether or not a typography is attached.

Skip nil values in attrs-to-styles (Draft.js style encoder) and in
attrs->styles (v2 CSS custom-property mapper) so nil typography-ref
entries are never serialised to CSS.

Replace when with if/acc in get-styles-from-style-declaration to prevent
the accumulator from being clobbered to nil when a mixed-value entry is
skipped during style decoding.

* 🎉 Add test

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-23 16:08:56 +02:00
Eva Marco
d6b341c053
🐛 Fix color token (#9095) 2026-04-23 10:51:30 +02:00
Eva Marco
5c9696e20c
🐛 Fix color dropdown option update (#9100) 2026-04-23 10:51:20 +02:00
Eva Marco
28b33b9acc
🐛 Fix props on text components (#9099) 2026-04-23 10:49:48 +02:00
Andrey Antukh
ba42cc04b7 ♻️ Derive v-sizing from values instead of passing as prop
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 14:17:15 +00:00
Luis de Dios
b60695f54a 🐛 Fix indicate that the mcp is disabled if the mcp key has expired
If the mcp key has expired, the switch that indicates the status in the dashboard will appear as disabled, and will show a modal for regenerate the key. It will also appear as disabled in the workspace, not allowing the plugin to connect
2026-04-22 16:00:52 +02:00
Andrey Antukh
8ad30e14b6 Merge remote-tracking branch 'origin/staging' into develop 2026-04-22 13:34:00 +02:00
Aitor Moreno
e3981a0cf3
Merge pull request #9077 from penpot/ladybenko-13971-fix-trailing-whitespace
🐛 Fix trailing whitespace behavior in v2 editor
2026-04-22 11:30:01 +02:00
Eva Marco
c02f0a2bc9
🐛 Fix grow options (#9097)
* 🐛 Fix grow options

* 🐛 Fix props when hidden is nil
2026-04-22 11:09:44 +02:00
Andrey Antukh
81faa5a728 Replace duplicate on-blur lambda with stable on-text-blur ref
The inline (fn [] (ts/schedule ...)) passed as :on-blur to text-options
was an exact copy of the on-text-blur callback already defined via
mf/use-fn earlier in the same let block. Pass on-text-blur directly
to avoid allocating a new function object on every render.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
7751d9a69b Remove spurious deps from toggle callbacks in text-menu*
toggle-main-menu and toggle-more-options close over a state atom and
need no external deps. The declared deps (main-menu-open? /
more-options-open?) were unused inside the function bodies, causing
each callback to be reallocated on every toggle — self-reinforcing
churn. Drop the mf/deps calls to make both callbacks stable.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
74d1288003 Hoist token-typography-row? flag check to namespace level
(contains? cf/flags :token-typography-row) is a pure constant:
cf/flags is immutable after startup. Define it once as a private
namespace-level var token-typography-row? instead of re-evaluating
the check on every render in text-decoration-options* and text-menu*.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
d28c0ea066 Memoize label computation in text-menu* component
Wrap the (case type (tr ...) ...) expression in mf/with-memo [type]
so the translation is resolved only when the type prop changes
instead of on every render.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
a94a7221fb Memoize options in text-decoration-options* component
Wrap the two radio-button option maps in mf/with-memo [token-applied]
so the vector and its (tr ...) calls are evaluated only when the
token-applied prop changes, not on every render.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
b8aa243c2b Memoize static options in grow-options* component
Wrap the three radio-button option maps in mf/with-memo [] so the
vector and its (tr ...) calls are evaluated once per mount instead
of on every render.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
dfd992aa49 Memoize static options in text-direction-options* component
Wrap the two radio-button option maps in mf/with-memo [] so the
vector and its (tr ...) calls are evaluated once per mount instead
of on every render.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
466f27eb7c Memoize static options in text-align-options* component
Wrap the four radio-button option maps in mf/with-memo [] so the
vector and its (tr ...) calls are evaluated once per mount instead
of on every render.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Andrey Antukh
6c19c7c0c4 Memoize static options in vertical-align* component
Wrap the radio-button options vector in `mf/with-memo []` so the
vector allocation and `(tr ...)` calls happen once per component
mount instead of on every render.

Also document the translation memoization rule in frontend/AGENTS.md:
`(tr ...)` must never be called at namespace level (locale is
runtime-only), and static option lists should always be wrapped in
`mf/with-memo []`.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-22 08:55:29 +02:00
Alejandro Alonso
ca97a28408 🐛 Avoid unnecesary repainting of frames when mouse hover 2026-04-22 07:37:38 +02:00
Andrey Antukh
6723e3bbea 🐛 Fix issues after staging merge 2026-04-21 22:52:19 +02:00
Andrey Antukh
c259fbdb5b Merge remote-tracking branch 'origin/staging' into develop 2026-04-21 22:43:46 +02:00
Andrey Antukh
a395768987 🐛 Fix incorrect handlig of version restore operation (#9041)
- Add session ID tracking to RPC layer (backend and frontend)
- Send session ID header with RPC requests for request correlation
- Rename file-restore to file-restored for consistency
- Extract initialize-file function from initialize-workspace flow
- Improve file restoration initialization with wait-for-persistence
- Extract initialize-version event handler for version restoration
- Fix viewport key generation with file version numbers for proper re-renders
- Update layout item schema and constraints to use internal sizing state
- Add v-sizing state retrieval in layout-size-constraints component
- Refactor file-change notifications stream handling with rx/map
- Fix team-id lookup in restore-version-from-plugins

Improves request traceability across frontend/backend sessions and streamlines
the workspace initialization flow for file restoration scenarios.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 20:50:41 +02:00
Andrey Antukh
8f2c467b82 Merge remote-tracking branch 'origin/main' into main-staging 2026-04-21 20:44:31 +02:00
Andrey Antukh
c1688edf66 ♻️ Convert frame-grid and grid-options to modern * suffix
Rename grid-options -> grid-options*, frame-grid -> frame-grid*.
Update internal call and call site in shapes/frame.cljs to [:> ...] syntax.
2026-04-21 20:31:30 +02:00
Andrey Antukh
08247aec3f ♻️ Convert svg-attrs-menu and attribute-value to modern * suffix
Rename attribute-value -> attribute-value*, svg-attrs-menu -> svg-attrs-menu*.
Update all call sites (circle, path, svg_raw, rect, group) to use [:> ...] syntax.
2026-04-21 20:31:30 +02:00
Andrey Antukh
95ca68e2b8 ♻️ Convert history-entry-details to modern rumext * format
Rename to history-entry-details* and update internal call site.
2026-04-21 20:31:30 +02:00
Andrey Antukh
e9e6796f05 ♻️ Convert text-menu and sub-components to modern rumext * format
Rename text-align-options, text-direction-options, vertical-align,
grow-options, text-decoration-options and text-menu to their * variants.
Update all call sites in shapes/text.cljs, shapes/group.cljs and
shapes/multiple.cljs.
2026-04-21 20:31:30 +02:00
Andrey Antukh
0e5d3e2619 ♻️ Convert blur-menu, constraints-menu and stroke-menu to modern rumext * format
Rename components to blur-menu*, constraints-menu* and stroke-menu*.

Update :refer imports and all [:& ...] call sites to [:> ...*] for
blur-menu*, constraints-menu* and stroke-menu* across all nine
shapes-specific options panels.
2026-04-21 20:31:30 +02:00
Andrey Antukh
f0d6e8cb2f ♻️ Convert text-edition-outline to modern rumext * format
Rename to text-edition-outline*, update call sites in viewport.cljs and
viewport_wasm.cljs to [:> text-edition-outline* ...].
2026-04-21 20:31:30 +02:00
Andrey Antukh
304a324529 ♻️ Convert image-upload to modern rumext * format
Rename to image-upload*, update internal call site in top-toolbar* to
[:> image-upload*].
2026-04-21 20:31:30 +02:00
Andrey Antukh
14ff56bc89 ♻️ Convert text-palette-ctx-menu to modern rumext * format
Rename to text-palette-ctx-menu*, rename show-menu? prop to show-menu,
update call site in palette.cljs to [:> text-palette-ctx-menu* ...].
2026-04-21 20:31:30 +02:00
Andrey Antukh
d8340d765a Merge remote-tracking branch 'origin/staging' into develop 2026-04-21 20:28:38 +02:00
Andrey Antukh
2bbd63287f Merge remote-tracking branch 'origin/main' into staging 2026-04-21 19:22:50 +02:00
Andrey Antukh
6eccffb8bb
🐛 Fix incorrect handlig of version restore operation (#9041)
- Add session ID tracking to RPC layer (backend and frontend)
- Send session ID header with RPC requests for request correlation
- Rename file-restore to file-restored for consistency
- Extract initialize-file function from initialize-workspace flow
- Improve file restoration initialization with wait-for-persistence
- Extract initialize-version event handler for version restoration
- Fix viewport key generation with file version numbers for proper re-renders
- Update layout item schema and constraints to use internal sizing state
- Add v-sizing state retrieval in layout-size-constraints component
- Refactor file-change notifications stream handling with rx/map
- Fix team-id lookup in restore-version-from-plugins

Improves request traceability across frontend/backend sessions and streamlines
the workspace initialization flow for file restoration scenarios.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 19:19:51 +02:00
Dexterity
e1d3106f61
Add color customization for ruler guides (#8986)
*  Add customizable colors for ruler guides

*  Update CHANGES.md

* 💄 Move guide color menu styles to SCSS

* 💄 Fix trailing whitespace in guides.cljs

---------

Signed-off-by: Dexterity <173429049+Dexterity104@users.noreply.github.com>
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 17:31:39 +02:00
Andrey Antukh
aed2f8a8f8
🐛 Fix removeChild errors from unmount race conditions (#8927)
Guard imperative DOM operations (removeChild, RAF callbacks) against
race conditions where React has already unmounted the target nodes.

- assets/common.cljs: add dom/child? guard before removeChild in RAF
- dynamic_modifiers.cljs: capture RAF IDs and cancel them on cleanup;
  add null guards for DOM nodes that may no longer exist
- hooks.cljs: guard portal container removal with dom/child? check
- errors.cljs: extract is-ignorable-exception? to a top-level defn
  and add NotFoundError/removeChild to ignorable exceptions, since
  these are caused by browser extensions modifying React-managed DOM
- Add unit tests for is-ignorable-exception? predicate

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 17:31:05 +02:00
Belén Albeza
f9f3955503 🐛 Fix trailing whitespace behavior in v2 editor 2026-04-21 15:43:10 +02:00
Eva Marco
f18670ed00
🐛 Fix errors from numeric input design review (#8993)
* 🐛 Fix blur input after enter value

* 🐛 Catch error on invalid maths

* 🐛 Fix race condition

* 🎉 Add tests that cover issues

* 🐛 Fix padding applying only to one side

* 🐛 Fix show broken pill when reference is on not active set
2026-04-21 14:39:06 +02:00
Xaviju
78c48f1953
🐛 Fix broken update library notification link UI (#9070)
* 🐛 Fix broken update library notification link UI

* ♻️ Format and lint
2026-04-21 13:33:38 +02:00
alonso.torres
3da74ed864 🐛 Fix problem with component thumbnails in swap component panel 2026-04-21 13:11:03 +02:00
Elena Torro
62ec66b974 Add lazy async rendering for component thumbnails 2026-04-21 11:40:53 +02:00
Xaviju
cd9151bf9f
🐛 Fix duplicate modal title (#9064) 2026-04-21 09:54:30 +02:00
Alejandro Alonso
0d17debde7 Merge remote-tracking branch 'origin/staging' into develop 2026-04-21 08:24:29 +02:00
Xaviju
e9105f3670
♻️ Fix linter errors under legacy resources scss (#9035) 2026-04-20 23:58:53 +02:00