Skip to content

Bug: [lexical] In Firefox, Shift+click on an inline decorator drops the selection #9840

Open

Description

@rinarakaki

Lexical version: 0.53.0, and the code is the same on main at 5326e06.

Steps To Reproduce

  1. Make an editor with registerRichText and an inline DecoratorNode whose createDOM returns a span holding text, with decorate() returning null. The node is in the code below.
  2. Put a paragraph in it: text, the decorator, text.
  3. In Firefox, click in the text before the decorator.
  4. Hold Shift and click on the decorator's text.
  5. Type a letter.

Link to code example:

No public repo, so here's the node. The rest is createEditor({nodes: [ChipNode]}), setRootElement on a contenteditable div and registerRichText(editor).

class ChipNode extends DecoratorNode {
  static getType() { return "chip"; }
  static clone(node) { return new ChipNode(node.__text, node.__key); }
  static importJSON(json) { return new ChipNode(json.text); }
  constructor(text, key) { super(key); this.__text = text; }
  exportJSON() { return { ...super.exportJSON(), text: this.__text }; }
  createDOM() { const span = document.createElement("span"); span.textContent = this.__text; return span; }
  updateDOM() { return false; }
  isInline() { return true; }
  getTextContent() { return this.__text; }
  decorate() { return null; }
}

The current behavior

DOM selection after the Shift+click Lexical's selection The letter
Firefox 157 none null lost
Chromium 156 "Before "@3 .. <span>@0 range, to the paragraph's offset 1 replaces the selected text, Befk[x + 1] …
WebKit 27.2 "Before "@2 .. "Before "@7 range, to the end of "Before " replaces the selected text, Bek[x + 1] …
Control, Firefox: Shift+click on the text after the decorator "Before "@2 .. " after and more words."@6 range across the decorator replaces it, Bek and more words.

In Firefox the events run pointerdown, mousedown, selectionchange with the focus in the decorator's text, selectionchange with no selection, pointerup. So the user's selection is gone before the button is released.

From reading the code, not stepped through: a press inside a decorator leaves inputState.mouseDrag null, because isDOMCapturingSelection is true there (LexicalEvents.ts L2680-L2687, LexicalUtils.ts L3519-L3533). So $adjustMouseDrag, which would keep the anchor and put the focus beside the decorator, doesn't run (L365-L368), and $internalResolveSelectionPoints gives null for the focus (LexicalSelection.ts L3444-L3475).

The expected behavior

The anchor stays, and the focus goes beside the decorator, as in Chromium and WebKit and as $moveMouseDragFocus does for a press beside one.

Impact of fix

It affects any editor with an inline decorator, such as a mention or an inline equation, in Firefox. A Shift+click meant to grow a selection over one loses the selection instead, and the next typed character goes nowhere.

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