'use client' import type { ChangeEvent, ComponentProps, ReactNode } from 'react' import { forwardRef } from 'react' import { Description, FieldError, type Input as HeroInput, InputGroup, Label, TextArea as HeroTextarea, TextField } from '@heroui/react' import { cn } from '@/lib/cn' interface LegacyClassNames { base?: string input?: string inputWrapper?: string innerWrapper?: string label?: string } interface SharedProps { 'aria-label'?: string autoFocus?: boolean className?: string classNames?: LegacyClassNames defaultValue?: string description?: ReactNode descriptionClassName?: string disabled?: boolean endContent?: ReactNode errorMessage?: ReactNode isClearable?: boolean isDisabled?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean label?: ReactNode labelPlacement?: 'inside' | 'outside' | 'outside-left' name?: string placeholder?: string radius?: 'none' | 'sm' | 'md' | 'lg' | 'full' size?: 'sm' | 'md' | 'lg' startContent?: ReactNode validationBehavior?: 'native' | 'aria' value?: string variant?: 'flat' | 'bordered' | 'faded' | 'underlined' onBlur?: ComponentProps['onBlur'] onChange?: (event: ChangeEvent) => void onClear?: () => void onValueChange?: (value: string) => void } export type InputProps = SharedProps & Omit< ComponentProps, 'children' | 'className' | 'defaultValue' | 'disabled' | 'onChange' | 'readOnly' | 'required' | 'size' | 'value' | 'variant' > function radiusClass(radius: SharedProps['radius']): string { if (!radius) return '' if (radius === 'none') return 'rounded-none' if (radius === 'full') return 'rounded-full' if (radius === 'lg') return 'rounded-2xl' if (radius === 'sm') return 'rounded-md' return 'rounded-lg' } function sizeClass(size: SharedProps['size']): string { if (size === 'sm') return 'min-h-8' if (size === 'lg') return 'min-h-12' return 'min-h-10' } function variantClass(variant: SharedProps['variant'], invalid?: boolean): string { if (invalid) return 'border-fourth' if (variant === 'underlined') return 'rounded-none border-x-0 border-t-0' if (variant === 'flat' || variant === 'faded') return 'border-transparent bg-default-100' return 'border-divider bg-surface' } const clearButtonClassName = 'flex size-5 shrink-0 items-center justify-center rounded-full bg-default-200 text-sm leading-none text-default-500 transition-colors hover:bg-default-300' export const Input = forwardRef(function Input( { className, classNames, description, descriptionClassName, disabled, endContent, errorMessage, isClearable, isDisabled, isInvalid, isReadOnly, isRequired, label, labelPlacement: _labelPlacement, radius, size, startContent, validationBehavior, variant, onChange, onClear, onValueChange, ...props }, ref ) { const handleChange = (event: ChangeEvent) => { onChange?.(event) onValueChange?.(event.target.value) } return ( {label ? : null} {startContent ? {startContent} : null} {isClearable && props.value ? ( ) : endContent ? ( {endContent} ) : null} {description ? {description} : null} {isInvalid && errorMessage ? {errorMessage} : null} ) }) export type TextareaProps = Omit & Omit< ComponentProps, 'children' | 'className' | 'defaultValue' | 'disabled' | 'onChange' | 'readOnly' | 'required' | 'size' | 'value' | 'variant' > & { minRows?: number onBlur?: ComponentProps['onBlur'] onChange?: (event: ChangeEvent) => void } export const Textarea = forwardRef(function Textarea( { className, classNames, description, descriptionClassName, disabled, errorMessage, isClearable, isDisabled, isInvalid, isReadOnly, isRequired, label, labelPlacement: _labelPlacement, minRows, radius, size, validationBehavior, variant, onClear, onValueChange, ...props }, ref ) { return ( {label ? : null}
{ props.onChange?.(event) onValueChange?.(event.target.value) }} /> {isClearable && props.value ? ( ) : null}
{description ? {description} : null} {isInvalid && errorMessage ? {errorMessage} : null}
) })