Skip to content

fix: merge consecutive text ops when one undoStepId is undefined#2334

Open
christianhg wants to merge 1 commit intomainfrom
fix/undo-step-id-leak
Open

fix: merge consecutive text ops when one undoStepId is undefined#2334
christianhg wants to merge 1 commit intomainfrom
fix/undo-step-id-leak

Conversation

@christianhg
Copy link
Member

Companion to #2243. That PR fixed the case where both undoStepIds are defined but different (consecutive forwarded events). This PR fixes the remaining case where the current operation has no undoStepId but the previous one did.

This happens when a forward-only behavior intercepts one keystroke (giving it an undoStepId from the send entry) but the next keystroke has no matching behavior (so its undoStepId is undefined). The mismatch prevented the consecutive insert_text merge heuristic from running, making each keystroke its own undo step.

The reverse case (current has ID, previous doesn't) is intentionally not merged. When a behavior claims an event and gets an undoStepId, that signals an intentional undo step boundary, like input rules replacing -> with .

When a forward-only behavior intercepts a typing event, the operation
gets applied with an undoStepId from the send entry. The next keystroke
(without a behavior) has undoStepId undefined. Previously, this mismatch
prevented the consecutive insert_text merge heuristic from running.

Now createUndoSteps tries the text merge heuristic when the current
operation has no undoStepId but the previous one did. The reverse case
(current has ID, previous doesn't) is intentionally not merged, as it
indicates a behavior deliberately claimed the event.
@vercel
Copy link

vercel bot commented Mar 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
portable-text-editor-documentation Ready Ready Preview, Comment Mar 6, 2026 10:58am
portable-text-example-basic Ready Ready Preview, Comment Mar 6, 2026 10:58am
portable-text-playground Ready Ready Preview, Comment Mar 6, 2026 10:58am

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Mar 6, 2026

🦋 Changeset detected

Latest commit: 1513782

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@portabletext/editor Patch
@portabletext/plugin-character-pair-decorator Patch
@portabletext/plugin-emoji-picker Patch
@portabletext/plugin-input-rule Patch
@portabletext/plugin-markdown-shortcuts Patch
@portabletext/plugin-one-line Patch
@portabletext/plugin-paste-link Patch
@portabletext/plugin-sdk-value Patch
@portabletext/plugin-typeahead-picker Patch
@portabletext/plugin-typography Patch
@portabletext/toolbar Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

📦 Bundle Stats — @portabletext/editor

Compared against main (be4d3b81)

@portabletext/editor

Metric Value vs main (be4d3b8)
Internal (raw) 811.2 KB +518 B, +0.1%
Internal (gzip) 151.5 KB +14 B, +0.0%
Bundled (raw) 1.42 MB +518 B, +0.0%
Bundled (gzip) 314.4 KB +12 B, +0.0%
Import time 101ms +0ms, +0.0%

@portabletext/editor/behaviors

Metric Value vs main (be4d3b8)
Internal (raw) 467 B -
Internal (gzip) 207 B -
Bundled (raw) 424 B -
Bundled (gzip) 171 B -
Import time 6ms -0ms, -0.2%

@portabletext/editor/plugins

Metric Value vs main (be4d3b8)
Internal (raw) 2.5 KB -
Internal (gzip) 910 B -
Bundled (raw) 2.3 KB -
Bundled (gzip) 839 B -
Import time 12ms -0ms, -0.7%

@portabletext/editor/selectors

Metric Value vs main (be4d3b8)
Internal (raw) 60.2 KB -
Internal (gzip) 9.4 KB -
Bundled (raw) 56.7 KB -
Bundled (gzip) 8.6 KB -
Import time 11ms +0ms, +3.0%

@portabletext/editor/utils

Metric Value vs main (be4d3b8)
Internal (raw) 24.2 KB -
Internal (gzip) 4.7 KB -
Bundled (raw) 22.2 KB -
Bundled (gzip) 4.4 KB -
Import time 9ms -0ms, -1.4%
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Treemap artifacts are attached to the CI run for detailed size analysis
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

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.

1 participant