select* resets its label to `default-selected` whenever its options
change identity. The access token dialog builds its options vector
inline, so picking an expiration re-rendered the dialog and the label
snapped back to "Never", although the form kept the picked value and
the token was created with it.
form-select* now passes the form value as `default-selected` when it
holds a non-blank string, so the reset lands on the picked option. The
caller's default still applies while the form value is blank.
Closes#11663
AI-assisted-by: claude-opus-5
Signed-off-by: chulgil <2044587+chulgil@users.noreply.github.com>
Co-authored-by: chulgil <2044587+chulgil@users.noreply.github.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
select* resets its label to `default-selected` whenever its options
change identity. The access token dialog builds its options vector
inline, so picking an expiration re-rendered the dialog and the label
snapped back to "Never", although the form kept the picked value and
the token was created with it.
form-select* now passes the form value as `default-selected` when it
holds a non-blank string, so the reset lands on the picked option. The
caller's default still applies while the form value is blank.
Closes#11663
AI-assisted-by: claude-opus-5
Signed-off-by: chulgil <2044587+chulgil@users.noreply.github.com>
Co-authored-by: chulgil <2044587+chulgil@users.noreply.github.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
Adds a 3x entry to the export scale selector in the workspace design
sidebar and in the viewer inspect panel, so @3x assets can be exported
natively without resizing them in external tools.
Signed-off-by: Shreyash Agare <agareshreyash26@gmail.com>
Co-authored-by: Shreyash Agare <agareshreyash26@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
Move SPA routing out of the URL fragment into the normal query
string. The screen travels in a reserved `screen` key holding
the route name (`?screen=workspace&team-id=…`); every other
param keeps its name. `rt/nav` and `rt/resolve` keep their
signatures.
This deletes the fragment-mirroring URL surgery, simplifies
link-preview (the server sees everything) and nginx (single
path, no SPA fallback rules needed), and migrates OIDC
redirects, email links, e2e helpers and plugin test utils to
the new format.
Legacy `#/…` URLs translate client-side for one Penpot version
(`legacy-routes`, marked TODO(next-version)); non-SPA paths
are untouched.
AI-assisted-by: muse-spark-1.3-contributor
Drop the onboarding-03 experiment consulted through
external-feature-flag, keeping the false-branch behavior: registration
never requests a welcome file and the workspace never shows the
onboarding modals. Remove the now-unused welcome-file machinery on the
backend (RPC wiring, welcome_file namespace, welcome-file-id prop and
the post-login redirect). Keep the external-feature-flag helper as the
seam for future experiments and note it in mem:frontend/core.
Closes#11705
AI-assisted-by: muse-spark-1.3-contributor
* 🎉 Add a context menu to the v3 text editor
Right-clicking while editing a text shape now opens a menu with Cut,
Copy, Paste and Select all, so those actions stop being reachable only
from the keyboard. Cut and Copy are disabled when nothing is selected,
and with no selection the caret first moves to the click position.
The menu is a new `:text` kind of the workspace context menu, so it
inherits the existing positioning, styling and shortcut hints. Its
entries emit events that drive the WASM editor through the same calls
the keyboard path uses, so a menu edit commits exactly like a
keystroke: same undo step, same layer rename.
A secondary click has to leave the text alone until the menu acts on
it. The pointer handlers now ignore it, both the right button and the
macOS Ctrl+Click that reports button 0, so it can no longer start a
drag-selection over what was selected. Pressing the mouse on the menu
would blur the capture surface and end the session, so the menu
cancels the default action of `mousedown` while a text is being
edited.
Paste reads the system clipboard through `navigator.clipboard`, since
a menu click carries no clipboard event.
Closes#10914
AI-assisted-by: claude-opus-5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ✨ Add Playwright tests for the text editor context menu
Eight tests under "Text Editor context menu" in the v3 editor spec.
They load the existing lorem ipsum fixture rather than drawing a shape,
enter edit mode, and drive the menu with a real right click.
They cover the four entries, that the right click keeps the selection
(copy returns the whole text), that a right button drag no longer
replaces it, that moving the caret abandons a staged typography, and
that cut and copy are disabled at a collapsed caret. Typing right after
a menu action also shows the editor kept the focus while the menu was
open.
AI-assisted-by: claude-opus-5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ♻️ Use a test id instead of a DOM id in the v3 editor spec
AI-assisted-by: claude-opus-5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Thumbnail :uri values arrive from the server over transit, so
media-ids decode to UUID objects instead of strings. The
resolved-uri? helper added in #11563 called
clojure.string/starts-with? on them unconditionally, raising
TypeError: str.lastIndexOf is not a function and crashing the
workspace on frame render. Guard with string? so non-string
URIs fall through to resolve-media, which stringifies them.
AI-assisted-by: muse-spark-1.3-contributor