12923 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
Luis de Dios
edccda2038 🐛 Fix remove prints 2026-04-27 15:26:55 +02:00
Marina López
4867358428 Add modal to subscribe to nitrate from unlimited 2026-04-27 14:11:47 +02:00
boskodev790
e5314f4a13
🐛 Fix restore-version-from-plugin promise hanging on restore failure (#9111)
Closes #9092.

`restore-version-from-plugin` accepted `_reject` as a dead parameter and
its stream had no `rx/catch`, so errors raised during the restore flow
(failed `rp/cmd! :restore-file-snapshot`, persistence timeouts, or
exceptions inside the watch body) silently swallowed instead of
rejecting the plugin-facing promise at `file.cljs:81`. Plugin code
that did `await version.restore()` would hang indefinitely on any
failure.

Wire `reject` through and wrap the emission with the same `rx/catch`
pattern already used by `create-version-from-plugins` in this file.

- Rename `_reject` to `reject` in the function signature
- Wrap the `rx/concat` body with `rx/catch` that calls `(reject error)`
  and returns `rx/empty` on error, mirroring `create-version-from-plugins`
- 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 10:17:00 +02:00
Pablo Alba
9c6cc5ec32 💄 Fix nitrate org arrow style 2026-04-27 10:16:40 +02:00
Andrey Antukh
feec89679a Merge remote-tracking branch 'origin/main' into main-staging 2026-04-27 09:58:13 +02:00
Luis de Dios
a5a8ab5de6 🐛 Fix MCP status is displayed as disabled when setting MCP key without expiration date
Fixes #14058 and #14061 in Taiga
2026-04-27 09:37:11 +02:00
Alejandro Alonso
c4e508a606 🐛 Fix text ellipsis merging error 2026-04-27 08:49:22 +02:00
Pablo Alba
700f3e9c10 MR changes 2026-04-24 17:19:41 +02:00
Pablo Alba
debfe5490f 🐛 Fix switching a team nitrate organization lose the background 2026-04-24 17:19:41 +02:00
Yamila Moreno
7031052c4e 🐛 Prevent invitations to blacklisted domains 2026-04-24 16:48:59 +02:00
Andrey Antukh
01d68ec09b Merge remote-tracking branch 'origin/staging' into develop 2026-04-24 14:16:03 +02:00
Andrey Antukh
35f8e1b084 Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-24 14:09:21 +02:00
Andrey Antukh
0b6416e53b Merge remote-tracking branch 'origin/main' into main-staging 2026-04-24 14:09:03 +02:00
Andrey Antukh
d380efdb0c
⬆️ Update devenv dependencies (#9142)
* ⬆️ Update devenv dependencies

*  Fix formatting issues

* 📎 Fix linter issues
2026-04-24 14:07:51 +02:00
moorsecopers99
7e499c5e5f
🐛 Fix Settings/Notifications submit button always active with no changes (#9091)
The "Update Settings" button in Your Account > Settings and Notifications
was always enabled, even when the form had no changes, and clicking it
emitted a success notification despite no data being modified.

Disable the submit button when the current form data equals its initial
state, so it activates only when there are actual changes to persist.

Signed-off-by: moorsecopers99 <patellscott18@gmail.com>
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-24 13:24:55 +02:00
Juan Flores
38d67c8e96
🐛 Fix Help & Learning submenu vertical alignment in account menu (#9138)
The submenu opened by hovering Help & Learning in the user account
menu rendered with a vertical offset, making it appear visually
disconnected from its parent row and aligned instead with the
Community

Signed-off-by: Juan Flores <112629487+juan-flores077@users.noreply.github.com>
2026-04-24 13:17:57 +02:00
Eva Marco
6c4ab8940d
🐛 Fix colorpicker eyedropper on gradients tab (#9125)
* 🐛 Fix colorpicker eyedropper on gradients tab

* 🐛 Fix gradient test deleting opacity input
2026-04-24 12:48:58 +02:00
Alejandro Alonso
89a1ee7813 Merge remote-tracking branch 'origin/main-staging' into staging 2026-04-24 12:06:27 +02:00
Andrey Antukh
29ba336928 Merge remote-tracking branch 'origin/main' into main-staging 2026-04-24 11:58:50 +02:00
Eva Marco
4a7140d82d
🐛 Fix theme modal height (#9105)
* 🐛 Fix CI

* 🐛 Fix theme modal height
2026-04-24 11:38:34 +02:00
Alejandro Alonso
58fae0a04d 🐛 Fix text.cljs error from staging merge 2026-04-24 10:10:00 +02:00
Alejandro Alonso
078663b0fa 🔧 Fix rust linter errors 2026-04-24 09:52:51 +02:00