UNPKG

braid-design-system

Version:
135 lines (134 loc) 4.97 kB
"use strict"; const jsxRuntime = require("react/jsx-runtime"); const react = require("react"); const lib_components_Box_Box_cjs = require("../Box/Box.cjs"); const lib_components_private_Field_Field_cjs = require("../private/Field/Field.cjs"); const lib_components_private_Field_getCharacterLimitStatus_cjs = require("../private/Field/getCharacterLimitStatus.cjs"); const lib_components_Textarea_formatRanges_cjs = require("./formatRanges.cjs"); const lib_components_Textarea_Textarea_css_cjs = require("./Textarea.css.cjs"); const pxToInt = (str) => typeof str === "string" ? parseInt(str.replace("px", ""), 10) : 0; const calculateLines = (target, lines, lineLimit) => { const { paddingBottom, paddingTop, lineHeight } = window.getComputedStyle(target); if (!lineHeight.endsWith("px")) { return lines; } const padding = pxToInt(paddingTop) + pxToInt(paddingBottom); const currentRows = Math.floor( (target.scrollHeight - padding) / pxToInt(lineHeight) ); if (target && target.value === "") { return lines; } return typeof lineLimit === "number" && currentRows > lineLimit ? lineLimit : currentRows; }; const Textarea = react.forwardRef( ({ value, onChange, onBlur, onFocus, onPaste, placeholder, characterLimit, highlightRanges: highlightRangesProp = [], lines = 3, lineLimit, grow = true, tone, spellCheck, ...restProps }, ref) => { const [rows, setRows] = react.useState(lines); const highlightsRef = react.useRef(null); const updateScroll = react.useCallback( (scrollTop) => { if (highlightsRef.current) { highlightsRef.current.scrollTop = scrollTop; } }, [highlightsRef] ); const inputLength = String(value).length; const hasExceededCharacterLimit = characterLimit && inputLength > characterLimit; const highlightTone = !hasExceededCharacterLimit && (tone === "critical" || tone === "caution") ? tone : "critical"; const highlightRanges = hasExceededCharacterLimit ? [{ start: characterLimit }] : highlightRangesProp; const hasHighlights = highlightRanges.length > 0; return /* @__PURE__ */ jsxRuntime.jsx( lib_components_private_Field_Field_cjs.Field, { ...restProps, componentName: "Textarea", tone, value, icon: void 0, prefix: void 0, secondaryMessage: characterLimit ? lib_components_private_Field_getCharacterLimitStatus_cjs.getCharacterLimitStatus({ value, characterLimit }) : null, children: (overlays, { className, borderRadius, background, ...fieldProps }) => /* @__PURE__ */ jsxRuntime.jsxs( lib_components_Box_Box_cjs.Box, { position: "relative", width: "full", zIndex: 0, background, borderRadius, children: [ hasHighlights ? /* @__PURE__ */ jsxRuntime.jsx( lib_components_Box_Box_cjs.Box, { ref: highlightsRef, position: "absolute", overflow: "hidden", pointerEvents: "none", height: "full", "aria-hidden": "true", top: 0, left: 0, className: [lib_components_Textarea_Textarea_css_cjs.highlights, className], ...fieldProps, children: lib_components_Textarea_formatRanges_cjs.formatRanges(String(value), highlightRanges, highlightTone) } ) : null, /* @__PURE__ */ jsxRuntime.jsx( lib_components_Box_Box_cjs.Box, { component: "textarea", position: "relative", zIndex: 1, rows, value, onChange: (e) => { if (grow) { setRows(calculateLines(e.currentTarget, lines, lineLimit)); } if (typeof onChange === "function") { onChange(e); } if (hasHighlights) { updateScroll(e.currentTarget.scrollTop); } }, onBlur, onFocus, onPaste, onScroll: hasHighlights ? (event) => updateScroll(event.currentTarget.scrollTop) : void 0, placeholder: !restProps.disabled ? placeholder : void 0, spellCheck, className: [lib_components_Textarea_Textarea_css_cjs.field, className], borderRadius, ...fieldProps, ref } ), overlays ] } ) } ); } ); Textarea.displayName = "Textarea"; exports.Textarea = Textarea;