-
Notifications
You must be signed in to change notification settings - Fork 184
[Table Improvements] Add undoSnapshot when tab on a table cell #3265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request fixes an undo functionality issue where typing content in a table cell and pressing Tab to move to another cell would result in losing all typed content when undoing. The fix adds an undo snapshot when Tab is pressed in a table cell with new content.
Changes:
- Added Tab key handling logic to create undo snapshots when tabbing between table cells with new content
- Implemented a helper method to detect if the current selection is inside a table cell
- Added comprehensive test coverage for the new Tab key behavior
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/roosterjs-content-model-core/lib/corePlugin/undo/UndoPlugin.ts | Added Tab key handling in onKeyDown method and implemented isInsideTableCell helper method to check if selection is within a table cell |
| packages/roosterjs-content-model-core/test/corePlugin/undo/UndoPluginTest.ts | Added 5 comprehensive test cases covering various scenarios for Tab key behavior in and out of table cells |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| private isInsideTableCell = (editor: IEditor, selection: DOMSelection | null) => { | ||
| if (selection?.type == 'range' && selection?.range.collapsed) { |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The optional chaining on selection?.range.collapsed is redundant. Once you've verified that selection?.type == 'range', the selection is guaranteed to be non-null, so you can safely access selection.range.collapsed without the optional chaining operator.
| if (selection?.type == 'range' && selection?.range.collapsed) { | |
| if (selection?.type == 'range' && selection.range.collapsed) { |
| private isInsideTableCell = (editor: IEditor, selection: DOMSelection | null) => { | ||
| if (selection?.type == 'range' && selection?.range.collapsed) { | ||
| const startContainer = selection.range.startContainer; | ||
| return editor.getDOMHelper().findClosestElementAncestor(startContainer, 'td, th'); |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better type safety and clarity, explicitly convert the return value to a boolean. The current code returns the HTMLElement or null/undefined from findClosestElementAncestor, which works in a boolean context but makes the return type less clear. Consider using double negation (!!) or checking !== null to ensure a boolean return type.
| return editor.getDOMHelper().findClosestElementAncestor(startContainer, 'td, th'); | |
| return !!editor.getDOMHelper().findClosestElementAncestor(startContainer, 'td, th'); |
Add undoSnapshot after pressing Tab key in a table that has new content, otherwise if the user type content in a table and press tab to move to another cell and then undo the content, all the typed content will be removed.


Before:
After: