10039 Commits

Author SHA1 Message Date
Xaviju
78c48f1953
🐛 Fix broken update library notification link UI (#9070)
* 🐛 Fix broken update library notification link UI

* ♻️ Format and lint
2026-04-21 13:33:38 +02:00
alonso.torres
3da74ed864 🐛 Fix problem with component thumbnails in swap component panel 2026-04-21 13:11:03 +02:00
Aitor Moreno
612855452a 🎉 Add render perf options 2026-04-21 11:43:22 +02:00
Elena Torro
62ec66b974 Add lazy async rendering for component thumbnails 2026-04-21 11:40:53 +02:00
alonso.torres
88ec9e4ff1 🐛 Fix problem with store font after cleanup 2026-04-21 11:03:04 +02:00
Xaviju
cd9151bf9f
🐛 Fix duplicate modal title (#9064) 2026-04-21 09:54:30 +02:00
Alejandro Alonso
0d17debde7 Merge remote-tracking branch 'origin/staging' into develop 2026-04-21 08:24:29 +02:00
Alejandro Alonso
98c8bb1746 🐛 Avoid sequential tile draws and flicker during shape transforms 2026-04-21 07:45:27 +02:00
Xaviju
e9105f3670
♻️ Fix linter errors under legacy resources scss (#9035) 2026-04-20 23:58:53 +02:00
Andrey Antukh
3a39676969 Backport MCP from staging (part 1) 2026-04-20 19:37:02 +02:00
alonso.torres
c42eb6ff86 🐛 Fix problem with selection performance 2026-04-20 17:30:07 +02:00
Elena Torro
b5701923ba 🐛 Fix dragging shape 2026-04-20 16:49:18 +02:00
Juan de la Cruz
876b8d645d
🎉 Add new page separators feature (#8561)
* 🎉 Add new page separators feature

* 📎 Add PR feedback changes

* 🐛 Fix page sitemap icons

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-20 15:33:42 +02:00
Eva Marco
adea81ceee
♻️ Update icon on typography section and scss files (#9021)
* ♻️ Update icon on new buttons

* ♻️ Update scss on typography section
2026-04-20 15:32:55 +02:00
Eva Marco
003b54421d
🐛 Fix empty warning on login (#9056) 2026-04-20 12:23:47 +02:00
Pablo Alba
ae66317d6c Add nitrate api to remove user from org 2026-04-20 11:18:07 +02:00
Dream
42ebee88d6
Add paste to replace (Cmd+Shift+V) (#9033)
Paste clipboard contents in place of the currently selected shape,
inheriting its position, parent, and z-index. The replaced shape
is deleted in the same transaction for a single undo step.

Signed-off-by: eureka0928 <meobius123@gmail.com>
2026-04-20 11:03:50 +02:00
Dream
f0c68fb826
Add search bar to color palette (#8994)
*  Add search bar to color palette

Fixes #7653

Signed-off-by: eureka0928 <meobius123@gmail.com>

* ♻️ Use search icon toggle for color palette search

Address UX feedback: replace always-visible search input with a
search icon that toggles the input on click. Hide the search
functionality when no colors exist. Move CHANGES.md entry to
2.16.0 section.

Signed-off-by: eureka0928 <meobius123@gmail.com>

---------

Signed-off-by: eureka0928 <meobius123@gmail.com>
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-20 11:02:23 +02:00
wdeveloper16
d772632b08
Allow customising the OIDC login button label (#9026)
*  Allow customising the OIDC login button label (#7027)

* 📚 Add CHANGES entry and docs for PENPOT_OIDC_NAME (#7027)

---------

Co-authored-by: wdeveloper16 <wdeveloer16@protonmail.com>
2026-04-17 16:56:29 +02:00
Pablo Alba
c5a2b592a2 Move team to another nitrate organization 2026-04-17 11:38:52 +02:00
Pablo Alba
a206d57443 Add team to a nitrate organization 2026-04-17 11:38:52 +02:00
alonso.torres
bfa1ae051f 🐛 Fix problem with dashboard thumbnails images 2026-04-17 10:43:41 +02:00
Elena Torró
b74d920d03
Merge pull request #8980 from penpot/superalex-atlas-2
🎉 Tiles atlas support
2026-04-17 09:38:27 +02:00
Alejandro Alonso
fb1f55c13e
Merge pull request #9039 from penpot/alotor-fix-position-data-ff
🐛 Fix problem with position data in Firefox
2026-04-17 09:36:48 +02:00
Alejandro Alonso
8775e234f3 🎉 Waiting for tiles complete in a non blocking way 2026-04-17 09:17:26 +02:00
Alejandro Alonso
c08c3bd160 🎉 Tiles atlas support 2026-04-17 09:05:52 +02:00
Andrey Antukh
6fa440cf92 🎉 Add chunked upload API for large media and binary files
Introduce a purpose-agnostic three-step session-based upload API that
allows uploading large binary blobs (media files and .penpot imports)
without hitting multipart size limits.

Backend:
- Migration 0147: new `upload_session` table (profile_id, total_chunks,
  created_at) with indexes on profile_id and created_at.
- Three new RPC commands in media.clj:
    * `create-upload-session`  – allocates a session row; enforces
      `upload-sessions-per-profile` and `upload-chunks-per-session`
      quota limits (configurable in config.clj, defaults 5 / 20).
    * `upload-chunk`           – stores each slice as a storage object;
      validates chunk index bounds and profile ownership.
    * `assemble-file-media-object` – reassembles chunks via the shared
      `assemble-chunks!` helper and creates the final media object.
- `assemble-chunks!` is a public helper in media.clj shared by both
  `assemble-file-media-object` and `import-binfile`.
- `import-binfile` (binfile.clj): accepts an optional `upload-id` param;
  when provided, materialises the temp file from chunks instead of
  expecting an inline multipart body, removing the 200 MiB body limit
  on .penpot imports.  Schema updated with an `:and` validator requiring
  either `:file` or `:upload-id`.
- quotes.clj: new `upload-sessions-per-profile` quota check.
- Background GC task (`tasks/upload_session_gc.clj`): deletes stalled
  (never-completed) sessions older than 1 hour; scheduled daily at
  midnight via the cron system in main.clj.
- backend/AGENTS.md: document the background-task wiring pattern.

Frontend:
- New `app.main.data.uploads` namespace: generic `upload-blob-chunked`
  helper drives steps 1–2 (create session + upload all chunks with a
  concurrency cap of 2) and emits `{:session-id uuid}` for callers.
- `config.cljs`: expose `upload-chunk-size` (default 25 MiB, overridable
  via `penpotUploadChunkSize` global).
- `workspace/media.cljs`: blobs ≥ chunk-size go through the chunked path
  (`upload-blob-chunked` → `assemble-file-media-object`); smaller blobs
  use the existing direct `upload-file-media-object` path.
  `handle-media-error` simplified; `on-error` callback removed.
- `worker/import.cljs`: new `import-blob-via-upload` helper replaces the
  inline multipart approach for both binfile-v1 and binfile-v3 imports.
- `repo.cljs`: `:upload-chunk` derived as a `::multipart-upload`;
  `form-data?` removed from `import-binfile` (JSON params only).

Tests:
- Backend (rpc_media_test.clj): happy path, idempotency, permission
  isolation, invalid media type, missing chunks, session-not-found,
  chunk-index out-of-range, and quota-limit scenarios.
- Frontend (uploads_test.cljs): session creation and chunk-count
  correctness for `upload-blob-chunked`.
- Frontend (workspace_media_test.cljs): direct-upload path for small
  blobs, chunked path for large blobs, and chunk-count correctness for
  `process-blobs`.
- `helpers/http.cljs`: shared fetch-mock helpers (`install-fetch-mock!`,
  `make-json-response`, `make-transit-response`, `url->cmd`).

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-16 19:43:57 +02:00
alonso.torres
47abe09cfe 🐛 Fix problem with position data in Firefox 2026-04-16 18:08:34 +02:00
Elena Torró
b02e05e23d
Merge pull request #8919 from penpot/alotor-fix-change-font-grow-text
🐛 Fix problem when changing font and grow text
2026-04-16 16:38:32 +02:00
Pablo Alba
39f4c13493
Add nitrate remove team from org 2026-04-16 11:46:05 +02:00
Pablo Alba
ac472c615a
🐛 Fix nitrate invitations org ux review 2026-04-16 11:18:11 +02:00
Andrey Antukh
b5922d32ca Merge remote-tracking branch 'origin/main' into staging 2026-04-16 10:59:36 +02:00
Dream
78381873eb
Edit ruler guide position by double-clicking the guide pill (#8987)
Drag-and-drop is the only way to move a ruler guide today, which makes
hitting an exact pixel painful. Double-clicking the guide pill now
swaps the position label for a numeric input — Enter commits, Escape
cancels — so users can type a precise value relative to the guide's
frame (or canvas).

Closes #2311

Signed-off-by: eureka0928 <meobius123@gmail.com>
2026-04-16 10:03:28 +02:00
Andrey Antukh
de27ea904d
Add minor adjustments to the auth events (#9027) 2026-04-16 09:59:45 +02:00
Andrey Antukh
f5271dabee
🐛 Fix error handling issues (#8962)
* 🚑 Fix RangeError from re-entrant error handling in errors.cljs

Two complementary changes to prevent 'RangeError: Maximum call stack
size exceeded' when an error fires while the potok store error pipeline
is still on the call stack:

1. Re-entrancy guard on on-error: a volatile flag (handling-error?)
   is set true for the duration of each on-error invocation. Any
   nested call (e.g. from a notification emit that itself throws) is
   suppressed with a console.error instead of recursing indefinitely.

2. Async notification in flash: the st/emit!(ntf/show ...) call is
   now wrapped in ts/schedule (setTimeout 0) so the notification event
   is pushed to the store on the next event-loop tick, outside the
   error-handler call stack. This matches the pattern already used by
   the :worker-error, :svg-parser and :comment-error handlers.

* 🐛 Add unit tests for app.main.errors

Test coverage for the error-handling module:

- stale-asset-error?: 6 cases covering keyword-constant and
  protocol-dispatch mismatch signatures, plus negative cases
- exception->error-data: plain JS Error, ex-info with/without :hint
- on-error dispatch: map errors routed via ptk/handle-error, JS
  exceptions wrapped into error-data before dispatch
- Re-entrancy guard: verifies that a second on-error call issued
  from within a handle-error method is suppressed (exactly one
  handler invocation)

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-15 23:37:04 +02:00
Aitor Moreno
1477758656 🐛 Fix pointer selection 2026-04-15 16:44:24 +02:00
Juanfran
3829443046 🐛 Skip onboarding modal for nitrate entry users 2026-04-15 16:32:58 +02:00
Elena Torró
b442ca2209
Merge pull request #8988 from penpot/alotor-improve-token-set-change
🐛 Improve change token set performance
2026-04-15 16:23:55 +02:00
alonso.torres
4d2d559383 🐛 Fix problem with finish render callback 2026-04-15 16:09:38 +02:00
alonso.torres
e3bafab529 🐛 Fix problem with resizes in plugins 2026-04-15 16:09:38 +02:00
alonso.torres
3f5226485b 🐛 Fix problem when changing font and grow text 2026-04-15 16:09:38 +02:00
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
Marina López
c10f945473 Add nitrate subscription expected cancel date 2026-04-15 13:42:04 +02:00
Juanfran
f5591ed22e 🐛 Forward email when adding user to Nitrate organization 2026-04-15 13:28:39 +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