wix-style-react
Version:
368 lines (300 loc) • 12.8 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: 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");
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;
return insertContent(editorState, 1, function (contentState, selectionState) {
contentState = contentState.createEntity(_constants.entityTypes.variable, 'IMMUTABLE', {
value: value,
text: text
});
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$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;
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
}
};
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) {
contentBlock.findEntityRanges(function (character) {
var entityKey = character.getEntity();
return entityKey === null;
}, callback);
},
component: function component(_ref5) {
var offsetKey = _ref5.offsetKey,
children = _ref5.children;
return /*#__PURE__*/_react["default"].createElement("span", {
"data-offset-key": offsetKey,
className: _VariableInputSt.classes.textWrapper
}, children);
}
}, {
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;
/** 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
}, /*#__PURE__*/_react["default"].createElement("span", {
className: _VariableInputSt.classes.textWrapper
}, " "), /*#__PURE__*/_react["default"].createElement(_Tag["default"], (0, _extends2["default"])({
id: "variableinput-tag-".concat(entityKey),
dataHook: _constants.dataHooks.tag,
removable: false,
size: size,
disabled: disabled
}, !disabled && {
theme: 'dark'
}), text), /*#__PURE__*/_react["default"].createElement("span", {
className: _VariableInputSt.classes.textWrapper
}), ' ');
}
}]);
};
/** When pushing content to EditorState selection is resets, we keep the selection and reset it after push */
var pushAndKeepSelection = function pushAndKeepSelection(_ref6) {
var editorState = _ref6.editorState,
content = _ref6.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 _default = {
insertText: insertText,
insertEntity: insertEntity,
getMatchesInString: getMatchesInString,
convertToString: convertToString,
stringToContentState: stringToContentState,
decoratorFactory: decoratorFactory,
pushAndKeepSelection: pushAndKeepSelection,
hasUnparsedEntity: hasUnparsedEntity,
moveToEdge: moveToEdge,
isContentChanged: isContentChanged,
isBlured: isBlured
};
exports["default"] = _default;