react-expanding-textarea
Version:
React textarea component to automatically expand and contract your textareas
102 lines (101 loc) • 4.93 kB
JavaScript
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "tslib", "react", "react-with-forwarded-ref", "fast-shallow-equal"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resize = exports.getHeight = void 0;
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importStar(require("react"));
var react_with_forwarded_ref_1 = tslib_1.__importDefault(require("react-with-forwarded-ref"));
var fast_shallow_equal_1 = require("fast-shallow-equal");
var getHeight = function (rows, el) {
var _a = window.getComputedStyle(el), borderBottomWidth = _a.borderBottomWidth, borderTopWidth = _a.borderTopWidth, fontSize = _a.fontSize, lineHeight = _a.lineHeight, paddingBottom = _a.paddingBottom, paddingTop = _a.paddingTop;
var lh = lineHeight === 'normal'
? parseFloat(fontSize) * 1.2
: parseFloat(lineHeight);
var rowHeight = rows === 0
? 0
: lh * rows +
parseFloat(borderBottomWidth) +
parseFloat(borderTopWidth) +
parseFloat(paddingBottom) +
parseFloat(paddingTop);
var scrollHeight = el.scrollHeight +
parseFloat(borderBottomWidth) +
parseFloat(borderTopWidth);
return Math.max(rowHeight, scrollHeight);
};
exports.getHeight = getHeight;
var resize = function (rows, el) {
if (el) {
var overflowY = 'hidden';
var maxHeight = window.getComputedStyle(el).maxHeight;
if (maxHeight !== 'none') {
var maxHeightN = parseFloat(maxHeight);
if (maxHeightN < el.scrollHeight) {
overflowY = '';
}
}
el.style.height = '0';
el.style.overflowY = overflowY;
el.style.height = "".concat((0, exports.getHeight)(rows, el), "px");
}
};
exports.resize = resize;
// =============================================================================
var useShallowObjectMemo = function (obj) {
var refObject = (0, react_1.useRef)(obj);
var refCounter = (0, react_1.useRef)(0);
if (!(0, fast_shallow_equal_1.equal)(obj, refObject.current)) {
refObject.current = obj;
refCounter.current += 1;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
return (0, react_1.useMemo)(function () { return refObject.current; }, [refCounter.current]);
};
// =============================================================================
var useSSRLayoutEffect = typeof window === 'undefined' ? Function.prototype : react_1.useLayoutEffect;
var ExpandingTextarea = function (_a) {
var forwardedRef = _a.forwardedRef, props = tslib_1.__rest(_a, ["forwardedRef"]);
var isForwardedRefFn = typeof forwardedRef === 'function';
var style = useShallowObjectMemo(props.style);
var internalRef = (0, react_1.useRef)();
var ref = (isForwardedRefFn || !forwardedRef ? internalRef : forwardedRef);
var rows = props.rows ? parseInt('' + props.rows, 10) : 0;
var onChange = props.onChange, onInput = props.onInput, rest = tslib_1.__rest(props, ["onChange", "onInput"]);
useSSRLayoutEffect(function () {
(0, exports.resize)(rows, ref.current);
}, [props.className, props.value, ref, rows, style]);
useSSRLayoutEffect(function () {
if (!window.ResizeObserver) {
return;
}
var observer = new ResizeObserver(function () {
(0, exports.resize)(rows, ref.current);
});
observer.observe(ref.current);
return function () {
observer.disconnect();
};
}, [ref, rows]);
var handleInput = (0, react_1.useCallback)(function (e) {
onChange === null || onChange === void 0 ? void 0 : onChange(e);
onInput === null || onInput === void 0 ? void 0 : onInput(e);
(0, exports.resize)(rows, ref.current);
}, [onChange, onInput, ref, rows]);
var handleRef = (0, react_1.useCallback)(function (node) {
ref.current = node;
if (isForwardedRefFn) {
forwardedRef(node);
}
}, [forwardedRef, isForwardedRefFn, ref]);
return (react_1.default.createElement("textarea", tslib_1.__assign({}, rest, { onInput: handleInput, ref: handleRef, rows: rows })));
};
exports.default = (0, react_with_forwarded_ref_1.default)(ExpandingTextarea);
});