nudge-components-library
Version:
A library of nudge UI components
87 lines (84 loc) • 4.39 kB
JavaScript
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