@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
143 lines (142 loc) • 5.01 kB
JavaScript
"use client";
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
let react = require("react");
react = require_runtime.__toESM(react);
let _mantine_hooks = require("@mantine/hooks");
let react_jsx_runtime = require("react/jsx-runtime");
//#region packages/@mantine/core/src/components/Textarea/Autosize.tsx
const SIZING_STYLE_KEYS = [
"borderBottomWidth",
"borderLeftWidth",
"borderRightWidth",
"borderTopWidth",
"boxSizing",
"fontFamily",
"fontSize",
"fontStyle",
"fontWeight",
"letterSpacing",
"lineHeight",
"paddingBottom",
"paddingLeft",
"paddingRight",
"paddingTop",
"tabSize",
"textIndent",
"textRendering",
"textTransform",
"width",
"wordBreak",
"wordSpacing",
"scrollbarGutter"
];
const HIDDEN_TEXTAREA_STYLE = {
"min-height": "0",
"max-height": "none",
height: "0",
visibility: "hidden",
overflow: "hidden",
position: "absolute",
"z-index": "-1000",
top: "0",
right: "0",
display: "block"
};
function forceHiddenStyles(node) {
Object.keys(HIDDEN_TEXTAREA_STYLE).forEach((key) => {
node.style.setProperty(key, HIDDEN_TEXTAREA_STYLE[key], "important");
});
}
function getSizingData(node) {
const style = window.getComputedStyle(node);
if (style === null) return null;
const sizingStyle = {};
for (const key of SIZING_STYLE_KEYS) sizingStyle[key] = style[key];
if (sizingStyle.boxSizing === "") return null;
return {
sizingStyle,
paddingSize: parseFloat(sizingStyle.paddingBottom) + parseFloat(sizingStyle.paddingTop),
borderSize: parseFloat(sizingStyle.borderBottomWidth) + parseFloat(sizingStyle.borderTopWidth)
};
}
let hiddenTextarea = null;
function calculateNodeHeight(sizingData, value, minRows = 1, maxRows = Infinity) {
if (!hiddenTextarea) {
hiddenTextarea = document.createElement("textarea");
hiddenTextarea.setAttribute("tabindex", "-1");
hiddenTextarea.setAttribute("aria-hidden", "true");
hiddenTextarea.setAttribute("aria-label", "autosize measurement");
forceHiddenStyles(hiddenTextarea);
}
if (hiddenTextarea.parentNode === null) document.body.appendChild(hiddenTextarea);
const { paddingSize, borderSize, sizingStyle } = sizingData;
const { boxSizing } = sizingStyle;
Object.keys(sizingStyle).forEach((key) => {
hiddenTextarea.style[key] = sizingStyle[key];
});
forceHiddenStyles(hiddenTextarea);
hiddenTextarea.value = value;
let height = boxSizing === "border-box" ? hiddenTextarea.scrollHeight + borderSize : hiddenTextarea.scrollHeight - paddingSize;
hiddenTextarea.value = value;
height = boxSizing === "border-box" ? hiddenTextarea.scrollHeight + borderSize : hiddenTextarea.scrollHeight - paddingSize;
hiddenTextarea.value = "x";
const rowHeight = hiddenTextarea.scrollHeight - paddingSize;
let minHeight = rowHeight * minRows;
if (boxSizing === "border-box") minHeight = minHeight + paddingSize + borderSize;
height = Math.max(minHeight, height);
let maxHeight = rowHeight * maxRows;
if (boxSizing === "border-box") maxHeight = maxHeight + paddingSize + borderSize;
height = Math.min(maxHeight, height);
return [height, rowHeight];
}
function TextareaAutosize({ maxRows, minRows, onChange, ref: userRef, ...props }) {
const isControlled = props.value !== void 0;
const libRef = (0, react.useRef)(null);
const ref = (0, _mantine_hooks.useMergedRef)(libRef, userRef);
const heightRef = (0, react.useRef)(0);
const resizeTextarea = () => {
const node = libRef.current;
const nodeSizingData = getSizingData(node);
if (!nodeSizingData) return;
const [height] = calculateNodeHeight(nodeSizingData, node.value || node.placeholder || "x", minRows, maxRows);
if (heightRef.current !== height) {
heightRef.current = height;
node.style.setProperty("height", `${height}px`, "important");
}
};
const handleChange = (event) => {
if (!isControlled) resizeTextarea();
onChange?.(event);
};
(0, react.useLayoutEffect)(resizeTextarea);
(0, react.useEffect)(() => {
const handleResize = () => resizeTextarea();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
(0, react.useEffect)(() => {
const handleFontsLoaded = () => resizeTextarea();
document.fonts.addEventListener("loadingdone", handleFontsLoaded);
return () => document.fonts.removeEventListener("loadingdone", handleFontsLoaded);
}, []);
(0, react.useEffect)(() => {
const handleReset = (event) => {
if (libRef.current?.form === event.target && !isControlled) {
const currentValue = libRef.current.value;
requestAnimationFrame(() => {
if (libRef.current && currentValue !== libRef.current.value) resizeTextarea();
});
}
};
document.body.addEventListener("reset", handleReset);
return () => document.body.removeEventListener("reset", handleReset);
}, [isControlled]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
...props,
onChange: handleChange,
ref
});
}
//#endregion
exports.TextareaAutosize = TextareaAutosize;
//# sourceMappingURL=Autosize.cjs.map