UNPKG

nudge-components-library

Version:

A library of nudge UI components

87 lines (84 loc) 4.39 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { useContext, useState, useRef, useEffect } from 'react'; import { ThemeContext } from '../../theme/ThemeContext.js'; import '../../styles/tokens.css.js'; import '../../styles/globals.css.js'; import styles from './TextArea.module.css.js'; function TextArea({ textAreaLabel, placeholder, value, defaultValue, onChange, disabled = false, nudgeText, id, ariaLabel, onFocus, onBlur, onCommit, nudgeVisible = true, nudgePosition = "bottom", renderNudge, rows = 4, }) { const theme = useContext(ThemeContext); const [text, setText] = useState(value !== undefined ? value : defaultValue); const textAreaRef = useRef(null); const containerRef = useRef(null); useEffect(() => { if (value !== undefined) { setText(value); } }, [value]); // When the textarea is focused or clicked, select all text const handleFocus = (e) => { e.target.select(); onFocus?.(e); }; // Simulate focus on touch devices const handleTouchStart = (e) => { if (onFocus) { onFocus(e); } }; const handleClick = (e) => { if (textAreaRef.current) { textAreaRef.current.select(); } }; // Handle input changes const handleChange = (event) => { const newValue = event.target.value; setText(newValue); onChange?.(newValue); }; // Listen for touches outside the component to simulate blur useEffect(() => { const handleTouchOutside = (event) => { if (containerRef.current && !containerRef.current.contains(event.target)) { if (onBlur) { const dummyEvent = { target: { value: text }, }; onBlur(dummyEvent); } onCommit?.(text); } }; document.addEventListener("touchstart", handleTouchOutside); return () => { document.removeEventListener("touchstart", handleTouchOutside); }; }, [onBlur, onCommit, text]); const nudgeId = id ? `${id}-nudge` : undefined; const nudgeElement = renderNudge && nudgeVisible ? (jsx("div", { id: nudgeId, style: theme.textArea?.nudgeText, children: renderNudge(text) })) : nudgeVisible && nudgeText ? (jsx("div", { id: nudgeId, style: theme.textArea?.nudgeText, children: nudgeText })) : null; // Build the textarea element const textAreaElement = (jsx("textarea", { id: id, ref: textAreaRef, value: text, onChange: handleChange, onFocus: handleFocus, onTouchStart: handleTouchStart, onClick: handleClick, onBlur: (e) => { onBlur?.(e); onCommit?.(e.target.value); }, "aria-label": ariaLabel ?? textAreaLabel, placeholder: placeholder, rows: rows, style: { ...theme.textArea?.input, "--base-border": theme.textArea?.input?.baseBorder, "--hover-border": theme.textArea?.hover?.hoverBorder, "--placeholder-color": theme.textArea?.input?.placeholderColor, "--placeholder-font-size": theme.textArea?.input?.placeholderFontSize, }, disabled: disabled, className: styles.textArea })); let content; if (nudgeVisible && (nudgePosition === "left" || nudgePosition === "right")) { content = (jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [nudgePosition === "left" && (jsx("div", { style: theme.textArea?.nudgeLeft, children: nudgeElement })), textAreaElement, nudgePosition === "right" && (jsx("div", { style: theme.textArea?.nudgeRight, children: nudgeElement }))] })); } else { content = (jsxs(Fragment, { children: [nudgeVisible && nudgePosition === "top" && (jsx("div", { style: theme.textArea?.nudgeTop, children: nudgeElement })), textAreaElement, nudgeVisible && nudgePosition === "bottom" && (jsx("div", { style: theme.textArea?.nudgeBottom, children: nudgeElement }))] })); } return (jsxs("div", { style: { ...theme.textArea?.wrapper, ...(disabled ? theme.textArea?.disabled : {}), }, ref: containerRef, children: [jsx("div", { style: theme.slider?.sliderLabel, children: jsx("label", { htmlFor: id, children: textAreaLabel }) }), content] })); } export { TextArea }; //# sourceMappingURL=TextArea.js.map