import { useCallback, useLayoutEffect, useMemo, useState, } from "react";
import { useCombinedRefs } from "../../../hook/useCombinedRefs";
import { useInputValidation, } from "../../../hook/useInputValidation";
import { useResize } from "../../../hook/useResize";
import { cx } from "../../../utils";
import * as inputStyles from "../input/input.css";
import * as styles from "./textarea.css";
/**
 * A textarea component that automatically resizes based on its content.
 *
 * @remarks
 * This component integrates with `useInputValidation` for validation and `useResize`
 * to handle dynamic resizing. It expands vertically as the user types, up to a specified
 * `maxBlockSize`.
 *
 * @param props - The component props.
 * @returns The rendered textarea element.
 *
 * @example
 * ```tsx
 * import { string, maxLength } from 'valibot';
 * import { Textarea } from './textarea';
 *
 * const bioSchema = string([maxLength(500)]);
 *
 * function BioField() {
 *   return (
 *     <Textarea
 *       name="bio"
 *       placeholder="Tell us about yourself"
 *       validate={bioSchema}
 *       minRows={3}
 *       maxBlockSize={300}
 *     />
 *   );
 * }
 * ```
 */
export function Textarea({ value, maxBlockSize = null, minRows = 1, className = "", style = {}, validate, onValidationError, onChange, onBlur, ref, ...rest }) {
    let [input, setInput] = useState(null);
    let textareaRef = useCombinedRefs(setInput, ref);
    let { paddingBlockEnd } = useMemo(() => {
        if (!input)
            return { paddingBlockEnd: "0px" };
        return window.getComputedStyle(input);
    }, [input]);
    let resize = useCallback(() => {
        if (input === null)
            return;
        input.style.blockSize = "auto";
        requestAnimationFrame(() => {
            if (input === null) {
                return;
            }
            let { scrollHeight } = input;
            input.style.blockSize = `calc(${scrollHeight}px + ${paddingBlockEnd})`;
        });
    }, [input, paddingBlockEnd]);
    useLayoutEffect(() => resize(), [resize]);
    useResize(resize);
    let inlineStyles = {
        ...style,
        maxBlockSize: maxBlockSize === null
            ? "auto"
            : typeof maxBlockSize === "number"
                ? `${maxBlockSize}px`
                : maxBlockSize,
        scrollbarWidth: maxBlockSize === null ? "none" : "thin",
    };
    let handlers = useInputValidation({
        name: rest.name,
        validate,
        required: rest.required,
        onValidationError,
        onChange,
        onBlur,
    });
    let handleChange = (e) => {
        handlers.onChange(e);
        resize();
    };
    return (<textarea {...rest} style={inlineStyles} ref={textareaRef} className={cx(className, styles.textarea, inputStyles.input)} value={value} rows={minRows} onChange={handleChange} onBlur={handlers.onBlur}/>);
}
