@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
202 lines (157 loc) • 6.37 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = exports.InputResizer = exports.OFFSET_CHAR = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _react = _interopRequireDefault(require("react"));
var _getValidProps = _interopRequireDefault(require("@helpscout/react-utils/dist/getValidProps"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _EventListener = _interopRequireDefault(require("../EventListener"));
var _classnames = _interopRequireDefault(require("classnames"));
var _InputResizer = require("./Input.Resizer.css");
var _jsxRuntime = require("react/jsx-runtime");
// Thanks Stephen <3
var OFFSET_CHAR = 'R';
exports.OFFSET_CHAR = OFFSET_CHAR;
var ENTITIES_TO_REPLACE = {
'&': '&',
'<': '<',
'>': '>',
'\n': '<br>'
};
var REPLACE_REGEX = /[\n&<>]/g;
var InputResizer = /*#__PURE__*/function (_React$PureComponent) {
(0, _inheritsLoose2.default)(InputResizer, _React$PureComponent);
function InputResizer() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _React$PureComponent.call.apply(_React$PureComponent, [this].concat(args)) || this;
_this.contentNode = void 0;
_this.minimumLinesNode = void 0;
_this._isMounted = false;
_this.handleOnResize = function () {
if (!_this.contentNode || !_this.minimumLinesNode) return;
var contentHeight = _this.contentNode.offsetHeight;
var minimumHeight = _this.minimumLinesNode ? _this.minimumLinesNode.offsetHeight : 0;
var newHeight = Math.max(contentHeight, minimumHeight);
var _this$props = _this.props,
currentHeight = _this$props.currentHeight,
onResize = _this$props.onResize;
if (newHeight !== currentHeight) {
onResize(newHeight);
}
};
_this.setMinimumLinesNode = function (node) {
return _this.minimumLinesNode = node;
};
_this.setContentNodeRef = function (node) {
return _this.contentNode = node;
};
return _this;
}
var _proto = InputResizer.prototype;
_proto.componentDidMount = function componentDidMount() {
var _this2 = this;
this._isMounted = true;
this.handleOnResize(); // Re-trigger to help recalculate when used within heavier components/views.
requestAnimationFrame(function () {
if (_this2._isMounted) {
_this2.handleOnResize();
}
});
};
_proto.componentWillUnmount = function componentWillUnmount() {
this._isMounted = false;
};
_proto.componentDidUpdate = function componentDidUpdate() {
this.handleOnResize();
};
_proto.getClassName = function getClassName() {
var className = this.props.className;
return (0, _classnames.default)(InputResizer.className, className);
};
_proto.getContentClassName = function getContentClassName() {
var seamless = this.props.seamless;
return (0, _classnames.default)('c-InputGhost', 'c-InputGhost--characters', seamless && 'is-seamless');
} // Ignoring as height calculation isn't possible with JSDOM
// (which is what Enzyme uses for tests)
;
_proto.replaceEntity = function replaceEntity(entity) {
return ENTITIES_TO_REPLACE[entity] || entity;
};
_proto.getContentsForMinimumLines = function getContentsForMinimumLines(minimumLines) {
var content = '';
for (var line = 0; line < minimumLines; line++) {
content += '<br>';
}
return content;
};
_proto.getFinalContents = function getFinalContents(contents) {
var charOffset = OFFSET_CHAR.repeat(this.props.offsetAmount);
return contents ? contents.replace(REPLACE_REGEX, this.replaceEntity).concat(charOffset) + "<br>" : '<br>';
};
_proto.renderMinimumLines = function renderMinimumLines() {
var minimumLines = this.props.minimumLines;
if (!minimumLines) return;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputResizer.GhostUI, {
ref: this.setMinimumLinesNode,
className: this.getContentClassName(),
dangerouslySetInnerHTML: {
__html: this.getContentsForMinimumLines(minimumLines)
}
});
};
_proto.render = function render() {
var _this$props2 = this.props,
contents = _this$props2.contents,
rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props2, ["contents"]);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_InputResizer.ResizerUI, (0, _extends2.default)({}, (0, _getValidProps.default)(rest), {
"aria-hidden": true,
className: this.getClassName(),
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_EventListener.default, {
event: "resize",
handler: this.handleOnResize
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputResizer.GhostUI, {
ref: this.setContentNodeRef,
className: this.getContentClassName(),
dangerouslySetInnerHTML: {
__html: this.getFinalContents(contents)
}
}), this.renderMinimumLines()]
}));
};
return InputResizer;
}(_react.default.PureComponent);
exports.InputResizer = InputResizer;
InputResizer.className = 'c-InputResizer';
function noop() {}
InputResizer.defaultProps = {
contents: '',
currentHeight: null,
'data-cy': 'InputResizer',
minimumLines: 1,
offsetAmount: 0,
onResize: noop,
seamless: false
};
InputResizer.propTypes = {
/** Custom class names to be added to the component. */
className: _propTypes.default.string,
contents: _propTypes.default.string,
currentHeight: _propTypes.default.number,
minimumLines: _propTypes.default.number,
/** Number of characters to offset (bottom-right) for multiline resizing. */
offsetAmount: _propTypes.default.number,
/** Callback when input is resized. */
onResize: _propTypes.default.func,
/** Removes the border around the input. */
seamless: _propTypes.default.bool,
/** Data attr for Cypress tests. */
'data-cy': _propTypes.default.string
};
var _default = InputResizer;
exports.default = _default;
;