{"version":3,"sources":["../src/textarea/index.tsx"],"names":["spacing","forwardRef","Textarea","useTheme","useState","useRef","useLayoutEffect","radius","transition","motion","jsx"],"mappings":"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","file":"textarea.cjs","sourcesContent":["/**\n * Textarea (web). Multi-line sibling of Input -- same theme styling and\n * size scale, plus optional auto-grow so the box tracks its content\n * instead of scrolling. The one field a resume, a bio, or a message box\n * always needs and Input can't cover.\n *\n * Controlled and uncontrolled both work. autoGrow measures scrollHeight\n * on each change and pins the element height between minRows and maxRows.\n *\n * Focus draws the same two-part ring as Input (page-fill gap +\n * primaryOrange). Inline styles can't express :focus-visible, so the\n * ring shows on every focus, not just keyboard focus.\n */\nimport {\n  forwardRef,\n  useLayoutEffect,\n  useRef,\n  useState,\n  type ChangeEvent,\n  type CSSProperties,\n} from \"react\";\nimport { useTheme } from \"@plyxui/styles\";\nimport { motion, radius, spacing, transition } from \"@plyxui/core\";\n\nexport type TextareaSize = \"sm\" | \"md\" | \"lg\";\n\nconst sizeMap: Record<TextareaSize, { fontSize: number; padX: number; padY: number; lineHeight: number }> = {\n  sm: { fontSize: 13, padX: spacing[2], padY: spacing[2], lineHeight: 18 },\n  md: { fontSize: 14, padX: spacing[3], padY: spacing[2], lineHeight: 21 },\n  lg: { fontSize: 16, padX: spacing[4], padY: spacing[3], lineHeight: 24 },\n};\n\nexport interface TextareaProps {\n  value?: string;\n  defaultValue?: string;\n  onChange?: (value: string, event: ChangeEvent<HTMLTextAreaElement>) => void;\n  placeholder?: string;\n  size?: TextareaSize;\n  invalid?: boolean;\n  disabled?: boolean;\n  /** Visible rows at rest (also the auto-grow floor). Default 3. */\n  rows?: number;\n  /** Grow with content up to maxRows instead of scrolling. Default true. */\n  autoGrow?: boolean;\n  /** Auto-grow ceiling; beyond it the textarea scrolls. Default 12. */\n  maxRows?: number;\n  className?: string;\n  style?: CSSProperties;\n  autoFocus?: boolean;\n  id?: string;\n  name?: string;\n  maxLength?: number;\n  \"aria-label\"?: string;\n}\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(\n  {\n    value,\n    defaultValue,\n    onChange,\n    placeholder,\n    size = \"md\",\n    invalid,\n    disabled,\n    rows = 3,\n    autoGrow = true,\n    maxRows = 12,\n    className,\n    style,\n    autoFocus,\n    id,\n    name,\n    maxLength,\n    ...aria\n  },\n  ref,\n) {\n  const { colors } = useTheme();\n  const [internal, setInternal] = useState<string>(defaultValue ?? \"\");\n  const [focused, setFocused] = useState(false);\n  const isControlled = value !== undefined;\n  const current = isControlled ? value : internal;\n  const dims = sizeMap[size];\n\n  // Merge the forwarded ref with our own so auto-grow can measure.\n  const innerRef = useRef<HTMLTextAreaElement | null>(null);\n  const setRefs = (el: HTMLTextAreaElement | null) => {\n    innerRef.current = el;\n    if (typeof ref === \"function\") ref(el);\n    else if (ref) (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = el;\n  };\n\n  const frame = dims.padY * 2 + 2; // vertical padding + 1px border top/bottom\n  const minH = rows * dims.lineHeight + frame;\n  const maxH = maxRows * dims.lineHeight + frame;\n\n  useLayoutEffect(() => {\n    const el = innerRef.current;\n    if (!el || !autoGrow) return;\n    el.style.height = \"auto\";\n    el.style.height = `${Math.min(Math.max(el.scrollHeight, minH), maxH)}px`;\n    el.style.overflowY = el.scrollHeight > maxH ? \"auto\" : \"hidden\";\n  }, [current, autoGrow, minH, maxH]);\n\n  const textareaStyle: CSSProperties = {\n    width: \"100%\",\n    boxSizing: \"border-box\",\n    minHeight: minH,\n    padding: `${dims.padY}px ${dims.padX}px`,\n    background: colors.surfaceFill,\n    border: `1px solid ${invalid ? colors.statusError : focused ? colors.primaryOrange : colors.stroke}`,\n    borderRadius: radius.md,\n    color: colors.text,\n    fontSize: dims.fontSize,\n    lineHeight: `${dims.lineHeight}px`,\n    fontFamily: \"inherit\",\n    outline: \"none\",\n    resize: autoGrow ? \"none\" : \"vertical\",\n    opacity: disabled ? 0.55 : 1,\n    boxShadow: focused\n      ? `0 0 0 2px ${colors.primaryFill}, 0 0 0 4px ${invalid ? colors.statusError : colors.primaryOrange}`\n      : \"none\",\n    transition: [\n      transition(\"border-color\", motion.controlHover),\n      transition(\"box-shadow\", motion.controlHover),\n    ].join(\", \"),\n    ...style,\n  };\n\n  return (\n    <textarea\n      ref={setRefs}\n      className={className}\n      id={id}\n      name={name}\n      value={current}\n      rows={rows}\n      maxLength={maxLength}\n      onChange={(e) => {\n        if (!isControlled) setInternal(e.target.value);\n        onChange?.(e.target.value, e);\n      }}\n      placeholder={placeholder}\n      disabled={disabled}\n      autoFocus={autoFocus}\n      aria-invalid={invalid || undefined}\n      aria-label={aria[\"aria-label\"]}\n      style={textareaStyle}\n      onFocus={() => setFocused(true)}\n      onBlur={() => setFocused(false)}\n    />\n  );\n});\n"]}