import { type CreateSyncularDatabaseOptions, type MutationReceipt, type MutationsApi, type SyncularBlobUploadQueueStats, type SyncularChangedRow, type SyncularClientLike, type SyncularClientStatus, type SyncularConflictStats, type SyncularConnectionState, type SyncularOutboxStats, type SyncularPresenceEntry, type SyncularRowsChangedEvent } from '@syncular/client';
import type { BlobRef } from '@syncular/core';
import type { CompiledQuery, Kysely } from 'kysely';
import { createElement, type ReactNode } from 'react';
export type SyncularReactStatus = 'idle' | 'loading' | 'ready' | 'error';
export interface SyncProviderProps<DB> {
    children?: ReactNode;
    client?: SyncularClientLike<DB>;
    options?: CreateSyncularDatabaseOptions;
    optionsKey?: unknown;
    closeOnUnmount?: boolean;
    onClient?: (client: SyncularClientLike<DB>) => void;
    onError?: (error: unknown) => void;
}
export interface SyncContextValue {
    status: SyncularReactStatus;
    error: unknown;
}
export interface SyncQueryContext<DB> {
    db: Kysely<DB>;
    selectFrom: Kysely<DB>['selectFrom'];
}
export interface UseSyncQueryOptions {
    enabled?: boolean;
    deps?: readonly unknown[];
    keyField?: string;
    watchTables?: readonly string[];
    tables?: readonly string[];
    pollIntervalMs?: number;
    staleAfterMs?: number;
    structuralSharing?: boolean;
    refreshOnDataChange?: boolean;
    loadingOnRefresh?: boolean;
    transitionUpdates?: boolean;
}
export interface UseSyncQueryResult<T> {
    data: T | undefined;
    isLoading: boolean;
    error: Error | null;
    isStale: boolean;
    lastSyncAt: number | null;
    refetch: () => Promise<void>;
}
export interface UseQueryOptions {
    enabled?: boolean;
    deps?: readonly unknown[];
    keyField?: string;
}
export interface UseQueryResult<T> {
    data: T | undefined;
    isLoading: boolean;
    error: Error | null;
    refetch: () => Promise<void>;
}
export type MutationInput = {
    rowId: string;
    op: 'delete';
    payload?: null;
    baseVersion?: number | null;
} | {
    rowId: string;
    op: 'upsert';
    payload?: Record<string, unknown> | null;
    baseVersion?: number | null;
};
export type MutationResult = MutationReceipt;
export interface FluentMutation {
    update: (rowId: string, payload: Record<string, unknown>, options?: {
        baseVersion?: number | null;
    }) => Promise<MutationResult>;
    upsert: (rowId: string, payload: Record<string, unknown>, options?: {
        baseVersion?: number | null;
    }) => Promise<MutationResult>;
    delete: (rowId: string, options?: {
        baseVersion?: number | null;
    }) => Promise<MutationResult>;
}
export interface UseMutationOptions<TTable extends string> {
    table: TTable;
    syncImmediately?: boolean;
    onSuccess?: (result: MutationResult) => void;
    onError?: (error: Error) => void;
}
export interface UseMutationResult {
    mutate: FluentMutation;
    mutateMany: (inputs: readonly MutationInput[]) => Promise<MutationResult>;
    isPending: boolean;
    error: Error | null;
    reset: () => void;
}
export type SyncMode = 'background' | 'await' | false;
export interface UseMutationsOptions {
    sync?: SyncMode;
    onSuccess?: (result: MutationReceipt & {
        opCount: number;
    }) => void;
    onError?: (error: Error) => void;
}
export type MutationsHook<DB> = MutationsApi<DB, {
    sync?: SyncMode;
}> & {
    readonly $isPending: boolean;
    readonly $error: Error | null;
    $reset: () => void;
};
export interface UseRowsChangedOptions {
    tables?: readonly string[];
    enabled?: boolean;
}
export interface UsePresenceResult<TMetadata extends Record<string, unknown> = Record<string, unknown>> {
    presence: SyncularPresenceEntry<TMetadata>[];
    isLoading: boolean;
}
export interface UsePresenceWithJoinOptions<TMetadata extends Record<string, unknown> = Record<string, unknown>> {
    metadata?: TMetadata;
    autoJoin?: boolean;
    enabled?: boolean;
}
export interface UsePresenceWithJoinResult<TMetadata extends Record<string, unknown> = Record<string, unknown>> extends UsePresenceResult<TMetadata> {
    updateMetadata: (metadata: TMetadata) => void;
    join: (metadata?: TMetadata) => void;
    leave: () => void;
    isJoined: boolean;
}
export interface UseSyncConnectionResult {
    state: SyncularConnectionState;
    isConnected: boolean;
    isReconnecting: boolean;
    reconnect: () => Promise<void>;
    disconnect: () => Promise<void>;
}
export interface UseBlobUploadQueueResult {
    stats: SyncularBlobUploadQueueStats | null;
    refresh(): Promise<void>;
    process(): Promise<{
        uploaded: number;
        failed: number;
    }>;
}
type ExecutableQuery<TResult> = {
    execute(): Promise<TResult>;
    compile?: () => CompiledQuery;
};
type SyncQueryFn<DB, TResult> = (ctx: SyncQueryContext<DB>) => ExecutableQuery<TResult> | Promise<TResult> | TResult;
type KnownTableKey<DB> = string extends keyof DB ? string : Extract<keyof DB, string>;
export declare function createSyncularReact<DB>(): {
    SyncProvider: (props: SyncProviderProps<DB>) => ReturnType<typeof createElement>;
    useBlob: (ref: BlobRef | null | undefined) => Uint8Array | null;
    useBlobUploadQueue: () => UseBlobUploadQueueResult;
    useConflictStats: () => SyncularConflictStats | null;
    useLeasedMutation: <TTable extends KnownTableKey<DB> & string>(options: UseMutationOptions<TTable>) => UseMutationResult;
    useLeasedMutations: (options?: UseMutationsOptions) => MutationsHook<DB>;
    useMutation: <TTable extends KnownTableKey<DB> & string>(options: UseMutationOptions<TTable>) => UseMutationResult;
    useMutations: (options?: UseMutationsOptions) => MutationsHook<DB>;
    useOutboxStats: () => SyncularOutboxStats | null;
    usePresence: <TMetadata extends Record<string, unknown> = Record<string, unknown>>(scopeKey: string, options?: {
        enabled?: boolean;
    }) => UsePresenceResult<TMetadata>;
    usePresenceWithJoin: <TMetadata extends Record<string, unknown> = Record<string, unknown>>(scopeKey: string, options?: UsePresenceWithJoinOptions<TMetadata>) => UsePresenceWithJoinResult<TMetadata>;
    useQuery: <TResult>(query: SyncQueryFn<DB, TResult>, options?: UseQueryOptions) => UseQueryResult<TResult>;
    useRowsChanged: (listener: (event: SyncularRowsChangedEvent) => void, options?: UseRowsChangedOptions) => void;
    useSyncConnection: () => UseSyncConnectionResult;
    useSyncContext: () => SyncContextValue;
    useSyncStatus: () => SyncularClientStatus;
    useSyncQuery: <TResult>(query: SyncQueryFn<DB, TResult>, options?: UseSyncQueryOptions) => UseSyncQueryResult<TResult>;
};
export declare function changedRowsForTable(event: SyncularRowsChangedEvent, table: string): SyncularChangedRow[];
export {};
//# sourceMappingURL=index.d.ts.map