35 Commits

Author SHA1 Message Date
Alonso Torres
7655f854a4
Improved api test suite (#10533)
* 🐛 Fix plugins api issues

* 🐛 Fix problem with text weight

* 🐛 Fix api problems

*  Updated plugins test suite

* 🐛 Referential integrity tests

*  Add resetOverrides method

* 🐛 Fix plugins components structure poluting
2026-07-07 16:12:12 +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
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
Alonso Torres
ecabe7ec32
🐛 Fix token creation fail when set inactive (#10297)
* 🐛 Fix token creatin fail when set inactive

* 🎉 Add a enable flag to addSet to enable the token set
2026-06-19 00:58:45 +02:00
alonso.torres
445d14293e 🐛 Fix issue with padding and margin tokens in plugins 2026-06-18 16:18:46 +02:00
Eva Marco
955da2a9c2
🐛 Fix circular reference error on token edition (#10185)
* 🐛 Fix circular reference error on token edition

* ♻️ Move the fn to the helpers page

* 🎉 Add comment
2026-06-18 15:46:07 +02:00
Andrés Moya
06c9a18ab0
🔧 Revert migration for tokens with clashing names (#9950)
* Revert "🐛 Detect duplicated token names in the whole library (#9034)"

This reverts commit 61cd7573553b1c5e9fc2d7300cf9b2c36b4dcbb6.

* 🔧 Preserve some enhancements and fixes that are still valid

* 🔧 Fix broken integration tests
2026-06-02 09:09:58 +02:00
Andrey Antukh
4a8fb5af53 Merge remote-tracking branch 'origin/staging' into develop 2026-06-01 13:15:57 +02:00
Andrey Antukh
c5de4c27b0 Merge remote-tracking branch 'origin/main' into staging 2026-06-01 12:57:39 +02:00
Yamila Moreno
ddba2ffa75
📎 Update Kaleidos Copyright (#9929) 2026-05-29 11:24:58 +02:00
Andrey Antukh
a228b257e9 Merge remote-tracking branch 'origin/staging' into develop 2026-05-11 09:37:32 +02:00
Andrey Antukh
f2c631b8b7 Merge remote-tracking branch 'origin/main-staging' into staging 2026-05-11 09:30:10 +02:00
Alonso Torres
9f05ba2fdf
Add plugins and mcp event data (#9228)
*  Add plugins and mcp event data

* ♻️ Changed data-event ::ev/event to ev/event
2026-05-11 08:36:53 +02:00
Andrés Moya
61cd757355
🐛 Detect duplicated token names in the whole library (#9034)
* 🐛 Detect duplicated token names in the whole library

* 🔧 Review comments

* 🐛 Prevent and repair token themes with inexistent sets

* 🔧 Convert tokens lib migration into file migration
2026-05-08 08:26:15 +02:00
Andrey Antukh
d06b45ec90 🐛 Fix Plugin API token application for JS array of strings
Two coupled defects made shape.applyToken(), token.applyToShapes() and

token.applyToSelected() silently no-op when invoked from JavaScript with

an array of strings (e.g. token.applyToShapes([rect], ["fill"])):

1. token-attr-plugin->token-attr only consulted its alias map when the

   input was already a keyword; string inputs fell through unchanged,

   causing downstream token-attr? to return false.

2. The inner schemas used plain [:set ...] which lacks the :decode/json

   transformer for JS array -> Clojure set coercion. Switching to

   Penpot's custom [::sm/set ...] lets the standard JSON decoder

   pipeline handle the conversion automatically.

This is a backport of commit 1eac3e2be5f973359ad2ec9bac4e80a9d5a9e022

which fixes GitHub #9162.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 19:09:25 +02:00
boskodev790
1eac3e2be5
🐛 Fix Plugin API token application for JS array of strings (#9166)
* 🐛 Fix Plugin API token application for JS array of strings

Plugin code calling `shape.applyToken(token, ["fill"])` or
`token.applyToShapes([rect], ["fill"])` from JavaScript supplies a JS
array of strings. The plugin proxies expected a Clojure set of
keywords, and two coupled defects made the calls silently no-op (or,
with `throwValidationErrors` enabled, throw "check error"):

1. `token-attr-plugin->token-attr` only consulted its alias map when
   the input was already a keyword. String inputs like "fill" fell
   through to the identity branch, so the downstream
   `cto/token-attr?` predicate (which checks against a set of
   keywords) returned false for every string. Coerce strings to
   keywords first.

2. The `applyToken` / `applyToShapes` / `applyToSelected` schemas
   used plain `[:set ...]`, which has no `:decode/json` transformer
   for JS array → Clojure set coercion. Switch to the registered
   `[::sm/set ...]` (in `app.common.schema`) which provides the
   array → set decoder. After the switch, the standard JSON pipeline
   converts `["fill"]` to `#{"fill"}`, then the inner
   `[:and ::sm/keyword [:fn token-attr?]]` decodes each element to a
   keyword and validates it.

Also extends the docstring on `token-attr-plugin->token-attr` to make
the string-friendly contract explicit, and registers a new
`tokens-test` ns under `frontend/test/frontend_tests/plugins/` with
six `deftest` blocks covering:

- known keywords passing through unchanged
- keyword aliases (`:r1` → `:border-radius-top-left`, etc.)
- string inputs coerced to keywords (regression for #9162)
- `token-attr?` accepting both keyword and string inputs
- `token-attr?` rejecting unknown attrs and nil

Closes #9162

* 🐛 Fix wrong direction in plugin-name alias tests

The added tests in tokens_test.cljs and the new docstring in tokens.cljs
described the alias resolution in the wrong direction. The map is
{:r1 :border-radius-top-left, …} then map-invert'd, so
token-attr-plugin->token-attr maps verbose plugin-side names
(:border-radius-top-left) to canonical internal short names (:r1),
not the other way around. Inputs already in canonical form (:r1, :fill,
"fill", …) pass through unchanged. Flipped the alias-resolution test
expectations and the keyword/string-input cases, refreshed the docstring
and the regression-coverage comment to match.

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 11:02:01 +02:00
Andrey Antukh
3a39676969 Backport MCP from staging (part 1) 2026-04-20 19:37:02 +02:00
Andrey Antukh
d4bc1d37f2 Merge remote-tracking branch 'origin/staging' into develop 2026-03-24 18:08:23 +01:00
alonso.torres
b6e300a6c7 🐛 Fix plugins addToken schema validation 2026-03-24 16:27:59 +01:00
Roland
bfb331d230
🐛 Fix pluings API theme.addSet() crash caused by async state race in token-set proxy (#8700)
When `catalog.addSet()` creates a new token set, `st/emit!` is async —
the set is not yet in `@st/state` when the returned proxy is used.
Calling `theme.addSet(proxy)` immediately after reads `.name` from the
proxy, which calls `locate-token-set` on stale state → returns nil →
`enable-set` conjs nil into the theme's `:sets` → backend rejects with
400 (`:sets #{nil}`) → workspace reloads → plugin disconnects.

Fix: store `initial-name` in the proxy at construction time as a
fallback for the `:name` getter during the async propagation window.
Also add nil guards in `addSet`/`removeSet` as defense-in-depth.

Closes #8698

Signed-off-by: rodo <roland@dolltons.com>
2026-03-23 11:24:29 +01:00
alonso.torres
a1a469449e Add throwValidationErrors flag for plugins 2026-03-19 15:37:08 +01:00
Andrés Moya
8e2a52af50 💄 Change function names 2026-03-18 15:30:04 +01:00
alonso.torres
4e1b940e04 Remap token properties for usability 2026-03-18 15:30:04 +01:00
Andrés Moya
c72e9ee1a0 🐛 Convert token values for the plugins 2026-02-25 14:04:20 +01:00
Andrés Moya
ba87ea1a44 🔧 Add tokenscript flag and more validations to token values 2026-02-25 14:04:20 +01:00
Andrés Moya
72a855d4ac 🐛 Fix activeSets in themes API 2026-02-25 14:04:20 +01:00
alonso.torres
cee974a906 🐛 Fix problem with tokens in plugins 2026-02-18 17:20:46 +01:00
Andrés Moya
643cd6f61f
🐛 Add resolved value to tokens in plugins API (#8372) 2026-02-17 09:20:04 +01:00
Andrés Moya
813c804d45 🔧 Enhance schema validation of token application 2026-02-16 15:16:14 +01:00
Andrés Moya
a23ca6a1cb 🐛 Fix applied tokens reading in shape proxy 2026-02-12 17:14:16 +01:00
Andrés Moya
11eedd0368 🐛 Patch alternative ways of applying tokens to shapes 2026-02-12 16:01:55 +01:00
Andrés Moya
5b5f22a8c6
🎉 Add tokens to Penpot Plugins API (#7756)
* 🎉 Add tokens to plugins API documentation

And add poc plugin example

* 📚 Document better the tokens value in plugins API

* 🔧 Refactor token validation schemas

* 🔧 Use automatic validation in token proxies

* 🔧 Use schemas to validate token creation

* 🔧 Use multi schema for token value

* 🔧 Use schema in token api methods

* 🐛 Fix review comments

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-02-09 14:18:31 +01:00
Andrés Moya
0858e297e5
🎉 Add composite tokens to plugins API (#7992) 2025-12-22 17:14:54 +01:00
Eva Marco
81e0e4f222
♻️ Replace token form files (#7896)
* ♻️ Replace shadow form

* ♻️ Rename files and components

* ♻️ Replace offsetx and offsety names

* ♻️ Replace form file for new form component using new form system

* ♻️ Rename files and props
2025-12-05 17:04:07 +01:00
Andrés Moya
3cc54fd988
🎉 Add design tokens to plugins API (#7602)
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2025-11-14 11:14:56 +01:00