"use client";
import { useCallback, useRef, useState } from "react";
import { getIcon } from "../icon/config.js";
import { useEnsuredId } from "../useEnsuredId.js";
import { useEnsuredRef } from "../useEnsuredRef.js";
import { useFormReset } from "./useFormReset.js";
import { defaultGetErrorIcon, defaultGetErrorMessage, defaultIsErrored } from "./validation.js";
const noop = ()=>{
// do nothing
};
/**
 * @see {@link https://react-md.dev/components/text-field | TextField Demos}
 * @see {@link https://react-md.dev/hooks/use-text-field | useTextField Demos}
 * @since 6.0.0
 */ export function useTextField(options) {
    const { id: propId, ref: propRef, name, form, defaultValue = "", isNumber = false, required, pattern, minLength, maxLength, onBlur = noop, onChange = noop, onInvalid = noop, counter = false, helpText, disableReset, validationType = "recommended", disableMessage = false, disableMaxLength = false, errorIcon: propErrorIcon, isErrored = defaultIsErrored, onErrorChange = noop, getErrorIcon = defaultGetErrorIcon, getErrorMessage = defaultGetErrorMessage } = options;
    const id = useEnsuredId(propId, "text-field");
    const messageId = `${id}-message`;
    const [fieldRef, ref] = useEnsuredRef(propRef);
    const [state, setState] = useState(()=>{
        const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
        return {
            value,
            error: false,
            errorMessage: ""
        };
    });
    const { value, error, errorMessage } = state;
    // using a `ref` instead of a `useCallback` makes it so the `defaultValue`
    // will always be used once reset.
    const reset = useRef(()=>{
        fieldRef.current?.setCustomValidity("");
        setState({
            value,
            error: false,
            errorMessage: ""
        });
    }).current;
    const errored = useRef(error);
    const checkValidity = useCallback((isBlurEvent)=>{
        const field = fieldRef.current;
        if (!field) {
            throw new Error("Unable to check validity due to missing ref");
        }
        // need to temporarily set the `maxLength` back so it can be "verified"
        // through the validity api
        /* istanbul ignore next */ if (isBlurEvent && disableMaxLength && typeof maxLength === "number") {
            field.maxLength = maxLength;
        }
        const { value } = field;
        field.setCustomValidity("");
        field.checkValidity();
        // remove the temporarily set `maxLength` attribute after checking the
        // validity
        /* istanbul ignore next */ if (disableMaxLength && typeof maxLength === "number") {
            field.removeAttribute("maxLength");
        }
        const options = {
            value,
            pattern,
            required,
            minLength,
            maxLength,
            isBlurEvent,
            isNumber,
            validationType,
            validity: field.validity,
            validationMessage: field.validationMessage
        };
        const errorMessage = getErrorMessage(options);
        const error = isErrored({
            ...options,
            errorMessage
        });
        if (errored.current !== error) {
            errored.current = error;
            onErrorChange({
                ref: fieldRef,
                name,
                error,
                errorMessage
            });
        }
        /* istanbul ignore next */ if (errorMessage !== field.validationMessage) {
            field.setCustomValidity(errorMessage);
        }
        setState((prevState)=>{
            if (prevState.value === value && prevState.error === error && prevState.errorMessage === errorMessage) {
                return prevState;
            }
            return {
                value,
                error,
                errorMessage
            };
        });
    }, [
        disableMaxLength,
        fieldRef,
        getErrorMessage,
        isErrored,
        isNumber,
        maxLength,
        minLength,
        name,
        onErrorChange,
        pattern,
        required,
        validationType
    ]);
    const errorIcon = getIcon("error", propErrorIcon);
    const fieldProps = {
        id,
        ref,
        name,
        value,
        error,
        required,
        pattern,
        minLength,
        maxLength: disableMaxLength ? undefined : maxLength,
        rightAddon: getErrorIcon({
            error,
            errorIcon,
            errorMessage
        }),
        onBlur (event) {
            onBlur(event);
            if (event.isPropagationStopped()) {
                return;
            }
            checkValidity(true);
        },
        onChange (event) {
            onChange(event);
            if (event.isPropagationStopped()) {
                return;
            }
            if (validationType === "blur") {
                const { value } = event.currentTarget;
                setState((prevState)=>({
                        ...prevState,
                        value
                    }));
                return;
            }
            checkValidity(false);
        },
        onInvalid (event) {
            onInvalid(event);
            if (event.isPropagationStopped() || event.currentTarget === document.activeElement) {
                return;
            }
            // this makes it so that if a submit button is clicked in a form, all
            // textfields will gain the error state immediately
            // also need to extract the validationMessage immediately because of the
            // SyntheticEvent behavior in React. By the time the `setState` is called,
            // the event might've been deleted
            const { validationMessage } = event.currentTarget;
            setState((prevState)=>{
                if (prevState.error) {
                    return prevState;
                }
                return {
                    ...prevState,
                    error: true,
                    errorMessage: validationMessage
                };
            });
        }
    };
    const isCounter = counter && typeof maxLength === "number";
    if (isCounter || helpText || !disableMessage) {
        fieldProps["aria-describedby"] = messageId;
        fieldProps.messageProps = {
            id: messageId,
            error,
            length: counter ? value.length : undefined,
            maxLength: counter && maxLength || undefined,
            children: !disableMessage && errorMessage || helpText
        };
    }
    useFormReset({
        form,
        onReset: disableReset ? undefined : reset,
        elementRef: fieldRef
    });
    return {
        ...state,
        reset,
        setState,
        fieldRef,
        fieldProps
    };
}

//# sourceMappingURL=useTextField.js.map