UNPKG

wix-style-react

Version:
335 lines (332 loc) • 12.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _react = _interopRequireDefault(require("react")); var _draftJs = require("draft-js"); var _Tag = _interopRequireDefault(require("../Tag")); var _constants = require("./constants"); var _VariableInputSt = require("./VariableInput.st.css"); var _index = require("../index"); var _jsxFileName = "/home/builduser/work/a9c1ac8876d5057c/packages/wix-style-react/dist/cjs/VariableInput/EditorUtilities.js"; var insertContent = (editorState, selectionOffset, modifyFn) => { var contentState = editorState.getCurrentContent(); var selectionState = editorState.getSelection(); if (!selectionState.isCollapsed()) { // Remove selection range when adding content contentState = _draftJs.Modifier.removeRange(contentState, selectionState, 'backward'); selectionState = contentState.getSelectionAfter(); } var newContent = modifyFn(contentState, selectionState); var newEditorState = _draftJs.EditorState.push(editorState, newContent, 'insert-characters'); var newSelection = newEditorState.getSelection(); return _moveSelectionTo(newEditorState, newSelection.getAnchorKey(), newSelection.getAnchorOffset() + selectionOffset); }; /** Insert text in current cursor position */ var insertText = (editorState, text) => insertContent(editorState, 0, (contentState, selectionState) => _draftJs.Modifier.insertText(contentState, selectionState, text)); /** Insert new entity in current cursor position, with the given text and value */ var insertEntity = (editorState, _ref) => { var { text, value, tagProps } = _ref; return insertContent(editorState, 1, (contentState, selectionState) => { contentState = contentState.createEntity(_constants.entityTypes.variable, 'IMMUTABLE', { value, text, tagProps }); var entityKey = contentState.getLastCreatedEntityKey(); contentState = _draftJs.Modifier.insertText(contentState, selectionState, ' '); // space after entity contentState = _draftJs.Modifier.insertText(contentState, selectionState, " ".concat(text, " "), null, entityKey); return contentState; }); }; var _escapeRegExp = text => text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); /** Get variable with given prefix and suffix in the given string */ var getMatchesInString = (str, prefix, suffix) => { var escPrefixFirstChar = _escapeRegExp(prefix[0]); var escPrefix = _escapeRegExp(prefix); var escSuffix = _escapeRegExp(suffix); var pattern = "(?:".concat(escPrefixFirstChar, ")*(").concat(escPrefix, "(.*?)").concat(escSuffix, ")"); var regex = new RegExp(pattern, 'g'); var part; var parts = []; while ((part = regex.exec(str)) !== null) { parts.push(part); } return parts; }; /** Check if editor has unparsed entities */ var hasUnparsedEntity = (editorState, prefix, suffix) => { return getMatchesInString(editorState.getCurrentContent().getPlainText(), prefix, suffix).length > 0; }; /** Convert editor content state, to string with placeholders instead of entities */ var convertToString = _ref2 => { var { editorState, prefix, suffix } = _ref2; var rawJS = (0, _draftJs.convertToRaw)(editorState.getCurrentContent()); var rawString = rawJS.blocks.map(block => { var baseString = Array.from(block.text); var indexOffset = 0; block.entityRanges.forEach(entityRange => { var entity = rawJS.entityMap[entityRange.key.toString()]; if (entity.type !== _constants.entityTypes.variable) { return baseString; } var entityData = entity.data; var placeholder = prefix + entityData.value + suffix; baseString.splice(entityRange.offset + indexOffset, entityRange.length, placeholder); indexOffset += 1 - entityRange.length; }); return baseString.join(''); }).join('\n'); return rawString; }; /** Convert string to editor content state */ var stringToContentState = _ref3 => { var { str = '', variableParser = () => {}, variableTagPropsParser = () => {}, prefix = '', suffix = '' } = _ref3; var entityIndex = 0; var entityMap = []; var blocks = str.split('\n').map(row => { var rowStr = row; var indexOffset = 0; var entityRanges = []; getMatchesInString(row, prefix, suffix).forEach(match => { var [wholeMatch, placeholder, value] = match; var matchIndex = match.index + wholeMatch.indexOf(placeholder); var text = variableParser(value) || false; var tagProps = variableTagPropsParser(value); if (text) { var utfOffset = getUtfOffsetValue(row.substr(0, matchIndex)); var contentPlaceholder = " ".concat(text, " "); var offset = matchIndex + indexOffset - utfOffset; rowStr = rowStr.replace(placeholder, contentPlaceholder); entityRanges.push({ offset, length: contentPlaceholder.length, key: entityIndex }); entityMap[entityIndex.toString()] = { type: _constants.entityTypes.variable, mutability: 'IMMUTABLE', data: { value, text, tagProps } }; entityIndex++; indexOffset += contentPlaceholder.length - placeholder.length; } }); return { key: (0, _draftJs.genKey)(), text: rowStr, type: 'unstyled', depth: 0, inlineStyleRanges: [], entityRanges, data: {} }; }); return (0, _draftJs.convertFromRaw)({ blocks, entityMap }); }; var decoratorFactory = _ref4 => { var { tag: { size, disabled } } = _ref4; return new _draftJs.CompositeDecorator([{ strategy: (contentBlock, callback) => { contentBlock.findEntityRanges(character => { var entityKey = character.getEntity(); return entityKey === null; }, callback); }, component: _ref5 => { var { offsetKey, children } = _ref5; return /*#__PURE__*/_react.default.createElement("span", { "data-offset-key": offsetKey, className: _VariableInputSt.classes.textWrapper, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 195, columnNumber: 11 } }, children); } }, { strategy: (contentBlock, callback, contentState) => { contentBlock.findEntityRanges(character => { var entityKey = character.getEntity(); return entityKey !== null && contentState.getEntity(entityKey).getType() === _constants.entityTypes.variable; }, callback); }, component: props => { var { offsetKey, contentState, entityKey } = props; var { text, tagProps } = contentState.getEntity(entityKey).getData(); /** We adding a space before and after the Tag, * to prevent from the cursor to enter the Tag while moving it. */ return /*#__PURE__*/_react.default.createElement("span", { "data-offset-key": offsetKey, contentEditable: false, className: _VariableInputSt.classes.tagWrapper, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 217, columnNumber: 11 } }, /*#__PURE__*/_react.default.createElement("span", { className: _VariableInputSt.classes.textWrapper, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 222, columnNumber: 13 } }, " "), /*#__PURE__*/_react.default.createElement(_Tag.default, (0, _extends2.default)({ id: "variableinput-tag-".concat(entityKey), dataHook: _constants.dataHooks.tag, removable: false }, !disabled && { theme: 'dark' }, tagProps, { size: size, disabled: disabled, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 223, columnNumber: 13 } }), text), /*#__PURE__*/_react.default.createElement("span", { className: _VariableInputSt.classes.textWrapper, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 234, columnNumber: 13 } }), ' '); } }]); }; /** When pushing content to EditorState selection is resets, we keep the selection and reset it after push */ var pushAndKeepSelection = _ref6 => { var { editorState, content } = _ref6; var selectionStateBefore = editorState.getSelection(); var blockIndex = Object.keys(editorState.getCurrentContent().getBlockMap().toJS()).indexOf(selectionStateBefore.getAnchorKey()); var updatedEditorState = _draftJs.EditorState.push(editorState, content); var blockMap = updatedEditorState.getCurrentContent().getBlockMap().toJS(); var blockKeys = Object.keys(blockMap); var blockKey = blockKeys[blockIndex]; var blockOffset = selectionStateBefore.getAnchorOffset(); if (!blockKey || blockOffset > blockMap[blockKey].text.length) { // Block not exists in new array, getting the last block and move to end return _draftJs.EditorState.moveSelectionToEnd(updatedEditorState); } // Keep selection in the same location after updating content, keys are updating var selectionAfter = updatedEditorState.getSelection().merge({ anchorKey: blockKey, anchorOffset: blockOffset, focusKey: blockKey, focusOffset: blockOffset, hasFocus: false }); return _draftJs.EditorState.acceptSelection(updatedEditorState, selectionAfter); }; /** Move selection to edge of entity */ var moveToEdge = function moveToEdge(editorState) { var forceEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var selectionOffset = editorState.getSelection().getFocusOffset(); var key = editorState.getSelection().getFocusKey(); var jumpToIndex = _findEntityEdgeIndex(editorState.getCurrentContent(), key, selectionOffset, forceEnd); if (jumpToIndex !== selectionOffset) { return _moveSelectionTo(editorState, key, jumpToIndex); } return editorState; }; var _moveSelectionTo = (editorState, key, offset) => { var selection = new _draftJs.SelectionState({ anchorKey: key, anchorOffset: offset, focusKey: key, focusOffset: offset }); return _draftJs.EditorState.forceSelection(editorState, selection); }; var _findEntityEdgeIndex = (currentContent, selectionKey, startIndex, forceEnd) => { var characterList = currentContent.getBlockForKey(selectionKey).getCharacterList().toJS(); var entityKey = characterList[startIndex] && characterList[startIndex].entity; if (!entityKey) { return startIndex; } var beforeOffset = startIndex; for (; beforeOffset >= 0; beforeOffset--) { if (characterList[beforeOffset].entity !== entityKey) { beforeOffset++; break; } } beforeOffset = Math.max(beforeOffset, 0); var afterOffset = characterList.findIndex((value, index) => index >= startIndex && value.entity !== entityKey); if (afterOffset === -1) { afterOffset = characterList.length; } if (!forceEnd && beforeOffset === startIndex) { // In case we clicked just at the beginning return beforeOffset; } return afterOffset; }; /** Returns true if content has changed */ var isContentChanged = (editorStateBefore, editorStateAfter) => editorStateBefore.getCurrentContent().getPlainText() !== editorStateAfter.getCurrentContent().getPlainText(); /** Returns true if state lost focus */ var isBlured = (editorStateBefore, editorStateAfter) => editorStateBefore.getSelection().getHasFocus() && !editorStateAfter.getSelection().getHasFocus(); var getUtfOffsetValue = aString => aString.split('').length - Array.from(aString).length; var _default = exports.default = { insertText, insertEntity, getMatchesInString, convertToString, stringToContentState, decoratorFactory, pushAndKeepSelection, hasUnparsedEntity, moveToEdge, isContentChanged, isBlured }; //# sourceMappingURL=EditorUtilities.js.map