wix-style-react
Version:
wix-style-react
335 lines (332 loc) • 12.2 kB
JavaScript
"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