@mtg-rio/mui-mentions
Version:
@mention people in a MUI TextField
81 lines • 4.05 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const material_1 = require("@mui/material");
const react_1 = tslib_1.__importDefault(require("react"));
const Mention_1 = tslib_1.__importDefault(require("./Mention"));
const utils_1 = require("./utils/utils");
function Highlighter(props) {
const { highlighterRef, cursorRef, selectionEnd, selectionStart, value, dataSources, multiline } = props;
const components = [];
const handleMention = (_markup, index, _plainTextIndex, id, display) => {
components.push(react_1.default.createElement(Mention_1.default, { key: `${id}-${index}`, display: display, color: props.color }));
};
const handlePlainText = (text, index, indexInPlaintext) => {
if (!multiline) {
text = text.replaceAll('\n', '');
}
const renderCursor = selectionStart &&
selectionStart === selectionEnd &&
selectionStart >= indexInPlaintext &&
selectionStart <= indexInPlaintext + text.length;
if (!renderCursor) {
components.push(react_1.default.createElement(material_1.Box, { key: `${index}-${indexInPlaintext}`, component: 'span', visibility: 'hidden' }, text));
}
else {
const splitIndex = selectionStart - indexInPlaintext;
const startText = text.substring(0, splitIndex);
const endText = text.substring(splitIndex);
if (startText) {
components.push(react_1.default.createElement(material_1.Box, { key: `${index}-${indexInPlaintext}-precursor`, component: 'span', visibility: 'hidden' }, startText));
}
components.push(react_1.default.createElement(material_1.Box, { key: 'cursor', ref: cursorRef, component: 'span', visibility: 'hidden' }));
if (endText) {
components.push(react_1.default.createElement(material_1.Box, { key: `${index}-${indexInPlaintext}-postcursor`, component: 'span', visibility: 'hidden' }, endText));
}
}
};
(0, utils_1.iterateMentionsMarkup)(value, dataSources, handleMention, handlePlainText, multiline);
const rect = getHighlighterRect(props.inputRef);
return (react_1.default.createElement(material_1.Portal, { container: () => { var _a; return ((_a = props.inputRef) === null || _a === void 0 ? void 0 : _a.parentElement) || null; } },
react_1.default.createElement(material_1.Box, { ref: highlighterRef, sx: {
position: 'absolute',
top: `${rect.y}px`,
left: `${rect.x}px`,
width: `${rect.width}px`,
height: `${rect.height}px`,
whiteSpace: multiline ? 'pre-wrap' : 'pre',
overflow: 'hidden',
overscrollBehavior: 'none',
zIndex: -1,
} },
components,
react_1.default.createElement(material_1.Box, { component: 'span', visibility: 'hidden' }, ' '))));
}
exports.default = Highlighter;
/**
* Gets the highlighter rectangle (x, y, width, height) for the provided input element.
* @param input The input element to overlay.
* @returns The highlighter rectangle.
*/
function getHighlighterRect(input) {
const rec = { x: 0, y: 0, width: 0, height: 0 };
if (!input) {
return rec;
}
const computedStyle = getComputedStyle(input);
rec.width = input.clientWidth;
rec.width -= parseFloat(computedStyle.paddingLeft);
rec.width -= parseFloat(computedStyle.paddingRight);
rec.height = input.clientHeight;
rec.height -= parseFloat(computedStyle.paddingTop);
rec.height -= parseFloat(computedStyle.paddingBottom);
rec.x = input.offsetLeft;
rec.x += parseFloat(computedStyle.paddingLeft);
rec.x += parseFloat(computedStyle.borderLeft);
rec.y = input.offsetTop;
rec.y += parseFloat(computedStyle.paddingTop);
rec.y += parseFloat(computedStyle.borderTop);
return rec;
}
//# sourceMappingURL=Highlighter.js.map