21226 Commits

Author SHA1 Message Date
Aitor Moreno
424b689dca 🐛 Fix mixed fills issues 2026-04-15 14:32:32 +02:00
Aitor Moreno
77b4d07d1f 🐛 Fix v3 text styles not being applied when inc/dec value 2026-04-15 14:32:32 +02:00
Aitor Moreno
6fd264051a 🐛 Fix v2/v3 wrong styling 2026-04-15 14:32:32 +02:00
Andrey Antukh
8f30a95ca0 🐛 Guard against nil variant-data in typography-item
When d/seek finds no matching font variant (e.g. the variant-id stored
on the typography no longer exists in the font's variants list),
variant-data is nil and (:name nil) produces nil, resulting in a
malformed label like "14px | ". Fall back to "--" in that case.
2026-04-15 12:27:18 +02:00
Andrey Antukh
e8547ab6dd 🐛 Pass on-finish-drag to harmony-selector in colorpicker
Without this, dragging the value/opacity sliders in the harmony tab
never called on-finish-drag, so the undo transaction started by
on-start-drag was never committed.
2026-04-15 12:27:18 +02:00
Andrey Antukh
628ce604c5 ♻️ Convert colorpicker and its sub-components to modern rumext * format
slider-selector (slider_selector.cljs):
- Rename to slider-selector*
- Rename prop vertical? to is-vertical
- Remove prop reverse? entirely: it was never passed by any callsite,
  so the related reversal logic in calculate-pos and handler positioning
  is also removed as dead code

value-saturation-selector (ramp.cljs):
- Rename to value-saturation-selector*
- Update internal call site to [:> value-saturation-selector* ...]
- Update slider-selector call sites to [:> slider-selector* ...]

harmony-selector (harmony.cljs):
- Rename to harmony-selector*
- Update slider-selector call sites to [:> slider-selector* ...] with
  renamed is-vertical prop
- Remove stale duplicate :vertical true prop
- Fix spurious extra wrapping vector around the opacity slider in the
  when branch

hsva-selector (hsva.cljs):
- Rename to hsva-selector*
- Update all four slider-selector call sites to [:> slider-selector* ...]
- Remove no-op :reverse? false prop from the value slider

color-inputs (color_inputs.cljs):
- Rename to color-inputs*

colorpicker.cljs:
- Update :refer imports for color-inputs*, harmony-selector*,
  hsva-selector* and libraries*
- Update all corresponding call sites from [:& ...] to [:> ...]
2026-04-15 12:27:18 +02:00
Andrey Antukh
90d052464f ♻️ Convert text-palette components to modern * format
Convert typography-item, palette and text-palette to typography-item*,
palette* and text-palette* using {:keys [...]} destructuring. Rename
prop name-only? to is-name-only in typography-item*. Update internal
call sites to [:> ...] and update the :refer import in palette.cljs.
2026-04-15 12:27:18 +02:00
Andrey Antukh
fbee875d75 ♻️ Convert active-sessions to modern * component format
Convert active-sessions to active-sessions* (zero-prop component).
Update call site in right_header.cljs to use [:> ...] and update the
:refer import accordingly.
2026-04-15 12:27:18 +02:00
Andrey Antukh
bf7c12ae75 ♻️ Convert coordinates to modern * component format
Convert coordinates to coordinates* using {:keys [...]} destructuring
and rename prop colorpalette? to is-colorpalette. Update call site in
workspace.cljs to use [:> ...] with new prop name.
2026-04-15 12:27:18 +02:00
Andrey Antukh
175f122a0f ♻️ Convert viewport-scrollbars to modern * component format
Convert viewport-scrollbars to viewport-scrollbars* using {:keys [...]}
destructuring and update call sites in viewport.cljs and viewport_wasm.cljs
to use [:> ...].
2026-04-15 12:27:18 +02:00
Andrey Antukh
b2f4e90a79 ♻️ Convert shape-distance-segment to modern * component format
Convert shape-distance-segment to shape-distance-segment* using {:keys [...]}
destructuring and update its internal call site in shape-distance to use [:> ...].
2026-04-15 12:27:18 +02:00
Andrey Antukh
b4ec0a6d55 🐛 Add missing zoom and page-id dep on snap-feedback use-effect 2026-04-15 12:27:18 +02:00
alonso.torres
988c277e37 🐛 Post-review enhancements 2026-04-15 09:53:36 +02:00
alonso.torres
1d8299a919 🐛 Fix problem with component thumbnails 2026-04-15 09:53:36 +02:00
Andrey Antukh
f07b954b7e
Add efficiency improvements to workspace components (refactor part 1) (#8887)
* ♻️ Convert snap-points components to modern rumext format

Migrate snap-point, snap-line, snap-feedback, and snap-points from
legacy mf/defc format to modern * suffix format. This enables
optimized props handling by the rumext macro, eliminating implicit
JS object wrapping overhead on each render. All internal and
external call sites updated to use [:> component* props] syntax.

* ♻️ Convert frame-title to modern rumext format

Migrate frame-title from legacy mf/defc format to modern * suffix
format. The component was using legacy implicit props wrapping without
::mf/wrap-props false or ::mf/props :obj, causing unnecessary JS
object conversion overhead on each render. The parent frame-titles*
call site updated to use [:> frame-title* props] syntax.

* ♻️ Convert interactions components to modern rumext format

Migrate interaction-marker, interaction-path, interaction-handle,
overlay-marker, and interactions from legacy mf/defc format to modern
* suffix format. These five components had zero props optimization
applied, causing implicit JS object wrapping on every render. All
internal and external call sites updated to use [:> component* props]
syntax.

* ♻️ Convert rulers components to modern rumext format

Migrate rulers-text, viewport-frame, and selection-area from legacy
mf/defc format to modern * suffix format. These three components in
the always-visible rulers layer had zero props optimization applied.
Internal call sites in the parent rulers component updated to use
[:> component* props] syntax.

* ♻️ Convert frame-grid components to modern rumext format

Migrate square-grid, layout-grid, grid-display-frame, and frame-grid
from legacy mf/defc format to modern * suffix format. These four
components render grid patterns per-frame with zero props optimization.
All internal and external call sites updated to use [:> component* props]
syntax.

* ♻️ Convert gradient handler components to modern rumext format

Migrate shadow, gradient-color-handler, and gradient-handler-transformed
from legacy mf/defc format to modern * suffix format. These components
are rendered during gradient editing with zero props optimization applied.
Internal call sites in gradient-handler-transformed and
gradient-handlers-impl updated to use [:> component* props] syntax.

* ♻️ Rename ?-ending props in modernized workspace viewport components

Apply prop naming rules to all * components migrated in the previous batch:
- remove-snap? -> remove-snap in snap-feedback* (and get-snap helper)
- selected? -> is-selected in interaction-path*
- hover-disabled? -> is-hover-disabled in overlay-marker* and interactions*
- show-rulers? -> show-rulers in viewport-frame*

Update all internal and external call sites consistently.

* 🐛 Fix get-snap call in snap-feedback* using JS props object

Modern rumext *-suffix components receive props as JS objects, not
Clojure maps. snap-feedback* was pushing the raw props object into the
rx/subject and get-snap was destructuring it as a Clojure map, causing
all keys to resolve to nil.

Fix by:
- Changing get-snap to take positional arguments (coord, shapes,
  page-id, remove-snap, zoom) instead of a map-destructured opts arg
- Building an explicit Clojure map from the bound locals before pushing
  to the subject
- Destructuring that map inside the rx/switch-map callback and calling
  get-snap with positional args

Also mark get-snap and add-point-to-snaps as private (defn-), consistent
with the other helpers in the namespace — none are referenced externally.
2026-04-14 19:48:59 +02:00
Andrey Antukh
3264bc746f 🔧 Backport ci configuration changes from develop 2026-04-14 12:33:10 +02:00
Andrey Antukh
a81cded0aa
Make the common fressian module more testable (#8859)
*  Add exhaustive unit tests for app.common.fressian encode/decode

Add a JVM-only test suite (41 tests, 172 assertions) for the fressian
serialisation layer, covering:

- All custom handlers: char, clj/keyword, clj/symbol, clj/vector,
  clj/set, clj/map, clj/seq, clj/ratio, clj/bigint, java/instant,
  OffsetDateTime, linked/map (order preserved), linked/set (order preserved)
- Built-in types: nil, boolean, int, long, double (NaN, ±Inf, boundaries),
  String, byte[], UUID
- Edge cases: empty collections, nil values, ArrayMap/HashMap size boundary,
  mixed key types
- Penpot-domain structures: shape maps with UUID keys, nested objects maps
- Correctness: encode→decode→encode idempotency, independent encode calls

* ♻️ Extract fressian handler helpers to private top-level functions

Extract adapt-write-handler, adapt-read-handler, and merge-handlers
out of the letfn in add-handlers! into reusable private functions.
Also creates xf:adapt-write-handler and xf:adapt-read-handler
transducers and adds overwrite-read-handlers and overwrite-write-handlers
for advanced handler override use cases.
2026-04-14 10:48:58 +02:00
Andrey Antukh
bc47b992eb Merge remote-tracking branch 'origin/main' into staging 2026-04-13 18:31:32 +02:00
Alejandro Alonso
367262f5a0
Merge pull request #8959 from penpot/elenatorro-fix-render-wasm-loading
🔧 Improve loading times
2026-04-13 16:50:30 +02:00
Elena Torro
6b3d5d930f 🔧 Improve zoom and pan performance 2026-04-13 16:35:36 +02:00
Elena Torró
a6c3767e2b
Merge pull request #8956 from penpot/alotor-poc-nofast-mode
🐛 Fix problem with fast mode
2026-04-13 15:38:04 +02:00
alonso.torres
2d07b9e77c 🐛 Fix problem with fast mode 2026-04-13 15:18:12 +02:00
Andrey Antukh
0fc2050526 ⬆️ Update deps on root package.json 2026-04-13 15:00:47 +02:00
Elena Torro
47eadab82e 🔧 Include DropShadows surface to reset 2026-04-13 14:42:03 +02:00
Elena Torro
d85d63ef3c 🔧 Improve page loading 2026-04-13 14:42:03 +02:00
Aitor Moreno
83e9f85ccf
Merge pull request #8943 from penpot/ladybenko-13949-fix-resize-call
🐛 Fix initializing guards in viewport loading
2026-04-13 13:37:25 +02:00
Andrey Antukh
28f65fec91 📚 Update changelog 2026-04-13 12:15:17 +02:00
Aitor Moreno
9c44f5bf65 🐛 Fix text editor v1 focus not being handled correctly (#8942) 2026-04-13 12:08:06 +02:00
Eva Marco
443fb60743 🐛 Fix highlight on frames after rename (#8938) 2026-04-13 12:04:04 +02:00
Luis de Dios
cbe9d31599 🐛 Fix dashboard navigation tabs overlap with content when scrolling (#8937)
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-13 12:01:10 +02:00
Luis de Dios
599a66979a
🐛 Fix dashboard navigation tabs overlap with content when scrolling (#8937)
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-13 11:59:19 +02:00
Andrey Antukh
d6045c80a1 💄 Fix docstrings and clarify filter expression in path namespaces
- Fix 'conten' typo to 'content' in path.cljc docstring
- Fix 'curvle' typo to 'curve' in shape_to_path.cljc docstring
- Replace confusing XOR-style filter with readable
  (contains? #{:line-to :curve-to} ...) in bool.cljc
- Align handler-indices and opposite-index docstrings with
  matching API in path.cljc
2026-04-13 11:48:30 +02:00
Andrey Antukh
8d1906f56e 🐛 Fix ^:cosnt typo to ^:const on bool-group-style-properties
The metadata key was misspelled as :cosnt instead of :const,
preventing the compiler from recognizing the Var as a compile-time
constant.
2026-04-13 11:48:30 +02:00
Andrey Antukh
2eaf117b56 🐛 Fix swapped arguments in CLJS PathData -nth with default
The CLJS implementation of PathData's -nth protocol method had
swapped arguments in the 3-arity version (with default value).
The call (d/in-range? i size) should be (d/in-range? size i)
to match the CLJ implementation. With swapped args, valid indices
always returned the default value, and invalid indices attempted
out-of-bounds buffer reads.
2026-04-13 11:48:30 +02:00
Andrey Antukh
e511576f66 🐛 Normalize PathData coordinates to safe integer bounds on read
Add normalize-coord helper function that clamps coordinate values to
max-safe-int and min-safe-int bounds when reading segments from PathData
binary buffer. Applies normalization to read-segment, impl-walk,
impl-reduce, and impl-lookup functions to ensure coordinates remain
within safe bounds.

Add corresponding test to verify out-of-bounds coordinates are properly
clamped when reading PathData.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-13 11:48:30 +02:00
Andrey Antukh
a403175d5c
🐛 Fix TypeError in sd-token-uuid when resolving tokens interactively (#8929)
The backtrace-tokens-tree function used a namespaced keyword :temp/id
which clj->js converted to the JS property "temp/id". The sd-token-uuid
function then tried to access .id on the sd-token top-level object,
which was undefined, causing "Cannot read properties of undefined
(reading uuid)".

Fix by using the existing token :id instead of generating a temporary
one, and read it from sd-token.original (matching sd-token-name pattern).
2026-04-13 11:34:15 +02:00
Aitor Moreno
bb85b312d6
🐛 Fix text editor v1 focus not being handled correctly (#8942) 2026-04-13 10:00:56 +02:00
Eva Marco
6d1a2d449a
🐛 Fix highlight on frames after rename (#8938) 2026-04-13 09:09:03 +02:00
Belén Albeza
eb811621a9 🐛 Fix initializing guards in viewport loading 2026-04-10 13:54:06 +02:00
Pablo Alba
ef6eeb5693
🐛 Fix variants corner cases with selrect and points (#8882)
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-10 11:23:03 +02:00
Marek Hrabe
9785a13e67
🐛 Add webp export format to plugin types (#8870)
* 🐛 Add webp export format to plugin types

Align plugin API typings with runtime export support by including 'webp' in
'Export.type' and updating the exported formats documentation.

Signed-off-by: Marek Hrabe <marekhrabe@me.com>

* 📚 Add plugin-types changelog entry for missing webp export format

Signed-off-by: Marek Hrabe <marekhrabe@me.com>

---------

Signed-off-by: Marek Hrabe <marekhrabe@me.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-10 11:22:20 +02:00
Dr. Dominik Jain
8101f58651
📚 Add improvements for mcp readme (#8930)
* 📚 Update description of mcp-remote usage

* Use Streamable HTTP endpoint instead of SSE
* Remove redundant global installation

* 📚 Add recommendations on model selection

* 📚 Use new tags in npx launch commands
2026-04-10 10:49:13 +02:00
Elena Torró
a87552bc45
Merge pull request #8926 from penpot/superalex-wasm-render-performance
🎉 Wasm render performance improvements
2026-04-10 09:11:50 +02:00
Alejandro Alonso
5eebc17ce2 🎉 Support for debugging cache texture 2026-04-09 19:02:14 +02:00
Alejandro Alonso
434e27bbe8 🎉 Improve panning performance 2026-04-09 19:02:14 +02:00
Alejandro Alonso
5c67cd0a4b 🐛 Avoid unnecesary text editor pointer movements 2026-04-09 16:18:58 +02:00
Eva Marco
290f37425f
🐛 Fix id prop on switch component (#8915) 2026-04-09 12:35:34 +02:00
Andrey Antukh
ef39afe9b5 Merge remote-tracking branch 'origin/main' into staging 2026-04-09 12:24:18 +02:00
Elena Torró
a88f8f1394
Merge pull request #8918 from penpot/niwinz-main-path-preview-issue
🐛 Fix path drawing preview passing shape instead of content to next-node
2.14.3-RC1
2026-04-09 11:48:58 +02:00
Eva Marco
b0a99b65e4
🐛 Fix highlight on shape after rename (#8890) 2026-04-09 11:27:36 +02:00