22864 Commits

Author SHA1 Message Date
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
Andrey Antukh
e2b52d88fc ⬆️ Update dependencies 2026-06-30 16:15:30 +02:00
Parinith
8d5b16295f
💄 Center libraries empty state placeholder vertically (#10452)
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-06-30 16:14:24 +02:00
Luis de Dios
28afe223f4
🐛 Invitations to a team can be sent to existing members without displaying any error (#10489)
* 🐛 Fix team invitations can be sent to existing members without displaying any error

*  Add tests
2026-06-30 15:39:59 +02:00
Alonso Torres
8823f7ac4d
Make v2 plugins default throw on error (#10433) 2026-06-30 14:50:50 +02:00
Luis de Dios
46f5346045
♻️ Merge :thumbnails and :thumbnails-meta into single state key (#10021)
* ♻️ Merge :thumbnails and :thumbnails-meta into single state key

♻️ Unify thumbnail refs in a single ref

🐛 Fix test

* ♻️ Update tests
2026-06-30 14:37:27 +02:00
Andrew Barnes
b3b3ea97db
📚 Fix Angular plugin usage doc link (#10349) 2026-06-30 14:35:55 +02:00
Alonso Torres
e0be9f7ade
Plugin for api testing (#10410) 2026-06-30 14:01:38 +02:00
Belén Albeza
e6a49adfbc
🐛 Fix crash on composition update when pressing Esc on a IME (#10479) 2026-06-30 13:55:06 +02:00
Alonso Torres
ca81776d04
🐛 Fix problems when dragging frame with comments (#10460)
* 🐛 Fix undo frame position not undoing comments

* 🐛 Fix problem with hover capturing dragging event

* 🐛 Fix watch updates for comment bubbles

* 🐛 Fix "Maximum update depth" crash on SVG shape transforms

* 🐛 Fix comment geometry problems
2026-06-30 13:33:47 +02:00
Elena Torró
21f646aeee
🐛 Fix decimal rounding and format in WebGL rulers (#10487) 2026-06-30 10:35:03 +02:00
Alonso Torres
f993f203bd
🐛 Fix problems with plugins API (#10412)
*  Adds static dispatch safe stubs in tests

* 🐛 Fix shapesColors metadata key to match ColorShapeInfo

* 🐛 Fix CommentThread.remove rejecting the owner's own threads

* 🐛 Fix page.removeCommentThread throwing on a spurious Promise

*  Implement ShapeBase.swapComponent in the plugin API

*  Expose File.revn in the plugin API

* 🐛 Fix FileVersion.createdAt calling Luxon method on a js/Date

* 🐛 Fix plugin font/typography application to text and ranges

* 🐛 Default plugin overlay interaction position for non-manual types

* 🐛 Fix plugin interaction setters passing an id-only shape

* 🐛 Fix grid addColumnAtIndex rejecting valid track types

* 🐛 Expose libraryId on library color/typography/component proxies

*  Implement LibraryTypography.setFont in the plugin API

* 🐛 Fix typography.applyToTextRange reading unexposed range bounds

* 🐛 Fix utils.geometry.center argument mismatch

* 🐛 Fix localStorage.removeItem calling getItem

* 🐛 Fix shape backgroundBlur proxy key casing

* 🐛 Report boolean shape type as 'boolean' in the plugin API

* 🐛 Return the resulting paths from plugin flatten

* 🐛 Make plugin z-order methods act on the target shape

* 🐛 Make is-variant-container? return a boolean

*  Implement Group.isMask in the plugin API

* 🐛 Return a shape proxy from TextRange.shape

* 🐛 Return the duplicated set from TokenSet.duplicate

* 🐛 Fix theme addSet/removeSet reading set name with a keyword

* 🐛 Accept string fontFamilies token value in the plugin API

* 🐛 Fix combineAsVariants ignoring the passed component ids

* 🐛 Fix board removeRulerGuide ignoring its argument

* 🐛 Fix board guides setter schema and parser

* 🐛 Avoid 0-byte allocation when syncing empty grid tracks

* 🐛 Validate grid track indices in the plugin API

* 🐛 Return null for empty input in group() and centerShapes()

* 🐛 Return TokenTypographyValue[] from a typography token's resolvedValue

* 🐛 Return TokenShadowValue[] from a shadow token's resolvedValue

* 🐛 Return string[] from a fontFamilies token's resolvedValue

* 🐛 Clear mutually-exclusive reps when setting LibraryColor gradient/image

* 🐛 Add readonly tags to types, deprecate Image type

* 📚 Update plugins changelog
2026-06-29 17:32:15 +02:00