@tiptap/extension-emoji 3.27.1 → 3.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,12 +5,13 @@ import {
5
5
  findChildrenInRange,
6
6
  getChangedRanges,
7
7
  InputRule,
8
+ isFirefox,
8
9
  mergeAttributes,
9
10
  Node,
10
11
  nodeInputRule,
11
12
  PasteRule
12
13
  } from "@tiptap/core";
13
- import { Plugin, PluginKey } from "@tiptap/pm/state";
14
+ import { Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
14
15
  import { Suggestion } from "@tiptap/suggestion";
15
16
  import emojiRegex from "emoji-regex";
16
17
  import { isEmojiSupported } from "is-emoji-supported";
@@ -23563,8 +23564,56 @@ var Emoji = Node.create({
23563
23564
  new Plugin({
23564
23565
  key: new PluginKey("emoji"),
23565
23566
  props: {
23566
- // double click to select emoji doesn’t work by default
23567
- // that’s why we simulate this behavior
23567
+ // Firefox cannot move the cursor past emoji nodes at paragraph
23568
+ // boundaries using arrow keys. We intercept plain (unmodified)
23569
+ // ArrowLeft/ArrowRight and manually resolve the correct position.
23570
+ // Only handles emoji nodes — other inline non-selectable nodes
23571
+ // (mentions, hard breaks) are out of scope for this extension.
23572
+ // See: https://github.com/ProseMirror/prosemirror/issues/1220
23573
+ handleKeyDown: (view, event) => {
23574
+ if (!isFirefox()) {
23575
+ return false;
23576
+ }
23577
+ const isLeft = event.key === "ArrowLeft";
23578
+ const isRight = event.key === "ArrowRight";
23579
+ if (!isLeft && !isRight) {
23580
+ return false;
23581
+ }
23582
+ if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) {
23583
+ return false;
23584
+ }
23585
+ const { state } = view;
23586
+ const { selection } = state;
23587
+ if (!selection.empty || !(selection instanceof TextSelection)) {
23588
+ return false;
23589
+ }
23590
+ const $pos = selection.$from;
23591
+ const emojiType = this.type;
23592
+ if (isLeft) {
23593
+ const nodeBefore = $pos.nodeBefore;
23594
+ if (!nodeBefore || nodeBefore.type !== emojiType) {
23595
+ return false;
23596
+ }
23597
+ const newPos = $pos.pos - nodeBefore.nodeSize;
23598
+ if (newPos >= $pos.start()) {
23599
+ view.dispatch(state.tr.setSelection(TextSelection.create(state.doc, newPos)));
23600
+ return true;
23601
+ }
23602
+ } else {
23603
+ const nodeAfter = $pos.nodeAfter;
23604
+ if (!nodeAfter || nodeAfter.type !== emojiType) {
23605
+ return false;
23606
+ }
23607
+ const newPos = $pos.pos + nodeAfter.nodeSize;
23608
+ if (newPos <= $pos.end()) {
23609
+ view.dispatch(state.tr.setSelection(TextSelection.create(state.doc, newPos)));
23610
+ return true;
23611
+ }
23612
+ }
23613
+ return false;
23614
+ },
23615
+ // double click to select emoji doesn't work by default
23616
+ // that's why we simulate this behavior
23568
23617
  handleDoubleClickOn: (view, pos, node) => {
23569
23618
  if (node.type !== this.type) {
23570
23619
  return false;