import { FieldApi } from '@tanstack/form-core';
import { createComponent, createComputed, createSignal, onCleanup, onMount, } from 'solid-js';
import { useStore } from '@tanstack/solid-store';
// ugly way to trick solid into triggering updates for changes on the fieldApi
function makeFieldReactive(fieldApi, { mode }) {
    const [field, setField] = createSignal(fieldApi, { equals: false });
    // Subscribe to the pieces of state that should trigger a re-render of the
    // field. For array mode, we only track the length of the array value to
    // avoid re-renders when child properties change. Meta is tracked piece by
    // piece so that consumers re-render when any meta property updates.
    // See: https://github.com/TanStack/form/issues/1961
    const reactiveStateValue = useStore(fieldApi.store, (state) => mode === 'array' ? state.meta._arrayVersion || 0 : state.value);
    const reactiveMetaIsTouched = useStore(fieldApi.store, (state) => state.meta.isTouched);
    const reactiveMetaIsBlurred = useStore(fieldApi.store, (state) => state.meta.isBlurred);
    const reactiveMetaIsDirty = useStore(fieldApi.store, (state) => state.meta.isDirty);
    const reactiveMetaErrorMap = useStore(fieldApi.store, (state) => state.meta.errorMap);
    const reactiveMetaErrorSourceMap = useStore(fieldApi.store, (state) => state.meta.errorSourceMap);
    const reactiveMetaIsValidating = useStore(fieldApi.store, (state) => state.meta.isValidating);
    // Run before initial render
    createComputed(() => {
        // Read all reactive sources to track them as dependencies
        reactiveStateValue();
        reactiveMetaIsTouched();
        reactiveMetaIsBlurred();
        reactiveMetaIsDirty();
        reactiveMetaErrorMap();
        reactiveMetaErrorSourceMap();
        reactiveMetaIsValidating();
        setField(fieldApi);
    });
    return field;
}
export function createField(opts) {
    const options = opts();
    const api = new FieldApi(options);
    const extendedApi = api;
    let mounted = false;
    // Instantiates field meta and removes it when unrendered
    onMount(() => {
        const cleanupFn = api.mount();
        mounted = true;
        onCleanup(() => {
            cleanupFn();
            mounted = false;
        });
    });
    /**
     * fieldApi.update should not have any side effects. Think of it like a `useRef`
     * that we need to keep updated every render with the most up-to-date information.
     *
     * createComputed to make sure this effect runs before render effects
     */
    createComputed(() => {
        if (!mounted)
            return;
        api.update(opts());
    });
    return makeFieldReactive(extendedApi, { mode: options.mode });
}
export function Field(props) {
    const fieldApi = createField(() => {
        const { children, ...fieldOptions } = props;
        return fieldOptions;
    });
    return <>{createComponent(() => props.children(fieldApi), {})}</>;
}
//# sourceMappingURL=createField.jsx.map