UNPKG

@yandex/ui

Version:

Yandex UI components

94 lines (93 loc) 5.87 kB
"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;