@mtg-rio/mui-mentions
Version:
@mention people in a MUI TextField
78 lines • 3.71 kB
JavaScript
import { Box, Portal } from '@mui/material';
import React from 'react';
import Mention from './Mention';
import { iterateMentionsMarkup } from './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.createElement(Mention, { 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.createElement(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.createElement(Box, { key: `${index}-${indexInPlaintext}-precursor`, component: 'span', visibility: 'hidden' }, startText));
}
components.push(React.createElement(Box, { key: 'cursor', ref: cursorRef, component: 'span', visibility: 'hidden' }));
if (endText) {
components.push(React.createElement(Box, { key: `${index}-${indexInPlaintext}-postcursor`, component: 'span', visibility: 'hidden' }, endText));
}
}
};
iterateMentionsMarkup(value, dataSources, handleMention, handlePlainText, multiline);
const rect = getHighlighterRect(props.inputRef);
return (React.createElement(Portal, { container: () => { var _a; return ((_a = props.inputRef) === null || _a === void 0 ? void 0 : _a.parentElement) || null; } },
React.createElement(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.createElement(Box, { component: 'span', visibility: 'hidden' }, ' '))));
}
export 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