UNPKG

@wix/design-system

Version:

@wix/design-system

368 lines (365 loc) 16.1 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 _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); 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.js"); var _index = require("../index"); var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/cjs/VariableInput/EditorUtilities.jsx", _this = void 0; function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } var insertContent = function 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 = function insertText(editorState, text) { return insertContent(editorState, 0, function (contentState, selectionState) { return _draftJs.Modifier.insertText(contentState, selectionState, text); }); }; /** Insert new entity in current cursor position, with the given text and value */ var insertEntity = function insertEntity(editorState, _ref) { var text = _ref.text, value = _ref.value, tagProps = _ref.tagProps; return insertContent(editorState, 1, function (contentState, selectionState) { contentState = contentState.createEntity(_constants.entityTypes.variable, 'IMMUTABLE', { value: value, text: text, tagProps: 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 = function _escapeRegExp(text) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); }; /** Get variable with given prefix and suffix in the given string */ var getMatchesInString = function 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 = function 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 = function convertToString(_ref2) { var editorState = _ref2.editorState, prefix = _ref2.prefix, suffix = _ref2.suffix; var rawJS = (0, _draftJs.convertToRaw)(editorState.getCurrentContent()); var rawString = rawJS.blocks.map(function (block) { var baseString = Array.from(block.text); var indexOffset = 0; block.entityRanges.forEach(function (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 = function stringToContentState(_ref3) { var _ref3$str = _ref3.str, str = _ref3$str === void 0 ? '' : _ref3$str, _ref3$variableParser = _ref3.variableParser, variableParser = _ref3$variableParser === void 0 ? function () {} : _ref3$variableParser, _ref3$variableTagProp = _ref3.variableTagPropsParser, variableTagPropsParser = _ref3$variableTagProp === void 0 ? function () {} : _ref3$variableTagProp, _ref3$prefix = _ref3.prefix, prefix = _ref3$prefix === void 0 ? '' : _ref3$prefix, _ref3$suffix = _ref3.suffix, suffix = _ref3$suffix === void 0 ? '' : _ref3$suffix; var entityIndex = 0; var entityMap = []; var blocks = str.split('\n').map(function (row) { var rowStr = row; var indexOffset = 0; var entityRanges = []; getMatchesInString(row, prefix, suffix).forEach(function (match) { var _match = (0, _slicedToArray2["default"])(match, 3), wholeMatch = _match[0], placeholder = _match[1], value = _match[2]; 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: offset, length: contentPlaceholder.length, key: entityIndex }); entityMap[entityIndex.toString()] = { type: _constants.entityTypes.variable, mutability: 'IMMUTABLE', data: { value: value, text: text, tagProps: tagProps } }; entityIndex++; indexOffset += contentPlaceholder.length - placeholder.length; } }); return { key: (0, _draftJs.genKey)(), text: rowStr, type: 'unstyled', depth: 0, inlineStyleRanges: [], entityRanges: entityRanges, data: {} }; }); return (0, _draftJs.convertFromRaw)({ blocks: blocks, entityMap: entityMap }); }; var decoratorFactory = function decoratorFactory(_ref4) { var _ref4$tag = _ref4.tag, size = _ref4$tag.size, disabled = _ref4$tag.disabled; return new _draftJs.CompositeDecorator([{ strategy: function strategy(contentBlock, callback, contentState) { contentBlock.findEntityRanges(function (character) { var entityKey = character.getEntity(); return entityKey !== null && contentState.getEntity(entityKey).getType() === _constants.entityTypes.variable; }, callback); }, component: function component(props) { var offsetKey = props.offsetKey, contentState = props.contentState, entityKey = props.entityKey; var _contentState$getEnti = contentState.getEntity(entityKey).getData(), text = _contentState$getEnti.text, tagProps = _contentState$getEnti.tagProps; /** 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: _this, __source: { fileName: _jsxFileName, lineNumber: 203, columnNumber: 11 } }, /*#__PURE__*/_react["default"].createElement("span", { className: _VariableInputSt.classes.textWrapper, __self: _this, __source: { fileName: _jsxFileName, lineNumber: 208, 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, className: _VariableInputSt.classes.tag, __self: _this, __source: { fileName: _jsxFileName, lineNumber: 209, columnNumber: 13 } }), text), /*#__PURE__*/_react["default"].createElement("span", { className: _VariableInputSt.classes.textWrapper, __self: _this, __source: { fileName: _jsxFileName, lineNumber: 221, columnNumber: 13 } }), ' '); } }]); }; /** When pushing content to EditorState selection is resets, we keep the selection and reset it after push */ var pushAndKeepSelection = function pushAndKeepSelection(_ref5) { var editorState = _ref5.editorState, content = _ref5.content; 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 = function _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 = function _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(function (value, index) { return 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 = function isContentChanged(editorStateBefore, editorStateAfter) { return editorStateBefore.getCurrentContent().getPlainText() !== editorStateAfter.getCurrentContent().getPlainText(); }; /** Returns true if state lost focus */ var isBlured = function isBlured(editorStateBefore, editorStateAfter) { return editorStateBefore.getSelection().getHasFocus() && !editorStateAfter.getSelection().getHasFocus(); }; var getUtfOffsetValue = function getUtfOffsetValue(aString) { return aString.split('').length - Array.from(aString).length; }; var findEntityRangeByKey = function findEntityRangeByKey(editorState, variableKey) { var contentState = editorState.getCurrentContent(); var rawContent = (0, _draftJs.convertToRaw)(contentState); var entityMap = rawContent.entityMap, blocks = rawContent.blocks; var targetEntityKey = Object.keys(entityMap).find(function (key) { var entity = entityMap[key]; return entity.type === _constants.entityTypes.variable && entity.data.value === variableKey; }); if (targetEntityKey) { var _iterator = _createForOfIteratorHelper(blocks), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var block = _step.value; var _iterator2 = _createForOfIteratorHelper(block.entityRanges), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var range = _step2.value; if (range.key.toString() === targetEntityKey) { return { blockKey: block.key, start: range.offset, end: range.offset + range.length }; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } return null; }; var _default = exports["default"] = { insertText: insertText, insertEntity: insertEntity, getMatchesInString: getMatchesInString, convertToString: convertToString, stringToContentState: stringToContentState, decoratorFactory: decoratorFactory, pushAndKeepSelection: pushAndKeepSelection, hasUnparsedEntity: hasUnparsedEntity, moveToEdge: moveToEdge, isContentChanged: isContentChanged, isBlured: isBlured, findEntityRangeByKey: findEntityRangeByKey };