21688 Commits

Author SHA1 Message Date
Jack Storment
22b85f1a92
Show specific error messages for invitation token failures (#9223)
*  Show specific error messages for invitation token failures

Surface distinct error messages for the three invitation-token failure
modes that the backend already distinguishes: email mismatch, expired
token, and invalid/corrupted token. Replaces the single generic
could not accept invitation message with actionable text so the
user knows what went wrong and how to recover.

Signed-off-by: jack-stormentswe <crazycoder131@gmail.com>

* 💄 Update CHANGE.md

Signed-off-by: jack-stormentswe <crazycoder131@gmail.com>

* 💄 Address review feedback on invitation-error messages

Signed-off-by: jack-stormentswe <crazycoder131@gmail.com>

---------

Signed-off-by: jack-stormentswe <crazycoder131@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 17:57:59 +02:00
Renzo
510a015424
🐛 Fix dashboard modal clipping behind sidebar (#9233)
Signed-off-by: RenzoMXD <170978465+RenzoMXD@users.noreply.github.com>
2026-04-29 17:44:49 +02:00
alonso.torres
5e3e66a99b 📚 Updated docs for MCP development environment 2026-04-29 16:39:19 +02:00
Andrey Antukh
05b4760583 📚 Set clearer expectations for PR reviews and prior discussion
Explicitly state that the team is small and reviews may take a
few days as they are handled in dedicated time blocks.

Remove mention of GitHub Discussions since it is not used.

Reword the discussion requirement to manage expectations: do not
expect a PR to be accepted without prior discussion.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 16:27:44 +02:00
Statxc
fd170b23f6
🐛 Fix Heroicons arrow paths broken after SVG import (#5283) (#9156)
Signed-off-by: statxc <181730535+statxc@users.noreply.github.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 15:45:22 +02:00
Dream
d668744a1f
Add search to board size presets dropdown (#9117)
Closes #4658

Signed-off-by: eureka0928 <meobius123@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 15:44:53 +02:00
María Valderrama
e22a03e7e8
Subscribe to nitrate with an activation code
*  Subscribe to nitrate with an activation code

* 📎 Code review
2026-04-29 12:42:25 +02:00
Jack Storment
3f40be6b4d
💄 Fix sucess typo in subscription dialog i18n keys (#9204)
Rename subscription.settings.sucess.dialog.{title,footer} to
subscription.settings.success.dialog.{title,footer} in en.po and
update the three callsites in subscription.cljs.

Closes #9203

Signed-off-by: jack-stormentswe <crazycoder131@gmail.com>
2026-04-29 11:07:30 +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
9751ac2b41 📎 Update changelog 2026-04-29 09:43:13 +02:00
Andrey Antukh
ea971a0109 🐛 Fix redundant longhand margin-block properties in options.scss
Combine margin-block-start and margin-block-end into the margin-block
shorthand to satisfy the declaration-block-no-redundant-longhand-properties
stylelint rule.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-29 07:39:05 +00:00
Pablo Alba
b8f1b6e0c3 Add nitrate api notify-user-orgs-deletion 2026-04-28 19:47:28 +02:00
FairyPiggyDev
61ce4b9e0d
Add "Delete group" to assets panel context menu (#9151)
When working with large asset groups, users asked for a one-click way
to remove every asset under a group path. Multi-select across hundreds
of items is impractical, and ungrouping first and then deleting leaves
the orphaned items in the flat list.

This change adds a "Delete group" option to the assets-panel
context-menu for three asset types that already carry group structure:

- Components (including variants — sibling variants sharing a variant
  container are deduplicated, and the container is deleted once via
  the same dispatch the per-item delete uses in file_library.cljs).
- Colors.
- Typographies.

A confirmation modal is shown before deletion, with the count of
assets to be removed, so the action is never silent. All deletes run
inside a single undo transaction, so one Cmd+Z restores the whole
group.

Changes
-------

- `assets/groups.cljs` — `asset-group-title*` accepts an optional
  `on-delete-group` prop and conditionally adds the menu entry
  between "Ungroup" and "Combine as variants". When the callback is
  not supplied the option is hidden, so asset sections that do not
  implement it stay unaffected.
- `assets/components.cljs` — threads `on-delete-group` through the
  recursive `components-group*` and defines the section-level
  handler, dispatching to `dwsh/delete-shapes` for variant containers
  and `dwl/delete-component` for plain components.
- `assets/colors.cljs` — same threading + a simple `dwl/delete-color`
  dispatch per color in the group.
- `assets/typographies.cljs` — same threading + a
  `dwl/delete-typography` dispatch per typography in the group.
- `translations/en.po` — three new strings: the menu label
  (`workspace.assets.delete-group`) and the modal title/message
  (`modals.delete-asset-group.title`/`.message`, plural-aware).

Github #9141

Signed-off-by: FairyPigDev <luislee3108@gmail.com>
Signed-off-by: FairyPiggyDev <luislee3108@gmail.com>
2026-04-28 15:59:05 +02:00
Andrey Antukh
b0ce644752 Merge remote-tracking branch 'origin/staging' into develop 2026-04-28 10:12:40 +02:00
Andrey Antukh
19e81560be Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-28 10:09:18 +02:00
Andrey Antukh
c0989d4261 Merge remote-tracking branch 'origin/main' into main-staging 2026-04-28 10:08:51 +02:00
alonso.torres
ad1111a613 🐛 Fix problem with align center + grow auto-width 2026-04-28 09:44:57 +02:00
andrés gonzález
aabdb69218
📚 Update MCP docs for public release (#9184) 2026-04-28 09:37:40 +02:00
Luis de Dios
a35b61ee0c
🐛 Fix put onboarding modals of top of libraries & templates panel (#9178) 2026-04-28 09:26:15 +02:00
Andrey Antukh
d9f099841a
🔥 Remove redundant mf/props metadata from modern components (#9192)
The ::mf/props and ::mf/wrap-props metadata keys are no-ops on modern
components (those defined with mf/defc and the * suffix) since the *
suffix already triggers the props behavior these keys attempt to
configure. This cleanup removes the redundant metadata from modern
components across all UI directories.

Changes:
- comments/: comments
- dashboard/: comments, deleted, files, fonts, grid, import, libraries,
  pin_button, projects, search, sidebar, subscription, team, templates
- exports/: files
- modal/: modal
- settings/: subscription
- static/: static
- viewer/: comments, interactions, viewer
- workspace/: context_menu, libraries, sidebar/assets,
  viewport/gradients, tokens/settings/menu
2026-04-28 09:23:56 +02:00
Andrey Antukh
4e1968bbab 📎 Add updated version of github cli to devenv 2026-04-28 00:01:46 +02:00
Jack Storment
aa5bfe6dda
Add customizable pixel grid color (#9155)
Let users pick the pixel grid color from a standard color picker.
The grid color was previously hardcoded, making it invisible on
mid-tone canvases. Choice is stored on the file so it persists
across sessions. Defaults preserve the current appearance when
unset.

Closes #7750

Signed-off-by: jack-stormentswe <crazycoder131@gmail.com>
2026-04-27 21:37:27 +02:00
Milos Milic
bd1e0fb23f
Add Alt+click to expand a layer subtree in the Layers sidebar (#9179)
Closes #7736.

The Layers sidebar offered no way to expand every nested level of a
single subtree at once. Unfolding a layer that wraps a deep tree
required clicking each disclosure indicator one level at a time -
O(siblings * depth) clicks. The asymmetry was particularly visible
next to the existing Shift+click gesture, which collapses every
layer in the panel in a single action via `dwc/collapse-all`, with
no expand counterpart for either a single subtree or the whole
tree.

Add a new `dwc/expand-subtree` event in
`app.main.data.workspace.collapse` that uses
`cfh/get-children-ids-with-self` to gather the shape's id together
with every descendant id, then merges `{descendant-id true}` entries
into `[:workspace-local :expanded]` so the entire subtree opens in
one update. Existing expansion state on unrelated branches is left
untouched (`merge`, not `assoc`), matching the per-key shape used by
`toggle-collapse` and `expand-collapse`.

Wire the gesture into `layer_item.cljs` `toggle-collapse` callback as
a third branch:

  - Shift+click while expanded - collapse every layer (existing).
  - Alt+click while collapsed   - expand the entire subtree (new).
  - Otherwise                   - toggle this single level (existing).

Alt is chosen instead of Shift to avoid the ambiguity the issue
author flagged: "for a layer of middle depth it is unclear whether
[Shift+click] should fold all (up to the topmost parent) or expand
all (only the current subtree)". Alt is a common platform
convention for "do this recursively" (Finder, file managers,
several IDEs), so the asymmetric mapping matches user expectations.
The callback's `mf/deps` vector is extended with `id` and `objects`
so the closure refreshes when the shape tree changes.

CHANGES.md entry added under the 2.17.0 New features section.
2026-04-27 21:36:15 +02:00
Renzo
8a8ebb7943
Preserve vector content when pasting from external tools (#9182)
Signed-off-by: RenzoMXD <170978465+RenzoMXD@users.noreply.github.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-27 21:35:52 +02:00
Andrey Antukh
84b3d467cf Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-27 20:36:45 +02:00
Andrey Antukh
592cc47336 Merge remote-tracking branch 'origin/main' into main-staging 2026-04-27 20:36:21 +02:00
Andrey Antukh
a58dbec8f2 ⬆️ Update root repo deps 2026-04-27 20:35:46 +02:00
Andrey Antukh
df4ffb9147 📚 Update prompt-assistant agent file 2026-04-27 20:35:28 +02:00
Andrey Antukh
ac5736957e 📚 Update commiter opencode agent 2026-04-27 20:34:45 +02:00
Andrey Antukh
eba4f15bba Backport transit and plugins hardening compatibility issue
From staging
2026-04-27 19:04:43 +02:00
boskodev790
ea265da1f3
🐛 Fix plugin library.connectLibrary breaking Promise contract on permission failure (#9158)
`library.connectLibrary()` declared its permission check **outside** the
`js/Promise.` wrapper, so when a plugin without `library:write` permission
called `await library.connectLibrary(id)` the method did not return a
`Promise` at all:

- With the default `throwValidationErrors` flag off → `u/not-valid`
  logs to console and returns `nil`. `await nil` resolves to `nil`, so
  the plugin sees a "successful" result and crashes later when it tries
  to use methods on what it thinks is a `LibraryProxy`.
- With `throwValidationErrors` on → `u/not-valid` throws synchronously,
  so the caller gets a thrown exception instead of a rejected promise —
  inconsistent with every other `library:*` / `content:*` method which
  always returns a Promise that rejects via `reject-not-valid`.

Additionally, the in-Promise `(not (string? library-id))` branch used
`(reject nil)` — the plugin got a rejected Promise but with no error
message.

Move the permission check inside the Promise constructor and replace
both validation errors with `u/reject-not-valid`, matching the pattern
used by the sibling methods `restore`, `remove`, `pin`, `saveVersion`,
`findVersions` in `frontend/src/app/plugins/file.cljs` and every other
promise-returning plugin method. No new imports.

Also add a CHANGES.md entry under the 2.17.0 Unreleased bugs-fixed section.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-27 17:59:09 +02:00
Andrey Antukh
f4cf667d2f 📚 Update changelog 2026-04-27 17:57:00 +02:00
Pablo Alba
f8e40a1ca5 🐛 Fix can't add team to nitrate organization 2026-04-27 17:50:42 +02:00
Belén Albeza
e99ed5e9f9 🐛 Fix modifiers streams 2026-04-27 17:45:18 +02:00
Belén Albeza
0bee3993ab 🐛 Avoid race condition in initialize-workspace 2026-04-27 17:45:18 +02:00
Belén Albeza
8f905be511 Ignore user renderer pref when render-switch flag is disabled 2026-04-27 17:45:18 +02:00
Belén Albeza
8afadb5199 Show toast when switching renderer 2026-04-27 17:45:18 +02:00
Belén Albeza
6ba68c1ac0 Hot swap of viewport when renderer changes 2026-04-27 17:45:18 +02:00
Belén Albeza
ffdbe242a7 🎉 Disable wasm if renderer profile prop is set to svg 2026-04-27 17:45:18 +02:00
Belén Albeza
46b81f4302 🎉 Store chosen renderer in user profile 2026-04-27 17:45:18 +02:00
Belén Albeza
12549df65c 🎉 Add UI for webgl rendering setting (under config flag) 2026-04-27 17:45:18 +02:00
Andrey Antukh
c41537eb55 Merge remote-tracking branch 'origin/staging' into develop 2026-04-27 17:31:15 +02:00
Andrey Antukh
82f1606377 Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-27 17:31:00 +02:00
Andrey Antukh
839754715a 📚 Update changelog 2026-04-27 17:30:02 +02:00
Andrey Antukh
db8aa9bccc Merge remote-tracking branch 'origin/staging' into develop 2026-04-27 17:27:45 +02:00
Andrey Antukh
ef2fe78aac Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-27 17:27:28 +02:00
Andrey Antukh
a3b9d7bed7 📎 Fix fmt issue 2026-04-27 17:26:59 +02:00
Andrey Antukh
57f1b80013 Merge remote-tracking branch 'origin/main' into main-staging 2026-04-27 17:26:30 +02:00
Andrey Antukh
cbd5f7795b Add minor compatibility adjustments for audit archive task (#8491) 2.14.5-RC2 2026-04-27 16:15:35 +02:00
Elenzakaleidos
99f006d728
💄 Update README.md (#9171)
We modified the Images and the text of the Read me page

Signed-off-by: Elenzakaleidos <elena.scilinguo@kaleidos.net>
2026-04-27 15:44:01 +02:00