UNPKG

@mtg-rio/mui-mentions

Version:

@mention people in a MUI TextField

81 lines 4.05 kB
"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