@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
123 lines (119 loc) • 4.34 kB
JavaScript
var slate = require('slate');
var getCharacter = require('../utils/get-character.cjs');
var getMatchRange = require('../utils/get-match-range.cjs');
var isEmptyString = require('../utils/is-empty-string.cjs');
var isWhitespaceCharacter = require('../utils/is-whitespace-character.cjs');
const MENTION_CHARACTER = "@";
function getMentionDraftAtSelection(editor) {
const { selection } = editor;
if (!selection || !slate.Range.isCollapsed(selection)) {
return;
}
const match = getMatchRange.getMatchRange(editor, selection, ["@"], {
include: true,
allowConsecutiveWhitespace: false,
ignoreTerminator: (_, point) => {
const characterBefore = getCharacter.getCharacterBefore(editor, point);
if (characterBefore && !isWhitespaceCharacter.isWhitespaceCharacter(characterBefore.text)) {
return true;
}
return false;
}
});
if (!match) {
return;
}
const matchText = slate.Editor.string(editor, match);
if (!matchText.startsWith(MENTION_CHARACTER) || matchText.length > 1 && isWhitespaceCharacter.isWhitespaceCharacter(matchText[1])) {
return;
}
return {
range: match,
text: matchText.substring(1)
};
}
function isComposerBodyMention(node) {
return slate.Element.isElement(node) && node.type === "mention";
}
function insertMention(editor, userId) {
const mention = {
type: "mention",
id: userId,
children: [{ text: "" }]
};
slate.Transforms.insertNodes(editor, mention);
slate.Transforms.move(editor);
const afterCharacter = editor.selection ? getCharacter.getCharacterAfter(editor, editor.selection) : void 0;
if (!afterCharacter || afterCharacter.void) {
slate.Transforms.insertText(editor, " ");
} else if (isEmptyString.isEmptyString(afterCharacter.text)) {
slate.Transforms.move(editor);
}
}
function insertMentionCharacter(editor) {
if (!editor.selection) {
return;
}
const beforeCharacter = getCharacter.getCharacterBefore(editor, editor.selection, {
filterVoids: true
});
const afterCharacter = getCharacter.getCharacterAfter(editor, editor.selection, {
filterVoids: true
});
const shouldInsertSpaceBefore = beforeCharacter && !isEmptyString.isEmptyString(beforeCharacter.text);
const shouldInsertSpaceAfter = afterCharacter && !isEmptyString.isEmptyString(afterCharacter.text);
if (!slate.Range.isCollapsed(editor.selection)) {
const text = (shouldInsertSpaceBefore ? " " : "") + MENTION_CHARACTER + (shouldInsertSpaceAfter ? " " : "");
editor.insertText(text);
if (shouldInsertSpaceAfter) {
slate.Transforms.move(editor, {
distance: 1,
unit: "character",
reverse: true
});
}
} else {
const beforeText = (shouldInsertSpaceBefore ? " " : "") + MENTION_CHARACTER;
editor.insertText(beforeText, { at: slate.Range.start(editor.selection) });
if (shouldInsertSpaceAfter) {
editor.insertText(" ", { at: slate.Range.end(editor.selection) });
}
slate.Transforms.collapse(editor, { edge: "end" });
}
}
function withMentions(editor) {
const { isInline, isVoid, markableVoid, deleteBackward } = editor;
editor.isInline = (element) => {
return isComposerBodyMention(element) || isInline(element);
};
editor.isVoid = (element) => {
return isComposerBodyMention(element) || isVoid(element);
};
editor.markableVoid = (element) => {
return isComposerBodyMention(element) || markableVoid(element);
};
editor.deleteBackward = (unit) => {
const { selection } = editor;
if (selection && slate.Range.isCollapsed(selection)) {
const [mention] = slate.Editor.nodes(editor, {
at: unit === "character" ? slate.Editor.before(editor, selection, { unit: "character" }) : selection,
match: isComposerBodyMention
});
deleteBackward(unit);
if (mention) {
slate.Transforms.insertText(editor, MENTION_CHARACTER);
}
} else {
deleteBackward(unit);
}
};
return editor;
}
exports.MENTION_CHARACTER = MENTION_CHARACTER;
exports.getMentionDraftAtSelection = getMentionDraftAtSelection;
exports.insertMention = insertMention;
exports.insertMentionCharacter = insertMentionCharacter;
exports.isComposerBodyMention = isComposerBodyMention;
exports.withMentions = withMentions;
//# sourceMappingURL=mentions.cjs.map
;