@yandex/ui
Version:
Yandex UI components
94 lines (93 loc) • 5.87 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.withAutoResize = void 0;
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importStar(require("react"));
var mergeRefs_1 = require("../../lib/mergeRefs");
var throttle_1 = require("../../lib/throttle");
var getDisplayName_1 = require("../../lib/getDisplayName");
var Textarea_1 = require("../Textarea");
require("./Textarea_autoResize.css");
/**
* Модификатор который увеличивает размер контрола при наборе текста.
*/
function withAutoResize(WrappedComponent) {
var WithAutoResize = /** @class */ (function (_super) {
tslib_1.__extends(WithAutoResize, _super);
function WithAutoResize() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.wrapRef = react_1.createRef();
_this.controlRef = react_1.createRef();
_this.initialHeight = 0;
_this.newHeight = 0;
_this.onResize = throttle_1.throttle(_this.updateHeight).bind(_this);
return _this;
}
WithAutoResize.prototype.componentDidMount = function () {
this.saveInitialHeight();
this.updateHeight();
window.addEventListener('resize', this.onResize);
};
WithAutoResize.prototype.componentDidUpdate = function (prevProps) {
// Если компонент скрыт на момент componentDidMount, то минимальная высота будет вычислена неверно (= 0).
// Используем активацию фокуса как признак того, что компонент был показан пользователю.
if (this.props.focused && this.props.focused !== prevProps.focused) {
this.recalcInitialHeight();
}
this.updateHeight();
};
WithAutoResize.prototype.componentWillUnmount = function () {
window.removeEventListener('resize', this.onResize);
};
WithAutoResize.prototype.render = function () {
var _a = this.props, className = _a.className, _b = _a.controlRef, controlRef = _b === void 0 ? null : _b, _c = _a.wrapRef, wrapRef = _c === void 0 ? null : _c;
return (react_1.default.createElement(WrappedComponent, tslib_1.__assign({}, this.props, { className: Textarea_1.cnTextarea({ autoResize: true }, [className]), controlRef: mergeRefs_1.mergeAllRefs(this.controlRef, controlRef), wrapRef: mergeRefs_1.mergeAllRefs(this.wrapRef, wrapRef) })));
};
/**
* Сохраняем минимальную высоту которую нужно будет проставлять при удалении текста.
*/
WithAutoResize.prototype.saveInitialHeight = function () {
if (this.wrapRef.current) {
this.initialHeight = this.wrapRef.current.clientHeight;
}
};
/**
* Пересчет минимальной высоты которую нужно будет проставлять при удалении текста.
*/
WithAutoResize.prototype.recalcInitialHeight = function () {
if (this.wrapRef.current) {
this.wrapRef.current.style.height = 'auto';
this.saveInitialHeight();
}
};
/**
* Обновление высоты корневому блоку компонента в зависимости от размера контрола.
* Для уменьшении блока при удалении текста нужно вначале выставить его стиль высоты в initialHeight.
* Иначе блок с удаленным текстом будет всегда оставаться с тем размером который ему выставили в стилях.
* Получается, что scrollHeight вычисляется всегда относительно initialHeight размера контейнера.
* Высота контейнера вычисляется относительно контрола учитывая его отступы.
*/
WithAutoResize.prototype.updateHeight = function () {
if (this.wrapRef && this.wrapRef.current) {
if (this.newHeight > this.initialHeight) {
this.wrapRef.current.style.height = this.initialHeight + "px";
this.newHeight = this.initialHeight;
}
if (this.controlRef && this.controlRef.current) {
// Цикл, чтобы перепроверить получившийся элемент, т.к. после его увеличения может появиться скролл
// который выдавит текст внутри него и тогда часть текста может быть не видна
var i = 2; // Подстраховка
while (this.controlRef.current.scrollHeight > this.controlRef.current.offsetHeight && i--) {
var padding = this.controlRef.current.offsetHeight - this.controlRef.current.clientHeight;
this.newHeight = this.controlRef.current.scrollHeight;
this.wrapRef.current.style.height = this.newHeight + padding + "px";
}
}
}
};
WithAutoResize.displayName = "withAutoResize(" + getDisplayName_1.getDisplayName(WrappedComponent) + ")";
return WithAutoResize;
}(react_1.PureComponent));
return WithAutoResize;
}
exports.withAutoResize = withAutoResize;