@chayns-components/emoji-input
Version:
Input field that supports HTML elements and emojis
110 lines (108 loc) • 4.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.replaceText = exports.insertTextAtCursorPosition = void 0;
var _selection = require("./selection");
/**
* This function inserts the passed text at the correct position in the editor element. If the
* element has the focus, the new emoji is inserted at the cursor position. If not, the emoji
* will be appended to the back of the input field content.
*
* In addition, this function also sets the cursor to the correct position when the input field
* has the focus. For this purpose, the current position of the cursor or a selection is read to
* calculate the cursor position after inserting the text.
*
* @param {Object} options - Object with element and text to insert
* @param {HTMLDivElement} options.editorElement - Element to insert text into
* @param {string} options.text - Text to insert into element
*/
const insertTextAtCursorPosition = ({
editorElement,
text,
shouldUseSavedSelection = false
}) => {
if (shouldUseSavedSelection) {
(0, _selection.restoreSelection)(editorElement);
}
const selection = window.getSelection();
(0, _selection.saveSelection)(editorElement);
if (selection !== null && selection !== void 0 && selection.anchorNode && editorElement.contains(selection.anchorNode)) {
let range = selection.getRangeAt(0);
const parts = text.split(/\r\n|\r|\n/);
const firstPart = parts.shift();
const textNodes = parts.map(part => document.createTextNode(part));
range.deleteContents();
if (firstPart) {
if (selection.anchorNode.nodeType === Node.TEXT_NODE) {
const {
nodeValue
} = selection.anchorNode;
if (typeof nodeValue === 'string') {
selection.anchorNode.nodeValue = nodeValue.slice(0, range.startOffset) + firstPart + nodeValue.slice(range.startOffset);
(0, _selection.moveSelectionOffset)(firstPart.length);
}
} else if (selection.anchorNode === editorElement) {
const textNode = document.createTextNode(firstPart);
// Inserts the text node before the node at the anchor offset.
// If that node doesn't exist, the text node is appended to the editor, as a fallback. I'm not sure if there is any case where this would happen.
const insertBefore = editorElement.childNodes[selection.anchorOffset];
if (insertBefore) {
insertBefore.before(textNode);
} else {
editorElement.appendChild(textNode);
}
const textNodeIndex = Array.from(editorElement.childNodes).indexOf(textNode);
(0, _selection.moveSelectionOffset)(firstPart.length);
(0, _selection.setChildIndex)(textNodeIndex);
}
}
(0, _selection.restoreSelection)(editorElement);
if (textNodes.length > 0) {
range = selection.getRangeAt(0);
let brElement = document.createElement('br');
range.insertNode(brElement);
range.setEndAfter(brElement);
range.setStartAfter(brElement);
textNodes.forEach((textNode, index) => {
range.insertNode(textNode);
range.setEndAfter(textNode);
range.setStartAfter(textNode);
if (index !== textNodes.length - 1) {
brElement = document.createElement('br');
range.insertNode(brElement);
range.setEndAfter(brElement);
range.setStartAfter(brElement);
}
});
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
} else {
// eslint-disable-next-line no-param-reassign
editorElement.innerText += text;
}
};
exports.insertTextAtCursorPosition = insertTextAtCursorPosition;
const replaceText = ({
editorElement,
searchText,
pasteText
}) => {
const selection = window.getSelection();
const rangeToReplace = (0, _selection.findAndSelectText)({
editorElement,
searchText
});
if (rangeToReplace && selection) {
selection.removeAllRanges();
selection.addRange(rangeToReplace);
insertTextAtCursorPosition({
editorElement,
text: pasteText
});
}
};
exports.replaceText = replaceText;
//# sourceMappingURL=insert.js.map