Skip to content

Conversation

@juliaroldi
Copy link
Contributor

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:
TabOnTableCellsBugs
After:
TabOnTableCells

Copy link
Contributor

Copilot AI left a 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) {
Copy link

Copilot AI Jan 19, 2026

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.

Suggested change
if (selection?.type == 'range' && selection?.range.collapsed) {
if (selection?.type == 'range' && selection.range.collapsed) {

Copilot uses AI. Check for mistakes.
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');
Copy link

Copilot AI Jan 19, 2026

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.

Suggested change
return editor.getDOMHelper().findClosestElementAncestor(startContainer, 'td, th');
return !!editor.getDOMHelper().findClosestElementAncestor(startContainer, 'td, th');

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants