{"version":3,"sources":["../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import {\n  TextareaHTMLAttributes,\n  ReactNode,\n  forwardRef,\n  useState,\n  useId,\n  useEffect,\n  useRef,\n  useImperativeHandle,\n  ChangeEvent,\n  FocusEvent,\n} from 'react';\nimport { WarningCircleIcon } from '@phosphor-icons/react/dist/csr/WarningCircle';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\n\n/**\n * TextArea size variants\n */\ntype TextAreaSize = 'small' | 'medium' | 'large' | 'extraLarge';\n\n/**\n * TextArea visual state\n */\ntype TextAreaState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations with exact pixel specifications\n */\nconst SIZE_CLASSES = {\n  small: {\n    textarea: 'h-24 text-sm', // 96px height, 14px font\n    textSize: 'sm' as const,\n  },\n  medium: {\n    textarea: 'h-24 text-base', // 96px height, 16px font\n    textSize: 'md' as const,\n  },\n  large: {\n    textarea: 'h-24 text-lg', // 96px height, 18px font\n    textSize: 'lg' as const,\n  },\n  extraLarge: {\n    textarea: 'h-24 text-xl', // 96px height, 20px font\n    textSize: 'xl' as const,\n  },\n} as const;\n\n/**\n * Base textarea styling classes using design system colors\n */\nconst BASE_TEXTAREA_CLASSES =\n  'w-full box-border p-3 bg-background border border-solid rounded-[4px] resize-none focus:outline-none font-roboto font-normal leading-[150%] placeholder:text-text-600 transition-all duration-200';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n  default: {\n    base: 'border-border-300 bg-background text-text-600',\n    hover: 'hover:border-border-400',\n    focus: 'focus:border-border-500',\n  },\n  hovered: {\n    base: 'border-border-400 bg-background text-text-600',\n    hover: '',\n    focus: 'focus:border-border-500',\n  },\n  focused: {\n    base: 'border-2 border-primary-950 bg-background text-text-900',\n    hover: '',\n    focus: '',\n  },\n  invalid: {\n    base: 'border-2 border-red-700 bg-white text-gray-800',\n    hover: 'hover:border-red-700',\n    focus: 'focus:border-red-700',\n  },\n  disabled: {\n    base: 'border-border-300 bg-background text-text-600 cursor-not-allowed opacity-40',\n    hover: '',\n    focus: '',\n  },\n} as const;\n\n/**\n * TextArea component props interface\n */\nexport type TextAreaProps = {\n  /** Label text to display above the textarea */\n  label?: ReactNode;\n  /** Size variant of the textarea */\n  size?: TextAreaSize;\n  /** Visual state of the textarea */\n  state?: TextAreaState;\n  /** Error message to display */\n  errorMessage?: string;\n  /** Helper text to display */\n  helperMessage?: string;\n  /** Additional CSS classes */\n  className?: string;\n  /** Label CSS classes */\n  labelClassName?: string;\n  /** Show character count when maxLength is provided */\n  showCharacterCount?: boolean;\n  /** Enable auto-resize based on content */\n  autoResize?: boolean;\n  /** Minimum height when autoResize is enabled (default: 96px) */\n  minHeight?: number;\n} & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'>;\n\n/**\n * TextArea component for Analytica Ensino platforms\n *\n * A textarea component with essential states, sizes and themes.\n * Uses exact design specifications with 288px width, 96px height, and specific\n * color values. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic textarea\n * <TextArea label=\"Description\" placeholder=\"Enter description...\" />\n *\n * // Small size\n * <TextArea size=\"small\" label=\"Comment\" />\n *\n * // Invalid state\n * <TextArea state=\"invalid\" label=\"Required field\" errorMessage=\"This field is required\" />\n *\n * // Disabled state\n * <TextArea disabled label=\"Read-only field\" />\n *\n * // Auto-resize textarea\n * <TextArea autoResize minHeight={200} placeholder=\"Grows with content...\" />\n * ```\n */\nconst TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(\n  (\n    {\n      label,\n      size = 'medium',\n      state = 'default',\n      errorMessage,\n      helperMessage,\n      className = '',\n      labelClassName = '',\n      disabled,\n      id,\n      onChange,\n      placeholder,\n      required,\n      showCharacterCount = false,\n      maxLength,\n      value,\n      autoResize = false,\n      minHeight = 96,\n      ...props\n    },\n    ref\n  ) => {\n    // Generate unique ID if not provided\n    const generatedId = useId();\n    const inputId = id ?? `textarea-${generatedId}`;\n\n    // Internal ref for auto-resize\n    const internalRef = useRef<HTMLTextAreaElement>(null);\n\n    // Expose ref to parent\n    useImperativeHandle(ref, () => internalRef.current as HTMLTextAreaElement);\n\n    // Internal state for focus tracking\n    const [isFocused, setIsFocused] = useState(false);\n\n    // Calculate current character count\n    const currentLength = typeof value === 'string' ? value.length : 0;\n    const isNearLimit = maxLength && currentLength >= maxLength * 0.8;\n\n    // Auto-resize effect\n    useEffect(() => {\n      if (autoResize && internalRef.current) {\n        const textarea = internalRef.current;\n        textarea.style.height = 'auto';\n        textarea.style.height = `${Math.max(textarea.scrollHeight, minHeight)}px`;\n      }\n    }, [autoResize, minHeight, value]);\n\n    // Handle change events\n    const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n      onChange?.(event);\n    };\n\n    // Handle focus events\n    const handleFocus = (event: FocusEvent<HTMLTextAreaElement>) => {\n      setIsFocused(true);\n      props.onFocus?.(event);\n    };\n\n    // Handle blur events\n    const handleBlur = (event: FocusEvent<HTMLTextAreaElement>) => {\n      setIsFocused(false);\n      props.onBlur?.(event);\n    };\n\n    // Determine current state based on props and focus\n    let currentState = disabled ? 'disabled' : state;\n\n    // Override state based on focus\n    if (\n      isFocused &&\n      currentState !== 'invalid' &&\n      currentState !== 'disabled'\n    ) {\n      currentState = 'focused';\n    }\n\n    // Get size classes\n    const sizeClasses = SIZE_CLASSES[size];\n\n    // Get styling classes\n    const stateClasses = STATE_CLASSES[currentState];\n\n    // Get height classes based on autoResize\n    const heightClasses = autoResize\n      ? 'h-auto overflow-hidden'\n      : sizeClasses.textarea;\n\n    // Get font size from size classes (extract only the text size)\n    const fontSizeClass =\n      sizeClasses.textarea.split(' ').find((c) => c.startsWith('text-')) ??\n      'text-base';\n\n    // Get final textarea classes\n    const textareaClasses = cn(\n      BASE_TEXTAREA_CLASSES,\n      autoResize ? fontSizeClass : sizeClasses.textarea,\n      heightClasses,\n      stateClasses.base,\n      stateClasses.hover,\n      stateClasses.focus,\n      className\n    );\n\n    return (\n      <div className={`flex flex-col`}>\n        {/* Label */}\n        {label && (\n          <Text\n            as=\"label\"\n            htmlFor={inputId}\n            size={sizeClasses.textSize}\n            weight=\"medium\"\n            color=\"text-text-950\"\n            className={cn('mb-1.5', labelClassName)}\n          >\n            {label}{' '}\n            {required && <span className=\"text-indicator-error\">*</span>}\n          </Text>\n        )}\n\n        {/* Textarea */}\n        <textarea\n          ref={internalRef}\n          id={inputId}\n          disabled={disabled}\n          onChange={handleChange}\n          onFocus={handleFocus}\n          onBlur={handleBlur}\n          className={textareaClasses}\n          placeholder={placeholder}\n          required={required}\n          maxLength={maxLength}\n          value={value}\n          {...props}\n        />\n\n        {/* Error message */}\n        {errorMessage && (\n          <p className=\"flex gap-1 items-center text-sm text-indicator-error mt-1.5\">\n            <WarningCircleIcon size={16} /> {errorMessage}\n          </p>\n        )}\n\n        {/* Helper text or Character count */}\n        {!errorMessage && showCharacterCount && maxLength && (\n          <Text\n            size=\"sm\"\n            weight=\"normal\"\n            className={`mt-1.5 ${isNearLimit ? 'text-indicator-warning' : 'text-text-500'}`}\n          >\n            {currentLength}/{maxLength} caracteres\n          </Text>\n        )}\n        {!errorMessage &&\n          helperMessage &&\n          !(showCharacterCount && maxLength) && (\n            <Text size=\"sm\" weight=\"normal\" className=\"mt-1.5 text-text-500\">\n              {helperMessage}\n            </Text>\n          )}\n      </div>\n    );\n  }\n);\n\nTextArea.displayName = 'TextArea';\n\nexport default TextArea;\n"],"mappings":"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","names":[]}