* fix: place cursor at start of inserted table row/column
When using Insert before for a table row or column, the selection was
collapsed onto the mapped previous selection — landing at the bottom of the
shifted neighbouring column rather than in the newly inserted cell. Move the
cursor to the start of the first cell of the inserted row/column instead.
* feat: Inline editor menu (#12611)
* wip
* Mobile support
* Address review feedback on inline menu
- Mark selection-restore transaction as not added to history
- Only open desktop inline menu when an anchor is available
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix: place cursor at start of inserted table row/column
When using Insert before for a table row or column, the selection was
collapsed onto the mapped previous selection — landing at the bottom of the
shifted neighbouring column rather than in the newly inserted cell. Move the
cursor to the start of the first cell of the inserted row/column instead.
* Add handling for After variants
Add lint rule
---------
Co-authored-by: Claude <noreply@anthropic.com>
* wip
* Mobile support
* Address review feedback on inline menu
- Mark selection-restore transaction as not added to history
- Only open desktop inline menu when an anchor is available
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix: New Czech translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: Increase valid user-supplied URL length to 1024
* fix: Wrap URL length migration in a transaction
Wrap the multi-column changeColumn operations in a transaction so a
failure on any column rolls back the whole migration rather than leaving
the database partially migrated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Re-frame the rendered SVG viewBox from a getBBox() measurement taken in
the visible editor rather than the hidden render element, where the
measurement is unreliable on high-DPI/RDP sessions. Bump the cache
namespace so previously mis-sized diagrams are re-rendered.
* fix: Remove unused grid snapping from element resizing
Horizontal resizing snapped widths to a 5% grid, which is no longer
desired. Replace the only remaining use of the gridSnap prop (the
minimum-width clamp) with a named constant and drop the prop entirely.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: Remove resize lag by disabling size transition while dragging
The width/height CSS transition on resizable elements existed to smooth
the discrete jumps from grid snapping. With pixel-by-pixel resizing the
element perpetually animates toward a target ~150ms in the future, so it
visibly trails the cursor. Disable the transition while actively dragging
and restore it afterwards so snap-back and collaborative size changes
still animate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: Constrain image resizing to editor edge instead of snapping to natural size
When dragging an element past the editor bounds, the full-width sentinel
forced the width to the natural size. For images narrower than the editor
this snapped them back to their (smaller) natural width at the boundary.
Only use the natural-width sentinel when the image is genuinely wider than
the editor; otherwise constrain to the editor edge.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* PR feedback
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The onerror handlers in FileHelper passed the raw DOM Event to reject,
which Sentry surfaced as "Event captured as promise rejection" with no
stack. Reject with an Error and revoke the blob URL on failure.
* refactor: introduce declarative menu registry for selection toolbar
Replace the hard-coded if-else chain in SelectionToolbar with a
priority-based menu registry system. Extensions can now declare
selection toolbar menus via `selectionToolbarMenus()`, following the
same pattern as `commands()` and `keys()`.
Key changes:
- Add SelectionContext interface computed once per toolbar render
- Add SelectionToolbarMenuDescriptor for declarative menu registration
- Add selectionToolbarMenus() to Extension base class
- Add buildSelectionContext() utility to eliminate repeated state queries
- ExtensionManager collects and sorts menus from all extensions
- SelectionToolbarExtension registers all 10 existing menus
- All menu functions now accept SelectionContext instead of raw state
- SelectionToolbar uses registry lookup instead of if-else chain
https://claude.ai/code/session_01MRyFysrGM9d8NhbAs7nrtU
* refactor: import t directly from i18next in menu functions
Remove the `t: TFunction` parameter from all menu functions and the
`SelectionToolbarMenuDescriptor.getItems` signature. Each menu file
now imports `t` directly from i18next, matching the pattern used
throughout the rest of the codebase (e.g. Image.tsx, Link.tsx).
https://claude.ai/code/session_01MRyFysrGM9d8NhbAs7nrtU
* refactor: move divider menu into HorizontalRule node extension
The divider selection toolbar menu is now declared via
selectionToolbarMenus() on the HorizontalRule node class, co-locating
the menu with the node that owns it. Delete the standalone
app/editor/menus/divider.tsx file and remove the entry from
SelectionToolbarExtension.
This is the first menu migrated from the centralized toolbar extension
to an individual node extension, demonstrating the pattern for the
remaining menus.
https://claude.ai/code/session_01MRyFysrGM9d8NhbAs7nrtU
* refactor: check readOnly in matches predicate for divider menu
https://claude.ai/code/session_01MRyFysrGM9d8NhbAs7nrtU
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* chore: Update JSON importer to use zip streaming, new importer flow
* chore: Drop teamId from import urlId collision check and remove unused internal-id scaffolding
urlId is globally unique on Document/Collection so the team scope was wrong.
Also removes leftover internal-id generation in JSONAPIImportTask that was
never used in task input/output.
* Restore classes used upstream
Safari keeps the heading actions widget at the end of headings to avoid
selection issues, but the widget was still using side metadata suited to
the leading placement.
With Chinese IME composition at the end of a heading, same-position
insertion could interact with the contentEditable=false widget and leave
the editor selection stuck. After that, Backspace stopped working until
the page was refreshed.
Use positive side metadata for the Safari trailing widget so composed
text stays before it, allow relaxed selection around the widget, and add
a narrow Safari-only ArrowLeft fallback for the heading-end boundary.
Chinese IME has been manually verified. Other composition-based IMEs may
follow a similar path, but are not claimed as verified here.
* fix: New French translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Spanish translations from Crowdin [ci skip]
* fix: New Czech translations from Crowdin [ci skip]
* fix: New Danish translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New Hebrew translations from Crowdin [ci skip]
* fix: New Hungarian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Japanese translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Dutch translations from Crowdin [ci skip]
* fix: New Polish translations from Crowdin [ci skip]
* fix: New Portuguese translations from Crowdin [ci skip]
* fix: New Swedish translations from Crowdin [ci skip]
* fix: New Turkish translations from Crowdin [ci skip]
* fix: New Ukrainian translations from Crowdin [ci skip]
* fix: New Chinese Simplified translations from Crowdin [ci skip]
* fix: New Chinese Traditional translations from Crowdin [ci skip]
* fix: New Vietnamese translations from Crowdin [ci skip]
* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
* fix: New Indonesian translations from Crowdin [ci skip]
* fix: New Persian translations from Crowdin [ci skip]
* fix: New Thai translations from Crowdin [ci skip]
* fix: New English, United Kingdom translations from Crowdin [ci skip]
* fix: New Norwegian Bokmal translations from Crowdin [ci skip]
* fix: New Romanian translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New Italian translations from Crowdin [ci skip]
* fix: New German translations from Crowdin [ci skip]
* fix: New French translations from Crowdin [ci skip]
* fix: New Korean translations from Crowdin [ci skip]
* fix: New Catalan translations from Crowdin [ci skip]
* feat: Toggle comments sidebar in editor lightbox
Adds a new comments toggle button to the lightbox top-right actions. When
toggled the sidebar slides out on the right and shows only the threads
anchored to the active image node. A new comment form at the bottom
creates a thread anchored to the image via a comment mark on the node.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* fix: Make lightbox comments sidebar interactable
The sidebar was being rendered as a sibling of Dialog.Content, so Radix's
focus/click-outside trap blocked all interaction with it. Move it inside
Dialog.Content so clicks and focus stay within the dialog.
Also scope the lightbox handleKeyDown to only preventDefault and act on
arrow/escape keys — and bail out entirely when typing into an input,
textarea, or contenteditable so the comment form receives keystrokes.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* fix: Align lightbox comments header with action buttons
Nudge the sidebar Comments heading 4px down so its baseline lines up
with the lightbox top-right action bar.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* fix: Render lightbox sidebar popovers inside the dialog
Reactions, menus, and tooltips inside the lightbox comments sidebar were
portalling into the editor wrapper via PortalContext — which is hidden
behind the lightbox overlay. Provide a PortalContext that targets the
sidebar element itself so popovers render inside the dialog and remain
visible.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* fix: Prevent lightbox handlers from stealing focus from reply input
Pointer events bubbling out of the comments sidebar were reaching the
ancestor Dialog.Content / lightbox handlers and somehow disrupting focus
on the ProseMirror reply input. Stop propagation of pointer, mouse, and
click events at the CommentsSidebar so the sidebar owns its own
interaction handling.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* fix: Anchor lightbox close animation to current image position
The close animation's translation was calculated relative to the image
position cached when the image first loaded — before the comments
sidebar could shift the image left. Recapture the natural position at
the start of setupZoomOut so the animation correctly starts where the
image actually is when the sidebar is open.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* fix: Fade the comments sidebar with the rest of the lightbox
The sidebar previously had only a slide-in animation on mount and stayed
fully opaque while the rest of the lightbox faded out on close. Wire the
sidebar to the shared fadeOut animation so it disappears in lockstep
with the overlay and action controls.
https://claude.ai/code/session_01W3duHkZJ6vgNPCQJL8hQK7
* Final fixes
---------
Co-authored-by: Claude <noreply@anthropic.com>
* chore(deps-dev): bump oxlint-tsgolint from 0.14.2 to 0.22.1
Bumps [oxlint-tsgolint](https://github.com/oxc-project/tsgolint) from 0.14.2 to 0.22.1.
- [Release notes](https://github.com/oxc-project/tsgolint/releases)
- [Commits](https://github.com/oxc-project/tsgolint/compare/v0.14.2...v0.22.1)
---
updated-dependencies:
- dependency-name: oxlint-tsgolint
dependency-version: 0.22.1
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* chore: Switch tsconfig to bundler resolution for tsgolint 0.22.1
oxlint-tsgolint 0.22.1 removed support for moduleResolution=node10
(the alias for "node"). Switch to "bundler" with resolvePackageJsonExports
disabled so packages whose exports field omits a types condition still
resolve. Update markdown-it type imports to sub-paths since the package's
.d.mts entry only re-exports a subset of named types.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: Resolve type-aware lint errors caught by tsgolint 0.22.1
oxlint-tsgolint 0.22.1 catches several await-thenable, no-floating-promises,
and no-meaningless-void-operator cases the prior 0.14.2 missed:
- Drop redundant inner `await` from Promise.all([await x, await y]) call sites
so the array entries are real Promises rather than already-resolved values.
- Replace Promise.all wrappers around synchronous presenters (presentEvent,
presentTemplate, presentPublicTeam) with plain map / direct calls.
- Wrap non-promise branches of ternaries inside Promise.all with
Promise.resolve so the array remains thenable across both arms.
- Add `void` to the unawaited provider.connect() in the auth-failed retry
chain, and remove `void` from the disconnect() call which returns void.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom@getoutline.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>