import { AxiosProgressEvent, AxiosResponse } from 'axios';
import { Response } from './response';
declare module 'axios' {
    interface AxiosProgressEvent {
        percentage: number | undefined;
    }
}
export type DefaultInertiaConfig = {
    errorValueType: string;
    sharedPageProps: PageProps;
};
/**
 * Designed to allow overriding of some core types using TypeScript
 * interface declaration merging.
 *
 * @see {@link DefaultInertiaConfig} for keys to override
 * @example
 * ```ts
 * declare module '@inertiajs/core' {
 *   export interface InertiaConfig {
 *     errorValueType: string[]
 *     sharedPageProps: {
 *       auth: { user: User | null }
 *       flash: { success?: string; error?: string }
 *     }
 *   }
 * }
 * ```
 */
export interface InertiaConfig {
}
export type InertiaConfigFor<Key extends keyof DefaultInertiaConfig> = Key extends keyof InertiaConfig ? InertiaConfig[Key] : DefaultInertiaConfig[Key];
export type ErrorValue = InertiaConfigFor<'errorValueType'>;
export type SharedPageProps = InertiaConfigFor<'sharedPageProps'>;
export type Errors = Record<string, ErrorValue>;
export type ErrorBag = Record<string, Errors>;
export type FormDataConvertibleValue = Blob | FormDataEntryValue | Date | boolean | number | null | undefined;
export type FormDataConvertible = Array<FormDataConvertible> | {
    [key: string]: FormDataConvertible;
} | FormDataConvertibleValue;
export type FormDataType<T extends object> = {
    [K in keyof T]: T[K] extends infer U ? U extends FormDataConvertibleValue ? U : U extends (...args: unknown[]) => unknown ? never : U extends object | Array<unknown> ? FormDataType<U> : never : never;
};
/**
 * Uses `0 extends 1 & T` to detect `any` type and prevent infinite recursion.
 */
export type FormDataKeys<T> = T extends Function | FormDataConvertibleValue ? never : T extends unknown[] ? ArrayFormDataKeys<T> : T extends object ? ObjectFormDataKeys<T> : never;
/**
 * Helper type for array form data keys
 */
type ArrayFormDataKeys<T extends unknown[]> = number extends T['length'] ? `${number}` | (0 extends 1 & T[number] ? never : T[number] extends FormDataConvertibleValue ? never : `${number}.${FormDataKeys<T[number]>}`) : Extract<keyof T, `${number}`> | {
    [Key in Extract<keyof T, `${number}`>]: 0 extends 1 & T[Key] ? never : T[Key] extends FormDataConvertibleValue ? never : `${Key & string}.${FormDataKeys<T[Key & string] & string>}`;
}[Extract<keyof T, `${number}`>];
/**
 * Helper type for object form data keys
 */
type ObjectFormDataKeys<T extends object> = string extends keyof T ? string : Extract<keyof T, string> | {
    [Key in Extract<keyof T, string>]: 0 extends 1 & T[Key] ? never : T[Key] extends FormDataConvertibleValue ? never : T[Key] extends any[] ? `${Key}.${FormDataKeys<T[Key]> & string}` : T[Key] extends Record<string, any> ? `${Key}.${FormDataKeys<T[Key]> & string}` : Exclude<T[Key], null | undefined> extends any[] ? never : Exclude<T[Key], null | undefined> extends Record<string, any> ? `${Key}.${FormDataKeys<Exclude<T[Key], null | undefined>> & string}` : never;
}[Extract<keyof T, string>];
type PartialFormDataErrors<T> = {
    [K in string extends keyof T ? string : Extract<keyof FormDataError<T>, string>]?: ErrorValue;
};
export type FormDataErrors<T> = PartialFormDataErrors<T> & {
    [K in keyof PartialFormDataErrors<T>]: NonNullable<PartialFormDataErrors<T>[K]>;
};
export type FormDataValues<T, K extends FormDataKeys<T>> = K extends `${infer P}.${infer Rest}` ? T extends unknown[] ? P extends `${infer I extends number}` ? Rest extends FormDataKeys<T[I]> ? FormDataValues<T[I], Rest> : never : never : P extends keyof T ? Rest extends FormDataKeys<T[P]> ? FormDataValues<T[P], Rest> : never : never : K extends keyof T ? T[K] : T extends unknown[] ? T[K & number] : never;
export type FormDataError<T> = Partial<Record<FormDataKeys<T>, ErrorValue>>;
export type Method = 'get' | 'post' | 'put' | 'patch' | 'delete';
export type RequestPayload = Record<string, FormDataConvertible> | FormData;
export interface PageProps {
    [key: string]: unknown;
}
export type ScrollProp = {
    pageName: string;
    previousPage: number | string | null;
    nextPage: number | string | null;
    currentPage: number | string | null;
    reset: boolean;
};
export interface Page<SharedProps extends PageProps = PageProps> {
    component: string;
    props: PageProps & SharedProps & {
        errors: Errors & ErrorBag;
        deferred?: Record<string, VisitOptions['only']>;
    };
    url: string;
    version: string | null;
    clearHistory: boolean;
    encryptHistory: boolean;
    deferredProps?: Record<string, VisitOptions['only']>;
    mergeProps?: string[];
    prependProps?: string[];
    deepMergeProps?: string[];
    matchPropsOn?: string[];
    scrollProps?: Record<keyof PageProps, ScrollProp>;
    /** @internal */
    rememberedState: Record<string, unknown>;
}
export type ScrollRegion = {
    top: number;
    left: number;
};
export interface ClientSideVisitOptions<TProps = Page['props']> {
    component?: Page['component'];
    url?: Page['url'];
    props?: ((props: TProps) => PageProps) | PageProps;
    clearHistory?: Page['clearHistory'];
    encryptHistory?: Page['encryptHistory'];
    preserveScroll?: VisitOptions['preserveScroll'];
    preserveState?: VisitOptions['preserveState'];
    errorBag?: string | null;
    viewTransition?: VisitOptions['viewTransition'];
    onError?: (errors: Errors) => void;
    onFinish?: (visit: ClientSideVisitOptions<TProps>) => void;
    onSuccess?: (page: Page) => void;
}
export type PageResolver = (name: string) => Component;
export type PageHandler<ComponentType = Component> = ({ component, page, preserveState, }: {
    component: ComponentType;
    page: Page;
    preserveState: boolean;
}) => Promise<unknown>;
export type PreserveStateOption = boolean | 'errors' | ((page: Page) => boolean);
export type QueryStringArrayFormatOption = 'indices' | 'brackets';
export type Progress = AxiosProgressEvent;
export type LocationVisit = {
    preserveScroll: boolean;
};
export type CancelToken = {
    cancel: VoidFunction;
};
export type CancelTokenCallback = (cancelToken: CancelToken) => void;
export type Visit<T extends RequestPayload = RequestPayload> = {
    method: Method;
    data: T;
    replace: boolean;
    preserveScroll: PreserveStateOption;
    preserveState: PreserveStateOption;
    only: Array<string>;
    except: Array<string>;
    headers: Record<string, string>;
    errorBag: string | null;
    forceFormData: boolean;
    queryStringArrayFormat: QueryStringArrayFormatOption;
    async: boolean;
    showProgress: boolean;
    prefetch: boolean;
    fresh: boolean;
    reset: string[];
    preserveUrl: boolean;
    invalidateCacheTags: string | string[];
    viewTransition: boolean | ((viewTransition: ViewTransition) => void);
};
export type GlobalEventsMap<T extends RequestPayload = RequestPayload> = {
    before: {
        parameters: [PendingVisit<T>];
        details: {
            visit: PendingVisit<T>;
        };
        result: boolean | void;
    };
    start: {
        parameters: [PendingVisit<T>];
        details: {
            visit: PendingVisit<T>;
        };
        result: void;
    };
    progress: {
        parameters: [Progress | undefined];
        details: {
            progress: Progress | undefined;
        };
        result: void;
    };
    finish: {
        parameters: [ActiveVisit<T>];
        details: {
            visit: ActiveVisit<T>;
        };
        result: void;
    };
    cancel: {
        parameters: [];
        details: {};
        result: void;
    };
    beforeUpdate: {
        parameters: [Page];
        details: {
            page: Page;
        };
        result: void;
    };
    navigate: {
        parameters: [Page];
        details: {
            page: Page;
        };
        result: void;
    };
    success: {
        parameters: [Page];
        details: {
            page: Page;
        };
        result: void;
    };
    error: {
        parameters: [Errors];
        details: {
            errors: Errors;
        };
        result: void;
    };
    invalid: {
        parameters: [AxiosResponse];
        details: {
            response: AxiosResponse;
        };
        result: boolean | void;
    };
    exception: {
        parameters: [Error];
        details: {
            exception: Error;
        };
        result: boolean | void;
    };
    prefetched: {
        parameters: [AxiosResponse, ActiveVisit<T>];
        details: {
            response: AxiosResponse;
            fetchedAt: number;
            visit: ActiveVisit<T>;
        };
        result: void;
    };
    prefetching: {
        parameters: [ActiveVisit<T>];
        details: {
            visit: ActiveVisit<T>;
        };
        result: void;
    };
};
export type PageEvent = 'newComponent' | 'firstLoad';
export type GlobalEventNames<T extends RequestPayload = RequestPayload> = keyof GlobalEventsMap<T>;
export type GlobalEvent<TEventName extends GlobalEventNames<T>, T extends RequestPayload = RequestPayload> = CustomEvent<GlobalEventDetails<TEventName, T>>;
export type GlobalEventParameters<TEventName extends GlobalEventNames<T>, T extends RequestPayload = RequestPayload> = GlobalEventsMap<T>[TEventName]['parameters'];
export type GlobalEventResult<TEventName extends GlobalEventNames<T>, T extends RequestPayload = RequestPayload> = GlobalEventsMap<T>[TEventName]['result'];
export type GlobalEventDetails<TEventName extends GlobalEventNames<T>, T extends RequestPayload = RequestPayload> = GlobalEventsMap<T>[TEventName]['details'];
export type GlobalEventTrigger<TEventName extends GlobalEventNames<T>, T extends RequestPayload = RequestPayload> = (...params: GlobalEventParameters<TEventName, T>) => GlobalEventResult<TEventName, T>;
export type GlobalEventCallback<TEventName extends GlobalEventNames<T>, T extends RequestPayload = RequestPayload> = (...params: GlobalEventParameters<TEventName, T>) => GlobalEventResult<TEventName, T>;
export type InternalEvent = 'missingHistoryItem' | 'loadDeferredProps';
export type VisitCallbacks<T extends RequestPayload = RequestPayload> = {
    onCancelToken: CancelTokenCallback;
    onBefore: GlobalEventCallback<'before', T>;
    onBeforeUpdate: GlobalEventCallback<'beforeUpdate', T>;
    onStart: GlobalEventCallback<'start', T>;
    onProgress: GlobalEventCallback<'progress', T>;
    onFinish: GlobalEventCallback<'finish', T>;
    onCancel: GlobalEventCallback<'cancel', T>;
    onSuccess: GlobalEventCallback<'success', T>;
    onError: GlobalEventCallback<'error', T>;
    onPrefetched: GlobalEventCallback<'prefetched', T>;
    onPrefetching: GlobalEventCallback<'prefetching', T>;
};
export type VisitOptions<T extends RequestPayload = RequestPayload> = Partial<Visit<T> & VisitCallbacks<T>>;
export type ReloadOptions<T extends RequestPayload = RequestPayload> = Omit<VisitOptions<T>, 'preserveScroll' | 'preserveState'>;
export type PollOptions = {
    keepAlive?: boolean;
    autoStart?: boolean;
};
export type VisitHelperOptions<T extends RequestPayload = RequestPayload> = Omit<VisitOptions<T>, 'method' | 'data'>;
export type RouterInitParams<ComponentType = Component> = {
    initialPage: Page;
    resolveComponent: PageResolver;
    swapComponent: PageHandler<ComponentType>;
};
export type PendingVisitOptions = {
    url: URL;
    completed: boolean;
    cancelled: boolean;
    interrupted: boolean;
};
export type PendingVisit<T extends RequestPayload = RequestPayload> = Visit<T> & PendingVisitOptions;
export type ActiveVisit<T extends RequestPayload = RequestPayload> = PendingVisit<T> & Required<VisitOptions<T>>;
export type InternalActiveVisit = ActiveVisit & {
    onPrefetchResponse?: (response: Response) => void;
    onPrefetchError?: (error: Error) => void;
};
export type VisitId = unknown;
export type Component = unknown;
type FirstLevelOptional<T> = {
    [K in keyof T]?: T[K] extends object ? {
        [P in keyof T[K]]?: T[K][P];
    } : T[K];
};
interface CreateInertiaAppOptions<TComponentResolver, TSetupOptions, TSetupReturn, TAdditionalInertiaAppConfig> {
    resolve: TComponentResolver;
    setup: (options: TSetupOptions) => TSetupReturn;
    title?: HeadManagerTitleCallback;
    defaults?: FirstLevelOptional<InertiaAppConfig & TAdditionalInertiaAppConfig>;
}
export interface CreateInertiaAppOptionsForCSR<SharedProps extends PageProps, TComponentResolver, TSetupOptions, TSetupReturn, TAdditionalInertiaAppConfig> extends CreateInertiaAppOptions<TComponentResolver, TSetupOptions, TSetupReturn, TAdditionalInertiaAppConfig> {
    id?: string;
    page?: Page<SharedProps>;
    progress?: false | {
        delay?: number;
        color?: string;
        includeCSS?: boolean;
        showSpinner?: boolean;
    };
    render?: undefined;
}
export interface CreateInertiaAppOptionsForSSR<SharedProps extends PageProps, TComponentResolver, TSetupOptions, TSetupReturn, TAdditionalInertiaAppConfig> extends CreateInertiaAppOptions<TComponentResolver, TSetupOptions, TSetupReturn, TAdditionalInertiaAppConfig> {
    id?: undefined;
    page: Page<SharedProps>;
    progress?: undefined;
    render: unknown;
}
export type InertiaAppSSRResponse = {
    head: string[];
    body: string;
};
export type InertiaAppResponse = Promise<InertiaAppSSRResponse | void>;
export type HeadManagerTitleCallback = (title: string) => string;
export type HeadManagerOnUpdateCallback = (elements: string[]) => void;
export type HeadManager = {
    forceUpdate: () => void;
    createProvider: () => {
        preferredAttribute: () => 'data-inertia' | 'inertia';
        reconnect: () => void;
        update: HeadManagerOnUpdateCallback;
        disconnect: () => void;
    };
};
export type LinkPrefetchOption = 'mount' | 'hover' | 'click';
export type TimeUnit = 'ms' | 's' | 'm' | 'h' | 'd';
export type CacheForOption = number | `${number}${TimeUnit}` | string;
export type PrefetchOptions = {
    cacheFor: CacheForOption | CacheForOption[];
    cacheTags: string | string[];
};
export type InertiaAppConfig = {
    form: {
        recentlySuccessfulDuration: number;
        forceIndicesArrayFormatInFormData: boolean;
    };
    future: {
        preserveEqualProps: boolean;
        useDataInertiaHeadAttribute: boolean;
        useDialogForErrorModal: boolean;
    };
    prefetch: {
        cacheFor: CacheForOption | CacheForOption[];
        hoverDelay: number;
    };
    visitOptions?: (href: string, options: VisitOptions) => VisitOptions;
};
export interface LinkComponentBaseProps extends Partial<Pick<Visit<RequestPayload>, 'data' | 'method' | 'replace' | 'preserveScroll' | 'preserveState' | 'preserveUrl' | 'only' | 'except' | 'headers' | 'queryStringArrayFormat' | 'async' | 'viewTransition'> & VisitCallbacks & {
    href: string | UrlMethodPair;
    prefetch: boolean | LinkPrefetchOption | LinkPrefetchOption[];
    cacheFor: CacheForOption | CacheForOption[];
    cacheTags: string | string[];
}> {
}
type PrefetchObject = {
    params: ActiveVisit;
    response: Promise<Response>;
};
export type InFlightPrefetch = PrefetchObject & {
    staleTimestamp: null;
    inFlight: true;
};
export type PrefetchCancellationToken = {
    isCancelled: boolean;
    cancel: () => void;
};
export type PrefetchedResponse = PrefetchObject & {
    staleTimestamp: number;
    timestamp: number;
    singleUse: boolean;
    inFlight: false;
    tags: string[];
};
export type PrefetchRemovalTimer = {
    params: ActiveVisit;
    timer: number;
};
export type ProgressSettings = {
    minimum: number;
    easing: string;
    positionUsing: 'translate3d' | 'translate' | 'margin';
    speed: number;
    trickle: boolean;
    trickleSpeed: number;
    showSpinner: boolean;
    barSelector: string;
    spinnerSelector: string;
    parent: string;
    template: string;
    includeCSS: boolean;
    color: string;
};
export type UrlMethodPair = {
    url: string;
    method: Method;
};
export type FormComponentOptions = Pick<VisitOptions, 'preserveScroll' | 'preserveState' | 'preserveUrl' | 'replace' | 'only' | 'except' | 'reset'>;
export type FormComponentProps = Partial<Pick<Visit, 'headers' | 'queryStringArrayFormat' | 'errorBag' | 'showProgress' | 'invalidateCacheTags'> & Omit<VisitCallbacks, 'onPrefetched' | 'onPrefetching'>> & {
    method?: Method | Uppercase<Method>;
    action?: string | UrlMethodPair;
    transform?: (data: Record<string, FormDataConvertible>) => Record<string, FormDataConvertible>;
    options?: FormComponentOptions;
    onSubmitComplete?: (props: FormComponentonSubmitCompleteArguments) => void;
    disableWhileProcessing?: boolean;
    resetOnSuccess?: boolean | string[];
    resetOnError?: boolean | string[];
    setDefaultsOnSuccess?: boolean;
};
export type FormComponentMethods = {
    clearErrors: (...fields: string[]) => void;
    resetAndClearErrors: (...fields: string[]) => void;
    setError(field: string, value: ErrorValue): void;
    setError(errors: Record<string, ErrorValue>): void;
    reset: (...fields: string[]) => void;
    submit: () => void;
    defaults: () => void;
    getData: () => Record<string, FormDataConvertible>;
    getFormData: () => FormData;
};
export type FormComponentonSubmitCompleteArguments = Pick<FormComponentMethods, 'reset' | 'defaults'>;
export type FormComponentState = {
    errors: Record<string, ErrorValue>;
    hasErrors: boolean;
    processing: boolean;
    progress: Progress | null;
    wasSuccessful: boolean;
    recentlySuccessful: boolean;
    isDirty: boolean;
};
export type FormComponentSlotProps = FormComponentMethods & FormComponentState;
export type FormComponentRef = FormComponentSlotProps;
export interface UseInfiniteScrollOptions {
    getPropName: () => string;
    inReverseMode: () => boolean;
    shouldFetchNext: () => boolean;
    shouldFetchPrevious: () => boolean;
    shouldPreserveUrl: () => boolean;
    getTriggerMargin: () => number;
    getStartElement: () => HTMLElement;
    getEndElement: () => HTMLElement;
    getItemsElement: () => HTMLElement;
    getScrollableParent: () => HTMLElement | null;
    onBeforePreviousRequest: () => void;
    onBeforeNextRequest: () => void;
    onCompletePreviousRequest: () => void;
    onCompleteNextRequest: () => void;
}
export interface UseInfiniteScrollDataManager {
    getLastLoadedPage: () => number | string | null;
    getPageName: () => string;
    getRequestCount: () => number;
    hasPrevious: () => boolean;
    hasNext: () => boolean;
    fetchNext: (reloadOptions?: ReloadOptions) => void;
    fetchPrevious: (reloadOptions?: ReloadOptions) => void;
    removeEventListener: () => void;
}
export interface UseInfiniteScrollElementManager {
    setupObservers: () => void;
    enableTriggers: () => void;
    disableTriggers: () => void;
    refreshTriggers: () => void;
    flushAll: () => void;
    processManuallyAddedElements: () => void;
    processServerLoadedElements: (loadedPage: string | number | null) => void;
}
export interface UseInfiniteScrollProps {
    dataManager: UseInfiniteScrollDataManager;
    elementManager: UseInfiniteScrollElementManager;
    flush: () => void;
}
export interface InfiniteScrollSlotProps {
    loading: boolean;
    loadingPrevious: boolean;
    loadingNext: boolean;
}
export interface InfiniteScrollActionSlotProps {
    loading: boolean;
    loadingPrevious: boolean;
    loadingNext: boolean;
    fetch: () => void;
    autoMode: boolean;
    manualMode: boolean;
    hasMore: boolean;
    hasPrevious: boolean;
    hasNext: boolean;
}
export interface InfiniteScrollRef {
    fetchNext: (reloadOptions?: ReloadOptions) => void;
    fetchPrevious: (reloadOptions?: ReloadOptions) => void;
    hasPrevious: () => boolean;
    hasNext: () => boolean;
}
export interface InfiniteScrollComponentBaseProps {
    data: string;
    buffer?: number;
    as?: string;
    manual?: boolean;
    manualAfter?: number;
    preserveUrl?: boolean;
    reverse?: boolean;
    autoScroll?: boolean;
    onlyNext?: boolean;
    onlyPrevious?: boolean;
}
declare global {
    interface DocumentEventMap {
        'inertia:before': GlobalEvent<'before'>;
        'inertia:start': GlobalEvent<'start'>;
        'inertia:progress': GlobalEvent<'progress'>;
        'inertia:success': GlobalEvent<'success'>;
        'inertia:error': GlobalEvent<'error'>;
        'inertia:invalid': GlobalEvent<'invalid'>;
        'inertia:exception': GlobalEvent<'exception'>;
        'inertia:finish': GlobalEvent<'finish'>;
        'inertia:beforeUpdate': GlobalEvent<'beforeUpdate'>;
        'inertia:navigate': GlobalEvent<'navigate'>;
    }
}
export {};
