UNPKG

@onesy/ui-react

Version:
1,059 lines (1,029 loc) 70.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _utils = require("@onesy/utils"); var _styleReact = require("@onesy/style-react"); var _IconMaterialFormatAlignLeftW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignLeftW100")); var _IconMaterialFormatAlignCenterW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignCenterW100")); var _IconMaterialFormatAlignRightW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignRightW100")); var _IconMaterialFormatAlignJustifyW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignJustifyW100")); var _IconMaterialFormatColorTextW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatColorTextW100")); var _IconMaterialFormatColorFillW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatColorFillW100")); var _IconMaterialFormatListNumberedW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatListNumberedW100")); var _IconMaterialFormatListBulletedW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatListBulletedW100")); var _IconMaterialSuperscriptW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialSuperscriptW100")); var _IconMaterialSubscriptW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialSubscriptW100")); var _IconMaterialFormatItalicW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatItalicW100")); var _IconMaterialFormatUnderlinedW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatUnderlinedW100")); var _IconMaterialStrikethroughSW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialStrikethroughSW100")); var _IconMaterialFormatBoldW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatBoldW100")); var _IconMaterialAddLinkW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialAddLinkW100")); var _IconMaterialLinkOffW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialLinkOffW100")); var _IconMaterialFormatClearW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatClearW100")); var _ColorTextField = _interopRequireDefault(require("../ColorTextField")); var _TextField = _interopRequireDefault(require("../TextField/TextField")); var _Line = _interopRequireDefault(require("../Line")); var _List = _interopRequireDefault(require("../List")); var _ListItem = _interopRequireDefault(require("../ListItem")); var _Avatar = _interopRequireDefault(require("../Avatar")); var _Type = _interopRequireDefault(require("../Type")); var _Surface = _interopRequireDefault(require("../Surface")); var _Button = _interopRequireDefault(require("../Button")); var _Append = _interopRequireDefault(require("../Append")); var _Fade = _interopRequireDefault(require("../Fade")); var _Tooltip = _interopRequireDefault(require("../Tooltip")); var _ToggleButton = _interopRequireDefault(require("../ToggleButton")); var _ClickListener = _interopRequireDefault(require("../ClickListener")); var _ToggleButtons = _interopRequireDefault(require("../ToggleButtons")); var _Menu = _interopRequireDefault(require("../Menu")); var _Divider = _interopRequireDefault(require("../Divider")); var _utils2 = require("../utils"); var _jsxRuntime = require("react/jsx-runtime"); const _excluded = ["ref", "tonal", "color", "version", "size", "valueDefault", "value", "inputProps", "onChange", "error", "name", "placeholder", "edit", "mention", "multiline", "onChangeMention", "optionsMention", "error", "helperText", "mentionLabel", "onKeyDown", "pasteText", "readOnly", "additional", "miniMenuExtended", "HelperTextProps", "ColorTextFieldProps", "className"], _excluded2 = ["color"], _excluded3 = ["ref", "version", "onUpdate", "onClose"], _excluded4 = ["ref", "label", "labelButton", "value", "onChange", "onClick", "placeholder", "InputComponent", "InputProps"], _excluded5 = ["open", "element", "anchorElement", "onClose", "children"], _excluded6 = ["ref", "open", "name", "children"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } const useStyle = (0, _styleReact.style)(theme => ({ root: { minHeight: '20px', width: '100%', '& .onesy-TextField-input': _objectSpread({ wordBreak: 'break-word', color: theme.methods.palette.color.value('primary', 10) }, theme.typography.values.b2), '& ul, & ol': { listStylePosition: 'inside' } }, root_type: { minHeight: '20px', width: '100%', cursor: 'text', '& .onesy-TextField-input': _objectSpread({ wordBreak: 'break-word', color: theme.methods.palette.color.value('primary', 10) }, theme.typography.values.b2), '& ul, & ol': { listStylePosition: 'inside' } }, menu: { width: '100vw', maxWidth: '240px', borderRadius: theme.methods.shape.radius.value(2.5), boxShadow: '0px 4px 32px 0px rgba(0, 0, 0, 0.04)', background: theme.palette.light ? theme.palette.color.neutral[99] : theme.palette.color.neutral[20] }, list: { maxHeight: '240px', overflow: 'hidden auto' }, textMiniMenuWrapper: { paddingBlock: theme.methods.space.value(1, 'px') }, textMiniMenu: { padding: theme.methods.space.value(1.5, 'px'), borderRadius: theme.methods.shape.radius.value(140, 'px'), boxShadow: theme.shadows.values.default[2], maxWidth: 'calc(100vw - 24px)', rowGap: '4px' }, textMiniMenuAdditionalMenu: { minWidth: 'clamp(140px, 90%, 250px)', zIndex: '1514', boxShadow: theme.shadows.values.default[2] }, inputWrapper: { padding: theme.methods.space.value(1, 'px'), borderRadius: theme.methods.shape.radius.value(1, 'px'), boxShadow: theme.shadows.values.default[2] }, singleLine: { whiteSpace: 'nowrap', overflow: 'hidden' }, input: { '&.onesy-TextField-root': { flex: '1 1 auto !important' } }, palette: { padding: theme.methods.space.value(1.5, 'px'), borderRadius: theme.methods.shape.radius.value(1, 'px'), boxShadow: theme.shadows.values.default[2] }, paletteItem: { position: 'relative', width: '17px', height: '17px', cursor: 'pointer', borderRadius: theme.methods.shape.radius.value(40, 'px'), boxShadow: theme.shadows.values.default[1], transition: theme.methods.transitions.make('box-shadow'), '&:hover': { boxShadow: theme.shadows.values.default[2] } }, textFieldColor: { '&.onesy-ColorTextField-root': { flex: '1 1 auto' } }, helperText: { display: 'inline-flex', color: theme.palette.text.default.secondary, userSelect: 'none' }, error_color: { color: [theme.palette.light ? theme.palette.color.error[40] : theme.palette.color.error[80], '!important'] }, error_hover_color: { color: [theme.palette.light ? theme.palette.color.error[20] : theme.palette.color.error[90], '!important'] } }), { name: 'onesy-SmartTextField' }); const SmartTextField = props_ => { var _theme$ui, _theme$ui2, _theme$elements, _theme$elements2, _theme$elements3, _theme$elements4, _theme$elements5, _theme$elements6, _theme$elements7, _theme$elements8, _theme$elements9, _theme$elements0, _theme$elements1, _theme$elements10, _theme$elements11, _theme$elements12, _theme$elements13, _theme$elements14, _theme$elements15, _refs$root$current; const theme = (0, _styleReact.useOnesyTheme)(); const l = theme.l; const props = _objectSpread(_objectSpread(_objectSpread({}, theme === null || theme === void 0 || (_theme$ui = theme.ui) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.elements) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.all) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.props) === null || _theme$ui === void 0 ? void 0 : _theme$ui.default), theme === null || theme === void 0 || (_theme$ui2 = theme.ui) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.elements) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.onesySmartTextField) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.props) === null || _theme$ui2 === void 0 ? void 0 : _theme$ui2.default), props_); const Line = (theme === null || theme === void 0 || (_theme$elements = theme.elements) === null || _theme$elements === void 0 ? void 0 : _theme$elements.Line) || _Line.default; const TextField = (theme === null || theme === void 0 || (_theme$elements2 = theme.elements) === null || _theme$elements2 === void 0 ? void 0 : _theme$elements2.TextField) || _TextField.default; const List = (theme === null || theme === void 0 || (_theme$elements3 = theme.elements) === null || _theme$elements3 === void 0 ? void 0 : _theme$elements3.List) || _List.default; const ListItem = (theme === null || theme === void 0 || (_theme$elements4 = theme.elements) === null || _theme$elements4 === void 0 ? void 0 : _theme$elements4.ListItem) || _ListItem.default; const Avatar = (theme === null || theme === void 0 || (_theme$elements5 = theme.elements) === null || _theme$elements5 === void 0 ? void 0 : _theme$elements5.Avatar) || _Avatar.default; const Type = (theme === null || theme === void 0 || (_theme$elements6 = theme.elements) === null || _theme$elements6 === void 0 ? void 0 : _theme$elements6.Type) || _Type.default; const Surface = (theme === null || theme === void 0 || (_theme$elements7 = theme.elements) === null || _theme$elements7 === void 0 ? void 0 : _theme$elements7.Surface) || _Surface.default; const Button = (theme === null || theme === void 0 || (_theme$elements8 = theme.elements) === null || _theme$elements8 === void 0 ? void 0 : _theme$elements8.Button) || _Button.default; const Append = (theme === null || theme === void 0 || (_theme$elements9 = theme.elements) === null || _theme$elements9 === void 0 ? void 0 : _theme$elements9.Append) || _Append.default; const Fade = (theme === null || theme === void 0 || (_theme$elements0 = theme.elements) === null || _theme$elements0 === void 0 ? void 0 : _theme$elements0.Fade) || _Fade.default; const Tooltip = (theme === null || theme === void 0 || (_theme$elements1 = theme.elements) === null || _theme$elements1 === void 0 ? void 0 : _theme$elements1.Tooltip) || _Tooltip.default; const ToggleButton = (theme === null || theme === void 0 || (_theme$elements10 = theme.elements) === null || _theme$elements10 === void 0 ? void 0 : _theme$elements10.ToggleButton) || _ToggleButton.default; const ClickListener = (theme === null || theme === void 0 || (_theme$elements11 = theme.elements) === null || _theme$elements11 === void 0 ? void 0 : _theme$elements11.ClickListener) || _ClickListener.default; const ToggleButtons = (theme === null || theme === void 0 || (_theme$elements12 = theme.elements) === null || _theme$elements12 === void 0 ? void 0 : _theme$elements12.ToggleButtons) || _ToggleButtons.default; const Menu = (theme === null || theme === void 0 || (_theme$elements13 = theme.elements) === null || _theme$elements13 === void 0 ? void 0 : _theme$elements13.Menu) || _Menu.default; const Divider = (theme === null || theme === void 0 || (_theme$elements14 = theme.elements) === null || _theme$elements14 === void 0 ? void 0 : _theme$elements14.Divider) || _Divider.default; const ColorTextField = (theme === null || theme === void 0 || (_theme$elements15 = theme.elements) === null || _theme$elements15 === void 0 ? void 0 : _theme$elements15.ColorTextField) || _ColorTextField.default; const { ref, tonal = true, color = 'default', version = 'text', size = 'regular', valueDefault, value: value_, inputProps, onChange, error: error_, name, placeholder, edit, mention, multiline, onChangeMention, optionsMention: optionsMention_, error, helperText, mentionLabel, onKeyDown: onKeyDown_, pasteText = true, readOnly, additional, miniMenuExtended, HelperTextProps, ColorTextFieldProps, className } = props, other = (0, _objectWithoutProperties2.default)(props, _excluded); const { classes } = useStyle(); const [value, setValue] = _react.default.useState(valueDefault || ''); const [openMenu, setOpenMenu] = _react.default.useState(false); const [offset, setOffset] = _react.default.useState([0, 8]); const [selectionMenu, setSelectionMenu] = _react.default.useState(); const [optionsMention, setOptionsMention] = _react.default.useState([]); const [textSelection, setTextSelection] = _react.default.useState(); const [textSelected, setTextSelected] = _react.default.useState([]); const [open, setOpen] = _react.default.useState({}); const [inputValues, setInputValues] = _react.default.useState({}); const refs = { root: _react.default.useRef(null), input: _react.default.useRef(null), searchElement: _react.default.useRef(null), error: _react.default.useRef(null), search: _react.default.useRef(null), open: _react.default.useRef(null), openMenu: _react.default.useRef(null), selectionMenu: _react.default.useRef(null), caret: _react.default.useRef(null), value: _react.default.useRef(null), version: _react.default.useRef(version), optionsMention: _react.default.useRef(optionsMention), validateMeta: _react.default.useRef({}), range: _react.default.useRef(null), inputValues: _react.default.useRef(null), miniMenu: _react.default.useRef(null), miniMenuElements: { color: _react.default.useRef(null), colorPalette: _react.default.useRef(null), background: _react.default.useRef(null), backgroundPalette: _react.default.useRef(null), linkAdd: _react.default.useRef(null), linkAddInput: _react.default.useRef(null), linkRemove: _react.default.useRef(null) }, elements: { color: _react.default.useRef(null), background: _react.default.useRef(null), linkAdd: _react.default.useRef(null), linkRemove: _react.default.useRef(null), quote: _react.default.useRef(null), image: _react.default.useRef(null), video: _react.default.useRef(null), videoYoutube: _react.default.useRef(null), table: _react.default.useRef(null), drawing: _react.default.useRef(null), drawingSvg: _react.default.useRef(null), drawingSize: _react.default.useRef(null), drawingSelect: _react.default.useRef(null), drawingPalette: _react.default.useRef(null), code: _react.default.useRef(null) }, textSelected: _react.default.useRef(null), textSelection: _react.default.useRef(null), rootDocument: _react.default.useRef(null), rootWindow: _react.default.useRef(null), edit: _react.default.useRef(edit), multiline: _react.default.useRef(multiline), readOnly: _react.default.useRef(readOnly), onChange: _react.default.useRef(onChange), props: _react.default.useRef(props) }; refs.value.current = value; refs.version.current = version; refs.open.current = open; refs.openMenu.current = openMenu; refs.selectionMenu.current = selectionMenu; refs.optionsMention.current = optionsMention; refs.inputValues.current = inputValues; refs.textSelected.current = textSelected; refs.textSelection.current = textSelection; refs.edit.current = edit; refs.multiline.current = multiline; refs.readOnly.current = readOnly; refs.onChange.current = onChange; refs.props.current = props; const rootDocument = (0, _utils.isEnvironment)('browser') && (((_refs$root$current = refs.root.current) === null || _refs$root$current === void 0 ? void 0 : _refs$root$current.ownerDocument) || window.document); const rootWindow = rootDocument && (rootDocument.defaultView || window); refs.rootDocument.current = rootDocument; refs.rootWindow.current = rootWindow; const init = () => { if (version === 'text') { const valueNew = valueDefault || value || ''; if (refs.root.current) { refs.root.current.innerHTML = valueNew; } } }; _react.default.useEffect(() => { // init init(); }, []); _react.default.useEffect(() => { setOptionsMention([...(optionsMention_ || [])]); }, [(0, _utils.hash)(optionsMention_)]); _react.default.useEffect(() => { const valuePrevious = (refs.root.current.innerHTML || '').replaceAll('&nbsp;', ' '); const valueNew_0 = (0, _utils.textToInnerHTML)(value_); if (value_ !== undefined && valuePrevious !== valueNew_0) validate(!value_ ? '' : (0, _utils2.sanitize)(value_)); }, [value_]); // Save selection to revive, use it on execComand _react.default.useEffect(() => { var _selection_$anchorNod; const selection_ = refs.rootWindow.current.getSelection(); if (selection_ && selection_.anchorNode && !((_selection_$anchorNod = selection_.anchorNode) !== null && _selection_$anchorNod !== void 0 && (_selection_$anchorNod = _selection_$anchorNod.className) !== null && _selection_$anchorNod !== void 0 && _selection_$anchorNod.includes('TextField'))) refs.range.current = selection_.getRangeAt(0); }, [open]); const updateInputValues = (property, itemValue) => { setInputValues(values => _objectSpread(_objectSpread({}, values), {}, { [property]: itemValue })); }; const updateOpen = (property_0, itemValue_0) => { setOpen(values_0 => _objectSpread(_objectSpread({}, values_0), {}, { [property_0]: itemValue_0 })); }; const validateElement = element => { if (element !== null && element !== void 0 && element.children) { Array.from(element === null || element === void 0 ? void 0 : element.children).forEach(child => { // Any tag if (child.dataset.onesyVersion === 'mention-user') { // Replace the child if label & textContent don't match if (child.dataset.onesyLabel !== child.innerHTML) { element.replaceChild(window.document.createTextNode(child.textContent), child); refs.validateMeta.current.restore = true; } } if (child !== null && child !== void 0 && child.children) validateElement(child); }); } }; const validate = (valueNew_1 = undefined) => { // Save caret position refs.caret.current = _utils2.caret.save(refs.root.current); // Update the root innerHTML if (valueNew_1 !== undefined) refs.root.current.innerHTML = valueNew_1; refs.validateMeta.current.restore = false; // Find all span onesy-mention children // if they aren't valid, replace them with text node of their textContent validateElement(refs.root.current); if (refs.validateMeta.current.restore) _utils2.caret.restore(refs.root.current, refs.caret.current); return refs.root.current.innerHTML; }; const getAtSearchData = () => { if (refs.root.current) { var _anchorNode, _range$commonAncestor, _anchorNode2; const windowSelection = window.document.getSelection(); if (!(windowSelection && windowSelection.rangeCount > 0)) return; const range = windowSelection === null || windowSelection === void 0 ? void 0 : windowSelection.getRangeAt(0); if (!range) return; // Only allow for text not in span user mention element if (((_anchorNode = windowSelection.anchorNode) === null || _anchorNode === void 0 || (_anchorNode = _anchorNode.parentElement) === null || _anchorNode === void 0 || (_anchorNode = _anchorNode.dataset) === null || _anchorNode === void 0 ? void 0 : _anchorNode.onesyVersion) === 'mention-user') return ''; // Text if (!['text', '#text'].includes(range === null || range === void 0 || (_range$commonAncestor = range.commonAncestorContainer) === null || _range$commonAncestor === void 0 ? void 0 : _range$commonAncestor.nodeName)) return ''; const text = ((_anchorNode2 = windowSelection.anchorNode) === null || _anchorNode2 === void 0 ? void 0 : _anchorNode2.textContent) || ''; const start = text.slice(0, range.endOffset).split('').reverse().join(''); let result = []; for (const valueText of start) { // All characters other than space, numbers if (!!valueText.match(/[^<>\\/\n\r\t]/)) result.unshift(valueText);else break; if (['@'].includes(valueText)) break; } result = result.includes('@') ? result.join('') : ''; // Allow 1 space only if (result && result.match(/\s{2}/g)) return ''; return result; } }; refs.search.current = getAtSearchData(); const onInput = event => { if (refs.root.current) { let valueInput = refs.root.current.innerHTML || ''; if (refs.root.current.textContent === '') { valueInput = ''; refs.root.current.innerHTML = ''; } if (!refs.multiline.current) { const previous = valueInput; valueInput = valueInput.replace(/\r?\n|\r/gm, ''); if (previous !== valueInput) refs.root.current.innerHTML = valueInput; } valueInput = (0, _utils.innerHTMLToText)(valueInput); setValue(valueInput); if ((0, _utils.is)('function', refs.onChange.current)) refs.onChange.current(valueInput, event); } }; _react.default.useEffect(() => { if (mention && refs.search.current !== undefined) onChangeMention === null || onChangeMention === void 0 || onChangeMention(refs.search.current, '@'); }, [mention, refs.search.current]); _react.default.useEffect(() => { const method = () => { if (window.document.activeElement === refs.input.current) onInput(); }; window.document.addEventListener('selectionchange', method); onChangeMention === null || onChangeMention === void 0 || onChangeMention(refs.search.current, '@'); return () => { window.document.removeEventListener('selectionchange', method); }; }, []); const updateSelection = () => { const windowSelection_0 = window.document.getSelection(); if (!(windowSelection_0 && windowSelection_0.rangeCount > 0)) return; const range_0 = windowSelection_0 === null || windowSelection_0 === void 0 ? void 0 : windowSelection_0.getRangeAt(0); if (range_0) setSelectionMenu(range_0 === null || range_0 === void 0 ? void 0 : range_0.getBoundingClientRect()); }; const onOpenSearch = async () => { if (!refs.openMenu.current && !!refs.optionsMention.current.length) { // open setOpenMenu(true); // selection updateSelection(); } }; const onCloseSearch = () => { if (refs.openMenu.current) { setOpenMenu(false); setSelectionMenu(null); } }; const updateOffset = () => { var _refs$searchElement$c; setOffset([-(((_refs$searchElement$c = refs.searchElement.current) === null || _refs$searchElement$c === void 0 ? void 0 : _refs$searchElement$c.clientWidth) || 0), 8]); }; const onFocus = () => { // setFocus(true); }; const onBlur = () => { // setFocus(false); }; const onKeyDown = event_0 => { const windowSelection_1 = window.getSelection(); if (windowSelection_1) { // if (event.key === 'Enter') { // event.preventDefault(); // const anchor = windowSelection.anchorNode as HTMLElement; // const element = anchor.parentElement; // const multiple = anchor.tagName === 'P' && anchor.children.length === 1 && anchor.children[0].tagName === 'BR'; // window.document.execCommand('insertHTML', false, `<p><br /></p>`.repeat(multiple ? 2 : 1)); // const range = new Range(); // const rangeStartElement = ((multiple ? anchor : element) as any)?.nextElementSibling; // if (rangeStartElement) range.setStart(rangeStartElement, 0); // windowSelection.removeAllRanges(); // windowSelection.addRange(range); // } if (event_0.key === 'ArrowRight') { var _caretElement$dataset; // If in user mention span // move out of it with adding new empty space root node after the user mention span // only if caret is at the end of the span, & span is last child of it's parent if (!(windowSelection_1 && windowSelection_1.rangeCount > 0)) return; const range_1 = windowSelection_1.getRangeAt(0); const caretElement = windowSelection_1.anchorNode.parentElement; const caretElementParent = caretElement.parentElement; const caretElementParentChildNodes = Array.from(caretElementParent.childNodes); if ((caretElement === null || caretElement === void 0 || (_caretElement$dataset = caretElement.dataset) === null || _caretElement$dataset === void 0 ? void 0 : _caretElement$dataset.onesyVersion) === 'mention-user' && range_1.endOffset === windowSelection_1.anchorNode.textContent.length && caretElementParentChildNodes[caretElementParentChildNodes.length - 1] === caretElement) { caretElementParent.insertBefore(window.document.createTextNode('\u00A0'), caretElement.nextElementSibling); } } } if (!refs.multiline.current) { if (event_0.key === 'Enter') { event_0.preventDefault(); } } if (!refs.edit.current && (event_0.metaKey && _utils2.keyboardStyleCommands.includes(event_0.key) || event_0.ctrlKey && _utils2.keyboardStyleCommands.includes(event_0.key))) { event_0.preventDefault(); } if ((0, _utils.is)('function', onKeyDown_)) onKeyDown_(event_0); }; const onPaste = event_1 => { // event.preventDefault(); // const text = event.clipboardData?.getData('text/plain'); // window.document.execCommand('insertText', false, text); }; const onPasteText = event_2 => { var _event_2$clipboardDat; event_2.preventDefault(); const text_0 = (_event_2$clipboardDat = event_2.clipboardData) === null || _event_2$clipboardDat === void 0 ? void 0 : _event_2$clipboardDat.getData('text/plain'); window.document.execCommand('insertText', false, text_0); }; const onDrop = event_3 => { event_3.preventDefault(); }; const addTag = (item, versionMention = 'user') => { // Save caret position refs.caret.current = _utils2.caret.save(refs.root.current); const itemName = item.name; const classesElement = ['onesy-mention']; // Query text node that equals selection anchorNode // and replace its textContent's search value with new span const windowSelection_2 = window.document.getSelection(); if (!(windowSelection_2 && windowSelection_2.rangeCount > 0)) return; const range_2 = windowSelection_2 === null || windowSelection_2 === void 0 ? void 0 : windowSelection_2.getRangeAt(0); if (!range_2) return; const textNode = windowSelection_2.anchorNode; const textContent = textNode.textContent; // Bug fix // only be able to insert data within the input // if by accident selection went outside the input // basically do nothing with it if (refs.root.current.contains(textNode.parentElement)) { const end = range_2.endOffset; const start_0 = end - refs.search.current.length; const pre = textContent.slice(0, start_0); const post = textContent.slice(end); // Insert before anchorNode pre, item mention, and post if (pre) textNode.parentElement.insertBefore(window.document.createTextNode(pre), windowSelection_2.anchorNode); const span = window.document.createElement('span'); span.className = classesElement.join(' '); span.dataset.onesyLabel = `@${itemName}`; span.dataset.onesyVersion = `mention-${versionMention}`; span.dataset.onesyObject = `${versionMention}`; span.dataset.onesyId = item.id; span.innerHTML = `@${itemName}`; textNode.parentElement.insertBefore(span, windowSelection_2.anchorNode); // 1 space only following the item mention textNode.parentElement.insertBefore(window.document.createTextNode('\u00A0'), windowSelection_2.anchorNode); if (post) textNode.parentElement.insertBefore(window.document.createTextNode(post), windowSelection_2.anchorNode); // Remove the text node textNode.remove(); // Invoke onChange method with new value const valueInput_0 = (0, _utils.innerHTMLToText)(refs.root.current.innerHTML); if ((0, _utils.is)('function', refs.onChange.current)) refs.onChange.current(valueInput_0, { target: refs.root.current }); // Update the caret position to be outside the span mention // for amount of added characters + 1 space const added = `@${itemName}`.length - refs.search.current.length + 1; refs.caret.current.start = refs.caret.current.end += added; _utils2.caret.restore(refs.root.current, refs.caret.current); } // Close the search onCloseSearch(); }; // If users response & not open, open // else if no users response & opened, close the search _react.default.useEffect(() => { if (mention) { if (refs.openMenu.current && !optionsMention.length) onCloseSearch();else if (!refs.openMenu.current && refs.search.current && !!optionsMention.length) onOpenSearch(); } }, [mention, optionsMention]); _react.default.useEffect(() => { if (mention) { // Validate validate(); // Update // open, selection & offset setTimeout(() => { refs.search.current ? onOpenSearch() : onCloseSearch(); if (refs.openMenu.current) updateSelection(); updateOffset(); }); } }, [mention, value]); _react.default.useEffect(() => { // setError(error_); }, [error_]); const label = () => (0, _utils.is)('function', mentionLabel) ? mentionLabel(optionsMention, { addTag }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { className: classes.menu, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(List, { size: "small", className: classes.list, children: optionsMention === null || optionsMention === void 0 ? void 0 : optionsMention.map((item_0, index) => { var _item_0$name; return /*#__PURE__*/(0, _jsxRuntime.jsx)(ListItem, { start: /*#__PURE__*/(0, _jsxRuntime.jsx)(Avatar, { color: (0, _utils.stringToColor)(item_0.name), size: "small", children: (_item_0$name = item_0.name) === null || _item_0$name === void 0 ? void 0 : _item_0$name.slice(0, 1) }), primary: /*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "l3", children: item_0.name }), onClick: () => addTag(item_0), button: true }, index); }) }) }); const paste = async () => { const valueClipboard = await navigator.clipboard.read(); if (valueClipboard) { let values_1 = ''; for (const item_1 of Array.from(valueClipboard)) { const valueItem = await item_1.getType('text/html'); values_1 += await valueItem.text(); } rootDocument.execCommand('insertHTML', undefined, values_1); } }; const query = command => { return (0, _utils.parse)(refs.rootDocument.current.queryCommandValue(command)); }; const textQueryUpdate = () => { const selected = []; const updateOptionValues = [{ name: 'italic', command: 'italic' }, { name: 'underline', command: 'underline' }, { name: 'bold', command: 'bold' }, { name: 'strike-line', command: 'strikeThrough' }]; updateOptionValues.forEach(item_2 => { if (query(item_2.command)) selected.push(item_2.name); }); setTextSelected(selected); }; const onMouseUp = () => { if (!refs.edit.current) return; const selection__0 = refs.rootWindow.current.getSelection(); if (!selection__0) return; if (!selection__0.anchorNode || !refs.root.current.contains(selection__0.anchorNode)) return setTextSelection(null); setTimeout(() => { var _selection__0$anchorN; const rect = selection__0.getRangeAt(0).getBoundingClientRect(); setTextSelection(Math.round(rect.width) ? { selection: rect, element: (_selection__0$anchorN = selection__0.anchorNode) === null || _selection__0$anchorN === void 0 ? void 0 : _selection__0$anchorN.parentElement } : null); textQueryUpdate(); }, 140); }; const onMouseDown = () => { if (!refs.edit.current) return; textQueryUpdate(); }; const onKeyUp = () => { if (!refs.edit.current) return; textQueryUpdate(); }; const textMethod = command_0 => argument => { var _refs$textSelection$c; switch (command_0) { // updates case 'italic': refs.rootDocument.current.execCommand('italic'); if (query('italic')) setTextSelected(values_24 => [...values_24, 'italic']);else setTextSelected(values_25 => values_25.filter(item_20 => item_20 !== 'italic')); break; case 'underline': refs.rootDocument.current.execCommand('underline'); if (query('underline')) setTextSelected(values_22 => [...values_22, 'underline']);else setTextSelected(values_23 => values_23.filter(item_19 => item_19 !== 'underline')); break; case 'bold': refs.rootDocument.current.execCommand('bold'); if (query('bold')) setTextSelected(values_20 => [...values_20, 'bold']);else setTextSelected(values_21 => values_21.filter(item_18 => item_18 !== 'bold')); break; case 'strike-line': refs.rootDocument.current.execCommand('strikeThrough'); if (query('strikeThrough')) setTextSelected(values_18 => [...values_18, 'strike-line']);else setTextSelected(values_19 => values_19.filter(item_17 => item_17 !== 'strike-line')); break; case 'align-left': refs.rootDocument.current.execCommand('justifyLeft'); if (query('justifyLeft')) setTextSelected(values_16 => [...values_16.filter(item_15 => !item_15.includes('align')), 'align-left']);else setTextSelected(values_17 => values_17.filter(item_16 => item_16 !== 'align-left')); break; case 'align-center': refs.rootDocument.current.execCommand('justifyCenter'); if (query('justifyCenter')) setTextSelected(values_14 => [...values_14.filter(item_13 => !item_13.includes('align')), 'align-center']);else setTextSelected(values_15 => values_15.filter(item_14 => item_14 !== 'align-center')); break; case 'align-right': refs.rootDocument.current.execCommand('justifyRight'); if (query('justifyRight')) setTextSelected(values_12 => [...values_12.filter(item_11 => !item_11.includes('align')), 'align-right']);else setTextSelected(values_13 => values_13.filter(item_12 => item_12 !== 'align-right')); break; case 'align-justify': refs.rootDocument.current.execCommand('justifyFull'); if (query('justifyFull')) setTextSelected(values_10 => [...values_10.filter(item_9 => !item_9.includes('align')), 'align-justify']);else setTextSelected(values_11 => values_11.filter(item_10 => item_10 !== 'align-justify')); break; case 'superscript': refs.rootDocument.current.execCommand('superscript'); if (query('superscript')) setTextSelected(values_8 => [...values_8, 'superscript']);else setTextSelected(values_9 => values_9.filter(item_8 => item_8 !== 'superscript')); break; case 'subscript': refs.rootDocument.current.execCommand('subscript'); if (query('subscript')) setTextSelected(values_6 => [...values_6, 'subscript']);else setTextSelected(values_7 => values_7.filter(item_7 => item_7 !== 'subscript')); break; case 'indent': refs.rootDocument.current.execCommand('indent'); break; case 'outdent': refs.rootDocument.current.execCommand('outdent'); break; case 'font-version': refs.rootDocument.current.execCommand('formatBlock', undefined, argument); break; case 'font-family': refs.rootDocument.current.execCommand('styleWithCSS', true); refs.rootDocument.current.execCommand('fontName', undefined, argument); refs.rootDocument.current.execCommand('styleWithCSS', false); break; case 'font-size': refs.rootDocument.current.execCommand('styleWithCSS', true); refs.rootDocument.current.execCommand('fontSize', undefined, argument); refs.rootDocument.current.execCommand('styleWithCSS', false); break; case 'font-color': refs.rootDocument.current.execCommand('styleWithCSS', true); refs.rootDocument.current.execCommand('foreColor', undefined, argument); refs.rootDocument.current.execCommand('styleWithCSS', false); break; case 'font-background': refs.rootDocument.current.execCommand('styleWithCSS', true); refs.rootDocument.current.execCommand('backColor', undefined, argument); refs.rootDocument.current.execCommand('styleWithCSS', false); break; case 'list-ordered': refs.rootDocument.current.execCommand('insertOrderedList'); if (query('insertOrderedList')) setTextSelected(values_4 => [...values_4.filter(item_5 => !item_5.includes('list')), 'list-ordered']);else setTextSelected(values_5 => values_5.filter(item_6 => item_6 !== 'list-ordered')); break; case 'list-unordered': refs.rootDocument.current.execCommand('insertUnorderedList'); if (query('insertUnorderedList')) setTextSelected(values_2 => [...values_2.filter(item_3 => !item_3.includes('list')), 'list-unordered']);else setTextSelected(values_3 => values_3.filter(item_4 => item_4 !== 'list-unordered')); break; case 'horizontal-rule': refs.rootDocument.current.execCommand('insertHorizontalRule'); break; case 'link-add': refs.rootDocument.current.execCommand('createLink', undefined, argument); break; case 'link-remove': refs.rootDocument.current.execCommand('unlink'); break; case 'image': refs.rootDocument.current.execCommand('insertImage', undefined, argument); break; case 'html': refs.rootDocument.current.execCommand('insertHTML', undefined, argument); break; // actions case 'copy': refs.rootDocument.current.execCommand('copy'); break; case 'cut': refs.rootDocument.current.execCommand('cut'); break; case 'paste': if (refs.rootDocument.current.queryCommandSupported('paste')) refs.rootDocument.current.execCommand('paste');else paste(); break; case 'delete': refs.rootDocument.current.execCommand('delete'); break; case 'clear': refs.rootDocument.current.execCommand('removeFormat'); break; case 'select-all': refs.rootDocument.current.execCommand('selectAll'); break; case 'undo': refs.rootDocument.current.execCommand('undo'); break; case 'redo': refs.rootDocument.current.execCommand('redo'); break; default: break; } const element_0 = (_refs$textSelection$c = refs.textSelection.current) === null || _refs$textSelection$c === void 0 ? void 0 : _refs$textSelection$c.element; if (element_0) { let valueElement = element_0.innerHTML || ''; if (element_0.textContent === '') { valueElement = ''; element_0.innerHTML = ''; } if (valueElement) valueElement = (0, _utils.innerHTMLToText)(valueElement); } textQueryUpdate(); }; const PaletteItem = propsItem => { const { color: color_ } = propsItem, other_ = (0, _objectWithoutProperties2.default)(propsItem, _excluded2); return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", _objectSpread({ className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('RichTextEditor', theme) && ['onesy-RichTextEditor-palette-item'], classes.paletteItem]), style: { background: color_ } }, other_)); }; const Palette = propsPalette => { const { ref: ref_, version: version_, onUpdate: onUpdate_, onClose } = propsPalette, other__0 = (0, _objectWithoutProperties2.default)(propsPalette, _excluded3); const onUpdateColor = itemColor => { if (refs.range.current) { const selection__1 = refs.rootWindow.current.getSelection(); selection__1.removeAllRanges(); selection__1.addRange(refs.range.current); } onUpdate_(itemColor); onClose(); }; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, _objectSpread(_objectSpread({ ref: ref_, gap: 1, direction: "column", tonal: tonal, color: refs.props.current.color !== undefined ? refs.props.current.color : 'themed', Component: Surface, className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('RichTextEditor', theme) && ['onesy-RichTextEditor-palette'], classes.palette]) }, other__0), {}, { children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0.5, style: { maxHeight: 136, padding: '10px 10px 0', overflow: 'hidden auto' }, children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0.5, direction: "row", style: { width: '100%' }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(PaletteItem, { color: "#000000", onClick: () => { onUpdateColor('#000000'); } }), /*#__PURE__*/(0, _jsxRuntime.jsx)(PaletteItem, { color: "#ffffff", onClick: () => { onUpdateColor('#ffffff'); } })] }), Object.keys(_styleReact.colors).filter(item_21 => !['black', 'white'].includes(item_21)).map((item_22, index_0) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { gap: 0.5, direction: "row", style: { width: '100%' }, children: Object.keys(_styleReact.colors[item_22]).map((item_, index_) => /*#__PURE__*/(0, _jsxRuntime.jsx)(PaletteItem, { color: _styleReact.colors[item_22][item_], onClick: () => { onUpdateColor(_styleReact.colors[item_22][item_]); } }, index_)) }, index_0))] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0.5, direction: "row", align: "center", fullWidth: true, style: { padding: '0px 10px 10px' }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(ColorTextField, _objectSpread(_objectSpread({ tonal: tonal, color: color, name: l('Custom color'), version: "outlined", size: "small", value: refs.inputValues.current[version_], onChange: valueNew_2 => updateInputValues(version_, valueNew_2) }, ColorTextFieldProps), {}, { className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('RichTextEditor', theme) && ['onesy-RichTextEditor-text-field-color'], ColorTextFieldProps === null || ColorTextFieldProps === void 0 ? void 0 : ColorTextFieldProps.className, classes.textFieldColor]) })), /*#__PURE__*/(0, _jsxRuntime.jsx)(Button, { tonal: tonal, color: "inherit", version: "text", size: "small", onClick: () => { if (refs.range.current) { const selection__2 = refs.rootWindow.current.getSelection(); selection__2.removeAllRanges(); selection__2.addRange(refs.range.current); } onUpdate_(refs.inputValues.current[version_]); onClose(); }, children: "Apply" })] })] })); }; const AppendProps = { padding: [14, 14] }; const IconProps = { size: 'small' }; const TooltipProps = { position: 'bottom', interactive: false }; const ToggleButtonsProps = { tonal: false, color: 'default', version: 'text', border: false }; const ToggleButtonProps = { size: 'small' }; const Input = propsInput => { const { ref: ref__0, label: labelInput, labelButton, value: value__, onChange: onChange__, onClick, placeholder: placeholderInputProps, InputComponent = TextField, InputProps } = propsInput, other__1 = (0, _objectWithoutProperties2.default)(propsInput, _excluded4); return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, _objectSpread(_objectSpread({ ref: ref__0, gap: 1, direction: "column", color: "themed", Component: Surface }, other__1), {}, { className: (0, _styleReact.classNames)([other__1 === null || other__1 === void 0 ? void 0 : other__1.className, classes.inputWrapper]), children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0.5, direction: "row", align: "center", style: { width: '100%' }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(InputComponent, _objectSpread(_objectSpread({ name: labelInput, version: "outlined", size: "small", valueDefault: value__, onChange: onChange__, placeholder: placeholderInputProps, flex: true }, InputProps), {}, { style: { width: 'unset', flex: '1 1 auto' } })), /*#__PURE__*/(0, _jsxRuntime.jsx)(Button, { color: "inherit", version: "text", size: "small", onClick: onClick, children: labelButton })] }) })); }; const WrapperAppend = propsWrapper => { const { open: open_, element: element_1, anchorElement, onClose: onClose_0, children: childrenWrapperAppend } = propsWrapper, other__2 = (0, _objectWithoutProperties2.default)(propsWrapper, _excluded5); return /*#__PURE__*/(0, _jsxRuntime.jsx)(Append, _objectSpread(_objectSpread({ open: open_, element: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('SmartTextField', theme) && ['onesy-SmartTextField-mini-menu-additional'], classes.textMiniMenuAdditionalMenu]), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Fade, { in: open_, add: true, children: /*#__PURE__*/_react.default.cloneElement(element_1) }) }), anchorElement: anchorElement, portal: true, alignment: "center", position: "bottom" }, AppendProps), {}, { children: /*#__PURE__*/_react.default.cloneElement(childrenWrapperAppend, _objectSpread(_objectSpread({}, other__2), childrenWrapperAppend.props)) })); }; const WrapperToggleButton = propsWrapperToggleButton => { const { ref: ref__1, open: open__0, name: nameWrapperToogleButton, children: childrenWrapperToggleButton } = propsWrapperToggleButton, other__3 = (0, _objectWithoutProperties2.default)(propsWrapperToggleButton, _excluded6); return /*#__PURE__*/(0, _jsxRuntime.jsx)(Tooltip, _objectSpread(_objectSpread({ ref: ref__1, open: open__0 !== undefined ? open__0 : undefined, name: nameWrapperToogleButton }, TooltipProps), {}, { children: /*#__PURE__*/_react.default.cloneElement(childrenWrapperToggleButton, _objectSpread(_objectSpread({}, other__3), childrenWrapperToggleButton.props)) })); }; const updateElements = { 'italic': /*#__PURE__*/(0, _jsxRuntime.jsx)(WrapperToggleButton, { name: l('Italic'), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ToggleButton, _objectSpread(_objectSpread({}, ToggleButtonProps), {}, { selected: refs.textSelected.current.includes('italic'), onClick: textMethod('italic'), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconMaterialFormatItalicW.default, _objectSpread({}, IconProps)) })) }), 'underline': /*#__PURE__*/(0, _jsxRuntime.jsx)(WrapperToggleButton, { name: l('Underline'), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ToggleButton, _objectSpread(_objectSpread({}, ToggleButtonProps), {}, { selected: refs.textSelected.current.includes('underline'), onClick: textMethod('underline'), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconMaterialFormatUnderlinedW.default, _objectSpread({}, IconProps)) })) }), 'bold': /*#__PURE__*/(0, _jsxRuntime.jsx)(WrapperToggleButton, { name: l('Bold'),