@chayns-components/emoji-input 5.6.3 → 5.6.6

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.
@@ -155,45 +155,74 @@ const restoreSelection = element => {
155
155
  range.collapse(true);
156
156
  };
157
157
  exports.restoreSelection = restoreSelection;
158
- const insertInvisibleCursorMarker = () => {
159
- const selection = window.getSelection();
160
- if (!selection || selection.rangeCount === 0) {
161
- return;
158
+ const CURSOR_MARKER_DELAY_MS = 10;
159
+ const pendingCursorMarkers = new WeakMap();
160
+ const insertInvisibleCursorMarker = editorElement => {
161
+ var _pendingCursorMarkers;
162
+ const ownerDocument = editorElement.ownerDocument;
163
+ (_pendingCursorMarkers = pendingCursorMarkers.get(ownerDocument)) === null || _pendingCursorMarkers === void 0 || _pendingCursorMarkers();
164
+ const selection = ownerDocument.getSelection();
165
+ if (!selection || selection.rangeCount === 0 || !editorElement.isConnected) {
166
+ return undefined;
167
+ }
168
+ if (!editorElement.contains(selection.getRangeAt(0).startContainer)) {
169
+ return undefined;
162
170
  }
163
- const range = selection.getRangeAt(0);
164
- const textNode = range.startContainer;
165
- const offset = range.startOffset;
166
171
 
167
172
  // noinspection JSDeprecatedSymbols
168
- document.execCommand('delete', false);
169
- const span = document.createElement('span');
173
+ ownerDocument.execCommand('delete', false);
174
+ if (selection.rangeCount === 0) {
175
+ return undefined;
176
+ }
177
+ const {
178
+ startContainer: textNode,
179
+ startOffset: offset
180
+ } = selection.getRangeAt(0);
181
+ const parent = textNode.parentNode;
182
+ if (!parent || !editorElement.contains(textNode) || textNode.nodeType !== Node.TEXT_NODE) {
183
+ return undefined;
184
+ }
185
+ const span = ownerDocument.createElement('span');
170
186
  span.style.display = 'inline-block';
171
187
  span.style.width = '0';
172
188
  span.style.height = '0';
173
189
  span.className = 'invisible-cursor-marker';
174
- const parent = textNode.parentNode;
175
- if (parent) {
176
- if (textNode.nodeType === Node.TEXT_NODE) {
177
- const textContent = textNode.textContent || '';
178
- const beforeText = textContent.slice(0, offset);
179
- const afterText = textContent.slice(offset);
180
- textNode.textContent = beforeText;
181
- parent.insertBefore(span, textNode.nextSibling);
182
- const afterTextNode = document.createTextNode(afterText);
183
- parent.insertBefore(afterTextNode, span.nextSibling);
184
- setTimeout(() => {
185
- // Set cursor to cursor element
186
- const newRange = document.createRange();
187
- newRange.setStartAfter(span);
188
- newRange.setEndAfter(span);
189
- selection.removeAllRanges();
190
- selection.addRange(newRange);
190
+ const textContent = textNode.textContent || '';
191
+ textNode.textContent = textContent.slice(0, offset);
192
+ parent.insertBefore(span, textNode.nextSibling);
193
+ parent.insertBefore(ownerDocument.createTextNode(textContent.slice(offset)), span.nextSibling);
191
194
 
192
- // Remove cursor element
193
- span.remove();
194
- }, 10);
195
+ // Capture the selection after synchronous editing and marker insertion have settled.
196
+ const expectedRange = selection.getRangeAt(0);
197
+ const {
198
+ anchorNode,
199
+ anchorOffset,
200
+ focusNode,
201
+ focusOffset
202
+ } = selection;
203
+ const activeElement = ownerDocument.activeElement;
204
+ const cleanup = () => {
205
+ clearTimeout(timer);
206
+ editorElement.removeEventListener('blur', cleanup, true);
207
+ span.remove();
208
+ if (pendingCursorMarkers.get(ownerDocument) === cleanup) {
209
+ pendingCursorMarkers.delete(ownerDocument);
195
210
  }
196
- }
211
+ };
212
+ const timer = setTimeout(() => {
213
+ const isCurrentSelection = selection.rangeCount > 0 && selection.getRangeAt(0) === expectedRange && selection.anchorNode === anchorNode && selection.anchorOffset === anchorOffset && selection.focusNode === focusNode && selection.focusOffset === focusOffset && ownerDocument.activeElement === activeElement;
214
+ if (span.isConnected && span.parentNode === parent && editorElement.isConnected && editorElement.contains(span) && isCurrentSelection) {
215
+ const newRange = ownerDocument.createRange();
216
+ newRange.setStartAfter(span);
217
+ newRange.collapse(true);
218
+ selection.removeAllRanges();
219
+ selection.addRange(newRange);
220
+ }
221
+ cleanup();
222
+ }, CURSOR_MARKER_DELAY_MS);
223
+ editorElement.addEventListener('blur', cleanup, true);
224
+ pendingCursorMarkers.set(ownerDocument, cleanup);
225
+ return cleanup;
197
226
  };
198
227
  exports.insertInvisibleCursorMarker = insertInvisibleCursorMarker;
199
228
  const insertPseudoMarker = () => {
@@ -418,7 +447,8 @@ const setCursorPositionByAbsIndex = ({
418
447
  editorElement,
419
448
  position
420
449
  }) => {
421
- var _window$getSelection3, _window2;
450
+ var _pendingCursorMarkers2, _window$getSelection3, _window2;
451
+ (_pendingCursorMarkers2 = pendingCursorMarkers.get(editorElement.ownerDocument)) === null || _pendingCursorMarkers2 === void 0 || _pendingCursorMarkers2();
422
452
  const selection = (_window$getSelection3 = (_window2 = window).getSelection) === null || _window$getSelection3 === void 0 ? void 0 : _window$getSelection3.call(_window2);
423
453
  if (!selection) {
424
454
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"selection.js","names":["_number","require","_text","childIndex","endOffset","startOffset","saveSelection","element","shouldIgnoreEmptyTextNodes","selection","window","getSelection","anchorNode","range","getRangeAt","childNodesArray","Array","from","childNodes","filter","nodeType","nodeValue","Node","TEXT_NODE","indexOf","exports","restoreSelection","hasFoundNoJoiner","forEach","node","noJoinerIndex","replace","childNode","elementTextLength","getElementTextLength","nextSibling","charCodeAt","_childNode$parentNode","textNode","document","createTextNode","parentNode","insertBefore","length","_childNode$parentNode2","_childNode$nextSiblin","_childNode$nextSiblin2","_childNode$parentNode3","_childNode$parentNode4","createRange","clamp","setStart","setEnd","error","removeAllRanges","addRange","collapse","insertInvisibleCursorMarker","rangeCount","startContainer","offset","execCommand","span","createElement","style","display","width","height","className","parent","textContent","beforeText","slice","afterText","afterTextNode","setTimeout","newRange","setStartAfter","setEndAfter","remove","insertPseudoMarker","marker","id","insertNode","insertCursorAtMarker","ref","_ref$current","current","querySelector","moveSelectionOffset","distance","setChildIndex","index","getCharCodeThatWillBeDeleted","event","_window$getSelection","_nextSibling$nodeValu","key","_previousSibling$node","previousSibling","endContainer","findAndSelectText","editorElement","searchText","options","shouldReplaceNearCursor","_editorElement$textCo","includes","cursorPos","getCurrentCursorPosition","matches","absCounter","searchNodesForText","push","absIndex","nodeName","match","reduce","prev","curr","Math","abs","_window$getSelection2","_window","sel","call","contains","commonAncestorContainer","pre","selectNodeContents","container","appendChild","cloneContents","bbCodeUntilCursor","convertHTMLToText","innerHTML","preserveSpaces","shouldSerializeNoEmojiToBBCode","getCursorTargetByAbsIndex","position","clampedPosition","searchNodes","nodeText","nextAbsCounter","child","found","rootNode","lastTextNode","lastChild","appendedTextNode","setCursorPositionByAbsIndex","_window$getSelection3","_window2","target","unwrapIgnoreEmojiSpanAtCursor","cursorOffset","ELEMENT_NODE","classList","cursorNode","cursorNodeOffset","clonedChild","cloneNode","removeChild","moveCursorOutOfIgnoreEmojiSpan","targetNode","walker","createTreeWalker","NodeFilter","SHOW_TEXT","firstTextNode","nextNode"],"sources":["../../../src/utils/selection.ts"],"sourcesContent":["import type { KeyboardEvent, RefObject } from 'react';\nimport { clamp } from './number';\nimport { convertHTMLToText, getElementTextLength } from './text';\n\nlet childIndex = -1;\nlet endOffset = -1;\nlet startOffset = -1;\n\ninterface SaveSelectionOptions {\n shouldIgnoreEmptyTextNodes?: boolean;\n}\n\nexport const saveSelection = (\n element: HTMLDivElement,\n { shouldIgnoreEmptyTextNodes }: SaveSelectionOptions = {},\n) => {\n const selection = window.getSelection();\n\n if (!selection) {\n return;\n }\n\n const { anchorNode } = selection;\n\n if (!anchorNode) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n\n let childNodesArray = Array.from(element.childNodes);\n\n if (shouldIgnoreEmptyTextNodes) {\n childNodesArray = childNodesArray.filter(\n ({ nodeType, nodeValue }) =>\n nodeType !== Node.TEXT_NODE || (nodeValue !== '' && nodeValue !== '\\u200B'),\n );\n }\n\n childIndex = childNodesArray.indexOf(anchorNode as ChildNode);\n\n endOffset = range.endOffset;\n startOffset = range.startOffset;\n};\n\nexport const restoreSelection = (element: HTMLDivElement) => {\n // Search for \\u200C in child nodes. If found, set the childIndex, startOffset, and endOffset to the\n // position of the \\u200C character. Also remove the \\u200C character from the child node. If not found,\n // the childIndex, startOffset, and endOffset will be like before.\n const childNodesArray = Array.from(element.childNodes);\n\n let hasFoundNoJoiner = false;\n\n childNodesArray.forEach((node) => {\n if (\n !hasFoundNoJoiner &&\n node.nodeType === Node.TEXT_NODE &&\n typeof node.nodeValue === 'string'\n ) {\n const noJoinerIndex = node.nodeValue.indexOf('\\u200C');\n\n if (noJoinerIndex !== -1) {\n hasFoundNoJoiner = true;\n\n childIndex = childNodesArray.indexOf(node);\n startOffset = noJoinerIndex;\n endOffset = noJoinerIndex;\n }\n }\n });\n\n // Remove all no joiner characters from the child nodes if no joiner was found\n if (hasFoundNoJoiner) {\n childNodesArray.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE && typeof node.nodeValue === 'string') {\n // eslint-disable-next-line no-param-reassign\n node.nodeValue = node.nodeValue.replace(/\\u200C/g, '');\n }\n });\n }\n\n let childNode = element.childNodes[childIndex];\n\n const selection = window.getSelection();\n\n if (!childNode || !element || !selection) {\n return;\n }\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n const elementTextLength = getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else if (childNode.nodeValue && endOffset > childNode.nodeValue.length) {\n if (childNode.nextSibling?.nodeValue) {\n let elementTextLength = childNode.nodeValue.length;\n\n childNode = childNode.nextSibling;\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n elementTextLength += getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling?.nodeValue) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n }\n } else {\n endOffset = childNode.nodeValue.length;\n startOffset = childNode.nodeValue.length;\n }\n }\n\n const range = document.createRange();\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue === 'string') {\n startOffset = clamp(startOffset, 0, childNode.nodeValue.length);\n endOffset = clamp(endOffset, 0, childNode.nodeValue.length);\n }\n\n try {\n range.setStart(childNode, startOffset);\n range.setEnd(childNode, endOffset);\n } catch (error) {\n // Do nothing\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\nexport const insertInvisibleCursorMarker = (): void => {\n const selection = window.getSelection();\n\n if (!selection || selection.rangeCount === 0) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n const textNode = range.startContainer;\n const offset = range.startOffset;\n\n // noinspection JSDeprecatedSymbols\n document.execCommand('delete', false);\n\n const span = document.createElement('span');\n span.style.display = 'inline-block';\n span.style.width = '0';\n span.style.height = '0';\n span.className = 'invisible-cursor-marker';\n\n const parent = textNode.parentNode;\n\n if (parent) {\n if (textNode.nodeType === Node.TEXT_NODE) {\n const textContent = textNode.textContent || '';\n const beforeText = textContent.slice(0, offset);\n const afterText = textContent.slice(offset);\n\n textNode.textContent = beforeText;\n\n parent.insertBefore(span, textNode.nextSibling);\n const afterTextNode = document.createTextNode(afterText);\n parent.insertBefore(afterTextNode, span.nextSibling);\n\n setTimeout(() => {\n // Set cursor to cursor element\n const newRange = document.createRange();\n newRange.setStartAfter(span);\n newRange.setEndAfter(span);\n selection.removeAllRanges();\n selection.addRange(newRange);\n\n // Remove cursor element\n span.remove();\n }, 10);\n }\n }\n};\n\nexport const insertPseudoMarker = () => {\n const selection = window.getSelection();\n\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n const marker = document.createElement('span');\n marker.id = 'cursor-marker';\n marker.style.display = 'inline-block';\n marker.style.width = '0';\n marker.style.height = '0';\n range.insertNode(marker);\n }\n};\n\nexport const insertCursorAtMarker = (ref: RefObject<HTMLDivElement>) => {\n const marker = ref.current?.querySelector('#cursor-marker');\n\n if (marker) {\n const selection = window.getSelection();\n const range = document.createRange();\n range.setStartAfter(marker);\n range.setEndAfter(marker);\n selection?.removeAllRanges();\n selection?.addRange(range);\n marker.remove();\n }\n};\n\nexport const moveSelectionOffset = (distance: number) => {\n endOffset += distance;\n startOffset += distance;\n};\n\nexport const setChildIndex = (index: number) => {\n childIndex = index;\n};\n\n/**\n * This function returns the code of the character that will be removed by the KeyDown event in the\n * next step, if the \"Backspace\" or \"Delete\" key was pressed and there is no selection of multiple\n * characters.\n *\n * @param event - Keyboard event from \"onKeyDown\"\n */\nexport const getCharCodeThatWillBeDeleted = (event: KeyboardEvent<HTMLDivElement>) => {\n const range = window.getSelection()?.getRangeAt(0);\n\n /**\n * At this point the function is aborted if there is no selection range, several characters have\n * been selected and therefore no single letter is removed or neither the \"Backspace\" nor the\n * \"Delete\" key has been pressed.\n */\n if (\n !range ||\n range.endOffset !== range.startOffset ||\n (event.key !== 'Backspace' && event.key !== 'Delete' && event.key !== 'Unidentified')\n ) {\n return null;\n }\n\n if (event.key === 'Backspace' || event.key === 'Unidentified') {\n const { nodeValue, previousSibling } = range.startContainer;\n\n if (range.startOffset > 0) {\n return nodeValue?.charCodeAt(range.startOffset - 1);\n }\n\n return previousSibling?.nodeValue?.charCodeAt(previousSibling.nodeValue.length - 1);\n }\n\n const { nextSibling, nodeValue } = range.endContainer;\n\n if (range.endOffset < (nodeValue?.length ?? 0)) {\n return nodeValue?.charCodeAt(range.endOffset);\n }\n\n return nextSibling?.nodeValue?.charCodeAt(0);\n};\n\nexport type ReplaceTextOptions = { shouldReplaceNearCursor?: boolean };\n\ninterface FindAndSelectTextOptions {\n editorElement: HTMLDivElement;\n searchText: string;\n options?: ReplaceTextOptions;\n}\n\nexport interface SetCursorPositionByAbsIndexOptions {\n editorElement: HTMLDivElement;\n position: number;\n}\n\ntype Match = { node: Node; offset: number; absIndex: number };\n\nexport const findAndSelectText = ({\n editorElement,\n searchText,\n options = { shouldReplaceNearCursor: true },\n}: FindAndSelectTextOptions): Range | null => {\n if (!editorElement.textContent?.includes(searchText)) {\n return null;\n }\n\n const range = document.createRange();\n\n const cursorPos = getCurrentCursorPosition(editorElement);\n\n const matches: Match[] = [];\n let absCounter = 0;\n\n const searchNodesForText = (node: Node) => {\n if (node.nodeType === Node.TEXT_NODE && node.textContent) {\n let index = node.textContent.indexOf(searchText);\n while (index !== -1) {\n matches.push({\n node,\n offset: index,\n absIndex: absCounter + index,\n });\n index = node.textContent.indexOf(searchText, index + 1);\n }\n absCounter += node.textContent.length;\n } else if (node.nodeName !== 'LC_MENTION') {\n Array.from(node.childNodes).forEach(searchNodesForText);\n }\n };\n\n searchNodesForText(editorElement);\n\n if (matches.length === 0) {\n return null;\n }\n\n let match = matches[0];\n\n if (options?.shouldReplaceNearCursor && cursorPos !== null) {\n match = matches.reduce((prev, curr) =>\n Math.abs(curr.absIndex - cursorPos) < Math.abs(prev.absIndex - cursorPos) ? curr : prev,\n );\n }\n\n if (!match) {\n return null;\n }\n\n range.setStart(match.node, match.offset);\n range.setEnd(match.node, match.offset + searchText.length);\n\n return range;\n};\n\nexport const getCurrentCursorPosition = (editorElement: HTMLDivElement | null): number | null => {\n if (!editorElement) {\n return null;\n }\n\n const sel = window.getSelection?.();\n if (!sel || sel.rangeCount === 0) {\n return null;\n }\n\n const range = sel.getRangeAt(0);\n\n if (!editorElement.contains(range.commonAncestorContainer)) {\n return null;\n }\n\n const pre = document.createRange();\n pre.selectNodeContents(editorElement);\n\n try {\n pre.setEnd(range.startContainer, range.startOffset);\n\n const container = document.createElement('div');\n container.appendChild(pre.cloneContents());\n\n const bbCodeUntilCursor = convertHTMLToText(container.innerHTML, {\n preserveSpaces: true,\n shouldSerializeNoEmojiToBBCode: false,\n });\n\n return bbCodeUntilCursor.length;\n } catch {\n return convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length;\n }\n};\n\ntype CursorTarget = { node: Text; offset: number };\n\nconst getCursorTargetByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): CursorTarget | null => {\n const childNodes = Array.from(editorElement.childNodes);\n\n if (childNodes.length === 0) {\n const textNode = document.createTextNode('');\n editorElement.appendChild(textNode);\n\n return { node: textNode, offset: 0 };\n }\n\n const clampedPosition = clamp(\n position,\n 0,\n convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length,\n );\n\n let absCounter = 0;\n\n const searchNodes = (node: Node): CursorTarget | null => {\n if (node.nodeType === Node.TEXT_NODE) {\n const textNode = node as Text;\n const nodeText = textNode.nodeValue ?? '';\n const nextAbsCounter = absCounter + nodeText.length;\n\n if (clampedPosition <= nextAbsCounter) {\n return {\n node: textNode,\n offset: clamp(clampedPosition - absCounter, 0, nodeText.length),\n };\n }\n\n absCounter = nextAbsCounter;\n\n return null;\n }\n\n if (node.nodeName === 'LC_MENTION') {\n return null;\n }\n\n for (const child of Array.from(node.childNodes)) {\n const found = searchNodes(child);\n if (found) {\n return found;\n }\n }\n\n return null;\n };\n\n for (const rootNode of childNodes) {\n const found = searchNodes(rootNode);\n if (found) {\n return found;\n }\n }\n\n const lastTextNode = editorElement.lastChild;\n if (lastTextNode?.nodeType === Node.TEXT_NODE) {\n const textNode = lastTextNode as Text;\n return { node: textNode, offset: textNode.length };\n }\n\n const appendedTextNode = document.createTextNode('\\u200B');\n editorElement.appendChild(appendedTextNode);\n\n return { node: appendedTextNode, offset: appendedTextNode.length };\n};\n\nexport const setCursorPositionByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): void => {\n const selection = window.getSelection?.();\n\n if (!selection) {\n return;\n }\n\n const target = getCursorTargetByAbsIndex({ editorElement, position });\n\n if (!target) {\n return;\n }\n\n const range = document.createRange();\n\n try {\n range.setStart(target.node, target.offset);\n range.setEnd(target.node, target.offset);\n } catch {\n return;\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\n/**\n * Unwraps any no-emoji-convert span that contains the cursor.\n * This removes the span element but keeps its text content, preventing the cursor from getting stuck.\n */\nexport const unwrapIgnoreEmojiSpanAtCursor = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n const cursorOffset = range.startOffset;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, unwrap it\n const span = commonAncestorContainer as Element;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Find which text node contains the cursor\n let cursorNode: Node | null = null;\n const cursorNodeOffset = cursorOffset;\n\n // Get all child nodes of the span\n const childNodes = Array.from(span.childNodes);\n\n // Insert all children before the span and find the cursor node\n childNodes.forEach((child) => {\n const clonedChild = child.cloneNode(true);\n parentNode.insertBefore(clonedChild, span);\n\n // If this is the node that contains the cursor, track it\n if (child === range.startContainer) {\n cursorNode = clonedChild;\n }\n });\n\n // Remove the span\n parentNode.removeChild(span);\n\n // Restore cursor position in the unwrapped content\n if (cursorNode) {\n range.setStart(cursorNode, cursorNodeOffset);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n\n/**\n * Moves the cursor outside of any no-emoji-convert span if it's currently inside one.\n * This prevents the cursor from getting \"stuck\" inside the protection span when typing.\n */\nexport const moveCursorOutOfIgnoreEmojiSpan = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, move cursor to after it\n const span = commonAncestorContainer as Element;\n const { nextSibling } = span;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Always ensure there's a text node AFTER the span\n let targetNode: Text;\n\n if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n // Next sibling is already a text node, use it\n targetNode = nextSibling as Text;\n } else if (nextSibling && nextSibling.nodeType === Node.ELEMENT_NODE) {\n // Next sibling is an element, find first text node in it\n const walker = document.createTreeWalker(nextSibling, NodeFilter.SHOW_TEXT);\n const firstTextNode = walker.nextNode() as Text;\n if (firstTextNode) {\n targetNode = firstTextNode;\n } else {\n // No text node found, create one\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n } else {\n // No next sibling or it's not a text/element node, create a new text node\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n\n // Place cursor at the start of the target node\n range.setStart(targetNode, 0);\n range.collapse(true);\n\n selection.removeAllRanges();\n selection.addRange(range);\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"selection.js","names":["_number","require","_text","childIndex","endOffset","startOffset","saveSelection","element","shouldIgnoreEmptyTextNodes","selection","window","getSelection","anchorNode","range","getRangeAt","childNodesArray","Array","from","childNodes","filter","nodeType","nodeValue","Node","TEXT_NODE","indexOf","exports","restoreSelection","hasFoundNoJoiner","forEach","node","noJoinerIndex","replace","childNode","elementTextLength","getElementTextLength","nextSibling","charCodeAt","_childNode$parentNode","textNode","document","createTextNode","parentNode","insertBefore","length","_childNode$parentNode2","_childNode$nextSiblin","_childNode$nextSiblin2","_childNode$parentNode3","_childNode$parentNode4","createRange","clamp","setStart","setEnd","error","removeAllRanges","addRange","collapse","CURSOR_MARKER_DELAY_MS","pendingCursorMarkers","WeakMap","insertInvisibleCursorMarker","editorElement","_pendingCursorMarkers","ownerDocument","get","rangeCount","isConnected","undefined","contains","startContainer","execCommand","offset","parent","span","createElement","style","display","width","height","className","textContent","slice","expectedRange","anchorOffset","focusNode","focusOffset","activeElement","cleanup","clearTimeout","timer","removeEventListener","remove","delete","setTimeout","isCurrentSelection","newRange","setStartAfter","addEventListener","set","insertPseudoMarker","marker","id","insertNode","insertCursorAtMarker","ref","_ref$current","current","querySelector","setEndAfter","moveSelectionOffset","distance","setChildIndex","index","getCharCodeThatWillBeDeleted","event","_window$getSelection","_nextSibling$nodeValu","key","_previousSibling$node","previousSibling","endContainer","findAndSelectText","searchText","options","shouldReplaceNearCursor","_editorElement$textCo","includes","cursorPos","getCurrentCursorPosition","matches","absCounter","searchNodesForText","push","absIndex","nodeName","match","reduce","prev","curr","Math","abs","_window$getSelection2","_window","sel","call","commonAncestorContainer","pre","selectNodeContents","container","appendChild","cloneContents","bbCodeUntilCursor","convertHTMLToText","innerHTML","preserveSpaces","shouldSerializeNoEmojiToBBCode","getCursorTargetByAbsIndex","position","clampedPosition","searchNodes","nodeText","nextAbsCounter","child","found","rootNode","lastTextNode","lastChild","appendedTextNode","setCursorPositionByAbsIndex","_pendingCursorMarkers2","_window$getSelection3","_window2","target","unwrapIgnoreEmojiSpanAtCursor","cursorOffset","ELEMENT_NODE","classList","cursorNode","cursorNodeOffset","clonedChild","cloneNode","removeChild","moveCursorOutOfIgnoreEmojiSpan","targetNode","walker","createTreeWalker","NodeFilter","SHOW_TEXT","firstTextNode","nextNode"],"sources":["../../../src/utils/selection.ts"],"sourcesContent":["import type { KeyboardEvent, RefObject } from 'react';\nimport { clamp } from './number';\nimport { convertHTMLToText, getElementTextLength } from './text';\n\nlet childIndex = -1;\nlet endOffset = -1;\nlet startOffset = -1;\n\ninterface SaveSelectionOptions {\n shouldIgnoreEmptyTextNodes?: boolean;\n}\n\nexport const saveSelection = (\n element: HTMLDivElement,\n { shouldIgnoreEmptyTextNodes }: SaveSelectionOptions = {},\n) => {\n const selection = window.getSelection();\n\n if (!selection) {\n return;\n }\n\n const { anchorNode } = selection;\n\n if (!anchorNode) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n\n let childNodesArray = Array.from(element.childNodes);\n\n if (shouldIgnoreEmptyTextNodes) {\n childNodesArray = childNodesArray.filter(\n ({ nodeType, nodeValue }) =>\n nodeType !== Node.TEXT_NODE || (nodeValue !== '' && nodeValue !== '\\u200B'),\n );\n }\n\n childIndex = childNodesArray.indexOf(anchorNode as ChildNode);\n\n endOffset = range.endOffset;\n startOffset = range.startOffset;\n};\n\nexport const restoreSelection = (element: HTMLDivElement) => {\n // Search for \\u200C in child nodes. If found, set the childIndex, startOffset, and endOffset to the\n // position of the \\u200C character. Also remove the \\u200C character from the child node. If not found,\n // the childIndex, startOffset, and endOffset will be like before.\n const childNodesArray = Array.from(element.childNodes);\n\n let hasFoundNoJoiner = false;\n\n childNodesArray.forEach((node) => {\n if (\n !hasFoundNoJoiner &&\n node.nodeType === Node.TEXT_NODE &&\n typeof node.nodeValue === 'string'\n ) {\n const noJoinerIndex = node.nodeValue.indexOf('\\u200C');\n\n if (noJoinerIndex !== -1) {\n hasFoundNoJoiner = true;\n\n childIndex = childNodesArray.indexOf(node);\n startOffset = noJoinerIndex;\n endOffset = noJoinerIndex;\n }\n }\n });\n\n // Remove all no joiner characters from the child nodes if no joiner was found\n if (hasFoundNoJoiner) {\n childNodesArray.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE && typeof node.nodeValue === 'string') {\n // eslint-disable-next-line no-param-reassign\n node.nodeValue = node.nodeValue.replace(/\\u200C/g, '');\n }\n });\n }\n\n let childNode = element.childNodes[childIndex];\n\n const selection = window.getSelection();\n\n if (!childNode || !element || !selection) {\n return;\n }\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n const elementTextLength = getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else if (childNode.nodeValue && endOffset > childNode.nodeValue.length) {\n if (childNode.nextSibling?.nodeValue) {\n let elementTextLength = childNode.nodeValue.length;\n\n childNode = childNode.nextSibling;\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n elementTextLength += getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling?.nodeValue) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n }\n } else {\n endOffset = childNode.nodeValue.length;\n startOffset = childNode.nodeValue.length;\n }\n }\n\n const range = document.createRange();\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue === 'string') {\n startOffset = clamp(startOffset, 0, childNode.nodeValue.length);\n endOffset = clamp(endOffset, 0, childNode.nodeValue.length);\n }\n\n try {\n range.setStart(childNode, startOffset);\n range.setEnd(childNode, endOffset);\n } catch (error) {\n // Do nothing\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\nconst CURSOR_MARKER_DELAY_MS = 10;\nconst pendingCursorMarkers = new WeakMap<Document, VoidFunction>();\n\nexport const insertInvisibleCursorMarker = (\n editorElement: HTMLDivElement,\n): VoidFunction | undefined => {\n const ownerDocument = editorElement.ownerDocument;\n pendingCursorMarkers.get(ownerDocument)?.();\n\n const selection = ownerDocument.getSelection();\n\n if (!selection || selection.rangeCount === 0 || !editorElement.isConnected) {\n return undefined;\n }\n\n if (!editorElement.contains(selection.getRangeAt(0).startContainer)) {\n return undefined;\n }\n\n // noinspection JSDeprecatedSymbols\n ownerDocument.execCommand('delete', false);\n\n if (selection.rangeCount === 0) {\n return undefined;\n }\n\n const { startContainer: textNode, startOffset: offset } = selection.getRangeAt(0);\n const parent = textNode.parentNode;\n\n if (!parent || !editorElement.contains(textNode) || textNode.nodeType !== Node.TEXT_NODE) {\n return undefined;\n }\n\n const span = ownerDocument.createElement('span');\n span.style.display = 'inline-block';\n span.style.width = '0';\n span.style.height = '0';\n span.className = 'invisible-cursor-marker';\n\n const textContent = textNode.textContent || '';\n textNode.textContent = textContent.slice(0, offset);\n parent.insertBefore(span, textNode.nextSibling);\n parent.insertBefore(ownerDocument.createTextNode(textContent.slice(offset)), span.nextSibling);\n\n // Capture the selection after synchronous editing and marker insertion have settled.\n const expectedRange = selection.getRangeAt(0);\n const { anchorNode, anchorOffset, focusNode, focusOffset } = selection;\n const activeElement = ownerDocument.activeElement;\n\n const cleanup = () => {\n clearTimeout(timer);\n editorElement.removeEventListener('blur', cleanup, true);\n span.remove();\n\n if (pendingCursorMarkers.get(ownerDocument) === cleanup) {\n pendingCursorMarkers.delete(ownerDocument);\n }\n };\n\n const timer = setTimeout(() => {\n const isCurrentSelection =\n selection.rangeCount > 0 &&\n selection.getRangeAt(0) === expectedRange &&\n selection.anchorNode === anchorNode &&\n selection.anchorOffset === anchorOffset &&\n selection.focusNode === focusNode &&\n selection.focusOffset === focusOffset &&\n ownerDocument.activeElement === activeElement;\n\n if (\n span.isConnected &&\n span.parentNode === parent &&\n editorElement.isConnected &&\n editorElement.contains(span) &&\n isCurrentSelection\n ) {\n const newRange = ownerDocument.createRange();\n newRange.setStartAfter(span);\n newRange.collapse(true);\n selection.removeAllRanges();\n selection.addRange(newRange);\n }\n\n cleanup();\n }, CURSOR_MARKER_DELAY_MS);\n\n editorElement.addEventListener('blur', cleanup, true);\n pendingCursorMarkers.set(ownerDocument, cleanup);\n\n return cleanup;\n};\n\nexport const insertPseudoMarker = () => {\n const selection = window.getSelection();\n\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n const marker = document.createElement('span');\n marker.id = 'cursor-marker';\n marker.style.display = 'inline-block';\n marker.style.width = '0';\n marker.style.height = '0';\n range.insertNode(marker);\n }\n};\n\nexport const insertCursorAtMarker = (ref: RefObject<HTMLDivElement>) => {\n const marker = ref.current?.querySelector('#cursor-marker');\n\n if (marker) {\n const selection = window.getSelection();\n const range = document.createRange();\n range.setStartAfter(marker);\n range.setEndAfter(marker);\n selection?.removeAllRanges();\n selection?.addRange(range);\n marker.remove();\n }\n};\n\nexport const moveSelectionOffset = (distance: number) => {\n endOffset += distance;\n startOffset += distance;\n};\n\nexport const setChildIndex = (index: number) => {\n childIndex = index;\n};\n\n/**\n * This function returns the code of the character that will be removed by the KeyDown event in the\n * next step, if the \"Backspace\" or \"Delete\" key was pressed and there is no selection of multiple\n * characters.\n *\n * @param event - Keyboard event from \"onKeyDown\"\n */\nexport const getCharCodeThatWillBeDeleted = (event: KeyboardEvent<HTMLDivElement>) => {\n const range = window.getSelection()?.getRangeAt(0);\n\n /**\n * At this point the function is aborted if there is no selection range, several characters have\n * been selected and therefore no single letter is removed or neither the \"Backspace\" nor the\n * \"Delete\" key has been pressed.\n */\n if (\n !range ||\n range.endOffset !== range.startOffset ||\n (event.key !== 'Backspace' && event.key !== 'Delete' && event.key !== 'Unidentified')\n ) {\n return null;\n }\n\n if (event.key === 'Backspace' || event.key === 'Unidentified') {\n const { nodeValue, previousSibling } = range.startContainer;\n\n if (range.startOffset > 0) {\n return nodeValue?.charCodeAt(range.startOffset - 1);\n }\n\n return previousSibling?.nodeValue?.charCodeAt(previousSibling.nodeValue.length - 1);\n }\n\n const { nextSibling, nodeValue } = range.endContainer;\n\n if (range.endOffset < (nodeValue?.length ?? 0)) {\n return nodeValue?.charCodeAt(range.endOffset);\n }\n\n return nextSibling?.nodeValue?.charCodeAt(0);\n};\n\nexport type ReplaceTextOptions = { shouldReplaceNearCursor?: boolean };\n\ninterface FindAndSelectTextOptions {\n editorElement: HTMLDivElement;\n searchText: string;\n options?: ReplaceTextOptions;\n}\n\nexport interface SetCursorPositionByAbsIndexOptions {\n editorElement: HTMLDivElement;\n position: number;\n}\n\ntype Match = { node: Node; offset: number; absIndex: number };\n\nexport const findAndSelectText = ({\n editorElement,\n searchText,\n options = { shouldReplaceNearCursor: true },\n}: FindAndSelectTextOptions): Range | null => {\n if (!editorElement.textContent?.includes(searchText)) {\n return null;\n }\n\n const range = document.createRange();\n\n const cursorPos = getCurrentCursorPosition(editorElement);\n\n const matches: Match[] = [];\n let absCounter = 0;\n\n const searchNodesForText = (node: Node) => {\n if (node.nodeType === Node.TEXT_NODE && node.textContent) {\n let index = node.textContent.indexOf(searchText);\n while (index !== -1) {\n matches.push({\n node,\n offset: index,\n absIndex: absCounter + index,\n });\n index = node.textContent.indexOf(searchText, index + 1);\n }\n absCounter += node.textContent.length;\n } else if (node.nodeName !== 'LC_MENTION') {\n Array.from(node.childNodes).forEach(searchNodesForText);\n }\n };\n\n searchNodesForText(editorElement);\n\n if (matches.length === 0) {\n return null;\n }\n\n let match = matches[0];\n\n if (options?.shouldReplaceNearCursor && cursorPos !== null) {\n match = matches.reduce((prev, curr) =>\n Math.abs(curr.absIndex - cursorPos) < Math.abs(prev.absIndex - cursorPos) ? curr : prev,\n );\n }\n\n if (!match) {\n return null;\n }\n\n range.setStart(match.node, match.offset);\n range.setEnd(match.node, match.offset + searchText.length);\n\n return range;\n};\n\nexport const getCurrentCursorPosition = (editorElement: HTMLDivElement | null): number | null => {\n if (!editorElement) {\n return null;\n }\n\n const sel = window.getSelection?.();\n if (!sel || sel.rangeCount === 0) {\n return null;\n }\n\n const range = sel.getRangeAt(0);\n\n if (!editorElement.contains(range.commonAncestorContainer)) {\n return null;\n }\n\n const pre = document.createRange();\n pre.selectNodeContents(editorElement);\n\n try {\n pre.setEnd(range.startContainer, range.startOffset);\n\n const container = document.createElement('div');\n container.appendChild(pre.cloneContents());\n\n const bbCodeUntilCursor = convertHTMLToText(container.innerHTML, {\n preserveSpaces: true,\n shouldSerializeNoEmojiToBBCode: false,\n });\n\n return bbCodeUntilCursor.length;\n } catch {\n return convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length;\n }\n};\n\ntype CursorTarget = { node: Text; offset: number };\n\nconst getCursorTargetByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): CursorTarget | null => {\n const childNodes = Array.from(editorElement.childNodes);\n\n if (childNodes.length === 0) {\n const textNode = document.createTextNode('');\n editorElement.appendChild(textNode);\n\n return { node: textNode, offset: 0 };\n }\n\n const clampedPosition = clamp(\n position,\n 0,\n convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length,\n );\n\n let absCounter = 0;\n\n const searchNodes = (node: Node): CursorTarget | null => {\n if (node.nodeType === Node.TEXT_NODE) {\n const textNode = node as Text;\n const nodeText = textNode.nodeValue ?? '';\n const nextAbsCounter = absCounter + nodeText.length;\n\n if (clampedPosition <= nextAbsCounter) {\n return {\n node: textNode,\n offset: clamp(clampedPosition - absCounter, 0, nodeText.length),\n };\n }\n\n absCounter = nextAbsCounter;\n\n return null;\n }\n\n if (node.nodeName === 'LC_MENTION') {\n return null;\n }\n\n for (const child of Array.from(node.childNodes)) {\n const found = searchNodes(child);\n if (found) {\n return found;\n }\n }\n\n return null;\n };\n\n for (const rootNode of childNodes) {\n const found = searchNodes(rootNode);\n if (found) {\n return found;\n }\n }\n\n const lastTextNode = editorElement.lastChild;\n if (lastTextNode?.nodeType === Node.TEXT_NODE) {\n const textNode = lastTextNode as Text;\n return { node: textNode, offset: textNode.length };\n }\n\n const appendedTextNode = document.createTextNode('\\u200B');\n editorElement.appendChild(appendedTextNode);\n\n return { node: appendedTextNode, offset: appendedTextNode.length };\n};\n\nexport const setCursorPositionByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): void => {\n pendingCursorMarkers.get(editorElement.ownerDocument)?.();\n\n const selection = window.getSelection?.();\n\n if (!selection) {\n return;\n }\n\n const target = getCursorTargetByAbsIndex({ editorElement, position });\n\n if (!target) {\n return;\n }\n\n const range = document.createRange();\n\n try {\n range.setStart(target.node, target.offset);\n range.setEnd(target.node, target.offset);\n } catch {\n return;\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\n/**\n * Unwraps any no-emoji-convert span that contains the cursor.\n * This removes the span element but keeps its text content, preventing the cursor from getting stuck.\n */\nexport const unwrapIgnoreEmojiSpanAtCursor = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n const cursorOffset = range.startOffset;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, unwrap it\n const span = commonAncestorContainer as Element;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Find which text node contains the cursor\n let cursorNode: Node | null = null;\n const cursorNodeOffset = cursorOffset;\n\n // Get all child nodes of the span\n const childNodes = Array.from(span.childNodes);\n\n // Insert all children before the span and find the cursor node\n childNodes.forEach((child) => {\n const clonedChild = child.cloneNode(true);\n parentNode.insertBefore(clonedChild, span);\n\n // If this is the node that contains the cursor, track it\n if (child === range.startContainer) {\n cursorNode = clonedChild;\n }\n });\n\n // Remove the span\n parentNode.removeChild(span);\n\n // Restore cursor position in the unwrapped content\n if (cursorNode) {\n range.setStart(cursorNode, cursorNodeOffset);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n\n/**\n * Moves the cursor outside of any no-emoji-convert span if it's currently inside one.\n * This prevents the cursor from getting \"stuck\" inside the protection span when typing.\n */\nexport const moveCursorOutOfIgnoreEmojiSpan = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, move cursor to after it\n const span = commonAncestorContainer as Element;\n const { nextSibling } = span;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Always ensure there's a text node AFTER the span\n let targetNode: Text;\n\n if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n // Next sibling is already a text node, use it\n targetNode = nextSibling as Text;\n } else if (nextSibling && nextSibling.nodeType === Node.ELEMENT_NODE) {\n // Next sibling is an element, find first text node in it\n const walker = document.createTreeWalker(nextSibling, NodeFilter.SHOW_TEXT);\n const firstTextNode = walker.nextNode() as Text;\n if (firstTextNode) {\n targetNode = firstTextNode;\n } else {\n // No text node found, create one\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n } else {\n // No next sibling or it's not a text/element node, create a new text node\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n\n // Place cursor at the start of the target node\n range.setStart(targetNode, 0);\n range.collapse(true);\n\n selection.removeAllRanges();\n selection.addRange(range);\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+
3
+ var _vitest = require("vitest");
4
+ var _selection = require("./selection");
5
+ const select = (node, offset) => {
6
+ const range = document.createRange();
7
+ range.setStart(node, offset);
8
+ range.collapse(true);
9
+ window.getSelection().removeAllRanges();
10
+ window.getSelection().addRange(range);
11
+ };
12
+ const createEditor = () => {
13
+ const editor = document.createElement('div');
14
+ editor.setAttribute('contenteditable', 'true');
15
+ editor.textContent = 'abcd';
16
+ document.body.append(editor);
17
+ editor.focus();
18
+ select(editor.firstChild, 2);
19
+ return editor;
20
+ };
21
+ (0, _vitest.beforeEach)(() => {
22
+ _vitest.vi.useFakeTimers();
23
+ // These single-line fixtures do not need layout-dependent innerText semantics.
24
+ Object.defineProperty(HTMLElement.prototype, 'innerText', {
25
+ configurable: true,
26
+ get() {
27
+ return this.textContent ?? '';
28
+ },
29
+ set(value) {
30
+ this.textContent = value;
31
+ }
32
+ });
33
+ // jsdom has Selection/Range but does not implement browser editing commands.
34
+ Object.defineProperty(document, 'execCommand', {
35
+ configurable: true,
36
+ value: _vitest.vi.fn()
37
+ });
38
+ });
39
+ (0, _vitest.afterEach)(() => {
40
+ _vitest.vi.runOnlyPendingTimers();
41
+ _vitest.vi.useRealTimers();
42
+ _vitest.vi.restoreAllMocks();
43
+ // @ts-expect-error - jsdom does not define innerText.
44
+ delete HTMLElement.prototype.innerText;
45
+ document.body.replaceChildren();
46
+ window.getSelection().removeAllRanges();
47
+ });
48
+ (0, _vitest.describe)('insertInvisibleCursorMarker', () => {
49
+ (0, _vitest.it)('does not restore a cursor after the editor content was removed', () => {
50
+ const editor = createEditor();
51
+ (0, _selection.insertInvisibleCursorMarker)(editor);
52
+ editor.replaceChildren();
53
+ (0, _vitest.expect)(() => _vitest.vi.advanceTimersByTime(10)).not.toThrow();
54
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
55
+ });
56
+ (0, _vitest.it)('does not restore a cursor after the editor was detached', () => {
57
+ const editor = createEditor();
58
+ (0, _selection.insertInvisibleCursorMarker)(editor);
59
+ editor.remove();
60
+ const focus = document.activeElement;
61
+ (0, _vitest.expect)(() => _vitest.vi.advanceTimersByTime(10)).not.toThrow();
62
+ (0, _vitest.expect)(document.activeElement).toBe(focus);
63
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
64
+ });
65
+ (0, _vitest.it)('does not use a marker moved into another editor', () => {
66
+ const editor = createEditor();
67
+ (0, _selection.insertInvisibleCursorMarker)(editor);
68
+ const marker = editor.querySelector('.invisible-cursor-marker');
69
+ const other = document.createElement('div');
70
+ other.setAttribute('contenteditable', 'true');
71
+ document.body.append(other);
72
+ other.append(marker);
73
+ const anchorNode = window.getSelection().anchorNode;
74
+ _vitest.vi.advanceTimersByTime(10);
75
+ (0, _vitest.expect)(window.getSelection().anchorNode).toBe(anchorNode);
76
+ (0, _vitest.expect)(marker.isConnected).toBe(false);
77
+ });
78
+ (0, _vitest.it)('preserves focus and the caret of another input', () => {
79
+ const editor = createEditor();
80
+ (0, _selection.insertInvisibleCursorMarker)(editor);
81
+ const input = document.createElement('input');
82
+ input.value = 'other';
83
+ document.body.append(input);
84
+ input.focus();
85
+ input.setSelectionRange(1, 3);
86
+ _vitest.vi.advanceTimersByTime(10);
87
+ (0, _vitest.expect)(document.activeElement).toBe(input);
88
+ (0, _vitest.expect)([input.selectionStart, input.selectionEnd]).toEqual([1, 3]);
89
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
90
+ });
91
+ (0, _vitest.it)('preserves a selection moved into another contenteditable', () => {
92
+ const editor = createEditor();
93
+ (0, _selection.insertInvisibleCursorMarker)(editor);
94
+ const other = createEditor();
95
+ select(other.firstChild, 1);
96
+ _vitest.vi.advanceTimersByTime(10);
97
+ (0, _vitest.expect)(document.activeElement).toBe(other);
98
+ (0, _vitest.expect)((0, _selection.getCurrentCursorPosition)(other)).toBe(1);
99
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
100
+ });
101
+ (0, _vitest.it)('preserves a newer cursor operation in the same editor', () => {
102
+ const editor = createEditor();
103
+ (0, _selection.insertInvisibleCursorMarker)(editor);
104
+ (0, _selection.setCursorPositionByAbsIndex)({
105
+ editorElement: editor,
106
+ position: 1
107
+ });
108
+ _vitest.vi.advanceTimersByTime(10);
109
+ (0, _vitest.expect)((0, _selection.getCurrentCursorPosition)(editor)).toBe(1);
110
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
111
+ });
112
+ (0, _vitest.it)('respects a replaced selection even at the same interim coordinates', () => {
113
+ const editor = createEditor();
114
+ (0, _selection.insertInvisibleCursorMarker)(editor);
115
+ const selection = window.getSelection();
116
+ select(selection.anchorNode, selection.anchorOffset);
117
+ const expectedRange = selection.getRangeAt(0);
118
+ _vitest.vi.advanceTimersByTime(10);
119
+ (0, _vitest.expect)(selection.getRangeAt(0)).toBe(expectedRange);
120
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
121
+ });
122
+ (0, _vitest.it)('supersedes an older marker operation', () => {
123
+ const editor = createEditor();
124
+ (0, _selection.insertInvisibleCursorMarker)(editor);
125
+ _vitest.vi.advanceTimersByTime(5);
126
+ select(editor.lastChild, 1);
127
+ (0, _selection.insertInvisibleCursorMarker)(editor);
128
+ (0, _vitest.expect)(editor.querySelectorAll('.invisible-cursor-marker')).toHaveLength(1);
129
+ _vitest.vi.advanceTimersByTime(5);
130
+ (0, _vitest.expect)(editor.querySelectorAll('.invisible-cursor-marker')).toHaveLength(1);
131
+ _vitest.vi.advanceTimersByTime(5);
132
+ (0, _vitest.expect)((0, _selection.getCurrentCursorPosition)(editor)).toBe(3);
133
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
134
+ });
135
+ (0, _vitest.it)('cleans up immediately when cancelled', () => {
136
+ const editor = createEditor();
137
+ const cancel = (0, _selection.insertInvisibleCursorMarker)(editor);
138
+ const timerCount = _vitest.vi.getTimerCount();
139
+ cancel === null || cancel === void 0 || cancel();
140
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
141
+ (0, _vitest.expect)(_vitest.vi.getTimerCount()).toBe(timerCount - 1);
142
+ });
143
+ (0, _vitest.it)('restores the cursor after backward deletion and removes the marker', () => {
144
+ const editor = createEditor();
145
+ _vitest.vi.mocked(document.execCommand).mockImplementation(() => {
146
+ const range = window.getSelection().getRangeAt(0);
147
+ range.setStart(range.startContainer, range.startOffset - 1);
148
+ range.deleteContents();
149
+ return true;
150
+ });
151
+ (0, _selection.insertInvisibleCursorMarker)(editor);
152
+ _vitest.vi.advanceTimersByTime(10);
153
+ (0, _vitest.expect)(document.execCommand).toHaveBeenCalledWith('delete', false);
154
+ (0, _vitest.expect)(editor.textContent).toBe('acd');
155
+ (0, _vitest.expect)((0, _selection.getCurrentCursorPosition)(editor)).toBe(1);
156
+ (0, _vitest.expect)(document.activeElement).toBe(editor);
157
+ (0, _vitest.expect)(editor.querySelector('.invisible-cursor-marker')).toBeNull();
158
+ });
159
+ });
160
+ //# sourceMappingURL=selection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.test.js","names":["_vitest","require","_selection","select","node","offset","range","document","createRange","setStart","collapse","window","getSelection","removeAllRanges","addRange","createEditor","editor","createElement","setAttribute","textContent","body","append","focus","firstChild","beforeEach","vi","useFakeTimers","Object","defineProperty","HTMLElement","prototype","configurable","get","set","value","fn","afterEach","runOnlyPendingTimers","useRealTimers","restoreAllMocks","innerText","replaceChildren","describe","it","insertInvisibleCursorMarker","expect","advanceTimersByTime","not","toThrow","querySelector","toBeNull","remove","activeElement","toBe","marker","other","anchorNode","isConnected","input","setSelectionRange","selectionStart","selectionEnd","toEqual","getCurrentCursorPosition","setCursorPositionByAbsIndex","editorElement","position","selection","anchorOffset","expectedRange","getRangeAt","lastChild","querySelectorAll","toHaveLength","cancel","timerCount","getTimerCount","mocked","execCommand","mockImplementation","startContainer","startOffset","deleteContents","toHaveBeenCalledWith"],"sources":["../../../src/utils/selection.test.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\nimport {\n getCurrentCursorPosition,\n insertInvisibleCursorMarker,\n setCursorPositionByAbsIndex,\n} from './selection';\n\nconst select = (node: Node, offset: number) => {\n const range = document.createRange();\n range.setStart(node, offset);\n range.collapse(true);\n window.getSelection()!.removeAllRanges();\n window.getSelection()!.addRange(range);\n};\n\nconst createEditor = () => {\n const editor = document.createElement('div');\n editor.setAttribute('contenteditable', 'true');\n editor.textContent = 'abcd';\n document.body.append(editor);\n editor.focus();\n select(editor.firstChild!, 2);\n return editor;\n};\n\nbeforeEach(() => {\n vi.useFakeTimers();\n // These single-line fixtures do not need layout-dependent innerText semantics.\n Object.defineProperty(HTMLElement.prototype, 'innerText', {\n configurable: true,\n get() {\n return this.textContent ?? '';\n },\n set(value: string) {\n this.textContent = value;\n },\n });\n // jsdom has Selection/Range but does not implement browser editing commands.\n Object.defineProperty(document, 'execCommand', { configurable: true, value: vi.fn() });\n});\n\nafterEach(() => {\n vi.runOnlyPendingTimers();\n vi.useRealTimers();\n vi.restoreAllMocks();\n // @ts-expect-error - jsdom does not define innerText.\n delete HTMLElement.prototype.innerText;\n document.body.replaceChildren();\n window.getSelection()!.removeAllRanges();\n});\n\ndescribe('insertInvisibleCursorMarker', () => {\n it('does not restore a cursor after the editor content was removed', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n editor.replaceChildren();\n expect(() => vi.advanceTimersByTime(10)).not.toThrow();\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('does not restore a cursor after the editor was detached', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n editor.remove();\n const focus = document.activeElement;\n expect(() => vi.advanceTimersByTime(10)).not.toThrow();\n expect(document.activeElement).toBe(focus);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('does not use a marker moved into another editor', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n const marker = editor.querySelector('.invisible-cursor-marker')!;\n const other = document.createElement('div');\n other.setAttribute('contenteditable', 'true');\n document.body.append(other);\n other.append(marker);\n const anchorNode = window.getSelection()!.anchorNode;\n vi.advanceTimersByTime(10);\n expect(window.getSelection()!.anchorNode).toBe(anchorNode);\n expect(marker.isConnected).toBe(false);\n });\n\n it('preserves focus and the caret of another input', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n const input = document.createElement('input');\n input.value = 'other';\n document.body.append(input);\n input.focus();\n input.setSelectionRange(1, 3);\n vi.advanceTimersByTime(10);\n expect(document.activeElement).toBe(input);\n expect([input.selectionStart, input.selectionEnd]).toEqual([1, 3]);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('preserves a selection moved into another contenteditable', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n const other = createEditor();\n select(other.firstChild!, 1);\n vi.advanceTimersByTime(10);\n expect(document.activeElement).toBe(other);\n expect(getCurrentCursorPosition(other)).toBe(1);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('preserves a newer cursor operation in the same editor', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n setCursorPositionByAbsIndex({ editorElement: editor, position: 1 });\n vi.advanceTimersByTime(10);\n expect(getCurrentCursorPosition(editor)).toBe(1);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('respects a replaced selection even at the same interim coordinates', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n const selection = window.getSelection()!;\n select(selection.anchorNode!, selection.anchorOffset);\n const expectedRange = selection.getRangeAt(0);\n vi.advanceTimersByTime(10);\n expect(selection.getRangeAt(0)).toBe(expectedRange);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('supersedes an older marker operation', () => {\n const editor = createEditor();\n insertInvisibleCursorMarker(editor);\n vi.advanceTimersByTime(5);\n select(editor.lastChild!, 1);\n insertInvisibleCursorMarker(editor);\n expect(editor.querySelectorAll('.invisible-cursor-marker')).toHaveLength(1);\n vi.advanceTimersByTime(5);\n expect(editor.querySelectorAll('.invisible-cursor-marker')).toHaveLength(1);\n vi.advanceTimersByTime(5);\n expect(getCurrentCursorPosition(editor)).toBe(3);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n\n it('cleans up immediately when cancelled', () => {\n const editor = createEditor();\n const cancel = insertInvisibleCursorMarker(editor);\n const timerCount = vi.getTimerCount();\n cancel?.();\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n expect(vi.getTimerCount()).toBe(timerCount - 1);\n });\n\n it('restores the cursor after backward deletion and removes the marker', () => {\n const editor = createEditor();\n vi.mocked(document.execCommand).mockImplementation(() => {\n const range = window.getSelection()!.getRangeAt(0);\n range.setStart(range.startContainer, range.startOffset - 1);\n range.deleteContents();\n return true;\n });\n insertInvisibleCursorMarker(editor);\n vi.advanceTimersByTime(10);\n expect(document.execCommand).toHaveBeenCalledWith('delete', false);\n expect(editor.textContent).toBe('acd');\n expect(getCurrentCursorPosition(editor)).toBe(1);\n expect(document.activeElement).toBe(editor);\n expect(editor.querySelector('.invisible-cursor-marker')).toBeNull();\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -55,6 +55,7 @@ const EmojiInput = /*#__PURE__*/forwardRef(({
55
55
  const prefixElementRef = useRef(null);
56
56
  const hasPrefixRendered = useRef(false);
57
57
  const hasPrefixChanged = useRef(false);
58
+ const cancelCursorMarkerRef = useRef();
58
59
  const shouldDeleteOneMoreBackwards = useRef(false);
59
60
  const shouldDeleteOneMoreForwards = useRef(false);
60
61
 
@@ -71,6 +72,7 @@ const EmojiInput = /*#__PURE__*/forwardRef(({
71
72
  isDisabled
72
73
  });
73
74
  const shouldChangeColor = useMemo(() => areaProvider.shouldChangeColor ?? false, [areaProvider.shouldChangeColor]);
75
+ useIsomorphicLayoutEffect(() => () => cancelCursorMarkerRef.current?.(), []);
74
76
  useEffect(() => {
75
77
  void loadEmojiShortList().then(({
76
78
  shortNameList,
@@ -179,7 +181,7 @@ const EmojiInput = /*#__PURE__*/forwardRef(({
179
181
  event.stopPropagation();
180
182
 
181
183
  // Remove content and set cursor to the right position
182
- insertInvisibleCursorMarker();
184
+ cancelCursorMarkerRef.current = insertInvisibleCursorMarker(editorRef.current);
183
185
  return;
184
186
  }
185
187
  if (shouldDeleteOneMoreForwards.current) {
@@ -207,6 +209,7 @@ const EmojiInput = /*#__PURE__*/forwardRef(({
207
209
  moveCursorOutOfIgnoreEmojiSpan(editorRef.current);
208
210
  }, [handleUpdateHTML, isDisabled, onInput]);
209
211
  const handleKeyDown = useCallback(event => {
212
+ cancelCursorMarkerRef.current?.();
210
213
  if (isDisabled) {
211
214
  event.preventDefault();
212
215
  event.stopPropagation();