22875 Commits

Author SHA1 Message Date
Andrey Antukh
a4ba5fc2e0 Merge remote-tracking branch 'origin/staging' into develop 2026-07-03 10:41:21 +02:00
Andrey Antukh
1228b9aa08 Merge remote-tracking branch 'origin/main' into staging 2026-07-03 10:41:01 +02:00
Andrey Antukh
62a9053422 📎 Add minor agents and skills restructuration for opencode 2026-07-03 10:39:42 +02:00
Marina López
04f6549e82 🐛 Replace hyphens with bullets in subscriptions benefits 2026-07-03 10:35:23 +02:00
Andrey Antukh
50c0299e7f ⬆️ Update devenv dockerfile 2026-07-03 09:49:31 +02:00
Juanfran
0182f239ae
Add Nitrate bulk profile creation endpoint (#10491)
Add a Nitrate-only management RPC method to create active Penpot profiles in
bulk through the existing shared-key protected management API.
2026-07-03 09:45:44 +02:00
Luis de Dios
2c4a9e0f82
Improve dashboard invitations modal (#10459) 2026-07-03 09:28:52 +02:00
Eva Marco
841b47736b
🐛 Fix token pill border color on invalid pills when not selected (#10535)
Signed-off-by: Eva Marco <eva.marco@kaleidos.net>
2026-07-03 09:28:27 +02:00
Eva Marco
0387cdf7e4
♻️ Migrate shared ancillary components to modern syntax (#10527)
* ♻️ Migrate shared ancillary components to modern syntax

* ♻️ Address shared ancillary syntax review

* ♻️ Apply Step 3 props destructuring on numeric-input*

Replaces the legacy ?-suffixed prop aliases with clean :keys destructuring
and updates internal references, addressing review on PR #9406.

* 🐛 Fix some problems on refactored components

---------

Co-authored-by: sxxtony <166789813+sxxtony@users.noreply.github.com>
2026-07-03 09:26:16 +02:00
Belén Albeza
2e32a8743e
♻️ Refactor rulers into ui modules (#10461)
* ♻️ Move rulers rendering to ui submodule

* ♻️ Refactor RulerState into UIState
2026-07-03 08:37:22 +02:00
Luis de Dios
d795a1f110
Manage rotation and color of selection size badge (#10393)
*  Rotate and move size badge when shape is rotated

* 🐛 Fix wrong text color in selection size badge

*  Add tests

* ♻️ Extract common constants
2026-07-02 14:59:33 +02:00
Alejandro Alonso
b82ab0c830 Merge remote-tracking branch 'origin/staging' into develop 2026-07-02 13:52:25 +02:00
alonso.torres
f1426cb3bb 🐛 Add test of fixes in the plugins api suite 2026-07-02 13:32:17 +02:00
RenzoMXD
1c9ab691e6 🐛 Plugin API theme.addSet/removeSet accept proxy or set ID
Signed-off-by: RenzoMXD <170978465+RenzoMXD@users.noreply.github.com>

🐛 Preserve validation errors for theme set APIs

Signed-off-by: RenzoMXD <170978465+RenzoMXD@users.noreply.github.com>

Co-authored-by: Alonso Torres <alonso.torres@kaleidos.net>
2026-07-02 13:32:17 +02:00
Filip Sajdak
5b7447fbe4 🐛 Accept delay 0 in plugin API interaction setter
The InteractionProxy `delay` setter rejected `0` via `(not (pos? value))`,
so an immediate after-delay interaction (`interaction.delay = 0`) was
refused. The model allows it: `set-delay`
(common/.../shape/interactions.cljc) only asserts `check-safe-int`, with
no positivity constraint, and `safe-int` permits 0.

Replace the guard with `(or (not (sm/valid-safe-int? value)) (neg? value))`:
it allows 0 and positive integers, rejects negatives, and rejects
non-integers cleanly (the previous `number?` check let fractional values
through, which then failed the model's `check-safe-int` assertion
downstream).

Adds a regression test (delay round-trips a positive value, then 0).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
2026-07-02 13:32:17 +02:00
Filip Sajdak
1c5c6ee072 🐛 Accept fractional border radius in plugin API shape setters
The ShapeProxy `borderRadius` setters (`borderRadius` and the four
per-corner variants) validated with `sm/valid-safe-int?`, so a fractional
radius (e.g. `shape.borderRadius = 7.5`) was rejected as invalid. The data
model types `:r1`-`:r4` as `::sm/safe-number` (shape.cljc), the radius
sidebar input only constrains `min 0` (not integer), and `set-radius-*`
store the value verbatim — so the plugin API was stricter than the model.
Same class of defect as the merged #9780.

Switch those 5 guards to `sm/valid-safe-number?`, keeping the existing
non-negative guard on the all-corners setter. Integer-only setters in the
file (`getRange` bounds, `setParentIndex`) keep `valid-safe-int?`.

Adds a regression test asserting fractional radius values are accepted
(with throwValidationErrors enabled).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
2026-07-02 13:32:17 +02:00
Filip Sajdak
c7ee54e849 🐛 Accept fractional gap and padding in plugin API layout setters
The flex and grid layout proxies validated `rowGap`, `columnGap` and the
four padding setters with `sm/valid-safe-int?`, so a fractional value
(e.g. `flex.rowGap = 10.5`) was rejected as invalid. The data model types
`:row-gap`/`:column-gap` and `:p1`-`:p4` as `::sm/safe-number`
(layout.cljc), and the sidebar accepts decimals, so the plugin API was
stricter than the model — the same class of defect as the merged #9780.

Switch those 16 gap/padding guards (8 in flex.cljs, 8 in grid.cljs) to
`sm/valid-safe-number?`, matching the model and the predicate already used
by the flex-element setters in the same file. Integer-only setters
(`zIndex`, grid track indices/counts and cell positions/spans) keep
`valid-safe-int?`. Also fixes a `:righPadding` typo in two grid
rightPadding error branches.

Adds a regression test asserting fractional gap/padding values are
accepted (with throwValidationErrors enabled) for both flex and grid.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
2026-07-02 13:32:17 +02:00
mvanhorn
355f7acb66 🐛 Make animation optional in plugin CloseOverlay type and align overlay typings 2026-07-02 13:32:17 +02:00
mvanhorn
ab623cc02d 🐛 Make overlay position optional in plugin open-overlay/toggle-overlay interactions 2026-07-02 13:32:17 +02:00
Filip Sajdak
76070008c2 🐛 Fix plugin API board.guides invalid-schema on set/clear
Setting or clearing `board.guides` from a plugin threw a malli
`:malli.core/invalid-schema` for every value, including `[]`. Causes:

- `shape.cljs` validated against `[:vector ::ctg/grid]`, but the
  `:app.common.types.grid/grid` reference is no longer registered
  (direct schemas replaced the namespaced-keyword registrations). Use
  the direct var `ctg/schema:grid`, matching every other setter.
- `parser.cljs` `parse-frame-guide` returned the `parse-frame-guide-column`
  / `parse-frame-guide-row` fns instead of calling them with the guide,
  so column/row guides parsed to a vector containing a function.
- `parse-frame-guide-square` used `parse-frame-guide-column-params`
  instead of the dedicated `parse-frame-guide-square-params`.

Adds a regression test parsing column/square guides and validating the
result (and an empty vector) against `ctg/schema:grid`.

Fixes #9773

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
2026-07-02 13:32:17 +02:00
Filip Sajdak
8fe835a9cc 🐛 Surface real plugin errors instead of bare "Value not valid"
The plugin proxy `:on-error` handler funneled every throwable through
`handle-error`, which only produced a message for malli ExceptionInfo
carrying `::sm/explain`. Two paths lost the real cause and rendered the
unhelpful "[PENPOT PLUGIN] Value not valid. Code: :error":

- A plain JS error (TypeError, etc.) is not an ExceptionInfo, so
  `(ex-data cause)` is nil and the message bound to nil; the real
  `.-message` only reached the host-page console, invisible to the
  plugin sandbox.
- A malli explain whose errors flatten to nothing made `error-messages`
  return "", which rendered as "Value not valid: . Code: :error".

`error-messages` now returns nil (not "") when there is nothing to
render, and `handle-error` falls back to the raw explain, then to the
throwable's `ex-message`/`str`, so a useful message always surfaces.
Working cases (well-formed explain) are unchanged.

Adds regression tests for the plain-JS-error path, the empty-explain
path, and the `error-messages` nil contract.

Fixes #9692

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
2026-07-02 13:32:17 +02:00
Eva Marco
f1f5a30624
🐛 Fix alignment selector for strokes (#10532) 2026-07-02 13:01:58 +02:00
andrés gonzález
40a79c2b5d
📚 Update user guide for 2.17 release (#10518) 2026-07-02 09:06:44 +02:00
Belén Albeza
6d458c80a1
🐛 Fix font and variant dropdowns on mixed text styles (#10520)
* 🐛 Fix dropdown shown Mixed Font Families for same family with different variant

* 🐛 Fix variants dropdown appearing blank on mixed variants but same family

*  Add playwright test for mixed font families/variants
2026-07-01 20:15:20 +02:00
Elena Torró
28b5371901
🔧 Improve text strokes in texts with emoji (#10519) 2026-07-01 18:10:46 +02:00
Alejandro Alonso
f25317ac47
🐛 Fix text inner stroke fill seam by compositing fill inside SrcIn (#10509)
* 🐛 Fix text inner stroke fill seam by compositing fill inside SrcIn

* 🔧 Update e2e Playwright screenshots
2026-07-01 16:24:23 +02:00
Andrey Antukh
6cc2c403c4 ⬆️ Update dependencies 2026-07-01 14:45:41 +02:00
Marina López
64ba70e6f3 🐛 Fix border color for selected subscription 2026-07-01 14:42:06 +02:00
Andrey Antukh
44d33a0c80 Merge remote-tracking branch 'origin/staging' into staging 2026-07-01 14:41:01 +02:00
Andrey Antukh
77a8677b60 Merge remote-tracking branch 'origin/main' into staging 2026-07-01 14:40:36 +02:00
Eva Marco
e6a341ff30
🐛 Fix text layout item menu (#10516) 2026-07-01 14:39:34 +02:00
Andrey Antukh
1006efc571 🐛 Fix translation strings 2.16.2 2026-07-01 14:38:08 +02:00
Eva Marco
04254c9fd1
🐛 Fix token tooltips (#10515) 2026-07-01 14:30:18 +02:00
Aitor Moreno
851fde01c1
🐛 Fix SVG Raw not being saved (#10492) 2026-07-01 14:08:54 +02:00
Eva Marco
665e8e018e
🐛 Fix overlay position grid (#10512) 2026-07-01 13:40:12 +02:00
Eva Marco
abbd28d101
🐛 Fix long text inside color tooltip (#10511) 2026-07-01 13:38:51 +02:00
Luis de Dios
7e8590b04c
🐛 Fix inspect in workspace displays shape size twice when selecting a shape (#10507) 2026-07-01 13:08:35 +02:00
Belén Albeza
215de966ae
🐛 Fix extra linebreak on MacOS IME (#10498)
* 🐛 Fix extra linebreak in Japense IME (MacOS)

* ♻️ Remove composing? from the state and query event instead
2026-07-01 12:40:25 +02:00
Elena Torró
c8f586a197
🐛 Fix async text rendering on tiles (#10504) 2026-07-01 11:09:57 +02:00
Belén Albeza
51877c4bca
🐛 Fix text editor cursor being too thin on dpr > 1 (#10501) 2026-07-01 10:43:59 +02:00
Alejandro Alonso
05e9c68a74
🐛 Fix preserving empty text fill when editing without changes (#10483) 2026-06-30 17:59:54 +02:00
Eva Marco
920c6d4e76
🐛 Fix token tooltips on numeric-input, color and typography (#10480) 2026-06-30 16:26:49 +02:00
Andrey Antukh
782adffec8 Merge remote-tracking branch 'origin/staging' into develop 2026-06-30 16:26:26 +02:00
Andrey Antukh
8087f2e42b 📎 Update .nvmrc 2026-06-30 16:25:24 +02:00
Andrey Antukh
c4e72fd7f9 Merge remote-tracking branch 'origin/staging' into develop 2026-06-30 16:23:23 +02:00
Andrey Antukh
88961c6fd3 🔧 Add recursive install to plugins test workflow 2026-06-30 16:15:30 +02:00
Andrey Antukh
5bae6bd078 📎 Fix mcp deprecation warning 2026-06-30 16:15:30 +02:00
Andrey Antukh
1c02810b83 📎 Fix fmt issues on plugins 2026-06-30 16:15:30 +02:00
Andrey Antukh
92035ebd94 ⬆️ Update and fixed warnings on plugins module 2026-06-30 16:15:30 +02:00
Andrey Antukh
f38d6cf0f2 ⬆️ Update nodejs version across docker images 2026-06-30 16:15:30 +02:00