13701 Commits

Author SHA1 Message Date
Juan de la Cruz 5dff551f31 🎉 Add page multi-selection in the workspace sitemap (#10581)
* 🎉 Add page multi-selection in the workspace sitemap

* ♻️ Simplify page selection state updates with single assoc

* 🐛 Fix SCSS issue

* ♻️ Update some components to new syntax

* ♻️ Adapt SCSS to the new guidelines

* ♻️ SCSS cleanup

---------

Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
2026-07-21 14:26:03 +02:00
Juan de la Cruz fa996ab240 Add list view toggle for dashboard files (#10692)
*  Add list view toggle for dashboard files

*  Add drop files visual feedback

* ♻️ Use radio buttons component from DS

* ♻️ Use hook to keep layout status

* ♻️ Refactor code and SCSS

---------

Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
2026-07-21 13:16:10 +02:00
Pablo Alba 0ff73ae711 Add prune-unrelated-items debug utility (#10687) 2026-07-21 12:31:23 +02:00
Alonso Torres 6c5d01283a 🐛 Add more test for reported bugs (#10765) 2026-07-21 12:18:40 +02:00
Dr. Dominik Jain 4ea56e0b89 🐛 Fix propagation of geometric changes to rotated component copies (#10574)
* 🐛 Fix geometry sync between mains and rotated component copies

Rotating a copy instance as a whole marked every shape inside it as
touched for geometry, so later geometric changes in the main (e.g. a
resize) were no longer propagated to that copy, while non-geometric
ones (e.g. fills) still were. And on paths where geometry did get
written to a rotated copy (e.g. resetting overrides), the sync engine
compensated only the roots' position delta, so the written values wiped
the copy's rotation back to 0.

Model the instance root's transformation as inherited, overridable
content, asymmetric to position (which remains free per-instance
placement):

- An untouched copy follows the main's transformation verbatim,
  including rotation and flips (preserving the BUG #13267 semantics
  that rotating a main propagates to its copies).

- Transforming a copy as a whole overrides only its ROOT: check-delta
  compares the root's rotation/flips absolutely, but the descendants
  relative to their root, so they merely follow and stay untouched.

- When a copy root's geometry is overridden, update-attrs expresses the
  main's geometry in the copy's own frame: reposition-shape applies the
  roots' relative transformation (rotation/flips) around the dest root
  center in addition to the position delta. Geometric changes from the
  main then keep propagating to the rotated copy, landing correctly in
  its rotated frame instead of destroying its placement.

Covered by the new composable test case
case-n-geometry-sync-with-rotated-instances: an 8-variant sweep over
optional copy rotation, optional main rotation, and one of a fills or
height edit on the main child, asserting the whole model through the
real workspace events (the new rotate operation dispatches
dwt/increase-rotation, whose apply-modifiers step runs the check-delta
classification under test; change-height dispatches
dwt/update-dimensions and implements IPropertyCheck so one-of sweeps
can mix property and geometry edits). Verified by temporarily reverting
the fix: the case then fails with 6 assertion failures and passes again
with the fix restored.

Fixes #10109

AI-assisted-by: claude-fable-5

* 🐛 Fix synchronization problems

---------

Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2026-07-21 10:05:31 +02:00
Alejandro Alonso 6c5618025d Merge pull request #10712 from penpot/elenatorro-10706-apply-background-blur-to-text-shapes
 Add background blur to text shapes
2026-07-21 09:53:01 +02:00
AK f2a9dd1a08 🐛 Reject invalid formulas on numeric inputs (#10659)
Relative operators were accepted in operand position, so "10+*3" silently evaluated to 310 instead of being rejected. Make negation a first-class operand so legitimate negative operands ("10 + -3") keep working.

Fixes #9581

Signed-off-by: Akshit Nassa <akshitnassa412@gmail.com>
Co-authored-by: Akshit Nassa <akshitnassa412@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-07-20 16:15:29 +02:00
María Valderrama f06339fb87 Update enterprise modals illustration (#10759) 2026-07-20 16:03:40 +02:00
Luis de Dios a0b5c23f99 🐛 Fix close comments panel button does not work (#10651) 2026-07-20 13:10:27 +02:00
Belén Albeza 4c21923c4a 🐛 Fix accent menu (MacOS) inserting an extra character (#10637) 2026-07-20 12:16:52 +02:00
Elena Torró 8d98877ba7 🐛 Fix using SVG image file as shape fill (#10707) 2026-07-20 10:41:07 +02:00
Shlok Goyal 826072c65d Remove misleading MCP config from success modal (#10415)
Signed-off-by: Shlok1729 <shlokgoyal1279@gmail.com>
Signed-off-by: Shlok Goyal <shlokgoyal1279@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-07-20 10:07:26 +02:00
Juan de la Cruz cddbd8e897 Add font family preview in typography selector (#10411)
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2026-07-20 10:06:02 +02:00
Marina López 33d478b532 ♻️ Rename org to organization 2026-07-17 11:36:08 +02:00
Andrey Antukh a4347451d0 Merge remote-tracking branch 'origin/staging' into develop 2026-07-16 16:57:32 +02:00
Andrey Antukh 779983d38e 📎 Standardize test scripts and add execution discipline docs
- Remove conditional build from test scripts (frontend, common)
- Remove test:jvm from common package.json (JVM tests via clojure directly)
- Remove test from backend package.json (JVM tests via clojure directly)
- Unify common/scripts/test-quiet.js with frontend's BUILD_STEPS pattern
- Add execution discipline section to mem:testing (no piping, tee to file)
- Add READ mem:testing FIRST directives to module testing docs

AI-assisted-by: deepseek-v4-flash
2026-07-16 14:57:05 +00:00
Andrey Antukh 5cc6477e3f Merge remote-tracking branch 'origin/staging' into develop 2026-07-16 13:52:41 +02:00
Andrey Antukh 8e8fb67793 Merge remote-tracking branch 'origin/main' into staging 2026-07-16 13:52:28 +02:00
Andrey Antukh 258dd6ad6c 🐛 Handle text node targets in closest-text-editor-content (#10641)
Event targets can be DOM text nodes (nodeType 3) which lack the
.closest() method. Add a get-element helper that normalizes text
nodes to their parent Element before calling .closest(), matching
the existing pattern in dom/get-parent-with-data.

Fixes #10640

AI-assisted-by: mimo-v2.5-pro
2026-07-16 12:19:50 +02:00
Elena Torro 001dba1bef Add background blur to text shapes 2026-07-16 08:33:36 +02:00
María Valderrama 792d88dc4f 🐛 Fix invalid org invitation show toast (#10693)
* 🐛 Fix invalid org invitation show toast

* 📎 Code review
2026-07-15 12:30:20 +02:00
María Valderrama 167aa7410f 🐛 Fix modals for nitrate subscription when unlimited (#10690) 2026-07-14 14:15:29 +02:00
Marina López c119622ad9 🐛 Changed color and text from nitrate banners 2026-07-14 12:59:16 +02:00
Pablo Alba 95cfbf5f7c Improve workspace debug sidebar workflow (#10678) 2026-07-14 12:42:19 +02:00
Elena Torró c11d3aaaa7 🐛 Add :stroke-image support to plugins API (#10683) 2026-07-14 10:26:19 +02:00
Elena Torró ab58d00d66 Improve bool intersection perfomance (#10671) 2026-07-14 07:43:52 +02:00
Dr. Dominik Jain 2c15dcdb84 Add systematic component tests via a composable test model (#10529)
*  Add systematic component tests via a composable test model

Introduce a framework for systematically testing Penpot component behaviour
(synchronisation/propagation, swaps, variant switches, nesting), plus a first
suite of cases built on it.

A test is expressed as a COMPOSITION OF OPERATIONS over a "situation" (an
in-memory file value plus named role bindings). Operations are reified as data
and composed by two combinators — `in-sequence` (threads the situation) and
`one-of`/`optional` (alternatives, enumerated into concrete variants). So one
written case stands for a whole matrix of variants, and coverage grows by
composition rather than by copying tests. Operations drive the REAL production
change pipeline, and event-operations dispatch the REAL workspace events and
await settlement, so the production watcher's automatic propagation is what is
exercised — the tests reflect genuine app behaviour, not a reimplementation.

Structure (frontend/test/frontend_tests/composable_tests/):
  - core            — the domain-agnostic engine: situation, the operation and
                      enumeration protocols, the combinators, and the runners.
  - comp/nodes      — the component operations (create/instantiate/reset, nesting,
                      swap, the variant ops, child add/remove/move, change, undo,
                      library sync).
  - comp/setups     — component-shaped starting configurations.
  - interpreter     — runs a case against the real frontend store: sync-ops apply
                      directly, event-ops dispatch real events and await
                      settlement (absorbing sync-file's delayed status RPC, which
                      would otherwise leak an error into subsequent tests).
  - comp/sync-test  — the cases (B-F, H, I, K, L, M).

This is test-only code with a single consumer — the frontend test suite (the
layer that runs the real app) — so it lives entirely under the frontend test
tree as .cljs, not under app/common.

The framework and its cases are documented in the project memory
frontend/composable-component-tests, added alongside.

Co-authored-by: Claude <noreply@anthropic.com>

* 🐛 Guard WASM mock teardown against an empty snapshot

`teardown-wasm-mocks!` unconditionally restored from the `originals` atom.
When run without a matching setup (double teardown, or `with-wasm-mocks*`
misused around an async test body), the snapshot is empty and every WASM API
function was `set!` to nil — permanently, for the remainder of the test run.
Any later code calling one of them (e.g. a leaked debounced resize-wasm-text
event firing during a subsequent test namespace) then crashed with
"initialized? is not a function".

Make the restore a no-op when there is nothing to restore.

Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-10 12:17:43 +02:00
Belén Albeza 176a813fb9 🐛 Fix selected text background color in light theme (#10614) 2026-07-10 12:02:30 +02:00
Andrey Antukh fd8cb957d1 Merge remote-tracking branch 'origin/staging' into develop 2026-07-10 11:23:42 +02:00
AK 89551b2415 🐛 Fix dashboard user menu submenu not closing on hover out (#10639)
The dashboard profile menu submenus (Help & Learning, Community &
Contributions, About Penpot) opened on pointer enter but nothing closed
them when the pointer left the option, leaving a stale submenu visible
until the whole menu closed.

Close the open submenu when the pointer leaves an expandable option or
its submenu, with a 200ms grace period (same approach as the workspace
context menu) so the submenu survives the pointer crossing the gap
between the parent menu and the floating submenu. Keyboard navigation
is unchanged and now covered by tests.

Closes #10549

AI-assisted-by: claude-fable-5

Signed-off-by: Akshit Nassa <nassaakshit@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-07-10 11:21:21 +02:00
Belén Albeza 3469867cf5 🐛 Fix text editor not auto-selecting all text on mount (#10573) 2026-07-10 11:08:10 +02:00
Eva Marco 3708cf31d4 🐛 Fix stroke cap selects (#10631) 2026-07-10 11:05:09 +02:00
Alonso Torres 3ee5b50007 🐛 Fix problems with padding multiple values in plugins and UI (#10602)
* 🐛 Fix problem with padding types in plugins

* 🐛 Fix problem with multiple selection paddings
2026-07-10 09:13:20 +02:00
Andrey Antukh f84a8687f6 Merge remote-tracking branch 'origin/staging' into develop 2026-07-09 19:37:16 +02:00
Andrey Antukh 3400d6afbb 🐛 Fix too much recursion when clicking shape in comments mode (#10622)
* 🐛 Fix too much recursion when clicking shape in comments mode

Remove `deselect-all` from `handle-interrupt` in comments mode. The
`select-shape` event emits `:interrupt` which the comments stream
watcher routes to `handle-interrupt`. In comments mode, calling
`deselect-all` cleared the selection and emitted a competing
`rt/nav`, creating a synchronous recursion cycle in the potok store
that overflowed the JS call stack.

Fixes #10620

AI-assisted-by: opencode

* 🐛 Add unit tests for comments handle-interrupt

Make `handle-interrupt` public (defn- → defn) and add 4 tests covering
each branch: draft thread, open thread, comments mode, and noop.

AI-assisted-by: opencode
2026-07-09 18:04:05 +02:00
Alonso Torres d6c50cc40b 🐛 Fix problems with plugins api setPluginData (#10632) 2026-07-09 18:00:26 +02:00
María Valderrama ebfcb716ac 🐛 Fix permission to add a team to an organization (#10623) 2026-07-09 14:12:41 +02:00
Alonso Torres 80d688be93 🐛 Fix problems with comments clusters (#10543) 2026-07-09 11:37:45 +02:00
Andrey Antukh 28fd798c52 🐛 Fix crash with degenerate selrect in text pipeline (#10618)
Guard remaining text pipeline locations that accessed :selrect directly
against nil/zero-dimension selrects by using safe-size-rect, which
provides a 4-level fallback chain (selrect -> points -> shape fields ->
empty 0.01x0.01 rect).

Fixes:
- fix-position in viewport_texts_html.cljs: replaced dm/get-prop
  :selrect with ctm/safe-size-rect for both old and new shape
- assoc-position-data in modifiers.cljs: replaced (:selrect ...)
  with ctm/safe-size-rect for delta computation
- change-orientation-modifiers in modifiers.cljc: replaced raw
  :selrect access with safe-size-rect for scale and origin computation

Closes #10617

AI-assisted-by: mimo-v2.5-pro
2026-07-09 11:03:06 +02:00
Andrey Antukh 47a3158602 🐛 Fix component variant panel crash with mismatched property counts (#10616)
Use `get` instead of `nth` to avoid index-out-of-bounds when a selected
component copy has fewer variant properties than the first component in
the selection.

Closes #10615

AI-assisted-by: deepseek-v4-pro
2026-07-09 11:01:08 +02:00
Andrey Antukh f2460eee29 🐛 Fix Draft.js selection offset DOMException on text editor re-render (#10608)
Clamp selection offset to node length in setDraftEditorSelection to
prevent DOMException when Draft.js SelectionState offset exceeds the
actual DOM text node length. This can happen during spellcheck, IME
composition, or race conditions during React re-renders.

Updates @penpot/draft-js to commit 09a33e0a which includes the fix
in addPointToSelection and addFocusToSelection.

Fixes #10607

AI-assisted-by: mimo-v2.5-pro
2026-07-09 10:59:40 +02:00
Andrey Antukh fb2ec4c617 Merge remote-tracking branch 'origin/staging' into develop 2026-07-09 08:14:15 +02:00
Elena Torró 8ac2e8c8a8 🐛 Fix sidebar scroll to shape (#10600) 2026-07-08 20:38:16 +02:00
Andrey Antukh a004f7cd84 Merge remote-tracking branch 'origin/staging' into develop 2026-07-08 15:44:37 +02:00
María Valderrama 5d933fd770 🐛 Organizations list sorted by name (#10589) 2026-07-08 15:43:36 +02:00
Elena Torró d656d342fe 🐛 Fix text selrect size (#10566)
* 🐛 Fix text selrect size

* 🐛 Fix blinks on complex files

---------

Co-authored-by: Belén Albeza <belen@hey.com>
2026-07-08 13:56:58 +02:00
Andrey Antukh 0e25f7d8ad Merge remote-tracking branch 'origin/staging' into develop 2026-07-08 10:25:25 +02:00
Eva Marco ff0d56a86e 🐛 Fix blur menu width (#10575) 2026-07-08 10:06:23 +02:00
Luis de Dios 4eaefec43e 🐛 Fix glitch when using drawing tool in toolbar (#10447) 2026-07-08 09:55:50 +02:00
Juan de la Cruz 8b16bb8874 Add new slides content for 2.17 release (#10577)
*  Add new slides content for 2.17 release

* 📎 Fix linter issues

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-07-08 09:39:38 +02:00