wix-style-react
Version:
wix-style-react
345 lines (344 loc) • 12 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 _propTypes = _interopRequireDefault(require("prop-types"));
var _draftJs = require("draft-js");
var _EditorUtilities = _interopRequireDefault(require("./EditorUtilities"));
var _constants = require("./constants");
var _VariableInputSt = require("./VariableInput.st.css");
var _StatusIndicator = _interopRequireDefault(require("../StatusIndicator"));
var _StatusContext = require("../FormField/StatusContext");
var _context = require("../WixStyleReactProvider/context");
var _jsxFileName = "/home/builduser/work/a9c1ac8876d5057c/packages/wix-style-react/dist/cjs/VariableInput/VariableInput.js";
/** Input with variables as tags */
class VariableInput extends _react.default.PureComponent {
constructor(props) {
var _this;
super(props);
_this = this;
this._handlePastedText = (text, html, editorState) => {
/** We need to prevent new line when `multilne` is false,
* here we are removing any new lines while pasting text */
if (/\r|\n/.exec(text)) {
text = text.replace(/(\r\n|\n|\r)/gm, '');
this._onEditorChange(_EditorUtilities.default.insertText(editorState, text));
return true;
}
return false;
};
this._isEmpty = () => this.state.editorState.getCurrentContent().getPlainText().length === 0;
this._inputToTagSize = inputSize => {
return _constants.inputToTagsSize[inputSize] || VariableInput.defaultProps.size;
};
this._toString = () => {
var {
variableTemplate: {
prefix,
suffix
}
} = this.props;
var {
editorState
} = this.state;
return _EditorUtilities.default.convertToString({
editorState,
prefix,
suffix
});
};
this._onBlur = () => {
var {
onBlur = () => {}
} = this.props;
onBlur(this._toString());
};
this._onFocus = () => {
var {
onFocus = () => {}
} = this.props;
onFocus(this._toString());
};
this._onSubmit = () => {
var {
onSubmit = () => {}
} = this.props;
onSubmit(this._toString());
};
this._onChange = () => {
var {
onChange = () => {}
} = this.props;
onChange(this._toString());
};
this._onEditorChange = editorState => {
this._setEditorState(editorState);
};
this._setEditorState = function (editorState) {
var onStateChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => {};
var {
editorState: editorStateBefore
} = _this.state;
var {
variableTemplate: {
prefix,
suffix
}
} = _this.props;
var updateEditorState = _EditorUtilities.default.moveToEdge(editorState);
var triggerCallback = () => {};
if (_EditorUtilities.default.isBlured(editorStateBefore, updateEditorState)) {
// onChange is called after the editor blur handler
// and we can't reflect the changes there, we moved the logic here.
triggerCallback = _this._onBlur;
if (_EditorUtilities.default.hasUnparsedEntity(updateEditorState, prefix, suffix)) {
updateEditorState = _this._stringToContentState(_EditorUtilities.default.convertToString({
editorState: updateEditorState,
prefix,
suffix
}));
}
} else if (_EditorUtilities.default.isContentChanged(editorStateBefore, updateEditorState)) {
triggerCallback = _this._onChange;
}
_this.setState({
editorState: updateEditorState
}, () => {
triggerCallback();
onStateChanged();
});
};
this._stringToContentState = str => {
var {
variableParser = () => {},
variableTagPropsParser,
variableTemplate: {
prefix,
suffix
}
} = this.props;
var {
editorState
} = this.state;
var content = _EditorUtilities.default.stringToContentState({
str,
variableParser,
variableTagPropsParser,
prefix,
suffix
});
return _EditorUtilities.default.pushAndKeepSelection({
editorState,
content
});
};
this._setStringValue = function (str) {
var afterUpdated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => {};
var updatedEditorState = _draftJs.EditorState.moveSelectionToEnd(_this._stringToContentState(str));
_this._setEditorState(updatedEditorState, () => {
afterUpdated(updatedEditorState);
});
};
/** Set value to display in the input */
this.setValue = value => {
this._setStringValue(value, () => {
this._onSubmit();
});
};
/** Insert variable at the input cursor position */
this.insertVariable = value => {
var {
variableParser,
variableTagPropsParser,
variableTemplate: {
prefix,
suffix
}
} = this.props;
var {
editorState
} = this.state;
var text = variableParser(value);
var tagProps = variableTagPropsParser(value);
var newState = text ? _EditorUtilities.default.insertEntity(editorState, {
text,
value,
tagProps
}) : _EditorUtilities.default.insertText(editorState, "".concat(prefix).concat(value).concat(suffix, " "));
this._setEditorState(newState, () => {
this._onSubmit();
});
};
var {
size,
disabled
} = props;
var decorator = _EditorUtilities.default.decoratorFactory({
tag: {
size: this._inputToTagSize(size),
disabled
}
});
this.state = {
editorState: _draftJs.EditorState.createEmpty(decorator)
};
}
componentDidMount() {
var {
initialValue
} = this.props;
this._setStringValue(initialValue);
this.editorRef = /*#__PURE__*/_react.default.createRef();
}
render() {
var {
dataHook,
multiline,
rows,
size,
disabled,
readOnly,
placeholder,
status,
statusMessage,
className
} = this.props;
var singleLineProps = {
handlePastedText: this._handlePastedText,
handleReturn: () => 'handled'
};
var finalStatus = (0, _StatusContext.getStatusFromContext)(this.context, status);
return /*#__PURE__*/_react.default.createElement(_context.WixStyleReactContext.Consumer, {
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 55,
columnNumber: 7
}
}, _ref => {
var {
newColorsBranding
} = _ref;
return /*#__PURE__*/_react.default.createElement("div", {
"data-hook": dataHook,
className: (0, _VariableInputSt.st)(_VariableInputSt.classes.root, {
disabled,
readOnly,
size,
status: finalStatus,
singleLine: !multiline,
newColorsBranding
}, className),
style: {
[_VariableInputSt.vars.rows]: rows
},
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 57,
columnNumber: 11
}
}, /*#__PURE__*/_react.default.createElement(_draftJs.Editor, (0, _extends2.default)({
ref: this.editorRef,
editorState: this.state.editorState,
onChange: this._onEditorChange,
onFocus: this._onFocus,
placeholder: placeholder,
readOnly: disabled || readOnly
}, readOnly && {
tabIndex: 0
}, !multiline && singleLineProps, {
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 73,
columnNumber: 13
}
})), (status || finalStatus === 'loading') && /*#__PURE__*/_react.default.createElement("span", {
className: _VariableInputSt.classes.indicatorWrapper,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 86,
columnNumber: 15
}
}, /*#__PURE__*/_react.default.createElement(_StatusIndicator.default, {
dataHook: _constants.dataHooks.indicator,
status: finalStatus,
message: statusMessage,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 87,
columnNumber: 17
}
})));
});
}
}
VariableInput.contextType = _StatusContext.StatusContext;
VariableInput.displayName = 'VariableInput';
VariableInput.propTypes = {
/** Specifies a CSS class name to be appended to the component’s root element */
className: _propTypes.default.string,
/** Applies a data-hook HTML attribute that can be used in the tests */
dataHook: _propTypes.default.string,
/** Specifies whether input should be disabled or not */
disabled: _propTypes.default.bool,
/** Specifies whether input is read only */
readOnly: _propTypes.default.bool,
/** Defines an initial value to display */
initialValue: _propTypes.default.string,
/** Specifies whether component allow multiple lines or not. If false, text won’t wrap and horizontal scroll will appear inside of a component. */
multiline: _propTypes.default.bool,
/** Defines a callback function that is called each time value is changed:
* `onChange(value: String): void` */
onChange: _propTypes.default.func,
/** Defines a callback function that is called on value submit, in other words after `insertVariable()` and `setValue()`
* `onSubmit(value: String): void` */
onSubmit: _propTypes.default.func,
/** Defines a callback function that is called on focus out:
* `onBlur(value: String): void` */
onBlur: _propTypes.default.func,
/** Defines a callback function that is called on focus in:
* `onFocus(value: String): void` */
onFocus: _propTypes.default.func,
/** Specify the status of a field */
status: _propTypes.default.oneOf(['error', 'warning', 'loading']),
/** Defines the message to display on status icon hover. If not given or empty there will be no tooltip. */
statusMessage: _propTypes.default.node,
/** Sets a placeholder message to display */
placeholder: _propTypes.default.string,
/** Set the height of a component to fit the given number of rows */
rows: _propTypes.default.number,
/** Controls the size of the input and variable tags */
size: _propTypes.default.oneOf(['small', 'medium', 'large']),
/** Defines the variable keys that component will parse and convert to <Tag/> components on blur and while using `insertVariable`.
* For each key `variableParser` will be called and should return a proper text for that key or false in case the key is invalid.
* `variableParser(key: String): String|boolean` */
variableParser: _propTypes.default.func,
/** A function callback that is being called on each keyboard enter and expects a return of object with properties meant for Tag component.
* It is designed to dynamically determine the styling or properties applied to variable tags within the input field.` */
variableTagPropsParser: _propTypes.default.func,
/** Defines a template for variable recognition. Typed text strings with matching prefix and suffix symbols will be converted to <Tag/> components. */
variableTemplate: _propTypes.default.shape({
prefix: _propTypes.default.string,
suffix: _propTypes.default.string
})
};
VariableInput.defaultProps = {
initialValue: '',
multiline: true,
rows: 1,
size: _constants.sizeTypes.medium,
variableParser: () => {},
variableTagPropsParser: () => ({}),
variableTemplate: {
prefix: '{{',
suffix: '}}'
}
};
var _default = exports.default = VariableInput;
//# sourceMappingURL=VariableInput.js.map