Skip to content

Bug: FreeText annotation text is silently lost when editor is re-focused without isEditing toggling #681

Description

@seanlim

Summary

A FreeText (and CalloutFreeText) annotation can end up with its typed text never committed to the annotation object — it stays only in the contentEditable DOM. exportAnnotations() and the onAnnotationEvent stream both miss it, so any host app that persists annotations will silently drop the text.

Affected versions

  • @embedpdf/plugin-annotation@2.14.4 (latest published)
  • Still present on main

Environment

  • Using @embedpdf/react-pdf-viewer, but the bug is in the shared component logic, not framework-specific.

Steps to reproduce

  1. Create a new FreeText annotation (enters edit mode).
  2. Open the "Free text styles" panel and change a style (e.g. background color). This blurs the editor and fires a style update event.
  3. Click back into the same text box and type some text.
  4. Click/focus away from the box.
  5. No update event fires, and the typed text is not in the annotation object — confirmed via exportAnnotations(), which still returns the old/empty contents.
Image

You can watch the desync happen in the UI: the comment list in the right sidebar renders from the annotation object's contents, so as you type in step 3 it stops tracking the contentEditable and keeps showing the last-committed (stale/empty) text. The visible gap between the sidebar entry and what's in the text box is the internal state divergence made observable — no debug API needed.

Recovery that proves the diagnosis: double-click the annotation again (re-enters edit mode) and blur — now an update fires, the text is committed, and the sidebar entry snaps back into sync, because the editor's DOM still held the typed text.

Expected vs actual

  • Expected: typing into a focused FreeText and blurring commits contents and emits an update.
  • Actual: if the editor was blurred once and re-focused without isEditing changing, the blur is a no-op and the text is lost.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions