import * as _liveblocks_core from '@liveblocks/core';
import { BaseMetadata, StorageStatus, QueryMetadata, AsyncResult, DRI, AsyncSuccess, Resolve, CommentBody, CommentAttachment, PartialUnless, Patchable, InboxNotificationData, UserNotificationSettings, Relax, ToImmutable, PartialUserNotificationSettings, AsyncLoading, AsyncError, ThreadData, HistoryVersion, Client, LiveblocksError, SyncStatus, RoomEventMessage, CommentData, MutableSignal, ThreadDataWithDeleteInfo, ThreadDeleteInfo, DerivedSignal, DefaultMap, OpaqueClient, CommentUserReaction, InboxNotificationDeleteInfo, RoomNotificationSettings as RoomNotificationSettings$1, ISignal, Permission, BaseUserMeta as BaseUserMeta$1, DistributiveOmit, DU, DM, TextEditorType, IYjsProvider, DP, DS, DE } from '@liveblocks/core';
import * as react_jsx_runtime from 'react/jsx-runtime';
import * as react from 'react';
import { Context, PropsWithChildren, ReactNode } from 'react';
import { JsonObject, LsonObject, BaseUserMeta, LiveObject, User, Json, RoomNotificationSettings, Room, Status, BroadcastOptions, OthersEvent, LostConnectionEvent, History, BaseMetadata as BaseMetadata$1, Client as Client$1, ClientOptions, StorageStatus as StorageStatus$1, ThreadData as ThreadData$1, CommentData as CommentData$1 } from '@liveblocks/client';

type UseSyncStatusOptions = {
    /**
     * When setting smooth, the hook will not update immediately as status
     * changes. This is because in typical applications, these states can change
     * quickly between synchronizing and synchronized. If you use this hook to
     * build a "Saving changes..." style UI, prefer setting `smooth: true`.
     */
    smooth?: boolean;
};
type UseStorageStatusOptions = UseSyncStatusOptions;
type StorageStatusSuccess = Exclude<StorageStatus, "not-loaded" | "loading">;
type ThreadsQuery<M extends BaseMetadata> = {
    /**
     * Whether to only return threads marked as resolved or unresolved. If not provided,
     * all threads will be returned.
     */
    resolved?: boolean;
    /**
     * The metadata to filter the threads by. If provided, only threads with metadata that matches
     * the provided metadata will be returned. If not provided, all threads will be returned.
     */
    metadata?: Partial<QueryMetadata<M>>;
};
type UseUserThreadsOptions<M extends BaseMetadata> = {
    /**
     * The query (including metadata) to filter the threads by. If provided, only threads
     * that match the query will be returned. If not provided, all threads will be returned.
     */
    query?: ThreadsQuery<M>;
};
type UseThreadsOptions<M extends BaseMetadata> = {
    /**
     * The query (including metadata) to filter the threads by. If provided, only threads
     * that match the query will be returned. If not provided, all threads will be returned.
     */
    query?: ThreadsQuery<M>;
    /**
     * Whether to scroll to a comment on load based on the URL hash. Defaults to `true`.
     *
     * @example
     * Given the URL `https://example.com/my-room#cm_xxx`, the `cm_xxx` comment will be
     * scrolled to on load if it exists in the page.
     */
    scrollOnLoad?: boolean;
};
type UserAsyncResult<T> = AsyncResult<T, "user">;
type UserAsyncSuccess<T> = AsyncSuccess<T, "user">;
type RoomInfoAsyncResult = AsyncResult<DRI, "info">;
type RoomInfoAsyncSuccess = AsyncSuccess<DRI, "info">;
type AttachmentUrlAsyncResult = AsyncResult<string, "url">;
type AttachmentUrlAsyncSuccess = AsyncSuccess<string, "url">;
type CreateThreadOptions<M extends BaseMetadata> = Resolve<{
    body: CommentBody;
    attachments?: CommentAttachment[];
} & PartialUnless<M, {
    metadata: M;
}>>;
type EditThreadMetadataOptions<M extends BaseMetadata> = {
    threadId: string;
    metadata: Patchable<M>;
};
type CreateCommentOptions = {
    threadId: string;
    body: CommentBody;
    attachments?: CommentAttachment[];
};
type EditCommentOptions = {
    threadId: string;
    commentId: string;
    body: CommentBody;
    attachments?: CommentAttachment[];
};
type DeleteCommentOptions = {
    threadId: string;
    commentId: string;
};
type CommentReactionOptions = {
    threadId: string;
    commentId: string;
    emoji: string;
};
type PaginationFields = {
    hasFetchedAll: boolean;
    isFetchingMore: boolean;
    fetchMore: () => void;
    fetchMoreError?: Error;
};
type PagedAsyncSuccess<T, F extends string> = Resolve<AsyncSuccess<T, F> & PaginationFields>;
type PagedAsyncResult<T, F extends string> = Relax<AsyncLoading<F> | AsyncError<F> | PagedAsyncSuccess<T, F>>;
type ThreadsAsyncSuccess<M extends BaseMetadata> = PagedAsyncSuccess<ThreadData<M>[], "threads">;
type ThreadsAsyncResult<M extends BaseMetadata> = PagedAsyncResult<ThreadData<M>[], "threads">;
type InboxNotificationsAsyncSuccess = PagedAsyncSuccess<InboxNotificationData[], "inboxNotifications">;
type InboxNotificationsAsyncResult = PagedAsyncResult<InboxNotificationData[], "inboxNotifications">;
type UnreadInboxNotificationsCountAsyncSuccess = AsyncSuccess<number, "count">;
type UnreadInboxNotificationsCountAsyncResult = AsyncResult<number, "count">;
type UserNotificationSettingsAsyncResult = AsyncResult<UserNotificationSettings, "settings">;
type RoomNotificationSettingsAsyncSuccess = AsyncSuccess<RoomNotificationSettings, "settings">;
type RoomNotificationSettingsAsyncResult = AsyncResult<RoomNotificationSettings, "settings">;
type HistoryVersionDataAsyncResult = AsyncResult<Uint8Array>;
type HistoryVersionsAsyncSuccess = AsyncSuccess<HistoryVersion[], "versions">;
type HistoryVersionsAsyncResult = AsyncResult<HistoryVersion[], "versions">;
type RoomProviderProps<P extends JsonObject, S extends LsonObject> = Resolve<{
    /**
     * The id of the room you want to connect to
     */
    id: string;
    children: ReactNode;
    /**
     * Whether or not the room should connect to Liveblocks servers
     * when the RoomProvider is rendered.
     *
     * By default equals to `typeof window !== "undefined"`,
     * meaning the RoomProvider tries to connect to Liveblocks servers
     * only on the client side.
     */
    autoConnect?: boolean;
} & PartialUnless<P, {
    /**
     * The initial Presence to use and announce when you enter the Room. The
     * Presence is available on all users in the Room (me & others).
     */
    initialPresence: P | ((roomId: string) => P);
}> & PartialUnless<S, {
    /**
     * The initial Storage to use when entering a new Room.
     */
    initialStorage: S | ((roomId: string) => S);
}>>;
/**
 * For any function type, returns a similar function type, but without the
 * first argument.
 */
type OmitFirstArg<F> = F extends (first: any, ...rest: infer A) => infer R ? (...args: A) => R : never;
type MutationContext<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta> = {
    storage: LiveObject<S>;
    self: User<P, U>;
    others: readonly User<P, U>[];
    setMyPresence: (patch: Partial<P>, options?: {
        addToHistory: boolean;
    }) => void;
};
type ThreadSubscription = Relax<{
    status: "not-subscribed";
} | {
    status: "subscribed";
    unreadSince: null;
} | {
    status: "subscribed";
    unreadSince: Date;
}>;
type SharedContextBundle<U extends BaseUserMeta> = {
    classic: {
        /**
         * Obtains a reference to the current Liveblocks client.
         */
        useClient(): Client<U>;
        /**
         * Returns user info from a given user ID.
         *
         * @example
         * const { user, error, isLoading } = useUser("user-id");
         */
        useUser(userId: string): UserAsyncResult<U["info"]>;
        /**
         * Returns room info from a given room ID.
         *
         * @example
         * const { info, error, isLoading } = useRoomInfo("room-id");
         */
        useRoomInfo(roomId: string): RoomInfoAsyncResult;
        /**
         * Returns whether the hook is called within a RoomProvider context.
         *
         * @example
         * const isInsideRoom = useIsInsideRoom();
         */
        useIsInsideRoom(): boolean;
        /**
         * useErrorListener is a React hook that allows you to respond to any
         * Liveblocks error, for example room connection errors, errors
         * creating/editing/deleting threads, etc.
         *
         * @example
         * useErrorListener(err => {
         *   console.error(err);
         * })
         */
        useErrorListener(callback: (err: LiveblocksError) => void): void;
        /**
         * Returns the current Liveblocks sync status, and triggers a re-render
         * whenever it changes. Can be used to render a "Saving..." indicator, or for
         * preventing that a browser tab can be closed until all changes have been
         * synchronized with the server.
         *
         * @example
         * const syncStatus = useSyncStatus();  // "synchronizing" | "synchronized"
         * const syncStatus = useSyncStatus({ smooth: true });
         */
        useSyncStatus(options?: UseSyncStatusOptions): SyncStatus;
    };
    suspense: {
        /**
         * Obtains a reference to the current Liveblocks client.
         */
        useClient(): Client<U>;
        /**
         * Returns user info from a given user ID.
         *
         * @example
         * const { user } = useUser("user-id");
         */
        useUser(userId: string): UserAsyncSuccess<U["info"]>;
        /**
         * Returns room info from a given room ID.
         *
         * @example
         * const { info } = useRoomInfo("room-id");
         */
        useRoomInfo(roomId: string): RoomInfoAsyncSuccess;
        /**
         * Returns whether the hook is called within a RoomProvider context.
         *
         * @example
         * const isInsideRoom = useIsInsideRoom();
         */
        useIsInsideRoom(): boolean;
        /**
         * useErrorListener is a React hook that allows you to respond to any
         * Liveblocks error, for example room connection errors, errors
         * creating/editing/deleting threads, etc.
         *
         * @example
         * useErrorListener(err => {
         *   console.error(err);
         * })
         */
        useErrorListener(callback: (err: LiveblocksError) => void): void;
        /**
         * Returns the current Liveblocks sync status, and triggers a re-render
         * whenever it changes. Can be used to render a "Saving..." indicator, or for
         * preventing that a browser tab can be closed until all changes have been
         * synchronized with the server.
         *
         * @example
         * const syncStatus = useSyncStatus();  // "synchronizing" | "synchronized"
         * const syncStatus = useSyncStatus({ smooth: true });
         */
        useSyncStatus(options?: UseSyncStatusOptions): SyncStatus;
    };
};
/**
 * Properties that are the same in RoomContext and RoomContext["suspense"].
 */
type RoomContextBundleCommon<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json, M extends BaseMetadata> = {
    /**
     * You normally don't need to directly interact with the RoomContext, but
     * it can be necessary if you're building an advanced app where you need to
     * set up a context bridge between two React renderers.
     */
    RoomContext: Context<Room<P, S, U, E, M> | null>;
    /**
     * Makes a Room available in the component hierarchy below.
     * Joins the room when the component is mounted, and automatically leaves
     * the room when the component is unmounted.
     */
    RoomProvider(props: RoomProviderProps<P, S>): JSX.Element;
    /**
     * Returns the Room of the nearest RoomProvider above in the React component
     * tree.
     */
    useRoom(options?: {
        allowOutsideRoom: false;
    }): Room<P, S, U, E, M>;
    useRoom(options: {
        allowOutsideRoom: boolean;
    }): Room<P, S, U, E, M> | null;
    /**
     * Returns the current connection status for the Room, and triggers
     * a re-render whenever it changes. Can be used to render a status badge.
     */
    useStatus(): Status;
    /**
     * @deprecated It's recommended to use `useMutation` for writing to Storage,
     * which will automatically batch all mutations.
     *
     * Returns a function that batches modifications made during the given function.
     * All the modifications are sent to other clients in a single message.
     * All the modifications are merged in a single history item (undo/redo).
     * All the subscribers are called only after the batch is over.
     */
    useBatch<T>(): (callback: () => T) => T;
    /**
     * Returns a callback that lets you broadcast custom events to other users in the room
     *
     * @example
     * const broadcast = useBroadcastEvent();
     *
     * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
     */
    useBroadcastEvent(): (event: E, options?: BroadcastOptions) => void;
    /**
     * Get informed when users enter or leave the room, as an event.
     *
     * @example
     * useOthersListener({ type, user, others }) => {
     *   if (type === 'enter') {
     *     // `user` has joined the room
     *   } else if (type === 'leave') {
     *     // `user` has left the room
     *   }
     * })
     */
    useOthersListener(callback: (event: OthersEvent<P, U>) => void): void;
    /**
     * Get informed when reconnecting to the Liveblocks servers is taking
     * longer than usual. This typically is a sign of a client that has lost
     * internet connectivity.
     *
     * This isn't problematic (because the Liveblocks client is still trying to
     * reconnect), but it's typically a good idea to inform users about it if
     * the connection takes too long to recover.
     *
     * @example
     * useLostConnectionListener(event => {
     *   if (event === 'lost') {
     *     toast.warn('Reconnecting to the Liveblocks servers is taking longer than usual...')
     *   } else if (event === 'failed') {
     *     toast.warn('Reconnecting to the Liveblocks servers failed.')
     *   } else if (event === 'restored') {
     *     toast.clear();
     *   }
     * })
     */
    useLostConnectionListener(callback: (event: LostConnectionEvent) => void): void;
    /**
     * useEventListener is a React hook that allows you to respond to events broadcast
     * by other users in the room.
     *
     * The `user` argument will indicate which `User` instance sent the message.
     * This will be equal to one of the others in the room, but it can be `null`
     * in case this event was broadcasted from the server.
     *
     * @example
     * useEventListener(({ event, user, connectionId }) => {
     * //                         ^^^^ Will be Client A
     *   if (event.type === "CUSTOM_EVENT") {
     *     // Do something
     *   }
     * });
     */
    useEventListener(callback: (data: RoomEventMessage<P, U, E>) => void): void;
    /**
     * Returns the room.history
     */
    useHistory(): History;
    /**
     * Returns a function that undoes the last operation executed by the current client.
     * It does not impact operations made by other clients.
     */
    useUndo(): () => void;
    /**
     * Returns a function that redoes the last operation executed by the current client.
     * It does not impact operations made by other clients.
     */
    useRedo(): () => void;
    /**
     * Returns whether there are any operations to undo.
     */
    useCanUndo(): boolean;
    /**
     * Returns whether there are any operations to redo.
     */
    useCanRedo(): boolean;
    /**
     * Returns the mutable (!) Storage root. This hook exists for
     * backward-compatible reasons.
     *
     * @example
     * const [root] = useStorageRoot();
     */
    useStorageRoot(): [root: LiveObject<S> | null];
    /**
     * Returns the presence of the current user of the current room, and a function to update it.
     * It is different from the setState function returned by the useState hook from React.
     * You don't need to pass the full presence object to update it.
     *
     * @example
     * const [myPresence, updateMyPresence] = useMyPresence();
     * updateMyPresence({ x: 0 });
     * updateMyPresence({ y: 0 });
     *
     * // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }"
     */
    useMyPresence(): [
        P,
        (patch: Partial<P>, options?: {
            addToHistory: boolean;
        }) => void
    ];
    /**
     * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.
     * If you don't use the current user presence in your component, but you need to update it (e.g. live cursor), it's better to use useUpdateMyPresence to avoid unnecessary renders.
     *
     * @example
     * const updateMyPresence = useUpdateMyPresence();
     * updateMyPresence({ x: 0 });
     * updateMyPresence({ y: 0 });
     *
     * // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }"
     */
    useUpdateMyPresence(): (patch: Partial<P>, options?: {
        addToHistory: boolean;
    }) => void;
    /**
     * Create a callback function that lets you mutate Liveblocks state.
     *
     * The first argument that gets passed into your callback will be
     * a "mutation context", which exposes the following:
     *
     *   - `storage` - The mutable Storage root.
     *                 You can mutate any Live structures with this, for example:
     *                 `storage.get('layers').get('layer1').set('fill', 'red')`
     *
     *   - `setMyPresence` - Call this with a new (partial) Presence value.
     *
     *   - `self` - A read-only version of the latest self, if you need it to
     *              compute the next state.
     *
     *   - `others` - A read-only version of the latest others list, if you
     *                need it to compute the next state.
     *
     * useMutation is like React's useCallback, except that the first argument
     * that gets passed into your callback will be a "mutation context".
     *
     * If you want get access to the immutable root somewhere in your mutation,
     * you can use `storage.ToImmutable()`.
     *
     * @example
     * const fillLayers = useMutation(
     *   ({ storage }, color: Color) => {
     *     ...
     *   },
     *   [],
     * );
     *
     * fillLayers('red');
     *
     * const deleteLayers = useMutation(
     *   ({ storage }) => {
     *     ...
     *   },
     *   [],
     * );
     *
     * deleteLayers();
     */
    useMutation<F extends (context: MutationContext<P, S, U>, ...args: any[]) => any>(callback: F, deps: readonly unknown[]): OmitFirstArg<F>;
    /**
     * Returns an array with information about all the users currently connected
     * in the room (except yourself).
     *
     * @example
     * const others = useOthers();
     *
     * // Example to map all cursors in JSX
     * return (
     *   <>
     *     {others.map((user) => {
     *        if (user.presence.cursor == null) {
     *          return null;
     *        }
     *        return <Cursor key={user.connectionId} cursor={user.presence.cursor} />
     *      })}
     *   </>
     * )
     */
    useOthers(): readonly User<P, U>[];
    /**
     * Extract arbitrary data based on all the users currently connected in the
     * room (except yourself).
     *
     * The selector function will get re-evaluated any time a user enters or
     * leaves the room, as well as whenever their presence data changes.
     *
     * The component that uses this hook will automatically re-render if your
     * selector function returns a different value from its previous run.
     *
     * By default `useOthers()` uses strict `===` to check for equality. Take
     * extra care when returning a computed object or list, for example when you
     * return the result of a .map() or .filter() call from the selector. In
     * those cases, you'll probably want to use a `shallow` comparison check.
     *
     * @example
     * const avatars = useOthers(users => users.map(u => u.info.avatar), shallow);
     * const cursors = useOthers(users => users.map(u => u.presence.cursor), shallow);
     * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));
     *
     */
    useOthers<T>(selector: (others: readonly User<P, U>[]) => T, isEqual?: (prev: T, curr: T) => boolean): T;
    /**
     * Returns an array of connection IDs. This matches the values you'll get by
     * using the `useOthers()` hook.
     *
     * Roughly equivalent to:
     *   useOthers((others) => others.map(other => other.connectionId), shallow)
     *
     * This is useful in particular to implement efficiently rendering components
     * for each user in the room, e.g. cursors.
     *
     * @example
     * const ids = useOthersConnectionIds();
     * // [2, 4, 7]
     */
    useOthersConnectionIds(): readonly number[];
    /**
     * Related to useOthers(), but optimized for selecting only "subsets" of
     * others. This is useful for performance reasons in particular, because
     * selecting only a subset of users also means limiting the number of
     * re-renders that will be triggered.
     *
     * @example
     * const avatars = useOthersMapped(user => user.info.avatar);
     * //    ^^^^^^^
     * //    { connectionId: number; data: string }[]
     *
     * The selector function you pass to useOthersMapped() is called an "item
     * selector", and operates on a single user at a time. If you provide an
     * (optional) "item comparison" function, it will be used to compare each
     * item pairwise.
     *
     * For example, to select multiple properties:
     *
     * @example
     * const avatarsAndCursors = useOthersMapped(
     *   user => [u.info.avatar, u.presence.cursor],
     *   shallow,  // 👈
     * );
     */
    useOthersMapped<T>(itemSelector: (other: User<P, U>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): ReadonlyArray<readonly [connectionId: number, data: T]>;
    /**
     * Given a connection ID (as obtained by using `useOthersConnectionIds`), you
     * can call this selector deep down in your component stack to only have the
     * component re-render if properties for this particular user change.
     *
     * @example
     * // Returns only the selected values re-renders whenever that selection changes)
     * const { x, y } = useOther(2, user => user.presence.cursor);
     */
    useOther<T>(connectionId: number, selector: (other: User<P, U>) => T, isEqual?: (prev: T, curr: T) => boolean): T;
    /**
     * Returns a function that creates a thread with an initial comment, and optionally some metadata.
     *
     * @example
     * const createThread = useCreateThread();
     * createThread({ body: {}, metadata: {} });
     */
    useCreateThread(): (options: CreateThreadOptions<M>) => ThreadData<M>;
    /**
     * Returns a function that deletes a thread and its associated comments.
     * Only the thread creator can delete a thread, it will throw otherwise.
     *
     * @example
     * const deleteThread = useDeleteThread();
     * deleteThread("th_xxx");
     */
    useDeleteThread(): (threadId: string) => void;
    /**
     * Returns a function that edits a thread's metadata.
     * To delete an existing metadata property, set its value to `null`.
     *
     * @example
     * const editThreadMetadata = useEditThreadMetadata();
     * editThreadMetadata({ threadId: "th_xxx", metadata: {} })
     */
    useEditThreadMetadata(): (options: EditThreadMetadataOptions<M>) => void;
    /**
     * Returns a function that marks a thread as resolved.
     *
     * @example
     * const markThreadAsResolved = useMarkThreadAsResolved();
     * markThreadAsResolved("th_xxx");
     */
    useMarkThreadAsResolved(): (threadId: string) => void;
    /**
     * Returns a function that marks a thread as unresolved.
     *
     * @example
     * const markThreadAsUnresolved = useMarkThreadAsUnresolved();
     * markThreadAsUnresolved("th_xxx");
     */
    useMarkThreadAsUnresolved(): (threadId: string) => void;
    /**
     * Returns a function that adds a comment to a thread.
     *
     * @example
     * const createComment = useCreateComment();
     * createComment({ threadId: "th_xxx", body: {} });
     */
    useCreateComment(): (options: CreateCommentOptions) => CommentData;
    /**
     * Returns a function that edits a comment's body.
     *
     * @example
     * const editComment = useEditComment()
     * editComment({ threadId: "th_xxx", commentId: "cm_xxx", body: {} })
     */
    useEditComment(): (options: EditCommentOptions) => void;
    /**
     * Returns a function that deletes a comment.
     * If it is the last non-deleted comment, the thread also gets deleted.
     *
     * @example
     * const deleteComment = useDeleteComment();
     * deleteComment({ threadId: "th_xxx", commentId: "cm_xxx" })
     */
    useDeleteComment(): (options: DeleteCommentOptions) => void;
    /**
     * Returns a function that adds a reaction from a comment.
     *
     * @example
     * const addReaction = useAddReaction();
     * addReaction({ threadId: "th_xxx", commentId: "cm_xxx", emoji: "👍" })
     */
    useAddReaction(): (options: CommentReactionOptions) => void;
    /**
     * Returns a function that removes a reaction on a comment.
     *
     * @example
     * const removeReaction = useRemoveReaction();
     * removeReaction({ threadId: "th_xxx", commentId: "cm_xxx", emoji: "👍" })
     */
    useRemoveReaction(): (options: CommentReactionOptions) => void;
    /**
     * Returns a function that updates the user's notification settings
     * for the current room.
     *
     * @example
     * const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
     * updateRoomNotificationSettings({ threads: "all" });
     */
    useUpdateRoomNotificationSettings(): (settings: Partial<RoomNotificationSettings>) => void;
    /**
     * Returns a function that marks a thread as read.
     *
     * @example
     * const markThreadAsRead = useMarkThreadAsRead();
     * markThreadAsRead("th_xxx");
     */
    useMarkThreadAsRead(): (threadId: string) => void;
    /**
     * Returns the subscription status of a thread.
     *
     * @example
     * const { status, unreadSince } = useThreadSubscription("th_xxx");
     */
    useThreadSubscription(threadId: string): ThreadSubscription;
};
type RoomContextBundle<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json, M extends BaseMetadata> = Resolve<RoomContextBundleCommon<P, S, U, E, M> & SharedContextBundle<U>["classic"] & {
    /**
     * Returns the current storage status for the Room, and triggers
     * a re-render whenever it changes. Can be used to render a "Saving..."
     * indicator.
     *
     * @deprecated Prefer useSyncStatus()
     */
    useStorageStatus(options?: UseStorageStatusOptions): StorageStatus;
    /**
     * Extract arbitrary data from the Liveblocks Storage state, using an
     * arbitrary selector function.
     *
     * The selector function will get re-evaluated any time something changes in
     * Storage. The value returned by your selector function will also be the
     * value returned by the hook.
     *
     * The `root` value that gets passed to your selector function is
     * a immutable/readonly version of your Liveblocks storage root.
     *
     * The component that uses this hook will automatically re-render if the
     * returned value changes.
     *
     * By default `useStorage()` uses strict `===` to check for equality. Take
     * extra care when returning a computed object or list, for example when you
     * return the result of a .map() or .filter() call from the selector. In
     * those cases, you'll probably want to use a `shallow` comparison check.
     */
    useStorage<T>(selector: (root: ToImmutable<S>) => T, isEqual?: (prev: T | null, curr: T | null) => boolean): T | null;
    /**
     * Gets the current user once it is connected to the room.
     *
     * @example
     * const me = useSelf();
     * if (me !== null) {
     *   const { x, y } = me.presence.cursor;
     * }
     */
    useSelf(): User<P, U> | null;
    /**
     * Extract arbitrary data based on the current user.
     *
     * The selector function will get re-evaluated any time your presence data
     * changes.
     *
     * The component that uses this hook will automatically re-render if your
     * selector function returns a different value from its previous run.
     *
     * By default `useSelf()` uses strict `===` to check for equality. Take extra
     * care when returning a computed object or list, for example when you return
     * the result of a .map() or .filter() call from the selector. In those
     * cases, you'll probably want to use a `shallow` comparison check.
     *
     * Will return `null` while Liveblocks isn't connected to a room yet.
     *
     * @example
     * const cursor = useSelf(me => me.presence.cursor);
     * if (cursor !== null) {
     *   const { x, y } = cursor;
     * }
     *
     */
    useSelf<T>(selector: (me: User<P, U>) => T, isEqual?: (prev: T, curr: T) => boolean): T | null;
    /**
     * Returns the threads within the current room.
     *
     * @example
     * const { threads, error, isLoading } = useThreads();
     */
    useThreads(options?: UseThreadsOptions<M>): ThreadsAsyncResult<M>;
    /**
     * Returns the user's notification settings for the current room
     * and a function to update them.
     *
     * @example
     * const [{ settings }, updateSettings] = useRoomNotificationSettings();
     */
    useRoomNotificationSettings(): [
        RoomNotificationSettingsAsyncResult,
        (settings: Partial<RoomNotificationSettings>) => void
    ];
    /**
     * Returns a presigned URL for an attachment by its ID.
     *
     * @example
     * const { url, error, isLoading } = useAttachmentUrl("at_xxx");
     */
    useAttachmentUrl(attachmentId: string): AttachmentUrlAsyncResult;
    /**
     * (Private beta)  Returns a history of versions of the current room.
     *
     * @example
     * const { versions, error, isLoading } = useHistoryVersions();
     */
    useHistoryVersions(): HistoryVersionsAsyncResult;
    /**
     * (Private beta) Returns the data of a specific version of the current room.
     *
     * @example
     * const { data, error, isLoading } = useHistoryVersionData(version.id);
     */
    useHistoryVersionData(id: string): HistoryVersionDataAsyncResult;
    suspense: Resolve<RoomContextBundleCommon<P, S, U, E, M> & SharedContextBundle<U>["suspense"] & {
        /**
         * Returns the current storage status for the Room, and triggers
         * a re-render whenever it changes. Can be used to render a "Saving..."
         * indicator.
         *
         * @deprecated Prefer useSyncStatus()
         */
        useStorageStatus(options?: UseStorageStatusOptions): StorageStatusSuccess;
        /**
         * Extract arbitrary data from the Liveblocks Storage state, using an
         * arbitrary selector function.
         *
         * The selector function will get re-evaluated any time something changes in
         * Storage. The value returned by your selector function will also be the
         * value returned by the hook.
         *
         * The `root` value that gets passed to your selector function is
         * a immutable/readonly version of your Liveblocks storage root.
         *
         * The component that uses this hook will automatically re-render if the
         * returned value changes.
         *
         * By default `useStorage()` uses strict `===` to check for equality. Take
         * extra care when returning a computed object or list, for example when you
         * return the result of a .map() or .filter() call from the selector. In
         * those cases, you'll probably want to use a `shallow` comparison check.
         */
        useStorage<T>(selector: (root: ToImmutable<S>) => T, isEqual?: (prev: T, curr: T) => boolean): T;
        /**
         * Gets the current user once it is connected to the room.
         *
         * @example
         * const me = useSelf();
         * const { x, y } = me.presence.cursor;
         */
        useSelf(): User<P, U>;
        /**
         * Extract arbitrary data based on the current user.
         *
         * The selector function will get re-evaluated any time your presence data
         * changes.
         *
         * The component that uses this hook will automatically re-render if your
         * selector function returns a different value from its previous run.
         *
         * By default `useSelf()` uses strict `===` to check for equality. Take extra
         * care when returning a computed object or list, for example when you return
         * the result of a .map() or .filter() call from the selector. In those
         * cases, you'll probably want to use a `shallow` comparison check.
         *
         * @example
         * const cursor = useSelf(me => me.presence.cursor);
         * const { x, y } = cursor;
         *
         */
        useSelf<T>(selector: (me: User<P, U>) => T, isEqual?: (prev: T, curr: T) => boolean): T;
        /**
         * Returns the threads within the current room.
         *
         * @example
         * const { threads } = useThreads();
         */
        useThreads(options?: UseThreadsOptions<M>): ThreadsAsyncSuccess<M>;
        /**
         * (Private beta) Returns a history of versions of the current room.
         *
         * @example
         * const { versions } = useHistoryVersions();
         */
        useHistoryVersions(): HistoryVersionsAsyncSuccess;
        /**
         * Returns the user's notification settings for the current room
         * and a function to update them.
         *
         * @example
         * const [{ settings }, updateSettings] = useRoomNotificationSettings();
         */
        useRoomNotificationSettings(): [
            RoomNotificationSettingsAsyncSuccess,
            (settings: Partial<RoomNotificationSettings>) => void
        ];
        /**
         * Returns a presigned URL for an attachment by its ID.
         *
         * @example
         * const { url } = useAttachmentUrl("at_xxx");
         */
        useAttachmentUrl(attachmentId: string): AttachmentUrlAsyncSuccess;
    }>;
}>;
/**
 * Properties that are the same in LiveblocksContext and LiveblocksContext["suspense"].
 */
type LiveblocksContextBundleCommon<M extends BaseMetadata> = {
    /**
     * Makes Liveblocks features outside of rooms (e.g. Notifications) available
     * in the component hierarchy below.
     */
    LiveblocksProvider(props: PropsWithChildren): JSX.Element;
    /**
     * Returns a function that marks an inbox notification as read for the current user.
     *
     * @example
     * const markInboxNotificationAsRead = useMarkInboxNotificationAsRead();
     * markInboxNotificationAsRead("in_xxx");
     */
    useMarkInboxNotificationAsRead(): (inboxNotificationId: string) => void;
    /**
     * Returns a function that marks all of the current user's inbox notifications as read.
     *
     * @example
     * const markAllInboxNotificationsAsRead = useMarkAllInboxNotificationsAsRead();
     * markAllInboxNotificationsAsRead();
     */
    useMarkAllInboxNotificationsAsRead(): () => void;
    /**
     * Returns a function that deletes an inbox notification for the current user.
     *
     * @example
     * const deleteInboxNotification = useDeleteInboxNotification();
     * deleteInboxNotification("in_xxx");
     */
    useDeleteInboxNotification(): (inboxNotificationId: string) => void;
    /**
     * Returns a function that deletes all of the current user's inbox notifications.
     *
     * @example
     * const deleteAllInboxNotifications = useDeleteAllInboxNotifications();
     * deleteAllInboxNotifications();
     */
    useDeleteAllInboxNotifications(): () => void;
    /**
     * Returns the thread associated with a `"thread"` inbox notification.
     *
     * It can **only** be called with IDs of `"thread"` inbox notifications,
     * so we recommend only using it when customizing the rendering or in other
     * situations where you can guarantee the kind of the notification.
     *
     * When `useInboxNotifications` returns `"thread"` inbox notifications,
     * it also receives the associated threads and caches them behind the scenes.
     * When you call `useInboxNotificationThread`, it simply returns the cached thread
     * for the inbox notification ID you passed to it, without any fetching or waterfalls.
     *
     * @example
     * const thread = useInboxNotificationThread("in_xxx");
     */
    useInboxNotificationThread(inboxNotificationId: string): ThreadData<M>;
    /**
     * Returns notification settings for the current user.
     *
     * @example
     * const [{ settings }, updateNotificationSettings] = useNotificationSettings()
     */
    useNotificationSettings(): [
        UserNotificationSettingsAsyncResult,
        (settings: PartialUserNotificationSettings) => void
    ];
    /**
     * Returns a function that updates the user's notification
     * settings for a project.
     *
     * @example
     * const updateNotificationSettings = useUpdateNotificationSettings()
     */
    useUpdateNotificationSettings(): (settings: PartialUserNotificationSettings) => void;
    /**
     * Returns the current Liveblocks sync status, and triggers a re-render
     * whenever it changes. Can be used to render a "Saving..." indicator, or for
     * preventing that a browser tab can be closed until all changes have been
     * synchronized with the server.
     *
     * @example
     * const syncStatus = useSyncStatus();  // "synchronizing" | "synchronized"
     * const syncStatus = useSyncStatus({ smooth: true });
     */
    useSyncStatus(options?: UseSyncStatusOptions): SyncStatus;
};
type LiveblocksContextBundle<U extends BaseUserMeta, M extends BaseMetadata> = Resolve<LiveblocksContextBundleCommon<M> & SharedContextBundle<U>["classic"] & {
    /**
     * Returns the inbox notifications for the current user.
     *
     * @example
     * const { inboxNotifications, error, isLoading } = useInboxNotifications();
     */
    useInboxNotifications(): InboxNotificationsAsyncResult;
    /**
     * Returns the number of unread inbox notifications for the current user.
     *
     * @example
     * const { count, error, isLoading } = useUnreadInboxNotificationsCount();
     */
    useUnreadInboxNotificationsCount(): UnreadInboxNotificationsCountAsyncResult;
    /**
     * @experimental
     *
     * This hook is experimental and could be removed or changed at any time!
     * Do not use unless explicitly recommended by the Liveblocks team.
     */
    useUserThreads_experimental(options?: UseUserThreadsOptions<M>): ThreadsAsyncResult<M>;
    suspense: Resolve<LiveblocksContextBundleCommon<M> & SharedContextBundle<U>["suspense"] & {
        /**
         * Returns the inbox notifications for the current user.
         *
         * @example
         * const { inboxNotifications } = useInboxNotifications();
         */
        useInboxNotifications(): InboxNotificationsAsyncSuccess;
        /**
         * Returns the number of unread inbox notifications for the current user.
         *
         * @example
         * const { count } = useUnreadInboxNotificationsCount();
         */
        useUnreadInboxNotificationsCount(): UnreadInboxNotificationsCountAsyncSuccess;
        /**
         * Returns notification settings for the current user.
         *
         * @example
         * const [{ settings }, updateNotificationSettings] = useNotificationSettings()
         */
        useNotificationSettings(): [
            UserNotificationSettingsAsyncResult,
            (settings: PartialUserNotificationSettings) => void
        ];
        /**
         * @experimental
         *
         * This hook is experimental and could be removed or changed at any time!
         * Do not use unless explicitly recommended by the Liveblocks team.
         */
        useUserThreads_experimental(options?: UseUserThreadsOptions<M>): ThreadsAsyncSuccess<M>;
    }>;
}>;

type ReadonlyThreadDB<M extends BaseMetadata> = Omit<ThreadDB<M>, "upsert" | "delete" | "signal">;
/**
 * This class implements a lightweight, in-memory, "database" for all Thread
 * instances.
 *
 * It exposes the following methods:
 *
 * - upsert: To add/update a thread
 * - upsertIfNewer: To add/update a thread. Only update an existing thread if
 *                  its newer
 * - delete: To mark existing threads as deleted
 * - get: To get any non-deleted thread
 * - getEvenIfDeleted: To get a thread which is possibly deleted
 * - findMany: To filter an ordered list of non-deleted threads
 * - clone: To clone the DB to mutate it further. This is used to mix in
 *          optimistic updates without losing the original thread contents.
 *
 */
declare class ThreadDB<M extends BaseMetadata> {
    #private;
    readonly signal: MutableSignal<this>;
    constructor();
    clone(): ThreadDB<M>;
    /** Returns an existing thread by ID. Will never return a deleted thread. */
    get(threadId: string): ThreadData<M> | undefined;
    /** Returns the (possibly deleted) thread by ID. */
    getEvenIfDeleted(threadId: string): ThreadDataWithDeleteInfo<M> | undefined;
    /** Adds or updates a thread in the DB. If the newly given thread is a deleted one, it will get deleted. */
    upsert(thread: ThreadDataWithDeleteInfo<M>): void;
    /** Like .upsert(), except it won't update if a thread by this ID already exists. */
    upsertIfNewer(thread: ThreadDataWithDeleteInfo<M>): void;
    applyDelta(newThreads: ThreadData<M>[], deletedThreads: ThreadDeleteInfo[]): void;
    /**
     * Marks a thread as deleted. It will no longer pop up in .findMany()
     * queries, but it can still be accessed via `.getEvenIfDeleted()`.
     */
    delete(threadId: string, deletedAt: Date): void;
    /**
     * Returns all threads matching a given roomId and query. If roomId is not
     * specified, it will return all threads matching the query, across all
     * rooms.
     *
     * Returns the results in the requested order. Please note:
     *   'asc'  means by createdAt ASC
     *   'desc' means by updatedAt DESC
     *
     * Will never return deleted threads in the result.
     */
    findMany(roomId: string | undefined, query: ThreadsQuery<M>, direction: "asc" | "desc"): ThreadData<M>[];
}

type OptimisticUpdate<M extends BaseMetadata> = CreateThreadOptimisticUpdate<M> | DeleteThreadOptimisticUpdate | EditThreadMetadataOptimisticUpdate<M> | MarkThreadAsResolvedOptimisticUpdate | MarkThreadAsUnresolvedOptimisticUpdate | CreateCommentOptimisticUpdate | EditCommentOptimisticUpdate | DeleteCommentOptimisticUpdate | AddReactionOptimisticUpdate | RemoveReactionOptimisticUpdate | MarkInboxNotificationAsReadOptimisticUpdate | MarkAllInboxNotificationsAsReadOptimisticUpdate | DeleteInboxNotificationOptimisticUpdate | DeleteAllInboxNotificationsOptimisticUpdate | UpdateNotificationSettingsOptimisticUpdate | UpdateUserNotificationSettingsOptimisticUpdate;
type CreateThreadOptimisticUpdate<M extends BaseMetadata> = {
    type: "create-thread";
    id: string;
    roomId: string;
    thread: ThreadData<M>;
};
type DeleteThreadOptimisticUpdate = {
    type: "delete-thread";
    id: string;
    roomId: string;
    threadId: string;
    deletedAt: Date;
};
type EditThreadMetadataOptimisticUpdate<M extends BaseMetadata> = {
    type: "edit-thread-metadata";
    id: string;
    threadId: string;
    metadata: Resolve<Patchable<M>>;
    updatedAt: Date;
};
type MarkThreadAsResolvedOptimisticUpdate = {
    type: "mark-thread-as-resolved";
    id: string;
    threadId: string;
    updatedAt: Date;
};
type MarkThreadAsUnresolvedOptimisticUpdate = {
    type: "mark-thread-as-unresolved";
    id: string;
    threadId: string;
    updatedAt: Date;
};
type CreateCommentOptimisticUpdate = {
    type: "create-comment";
    id: string;
    comment: CommentData;
};
type EditCommentOptimisticUpdate = {
    type: "edit-comment";
    id: string;
    comment: CommentData;
};
type DeleteCommentOptimisticUpdate = {
    type: "delete-comment";
    id: string;
    roomId: string;
    threadId: string;
    deletedAt: Date;
    commentId: string;
};
type AddReactionOptimisticUpdate = {
    type: "add-reaction";
    id: string;
    threadId: string;
    commentId: string;
    reaction: CommentUserReaction;
};
type RemoveReactionOptimisticUpdate = {
    type: "remove-reaction";
    id: string;
    threadId: string;
    commentId: string;
    emoji: string;
    userId: string;
    removedAt: Date;
};
type MarkInboxNotificationAsReadOptimisticUpdate = {
    type: "mark-inbox-notification-as-read";
    id: string;
    inboxNotificationId: string;
    readAt: Date;
};
type MarkAllInboxNotificationsAsReadOptimisticUpdate = {
    type: "mark-all-inbox-notifications-as-read";
    id: string;
    readAt: Date;
};
type DeleteInboxNotificationOptimisticUpdate = {
    type: "delete-inbox-notification";
    id: string;
    inboxNotificationId: string;
    deletedAt: Date;
};
type DeleteAllInboxNotificationsOptimisticUpdate = {
    type: "delete-all-inbox-notifications";
    id: string;
    deletedAt: Date;
};
type UpdateNotificationSettingsOptimisticUpdate = {
    type: "update-notification-settings";
    id: string;
    roomId: string;
    settings: Partial<RoomNotificationSettings$1>;
};
type UpdateUserNotificationSettingsOptimisticUpdate = {
    type: "update-user-notification-settings";
    id: string;
    settings: PartialUserNotificationSettings;
};
/**
 * Like Promise<T>, except it will have a synchronously readable `status`
 * field, indicating the status of the promise.
 * This is compatible with React's `use()` promises, hence the name.
 */
type UsablePromise<T> = Promise<T> & ({
    status: "pending";
} | {
    status: "rejected";
    reason: Error;
} | {
    status: "fulfilled";
    value: T;
});
type LoadableResource<T> = {
    signal: ISignal<T>;
    waitUntilLoaded: () => UsablePromise<void>;
};
type RoomId = string;
type UserQueryKey = string;
type RoomQueryKey = string;
/**
 * A lookup table (LUT) for all the inbox notifications.
 */
type NotificationsLUT = Map<string, InboxNotificationData>;
/**
 * Notification settings by room ID.
 * e.g. { 'room-abc': { threads: "all" },
 *        'room-def': { threads: "replies_and_mentions" },
 *        'room-xyz': { threads: "none" },
 *      }
 */
type SettingsByRoomId = Record<RoomId, RoomNotificationSettings$1>;
type PermissionHintsLUT = DefaultMap<RoomId, Set<Permission>>;
type CleanThreadifications<M extends BaseMetadata> = CleanThreads<M> & CleanNotifications;
type CleanThreads<M extends BaseMetadata> = {
    /**
     * Keep track of loading and error status of all the queries made by the client.
     * e.g. 'room-abc-{"color":"red"}'  - ok
     * e.g. 'room-abc-{}'               - loading
     */
    threadsDB: ReadonlyThreadDB<M>;
};
type CleanNotifications = {
    /**
     * All inbox notifications in a sorted array, optimistic updates applied.
     */
    sortedNotifications: InboxNotificationData[];
    /**
     * Inbox notifications by ID.
     * e.g. `in_${string}`
     */
    notificationsById: Record<string, InboxNotificationData>;
};
declare function createStore_forNotifications(): {
    signal: ISignal<NotificationsLUT>;
    markAllRead: (readAt: Date) => void;
    markRead: (notificationId: string, readAt: Date) => void;
    delete: (inboxNotificationId: string) => void;
    applyDelta: (newNotifications: InboxNotificationData[], deletedNotifications: InboxNotificationDeleteInfo[]) => void;
    clear: () => void;
    updateAssociatedNotification: (newComment: CommentData) => void;
    upsert: (notification: InboxNotificationData) => void;
};
declare function createStore_forRoomNotificationSettings(updates: ISignal<readonly OptimisticUpdate<BaseMetadata>[]>): {
    signal: DerivedSignal<SettingsByRoomId>;
    update: (roomId: string, settings: RoomNotificationSettings$1) => void;
};
declare function createStore_forHistoryVersions(): {
    signal: DerivedSignal<{
        [k: string]: {
            [k: string]: HistoryVersion;
        };
    }>;
    update: (roomId: string, versions: HistoryVersion[]) => void;
};
declare function createStore_forPermissionHints(): {
    signal: ISignal<PermissionHintsLUT>;
    update: (newHints: Record<string, Permission[]>) => void;
};
/**
 * User notification settings
 * e.g.
 *  {
 *    email: {
 *      thread: true,
 *      textMention: false,
 *      $customKind: true | false,
 *    }
 *    slack: {
 *      thread: true,
 *      textMention: false,
 *      $customKind: true | false,
 *    }
 *  }
 * e.g. {} when before the first successful fetch.
 */
declare function createStore_forUserNotificationSettings(updates: ISignal<readonly OptimisticUpdate<BaseMetadata>[]>): {
    signal: DerivedSignal<UserNotificationSettings>;
    update: (settings: UserNotificationSettings) => void;
};
declare function createStore_forOptimistic<M extends BaseMetadata>(client: Client<BaseUserMeta$1, M>): {
    signal: ISignal<readonly OptimisticUpdate<M>[]>;
    add: (optimisticUpdate: DistributiveOmit<OptimisticUpdate<M>, "id">) => string;
    remove: (optimisticId: string) => void;
};
declare class UmbrellaStore<M extends BaseMetadata> {
    #private;
    readonly threads: ThreadDB<M>;
    readonly notifications: ReturnType<typeof createStore_forNotifications>;
    readonly roomNotificationSettings: ReturnType<typeof createStore_forRoomNotificationSettings>;
    readonly historyVersions: ReturnType<typeof createStore_forHistoryVersions>;
    readonly permissionHints: ReturnType<typeof createStore_forPermissionHints>;
    readonly userNotificationSettings: ReturnType<typeof createStore_forUserNotificationSettings>;
    readonly optimisticUpdates: ReturnType<typeof createStore_forOptimistic<M>>;
    readonly outputs: {
        readonly threadifications: DerivedSignal<CleanThreadifications<M>>;
        readonly threads: DerivedSignal<ReadonlyThreadDB<M>>;
        readonly loadingRoomThreads: DefaultMap<RoomQueryKey, LoadableResource<ThreadsAsyncResult<M>>>;
        readonly loadingUserThreads: DefaultMap<UserQueryKey, LoadableResource<ThreadsAsyncResult<M>>>;
        readonly notifications: DerivedSignal<CleanNotifications>;
        readonly loadingNotifications: LoadableResource<InboxNotificationsAsyncResult>;
        readonly settingsByRoomId: DefaultMap<RoomId, LoadableResource<RoomNotificationSettingsAsyncResult>>;
        readonly versionsByRoomId: DefaultMap<RoomId, LoadableResource<HistoryVersionsAsyncResult>>;
        readonly userNotificationSettings: LoadableResource<UserNotificationSettingsAsyncResult>;
    };
    constructor(client: OpaqueClient);
    /**
     * Updates an existing inbox notification with a new value, replacing the
     * corresponding optimistic update.
     *
     * This will not update anything if the inbox notification ID isn't found.
     */
    markInboxNotificationRead(inboxNotificationId: string, readAt: Date, optimisticId: string): void;
    markAllInboxNotificationsRead(optimisticId: string, readAt: Date): void;
    /**
     * Deletes an existing inbox notification, replacing the corresponding
     * optimistic update.
     */
    deleteInboxNotification(inboxNotificationId: string, optimisticId: string): void;
    /**
     * Deletes *all* inbox notifications, replacing the corresponding optimistic
     * update.
     */
    deleteAllInboxNotifications(optimisticId: string): void;
    /**
     * Creates an new thread, replacing the corresponding optimistic update.
     */
    createThread(optimisticId: string, thread: Readonly<ThreadDataWithDeleteInfo<M>>): void;
    patchThread(threadId: string, optimisticId: string | null, patch: {
        metadata?: M;
        resolved?: boolean;
    }, updatedAt: Date): void;
    addReaction(threadId: string, optimisticId: string | null, commentId: string, reaction: CommentUserReaction, createdAt: Date): void;
    removeReaction(threadId: string, optimisticId: string | null, commentId: string, emoji: string, userId: string, removedAt: Date): void;
    /**
     * Soft-deletes an existing thread by setting its `deletedAt` value,
     * replacing the corresponding optimistic update.
     *
     * This will not update anything if:
     * - The thread ID isn't found; or
     * - The thread ID was already deleted
     */
    deleteThread(threadId: string, optimisticId: string | null): void;
    /**
     * Creates an existing comment and ensures the associated notification is
     * updated correctly, replacing the corresponding optimistic update.
     */
    createComment(newComment: CommentData, optimisticId: string): void;
    editComment(threadId: string, optimisticId: string, editedComment: CommentData): void;
    deleteComment(threadId: string, optimisticId: string, commentId: string, deletedAt: Date): void;
    updateThreadifications(threads: ThreadData<M>[], notifications: InboxNotificationData[], deletedThreads?: ThreadDeleteInfo[], deletedNotifications?: InboxNotificationDeleteInfo[]): void;
    /**
     * Updates existing notification setting for a room with a new value,
     * replacing the corresponding optimistic update.
     */
    updateRoomNotificationSettings(roomId: string, optimisticId: string, settings: Readonly<RoomNotificationSettings$1>): void;
    fetchNotificationsDeltaUpdate(signal: AbortSignal): Promise<void>;
    fetchRoomThreadsDeltaUpdate(roomId: string, signal: AbortSignal): Promise<void>;
    fetchUserThreadsDeltaUpdate(signal: AbortSignal): Promise<void>;
    fetchRoomVersionsDeltaUpdate(roomId: string, signal: AbortSignal): Promise<void>;
    refreshRoomNotificationSettings(roomId: string, signal: AbortSignal): Promise<void>;
    /**
     * Refresh User Notification Settings from poller
     */
    refreshUserNotificationSettings(signal: AbortSignal): Promise<void>;
    /**
     * Updates user notification settings with a new value, replacing the
     * corresponding optimistic update.
     */
    updateUserNotificationSettings_confirmOptimisticUpdate(settings: UserNotificationSettings, optimisticUpdateId: string): void;
}

/**
 * Raw access to the React context where the LiveblocksProvider stores the
 * current client. Exposed for advanced use cases only.
 *
 * @private This is a private/advanced API. Do not rely on it.
 */
declare const ClientContext: react.Context<OpaqueClient | null>;
/**
 * Gets or creates a unique Umbrella store for each unique client instance.
 *
 * @private
 */
declare function getUmbrellaStoreForClient<M extends BaseMetadata$1>(client: OpaqueClient): UmbrellaStore<M>;
/**
 * @private This is an internal API.
 */
declare function useClientOrNull<U extends BaseUserMeta>(): Client$1<U> | null;
/**
 * Obtains a reference to the current Liveblocks client.
 */
declare function useClient<U extends BaseUserMeta>(): Client$1<U>;
/**
 * Sets up a client for connecting to Liveblocks, and is the recommended way to do
 * this for React apps. You must define either `authEndpoint` or `publicApiKey`.
 * Resolver functions should be placed inside here, and a number of other options
 * are available, which correspond with those passed to `createClient`.
 * Unlike `RoomProvider`, `LiveblocksProvider` doesn’t call Liveblocks servers when mounted,
 * and it should be placed higher in your app’s component tree.
 */
declare function LiveblocksProvider<U extends BaseUserMeta = DU>(props: PropsWithChildren<ClientOptions<U>>): react_jsx_runtime.JSX.Element;
/**
 * Creates a LiveblocksProvider and a set of typed hooks. Note that any
 * LiveblocksProvider created in this way takes no props, because it uses
 * settings from the given client instead.
 */
declare function createLiveblocksContext<U extends BaseUserMeta = DU, M extends BaseMetadata$1 = DM>(client: OpaqueClient): LiveblocksContextBundle<U, M>;
/**
 * Returns the inbox notifications for the current user.
 *
 * @example
 * const { inboxNotifications, error, isLoading } = useInboxNotifications();
 */
declare function useInboxNotifications(): InboxNotificationsAsyncResult;
/**
 * Returns the inbox notifications for the current user.
 *
 * @example
 * const { inboxNotifications } = useInboxNotifications();
 */
declare function useInboxNotificationsSuspense(): {
    readonly isLoading: false;
    readonly inboxNotifications: _liveblocks_core.InboxNotificationData[];
    readonly error?: undefined;
    hasFetchedAll: boolean;
    isFetchingMore: boolean;
    fetchMore: () => void;
    fetchMoreError?: Error | undefined;
};
/**
 * Returns a function that marks all of the current user's inbox notifications as read.
 *
 * @example
 * const markAllInboxNotificationsAsRead = useMarkAllInboxNotificationsAsRead();
 * markAllInboxNotificationsAsRead();
 */
declare function useMarkAllInboxNotificationsAsRead(): () => void;
/**
 * Returns a function that marks an inbox notification as read for the current user.
 *
 * @example
 * const markInboxNotificationAsRead = useMarkInboxNotificationAsRead();
 * markInboxNotificationAsRead("in_xxx");
 */
declare function useMarkInboxNotificationAsRead(): (inboxNotificationId: string) => void;
/**
 * Returns a function that deletes all of the current user's inbox notifications.
 *
 * @example
 * const deleteAllInboxNotifications = useDeleteAllInboxNotifications();
 * deleteAllInboxNotifications();
 */
declare function useDeleteAllInboxNotifications(): () => void;
/**
 * Returns a function that deletes an inbox notification for the current user.
 *
 * @example
 * const deleteInboxNotification = useDeleteInboxNotification();
 * deleteInboxNotification("in_xxx");
 */
declare function useDeleteInboxNotification(): (inboxNotificationId: string) => void;
/**
 * Returns the number of unread inbox notifications for the current user.
 *
 * @example
 * const { count, error, isLoading } = useUnreadInboxNotificationsCount();
 */
declare function useUnreadInboxNotificationsCount(): UnreadInboxNotificationsCountAsyncResult;
/**
 * Returns the number of unread inbox notifications for the current user.
 *
 * @example
 * const { count } = useUnreadInboxNotificationsCount();
 */
declare function useUnreadInboxNotificationsCountSuspense(): {
    readonly isLoading: false;
    readonly count: number;
    readonly error?: undefined;
};
/**
 * Returns notification settings for the current user.
 *
 * @example
 * const [{ settings }, updateNotificationSettings] = useNotificationSettings()
 */
declare function useNotificationSettings(): [UserNotificationSettingsAsyncResult, (settings: PartialUserNotificationSettings) => void];
/**
 * Returns notification settings for the current user.
 *
 * @example
 * const [{ settings }, updateNotificationSettings] = useNotificationSettings()
 */
declare function useNotificationSettingsSuspense(): [{
    readonly isLoading: false;
    readonly settings: _liveblocks_core.UserNotificationSettings;
    readonly error?: undefined;
}, (settings: PartialUserNotificationSettings) => void];
/**
 * Returns a function that updates the user's notification
 * settings for a project.
 *
 * @example
 * const updateNotificationSettings = useUpdateNotificationSettings()
 */
declare function useUpdateNotificationSettings(): (settings: PartialUserNotificationSettings) => void;
/**
 * Returns room info from a given room ID.
 *
 * @example
 * const { info, error, isLoading } = useRoomInfo("room-id");
 */
declare function useRoomInfo(roomId: string): RoomInfoAsyncResult;
/**
 * Returns room info from a given room ID.
 *
 * @example
 * const { info } = useRoomInfo("room-id");
 */
declare function useRoomInfoSuspense(roomId: string): RoomInfoAsyncSuccess;
type TypedBundle$1 = LiveblocksContextBundle<DU, DM>;
/**
 * Returns the thread associated with a `"thread"` inbox notification.
 *
 * It can **only** be called with IDs of `"thread"` inbox notifications,
 * so we recommend only using it when customizing the rendering or in other
 * situations where you can guarantee the kind of the notification.
 *
 * When `useInboxNotifications` returns `"thread"` inbox notifications,
 * it also receives the associated threads and caches them behind the scenes.
 * When you call `useInboxNotificationThread`, it simply returns the cached thread
 * for the inbox notification ID you passed to it, without any fetching or waterfalls.
 *
 * @example
 * const thread = useInboxNotificationThread("in_xxx");
 */
declare const _useInboxNotificationThread: TypedBundle$1["useInboxNotificationThread"];
/**
 * Returns user info from a given user ID.
 *
 * @example
 * const { user, error, isLoading } = useUser("user-id");
 */
declare const _useUser: TypedBundle$1["useUser"];
/**
 * Returns user info from a given user ID.
 *
 * @example
 * const { user } = useUser("user-id");
 */
declare const _useUserSuspense: TypedBundle$1["suspense"]["useUser"];
/**
 * @experimental
 *
 * This hook is experimental and could be removed or changed at any time!
 * Do not use unless explicitly recommended by the Liveblocks team.
 *
 * WARNING:
 * Please note that this hook currently returns all threads by most recently
 * updated threads first. This is inconsistent with the default sort order of
 * the useThreads() hook, which returns them in chronological order (by
 * creation date). In the final version, we will make these hooks behave
 * consistently, so expect that in the final version, you'll have to explicitly
 * specify the sort order to be by most recently updated first somehow.
 * The final API for that is still TBD.
 */
declare const _useUserThreads_experimental: TypedBundle$1["useUserThreads_experimental"];
/**
 * @experimental
 *
 * This hook is experimental and could be removed or changed at any time!
 * Do not use unless explicitly recommended by the Liveblocks team.
 *
 * WARNING:
 * Please note that this hook currently returns all threads by most recently
 * updated threads first. This is inconsistent with the default sort order of
 * the useThreads() hook, which returns them in chronological order (by
 * creation date). In the final version, we will make these hooks behave
 * consistently, so expect that in the final version, you'll have to explicitly
 * specify the sort order to be by most recently updated first somehow.
 * The final API for that is still TBD.
 */
declare const _useUserThreadsSuspense_experimental: TypedBundle$1["suspense"]["useUserThreads_experimental"];
/**
 * Returns the current Liveblocks sync status, and triggers a re-render
 * whenever it changes. Can be used to render a "Saving..." indicator, or for
 * preventing that a browser tab can be closed until all changes have been
 * synchronized with the server.
 *
 * @example
 * const syncStatus = useSyncStatus();  // "synchronizing" | "synchronized"
 * const syncStatus = useSyncStatus({ smooth: true });
 */
declare function useSyncStatus(options?: UseSyncStatusOptions): SyncStatus;
/**
 * useErrorListener is a React hook that allows you to respond to any
 * Liveblocks error, for example room connection errors, errors
 * creating/editing/deleting threads, etc.
 *
 * @example
 * useErrorListener(err => {
 *   console.error(err);
 * })
 */
declare function useErrorListener(callback: (err: LiveblocksError) => void): void;

/**
 * Returns the current connection status for the Room, and triggers
 * a re-render whenever it changes. Can be used to render a status badge.
 */
declare function useStatus(): Status;
/** @private - Internal API, do not rely on it. */
declare function useReportTextEditor(editor: TextEditorType, rootKey: string): void;
/** @private - Internal API, do not rely on it. */
declare function useYjsProvider(): IYjsProvider | undefined;
/** @private - Internal API, do not rely on it. */
declare function useCreateTextMention(): (userId: string, mentionId: string) => void;
/** @private - Internal API, do not rely on it. */
declare function useDeleteTextMention(): (mentionId: string) => void;
/** @private - Internal API, do not rely on it. */
declare function useResolveMentionSuggestions(): ((args: _liveblocks_core.ResolveMentionSuggestionsArgs) => _liveblocks_core.Awaitable<string[]>) | undefined;
/** @private - Internal API, do not rely on it. */
declare function useMentionSuggestionsCache(): Map<string, string[]>;
/**
 * Returns the current storage status for the Room, and triggers
 * a re-render whenever it changes. Can be used to render a "Saving..."
 * indicator.
 *
 * @deprecated Prefer useSyncStatus()
 */
declare function useStorageStatus(options?: UseStorageStatusOptions): StorageStatus$1;
/**
 * @deprecated It's recommended to use `useMutation` for writing to Storage,
 * which will automatically batch all mutations.
 *
 * Returns a function that batches modifications made during the given function.
 * All the modifications are sent to other clients in a single message.
 * All the modifications are merged in a single history item (undo/redo).
 * All the subscribers are called only after the batch is over.
 */
declare function useBatch<T>(): (callback: () => T) => T;
/**
 * Get informed when reconnecting to the Liveblocks servers is taking
 * longer than usual. This typically is a sign of a client that has lost
 * internet connectivity.
 *
 * This isn't problematic (because the Liveblocks client is still trying to
 * reconnect), but it's typically a good idea to inform users about it if
 * the connection takes too long to recover.
 *
 * @example
 * useLostConnectionListener(event => {
 *   if (event === 'lost') {
 *     toast.warn('Reconnecting to the Liveblocks servers is taking longer than usual...')
 *   } else if (event === 'failed') {
 *     toast.warn('Reconnecting to the Liveblocks servers failed.')
 *   } else if (event === 'restored') {
 *     toast.clear();
 *   }
 * })
 */
declare function useLostConnectionListener(callback: (event: LostConnectionEvent) => void): void;
/**
 * Returns the room.history
 */
declare function useHistory(): History;
/**
 * Returns a function that undoes the last operation executed by the current
 * client. It does not impact operations made by other clients.
 */
declare function useUndo(): () => void;
/**
 * Returns a function that redoes the last operation executed by the current
 * client. It does not impact operations made by other clients.
 */
declare function useRedo(): () => void;
/**
 * Returns whether there are any operations to undo.
 */
declare function useCanUndo(): boolean;
/**
 * Returns whether there are any operations to redo.
 */
declare function useCanRedo(): boolean;
/**
 * Returns an array of connection IDs. This matches the values you'll get by
 * using the `useOthers()` hook.
 *
 * Roughly equivalent to:
 *   useOthers((others) => others.map(other => other.connectionId), shallow)
 *
 * This is useful in particular to implement efficiently rendering components
 * for each user in the room, e.g. cursors.
 *
 * @example
 * const ids = useOthersConnectionIds();
 * // [2, 4, 7]
 */
declare function useOthersConnectionIds(): readonly number[];
/**
 * @private
 */
declare function useCreateRoomThread<M extends BaseMetadata$1>(roomId: string): (options: CreateThreadOptions<M>) => ThreadData$1<M>;
declare function useDeleteRoomThread(roomId: string): (threadId: string) => void;
declare function useEditRoomThreadMetadata<M extends BaseMetadata$1>(roomId: string): (options: EditThreadMetadataOptions<M>) => void;
/**
 * Returns a function that adds a comment to a thread.
 *
 * @example
 * const createComment = useCreateComment();
 * createComment({ threadId: "th_xxx", body: {} });
 */
declare function useCreateComment(): (options: CreateCommentOptions) => CommentData$1;
/**
 * @private
 */
declare function useCreateRoomComment(roomId: string): (options: CreateCommentOptions) => CommentData$1;
/**
 * Returns a function that edits a comment's body.
 *
 * @example
 * const editComment = useEditComment()
 * editComment({ threadId: "th_xxx", commentId: "cm_xxx", body: {} })
 */
declare function useEditComment(): (options: EditCommentOptions) => void;
/**
 * @private
 */
declare function useEditRoomComment(roomId: string): (options: EditCommentOptions) => void;
/**
 * Returns a function that deletes a comment.
 * If it is the last non-deleted comment, the thread also gets deleted.
 *
 * @example
 * const deleteComment = useDeleteComment();
 * deleteComment({ threadId: "th_xxx", commentId: "cm_xxx" })
 */
declare function useDeleteComment(): ({ threadId, commentId }: DeleteCommentOptions) => void;
/**
 * @private
 */
declare function useDeleteRoomComment(roomId: string): ({ threadId, commentId }: DeleteCommentOptions) => void;
/**
 * @private
 */
declare function useAddRoomCommentReaction<M extends BaseMetadata$1>(roomId: string): ({ threadId, commentId, emoji }: CommentReactionOptions) => void;
/**
 * Returns a function that removes a reaction on a comment.
 *
 * @example
 * const removeReaction = useRemoveReaction();
 * removeReaction({ threadId: "th_xxx", commentId: "cm_xxx", emoji: "👍" })
 */
declare function useRemoveReaction(): ({ threadId, commentId, emoji }: CommentReactionOptions) => void;
/**
 * @private
 */
declare function useRemoveRoomCommentReaction(roomId: string): ({ threadId, commentId, emoji }: CommentReactionOptions) => void;
/**
 * Returns a function that marks a thread as read.
 *
 * @example
 * const markThreadAsRead = useMarkThreadAsRead();
 * markThreadAsRead("th_xxx");
 */
declare function useMarkThreadAsRead(): (threadId: string) => void;
/**
 * @private
 */
declare function useMarkRoomThreadAsRead(roomId: string): (threadId: string) => void;
/**
 * Returns a function that marks a thread as resolved.
 *
 * @example
 * const markThreadAsResolved = useMarkThreadAsResolved();
 * markThreadAsResolved("th_xxx");
 */
declare function useMarkThreadAsResolved(): (threadId: string) => void;
/**
 * @private
 */
declare function useMarkRoomThreadAsResolved(roomId: string): (threadId: string) => void;
/**
 * Returns a function that marks a thread as unresolved.
 *
 * @example
 * const markThreadAsUnresolved = useMarkThreadAsUnresolved();
 * markThreadAsUnresolved("th_xxx");
 */
declare function useMarkThreadAsUnresolved(): (threadId: string) => void;
/**
 * @private
 */
declare function useMarkRoomThreadAsUnresolved(roomId: string): (threadId: string) => void;
/**
 * Returns the subscription status of a thread.
 *
 * @example
 * const { status, unreadSince } = useThreadSubscription("th_xxx");
 */
declare function useThreadSubscription(threadId: string): ThreadSubscription;
/**
 * Returns the version data bianry for a given version
 *
 * @example
 * const {data} = useHistoryVersionData(versionId);
 */
declare function useHistoryVersionData(versionId: string): HistoryVersionDataAsyncResult;
/**
 * Returns a function that updates the user's notification settings
 * for the current room.
 *
 * @example
 * const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
 * updateRoomNotificationSettings({ threads: "all" });
 */
declare function useUpdateRoomNotificationSettings(): (settings: Partial<RoomNotificationSettings>) => void;
/**
 * Returns an array of connection IDs. This matches the values you'll get by
 * using the `useOthers()` hook.
 *
 * Roughly equivalent to:
 *   useOthers((others) => others.map(other => other.connectionId), shallow)
 *
 * This is useful in particular to implement efficiently rendering components
 * for each user in the room, e.g. cursors.
 *
 * @example
 * const ids = useOthersConnectionIds();
 * // [2, 4, 7]
 */
declare function useOthersConnectionIdsSuspense(): readonly number[];
/**
 * Returns the current storage status for the Room, and triggers
 * a re-render whenever it changes. Can be used to render a "Saving..."
 * indicator.
 *
 * @deprecated Prefer useSyncStatus()
 */
declare function useStorageStatusSuspense(options?: UseStorageStatusOptions): StorageStatusSuccess;
/**
 * Returns a presigned URL for an attachment by its ID.
 *
 * @example
 * const { url, error, isLoading } = useAttachmentUrl("at_xxx");
 */
declare function useAttachmentUrl(attachmentId: string): AttachmentUrlAsyncResult;
/**
 * @private For internal use only. Do not rely on this hook. Use `useAttachmentUrl` instead.
 */
declare function useRoomAttachmentUrl(attachmentId: string, roomId: string): AttachmentUrlAsyncResult;
/**
 * Returns a presigned URL for an attachment by its ID.
 *
 * @example
 * const { url } = useAttachmentUrl("at_xxx");
 */
declare function useAttachmentUrlSuspense(attachmentId: string): {
    readonly isLoading: false;
    readonly url: string;
    readonly error: undefined;
};
/**
 * @private For internal use only. Do not rely on this hook.
 */
declare function useRoomPermissions(roomId: string): Set<unknown>;
/**
 * Creates a RoomProvider and a set of typed hooks to use in your app. Note
 * that any RoomProvider created in this way does not need to be nested in
 * LiveblocksProvider, as it already has access to the client.
 */
declare function createRoomContext<P extends JsonObject = DP, S extends LsonObject = DS, U extends BaseUserMeta = DU, E extends Json = DE, M extends BaseMetadata$1 = DM>(client: OpaqueClient): RoomContextBundle<P, S, U, E, M>;
type TypedBundle = RoomContextBundle<DP, DS, DU, DE, DM>;
/**
 * Makes a Room available in the component hierarchy below.
 * Joins the room when the component is mounted, and automatically leaves
 * the room when the component is unmounted.
 */
declare const _RoomProvider: TypedBundle["RoomProvider"];
/**
 * Returns a callback that lets you broadcast custom events to other users in the room
 *
 * @example
 * const broadcast = useBroadcastEvent();
 *
 * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
 */
declare const _useBroadcastEvent: TypedBundle["useBroadcastEvent"];
/**
 * Get informed when users enter or leave the room, as an event.
 *
 * @example
 * useOthersListener({ type, user, others }) => {
 *   if (type === 'enter') {
 *     // `user` has joined the room
 *   } else if (type === 'leave') {
 *     // `user` has left the room
 *   }
 * })
 */
declare const _useOthersListener: TypedBundle["useOthersListener"];
/**
 * Returns the Room of the nearest RoomProvider above in the React component
 * tree.
 */
declare const _useRoom: TypedBundle["useRoom"];
/**
 * Returns whether the hook is called within a RoomProvider context.
 *
 * @example
 * const isInsideRoom = useIsInsideRoom();
 */
declare const _useIsInsideRoom: TypedBundle["useIsInsideRoom"];
/**
 * Returns a function that adds a reaction from a comment.
 *
 * @example
 * const addReaction = useAddReaction();
 * addReaction({ threadId: "th_xxx", commentId: "cm_xxx", emoji: "👍" })
 */
declare const _useAddReaction: TypedBundle["useAddReaction"];
/**
 * Create a callback function that lets you mutate Liveblocks state.
 *
 * The first argument that gets passed into your callback will be
 * a "mutation context", which exposes the following:
 *
 *   - `storage` - The mutable Storage root.
 *                 You can mutate any Live structures with this, for example:
 *                 `storage.get('layers').get('layer1').set('fill', 'red')`
 *
 *   - `setMyPresence` - Call this with a new (partial) Presence value.
 *
 *   - `self` - A read-only version of the latest self, if you need it to
 *              compute the next state.
 *
 *   - `others` - A read-only version of the latest others list, if you
 *                need it to compute the next state.
 *
 * useMutation is like React's useCallback, except that the first argument
 * that gets passed into your callback will be a "mutation context".
 *
 * If you want get access to the immutable root somewhere in your mutation,
 * you can use `storage.ToImmutable()`.
 *
 * @example
 * const fillLayers = useMutation(
 *   ({ storage }, color: Color) => {
 *     ...
 *   },
 *   [],
 * );
 *
 * fillLayers('red');
 *
 * const deleteLayers = useMutation(
 *   ({ storage }) => {
 *     ...
 *   },
 *   [],
 * );
 *
 * deleteLayers();
 */
declare const _useMutation: TypedBundle["useMutation"];
/**
 * Returns a function that creates a thread with an initial comment, and optionally some metadata.
 *
 * @example
 * const createThread = useCreateThread();
 * createThread({ body: {}, metadata: {} });
 */
declare const _useCreateThread: TypedBundle["useCreateThread"];
/**
 * Returns a function that deletes a thread and its associated comments.
 * Only the thread creator can delete a thread, it will throw otherwise.
 *
 * @example
 * const deleteThread = useDeleteThread();
 * deleteThread("th_xxx");
 */
declare const _useDeleteThread: TypedBundle["useDeleteThread"];
/**
 * Returns a function that edits a thread's metadata.
 * To delete an existing metadata property, set its value to `null`.
 *
 * @example
 * const editThreadMetadata = useEditThreadMetadata();
 * editThreadMetadata({ threadId: "th_xxx", metadata: {} })
 */
declare const _useEditThreadMetadata: TypedBundle["useEditThreadMetadata"];
/**
 * useEventListener is a React hook that allows you to respond to events broadcast
 * by other users in the room.
 *
 * The `user` argument will indicate which `User` instance sent the message.
 * This will be equal to one of the others in the room, but it can be `null`
 * in case this event was broadcasted from the server.
 *
 * @example
 * useEventListener(({ event, user, connectionId }) => {
 * //                         ^^^^ Will be Client A
 *   if (event.type === "CUSTOM_EVENT") {
 *     // Do something
 *   }
 * });
 */
declare const _useEventListener: TypedBundle["useEventListener"];
/**
 * Returns the presence of the current user of the current room, and a function to update it.
 * It is different from the setState function returned by the useState hook from
 * You don't need to pass the full presence object to update it.
 *
 * @example
 * const [myPresence, updateMyPresence] = useMyPresence();
 * updateMyPresence({ x: 0 });
 * updateMyPresence({ y: 0 });
 *
 * // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }"
 */
declare const _useMyPresence: TypedBundle["useMyPresence"];
/**
 * Related to useOthers(), but optimized for selecting only "subsets" of
 * others. This is useful for performance reasons in particular, because
 * selecting only a subset of users also means limiting the number of
 * re-renders that will be triggered.
 *
 * @example
 * const avatars = useOthersMapped(user => user.info.avatar);
 * //    ^^^^^^^
 * //    { connectionId: number; data: string }[]
 *
 * The selector function you pass to useOthersMapped() is called an "item
 * selector", and operates on a single user at a time. If you provide an
 * (optional) "item comparison" function, it will be used to compare each
 * item pairwise.
 *
 * For example, to select multiple properties:
 *
 * @example
 * const avatarsAndCursors = useOthersMapped(
 *   user => [u.info.avatar, u.presence.cursor],
 *   shallow,  // 👈
 * );
 */
declare const _useOthersMapped: TypedBundle["useOthersMapped"];
/**
 * Related to useOthers(), but optimized for selecting only "subsets" of
 * others. This is useful for performance reasons in particular, because
 * selecting only a subset of users also means limiting the number of
 * re-renders that will be triggered.
 *
 * @example
 * const avatars = useOthersMapped(user => user.info.avatar);
 * //    ^^^^^^^
 * //    { connectionId: number; data: string }[]
 *
 * The selector function you pass to useOthersMapped() is called an "item
 * selector", and operates on a single user at a time. If you provide an
 * (optional) "item comparison" function, it will be used to compare each
 * item pairwise.
 *
 * For example, to select multiple properties:
 *
 * @example
 * const avatarsAndCursors = useOthersMapped(
 *   user => [u.info.avatar, u.presence.cursor],
 *   shallow,  // 👈
 * );
 */
declare const _useOthersMappedSuspense: TypedBundle["suspense"]["useOthersMapped"];
/**
 * Returns the threads within the current room.
 *
 * @example
 * const { threads, error, isLoading } = useThreads();
 */
declare const _useThreads: TypedBundle["useThreads"];
/**
 * Returns the threads within the current room.
 *
 * @example
 * const { threads } = useThreads();
 */
declare const _useThreadsSuspense: TypedBundle["suspense"]["useThreads"];
/**
 * Returns the user's notification settings for the current room
 * and a function to update them.
 *
 * @example
 * const [{ settings }, updateSettings] = useRoomNotificationSettings();
 */
declare const _useRoomNotificationSettings: TypedBundle["useRoomNotificationSettings"];
/**
 * Returns the user's notification settings for the current room
 * and a function to update them.
 *
 * @example
 * const [{ settings }, updateSettings] = useRoomNotificationSettings();
 */
declare const _useRoomNotificationSettingsSuspense: TypedBundle["suspense"]["useRoomNotificationSettings"];
/**
 * (Private beta) Returns a history of versions of the current room.
 *
 * @example
 * const { versions, error, isLoading } = useHistoryVersions();
 */
declare const _useHistoryVersions: TypedBundle["useHistoryVersions"];
/**
 * (Private beta) Returns a history of versions of the current room.
 *
 * @example
 * const { versions } = useHistoryVersions();
 */
declare const _useHistoryVersionsSuspense: TypedBundle["suspense"]["useHistoryVersions"];
/**
 * Given a connection ID (as obtained by using `useOthersConnectionIds`), you
 * can call this selector deep down in your component stack to only have the
 * component re-render if properties for this particular user change.
 *
 * @example
 * // Returns only the selected values re-renders whenever that selection changes)
 * const { x, y } = useOther(2, user => user.presence.cursor);
 */
declare const _useOther: TypedBundle["useOther"];
/**
 * Returns an array with information about all the users currently connected in
 * the room (except yourself).
 *
 * @example
 * const others = useOthers();
 *
 * // Example to map all cursors in JSX
 * return (
 *   <>
 *     {others.map((user) => {
 *        if (user.presence.cursor == null) {
 *          return null;
 *        }
 *        return <Cursor key={user.connectionId} cursor={user.presence.cursor} />
 *      })}
 *   </>
 * )
 */
declare function _useOthers(): readonly User<DP, DU>[];
/**
 * Extract arbitrary data based on all the users currently connected in the
 * room (except yourself).
 *
 * The selector function will get re-evaluated any time a user enters or
 * leaves the room, as well as whenever their presence data changes.
 *
 * The component that uses this hook will automatically re-render if your
 * selector function returns a different value from its previous run.
 *
 * By default `useOthers()` uses strict `===` to check for equality. Take
 * extra care when returning a computed object or list, for example when you
 * return the result of a .map() or .filter() call from the selector. In
 * those cases, you'll probably want to use a `shallow` comparison check.
 *
 * @example
 * const avatars = useOthers(users => users.map(u => u.info.avatar), shallow);
 * const cursors = useOthers(users => users.map(u => u.presence.cursor), shallow);
 * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));
 *
 */
declare function _useOthers<T>(selector: (others: readonly User<DP, DU>[]) => T, isEqual?: (prev: T, curr: T) => boolean): T;
/**
 * Given a connection ID (as obtained by using `useOthersConnectionIds`), you
 * can call this selector deep down in your component stack to only have the
 * component re-render if properties for this particular user change.
 *
 * @example
 * // Returns only the selected values re-renders whenever that selection changes)
 * const { x, y } = useOther(2, user => user.presence.cursor);
 */
declare const _useOtherSuspense: TypedBundle["suspense"]["useOther"];
/**
 * Returns an array with information about all the users currently connected in
 * the room (except yourself).
 *
 * @example
 * const others = useOthers();
 *
 * // Example to map all cursors in JSX
 * return (
 *   <>
 *     {others.map((user) => {
 *        if (user.presence.cursor == null) {
 *          return null;
 *        }
 *        return <Cursor key={user.connectionId} cursor={user.presence.cursor} />
 *      })}
 *   </>
 * )
 */
declare function _useOthersSuspense(): readonly User<DP, DU>[];
/**
 * Extract arbitrary data based on all the users currently connected in the
 * room (except yourself).
 *
 * The selector function will get re-evaluated any time a user enters or
 * leaves the room, as well as whenever their presence data changes.
 *
 * The component that uses this hook will automatically re-render if your
 * selector function returns a different value from its previous run.
 *
 * By default `useOthers()` uses strict `===` to check for equality. Take
 * extra care when returning a computed object or list, for example when you
 * return the result of a .map() or .filter() call from the selector. In
 * those cases, you'll probably want to use a `shallow` comparison check.
 *
 * @example
 * const avatars = useOthers(users => users.map(u => u.info.avatar), shallow);
 * const cursors = useOthers(users => users.map(u => u.presence.cursor), shallow);
 * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));
 *
 */
declare function _useOthersSuspense<T>(selector: (others: readonly User<DP, DU>[]) => T, isEqual?: (prev: T, curr: T) => boolean): T;
/**
 * Extract arbitrary data from the Liveblocks Storage state, using an
 * arbitrary selector function.
 *
 * The selector function will get re-evaluated any time something changes in
 * Storage. The value returned by your selector function will also be the
 * value returned by the hook.
 *
 * The `root` value that gets passed to your selector function is
 * a immutable/readonly version of your Liveblocks storage root.
 *
 * The component that uses this hook will automatically re-render if the
 * returned value changes.
 *
 * By default `useStorage()` uses strict `===` to check for equality. Take
 * extra care when returning a computed object or list, for example when you
 * return the result of a .map() or .filter() call from the selector. In
 * those cases, you'll probably want to use a `shallow` comparison check.
 */
declare const _useStorage: TypedBundle["useStorage"];
/**
 * Extract arbitrary data from the Liveblocks Storage state, using an
 * arbitrary selector function.
 *
 * The selector function will get re-evaluated any time something changes in
 * Storage. The value returned by your selector function will also be the
 * value returned by the hook.
 *
 * The `root` value that gets passed to your selector function is
 * a immutable/readonly version of your Liveblocks storage root.
 *
 * The component that uses this hook will automatically re-render if the
 * returned value changes.
 *
 * By default `useStorage()` uses strict `===` to check for equality. Take
 * extra care when returning a computed object or list, for example when you
 * return the result of a .map() or .filter() call from the selector. In
 * those cases, you'll probably want to use a `shallow` comparison check.
 */
declare const _useStorageSuspense: TypedBundle["suspense"]["useStorage"];
/**
 * Gets the current user once it is connected to the room.
 *
 * @example
 * const me = useSelf();
 * if (me !== null) {
 *   const { x, y } = me.presence.cursor;
 * }
 */
declare function _useSelf(): User<DP, DU> | null;
/**
 * Extract arbitrary data based on the current user.
 *
 * The selector function will get re-evaluated any time your presence data
 * changes.
 *
 * The component that uses this hook will automatically re-render if your
 * selector function returns a different value from its previous run.
 *
 * By default `useSelf()` uses strict `===` to check for equality. Take extra
 * care when returning a computed object or list, for example when you return
 * the result of a .map() or .filter() call from the selector. In those
 * cases, you'll probably want to use a `shallow` comparison check.
 *
 * Will return `null` while Liveblocks isn't connected to a room yet.
 *
 * @example
 * const cursor = useSelf(me => me.presence.cursor);
 * if (cursor !== null) {
 *   const { x, y } = cursor;
 * }
 *
 */
declare function _useSelf<T>(selector: (me: User<DP, DU>) => T, isEqual?: (prev: T, curr: T) => boolean): T | null;
/**
 * Gets the current user once it is connected to the room.
 *
 * @example
 * const me = useSelf();
 * const { x, y } = me.presence.cursor;
 */
declare function _useSelfSuspense(): User<DP, DU>;
/**
 * Extract arbitrary data based on the current user.
 *
 * The selector function will get re-evaluated any time your presence data
 * changes.
 *
 * The component that uses this hook will automatically re-render if your
 * selector function returns a different value from its previous run.
 *
 * By default `useSelf()` uses strict `===` to check for equality. Take extra
 * care when returning a computed object or list, for example when you return
 * the result of a .map() or .filter() call from the selector. In those
 * cases, you'll probably want to use a `shallow` comparison check.
 *
 * @example
 * const cursor = useSelf(me => me.presence.cursor);
 * const { x, y } = cursor;
 *
 */
declare function _useSelfSuspense<T>(selector: (me: User<DP, DU>) => T, isEqual?: (prev: T, curr: T) => boolean): T;
/**
 * Returns the mutable (!) Storage root. This hook exists for
 * backward-compatible reasons.
 *
 * @example
 * const [root] = useStorageRoot();
 */
declare const _useStorageRoot: TypedBundle["useStorageRoot"];
/**
 * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.
 * If you don't use the current user presence in your component, but you need to update it (e.g. live cursor), it's better to use useUpdateMyPresence to avoid unnecessary renders.
 *
 * @example
 * const updateMyPresence = useUpdateMyPresence();
 * updateMyPresence({ x: 0 });
 * updateMyPresence({ y: 0 });
 *
 * // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }"
 */
declare const _useUpdateMyPresence: TypedBundle["useUpdateMyPresence"];

export { useLostConnectionListener as $, useErrorListener as A, useMarkAllInboxNotificationsAsRead as B, ClientContext as C, useMarkInboxNotificationAsRead as D, useSyncStatus as E, createRoomContext as F, _RoomProvider as G, _useAddReaction as H, useBatch as I, _useBroadcastEvent as J, useCanRedo as K, LiveblocksProvider as L, type MutationContext as M, useCanUndo as N, useCreateComment as O, _useCreateThread as P, useDeleteComment as Q, _useDeleteThread as R, useEditComment as S, _useEditThreadMetadata as T, type UseStorageStatusOptions as U, useMarkThreadAsResolved as V, useMarkThreadAsUnresolved as W, _useEventListener as X, useHistory as Y, _useIsInsideRoom as Z, _useInboxNotificationThread as _, useAddRoomCommentReaction as a, useMarkThreadAsRead as a0, _useMutation as a1, _useMyPresence as a2, _useOthersListener as a3, useRedo as a4, useRemoveReaction as a5, _useRoom as a6, useStatus as a7, _useStorageRoot as a8, useThreadSubscription as a9, _useSelfSuspense as aA, _useStorageSuspense as aB, useStorageStatusSuspense as aC, _useThreadsSuspense as aD, useAttachmentUrlSuspense as aE, _useHistoryVersionsSuspense as aF, _useRoomNotificationSettingsSuspense as aG, useInboxNotificationsSuspense as aH, useNotificationSettingsSuspense as aI, useRoomInfoSuspense as aJ, useUnreadInboxNotificationsCountSuspense as aK, _useUserSuspense as aL, _useUserThreadsSuspense_experimental as aM, useUndo as aa, _useUpdateMyPresence as ab, useUpdateRoomNotificationSettings as ac, useHistoryVersionData as ad, _useOther as ae, _useOthers as af, useOthersConnectionIds as ag, _useOthersMapped as ah, _useSelf as ai, _useStorage as aj, useStorageStatus as ak, _useThreads as al, useAttachmentUrl as am, _useHistoryVersions as an, _useRoomNotificationSettings as ao, useInboxNotifications as ap, useNotificationSettings as aq, useUpdateNotificationSettings as ar, _useUserThreads_experimental as as, useRoomInfo as at, useUnreadInboxNotificationsCount as au, _useUser as av, _useOtherSuspense as aw, _useOthersSuspense as ax, useOthersConnectionIdsSuspense as ay, _useOthersMappedSuspense as az, useCreateRoomComment as b, useCreateRoomThread as c, useCreateTextMention as d, useDeleteRoomComment as e, useDeleteRoomThread as f, getUmbrellaStoreForClient as g, useDeleteTextMention as h, useEditRoomComment as i, useEditRoomThreadMetadata as j, useMarkRoomThreadAsRead as k, useMarkRoomThreadAsResolved as l, useMarkRoomThreadAsUnresolved as m, useMentionSuggestionsCache as n, useRemoveRoomCommentReaction as o, useReportTextEditor as p, useResolveMentionSuggestions as q, useRoomAttachmentUrl as r, useRoomPermissions as s, useYjsProvider as t, useClientOrNull as u, type UseThreadsOptions as v, createLiveblocksContext as w, useClient as x, useDeleteAllInboxNotifications as y, useDeleteInboxNotification as z };
