@liveblocks/react 1.2.2-comments1 → 1.2.2-comments2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +29 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -71,6 +71,13 @@ declare type RoomThreads<TThreadMetadata extends BaseMetadata> = {
|
|
|
71
71
|
error?: never;
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
+
declare type ResolveUserOptions = {
|
|
75
|
+
userId: string;
|
|
76
|
+
};
|
|
77
|
+
declare type ResolveMentionSuggestionsOptions = {
|
|
78
|
+
roomId: string;
|
|
79
|
+
text: string;
|
|
80
|
+
};
|
|
74
81
|
declare type UserState<T> = {
|
|
75
82
|
user?: never;
|
|
76
83
|
isLoading: true;
|
|
@@ -673,11 +680,11 @@ declare type Options<TUserMeta extends BaseUserMeta> = {
|
|
|
673
680
|
/**
|
|
674
681
|
* An asynchronous function that returns user info from a user ID.
|
|
675
682
|
*/
|
|
676
|
-
resolveUser?: (
|
|
683
|
+
resolveUser?: (options: ResolveUserOptions) => Promise<TUserMeta["info"] | undefined>;
|
|
677
684
|
/**
|
|
678
685
|
* An asynchronous function that returns a list of user IDs matching a string.
|
|
679
686
|
*/
|
|
680
|
-
resolveMentionSuggestions?: (
|
|
687
|
+
resolveMentionSuggestions?: (options: ResolveMentionSuggestionsOptions) => Promise<string[]>;
|
|
681
688
|
};
|
|
682
689
|
declare function useRoomContextBundle(): {
|
|
683
690
|
RoomContext: React$1.Context<Room<JsonObject, LsonObject, BaseUserMeta, never> | null>;
|
|
@@ -1398,4 +1405,4 @@ declare function useRoomContextBundle(): {
|
|
|
1398
1405
|
};
|
|
1399
1406
|
declare function createRoomContext<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never, TThreadMetadata extends BaseMetadata = never>(client: Client, options?: Options<TUserMeta>): RoomContextBundle<TPresence, TStorage, TUserMeta, TRoomEvent, TThreadMetadata>;
|
|
1400
1407
|
|
|
1401
|
-
export { ClientSideSuspense, MutationContext, createRoomContext, useRoomContextBundle };
|
|
1408
|
+
export { ClientSideSuspense, MutationContext, ResolveMentionSuggestionsOptions, ResolveUserOptions, createRoomContext, useRoomContextBundle };
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,13 @@ declare type RoomThreads<TThreadMetadata extends BaseMetadata> = {
|
|
|
71
71
|
error?: never;
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
+
declare type ResolveUserOptions = {
|
|
75
|
+
userId: string;
|
|
76
|
+
};
|
|
77
|
+
declare type ResolveMentionSuggestionsOptions = {
|
|
78
|
+
roomId: string;
|
|
79
|
+
text: string;
|
|
80
|
+
};
|
|
74
81
|
declare type UserState<T> = {
|
|
75
82
|
user?: never;
|
|
76
83
|
isLoading: true;
|
|
@@ -673,11 +680,11 @@ declare type Options<TUserMeta extends BaseUserMeta> = {
|
|
|
673
680
|
/**
|
|
674
681
|
* An asynchronous function that returns user info from a user ID.
|
|
675
682
|
*/
|
|
676
|
-
resolveUser?: (
|
|
683
|
+
resolveUser?: (options: ResolveUserOptions) => Promise<TUserMeta["info"] | undefined>;
|
|
677
684
|
/**
|
|
678
685
|
* An asynchronous function that returns a list of user IDs matching a string.
|
|
679
686
|
*/
|
|
680
|
-
resolveMentionSuggestions?: (
|
|
687
|
+
resolveMentionSuggestions?: (options: ResolveMentionSuggestionsOptions) => Promise<string[]>;
|
|
681
688
|
};
|
|
682
689
|
declare function useRoomContextBundle(): {
|
|
683
690
|
RoomContext: React$1.Context<Room<JsonObject, LsonObject, BaseUserMeta, never> | null>;
|
|
@@ -1398,4 +1405,4 @@ declare function useRoomContextBundle(): {
|
|
|
1398
1405
|
};
|
|
1399
1406
|
declare function createRoomContext<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never, TThreadMetadata extends BaseMetadata = never>(client: Client, options?: Options<TUserMeta>): RoomContextBundle<TPresence, TStorage, TUserMeta, TRoomEvent, TThreadMetadata>;
|
|
1400
1407
|
|
|
1401
|
-
export { ClientSideSuspense, MutationContext, createRoomContext, useRoomContextBundle };
|
|
1408
|
+
export { ClientSideSuspense, MutationContext, ResolveMentionSuggestionsOptions, ResolveUserOptions, createRoomContext, useRoomContextBundle };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var _core = require('@liveblocks/core');
|
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
7
|
var PKG_NAME = "@liveblocks/react";
|
|
8
|
-
var PKG_VERSION = "1.2.2-
|
|
8
|
+
var PKG_VERSION = "1.2.2-comments2";
|
|
9
9
|
var PKG_FORMAT = "cjs";
|
|
10
10
|
|
|
11
11
|
// src/ClientSideSuspense.tsx
|
|
@@ -303,7 +303,6 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
303
303
|
type: "comment",
|
|
304
304
|
createdAt: now,
|
|
305
305
|
userId: getCurrentUserId(),
|
|
306
|
-
mentionedIds: [],
|
|
307
306
|
body
|
|
308
307
|
};
|
|
309
308
|
setThreads(
|
|
@@ -368,8 +367,7 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
368
367
|
(comment) => comment.id === commentId ? {
|
|
369
368
|
...comment,
|
|
370
369
|
deletedAt: now,
|
|
371
|
-
body: void 0
|
|
372
|
-
mentionedIds: []
|
|
370
|
+
body: void 0
|
|
373
371
|
} : comment
|
|
374
372
|
)
|
|
375
373
|
};
|
|
@@ -1059,9 +1057,17 @@ function createRoomContext(client, options) {
|
|
|
1059
1057
|
);
|
|
1060
1058
|
}
|
|
1061
1059
|
const { resolveUser, resolveMentionSuggestions } = _nullishCoalesce(options, () => ( {}));
|
|
1062
|
-
const usersCache = resolveUser ? _core.createAsyncCache.call(void 0,
|
|
1060
|
+
const usersCache = resolveUser ? _core.createAsyncCache.call(void 0, (stringifiedOptions) => {
|
|
1061
|
+
return resolveUser(
|
|
1062
|
+
JSON.parse(stringifiedOptions)
|
|
1063
|
+
);
|
|
1064
|
+
}) : void 0;
|
|
1063
1065
|
function useUser(userId) {
|
|
1064
|
-
const
|
|
1066
|
+
const resolverKey = React2.useMemo(
|
|
1067
|
+
() => JSON.stringify({ userId }),
|
|
1068
|
+
[userId]
|
|
1069
|
+
);
|
|
1070
|
+
const state = useAsyncCache(usersCache, resolverKey);
|
|
1065
1071
|
React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
|
|
1066
1072
|
if (state.isLoading) {
|
|
1067
1073
|
return {
|
|
@@ -1076,7 +1082,11 @@ function createRoomContext(client, options) {
|
|
|
1076
1082
|
}
|
|
1077
1083
|
}
|
|
1078
1084
|
function useUserSuspense(userId) {
|
|
1079
|
-
const
|
|
1085
|
+
const resolverKey = React2.useMemo(
|
|
1086
|
+
() => JSON.stringify({ userId }),
|
|
1087
|
+
[userId]
|
|
1088
|
+
);
|
|
1089
|
+
const state = useAsyncCache(usersCache, resolverKey, {
|
|
1080
1090
|
suspense: true
|
|
1081
1091
|
});
|
|
1082
1092
|
React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
|
|
@@ -1087,17 +1097,22 @@ function createRoomContext(client, options) {
|
|
|
1087
1097
|
};
|
|
1088
1098
|
}
|
|
1089
1099
|
const mentionSuggestionsCache = _core.createAsyncCache.call(void 0,
|
|
1090
|
-
|
|
1100
|
+
resolveMentionSuggestions ? (stringifiedOptions) => {
|
|
1101
|
+
return resolveMentionSuggestions(
|
|
1102
|
+
JSON.parse(stringifiedOptions)
|
|
1103
|
+
);
|
|
1104
|
+
} : () => Promise.resolve([])
|
|
1091
1105
|
);
|
|
1092
1106
|
function useMentionSuggestions(search) {
|
|
1107
|
+
const room = useRoom();
|
|
1093
1108
|
const debouncedSearch = useDebounce(search, 500);
|
|
1094
|
-
const
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
{
|
|
1098
|
-
keepPreviousDataWhileLoading: true
|
|
1099
|
-
}
|
|
1109
|
+
const resolverKey = React2.useMemo(
|
|
1110
|
+
() => debouncedSearch !== void 0 ? JSON.stringify({ text: debouncedSearch, roomId: room.id }) : null,
|
|
1111
|
+
[debouncedSearch, room.id]
|
|
1100
1112
|
);
|
|
1113
|
+
const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {
|
|
1114
|
+
keepPreviousDataWhileLoading: true
|
|
1115
|
+
});
|
|
1101
1116
|
React2.useEffect(
|
|
1102
1117
|
() => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),
|
|
1103
1118
|
[]
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/ClientSideSuspense.tsx","../src/factory.tsx","../src/comments/CommentsRoom.ts","../../../node_modules/nanoid/index.js","../../../node_modules/nanoid/url-alphabet/index.js","../src/comments/errors.ts","../src/comments/lib/store.ts","../src/comments/lib/use-async-cache.ts","../src/comments/lib/use-initial.ts","../src/comments/lib/use-debounce.ts","../src/hooks.ts"],"names":["makeEventSource","React","useEffect","useRef","useSyncExternalStore","cacheItem","useState","useInitial","noop","room","other","options","rootOrNull","shallow"],"mappings":"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","sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { ClientSideSuspense } from \"./ClientSideSuspense\";\nexport { createRoomContext, useRoomContextBundle } from \"./factory\";\nexport type { MutationContext } from \"./types\";\n\n// Re-exports from @liveblocks/client, for convenience\nexport type { Json, JsonObject } from \"@liveblocks/client\";\nexport { shallow } from \"@liveblocks/client\";\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n","import type { ReactElement, ReactNode } from \"react\";\nimport * as React from \"react\";\n\ntype Props = {\n fallback: NonNullable<ReactNode> | null;\n children: () => ReactNode | undefined;\n};\n\n/**\n * Almost like a normal <Suspense> component, except that for server-side\n * renders, the fallback will be used.\n *\n * The child props will have to be provided in a function, i.e. change:\n *\n * <Suspense fallback={<Loading />}>\n * <MyRealComponent a={1} />\n * </Suspense>\n *\n * To:\n *\n * <ClientSideSuspense fallback={<Loading />}>\n * {() => <MyRealComponent a={1} />}\n * </ClientSideSuspense>\n *\n */\nexport function ClientSideSuspense(props: Props): ReactElement {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n // Effects are never executed on the server side. The point of this is to\n // delay the flipping of this boolean until after hydration has happened.\n setMounted(true);\n }, []);\n\n return (\n <React.Suspense fallback={props.fallback}>\n {mounted ? props.children() : props.fallback}\n </React.Suspense>\n );\n}\n","import type {\n BaseUserMeta,\n BroadcastOptions,\n Client,\n History,\n Json,\n JsonObject,\n LiveObject,\n LostConnectionEvent,\n LsonObject,\n Others,\n Room,\n Status,\n User,\n} from \"@liveblocks/client\";\nimport { shallow } from \"@liveblocks/client\";\nimport type {\n AsyncCache,\n BaseMetadata,\n CommentData,\n ToImmutable,\n} from \"@liveblocks/core\";\nimport {\n asArrayWithLegacyMethods,\n createAsyncCache,\n deprecateIf,\n errorIf,\n makeEventSource,\n} from \"@liveblocks/core\";\nimport * as React from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector.js\";\n\nimport type {\n CommentsRoom,\n CreateCommentOptions,\n CreateThreadOptions,\n DeleteCommentOptions,\n EditCommentOptions,\n EditThreadMetadataOptions,\n RoomThreads,\n} from \"./comments/CommentsRoom\";\nimport { createCommentsRoom } from \"./comments/CommentsRoom\";\nimport type { CommentsApiError } from \"./comments/errors\";\nimport { useAsyncCache } from \"./comments/lib/use-async-cache\";\nimport { useDebounce } from \"./comments/lib/use-debounce\";\nimport { useInitial, useRerender } from \"./hooks\";\nimport type {\n MutationContext,\n OmitFirstArg,\n RoomContextBundle,\n RoomProviderProps,\n UserState,\n UserStateSuspense,\n} from \"./types\";\n\nconst noop = () => {};\nconst identity: <T>(x: T) => T = (x) => x;\n\nconst missing_unstable_batchedUpdates = (\n reactVersion: number,\n roomId: string\n) =>\n `We noticed you’re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you’re ready to upgrade to React 18:\n\n import { unstable_batchedUpdates } from \"react-dom\"; // or \"react-native\"\n\n <RoomProvider id=${JSON.stringify(\n roomId\n )} ... unstable_batchedUpdates={unstable_batchedUpdates}>\n ...\n </RoomProvider>\n\nWhy? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;\n\nconst superfluous_unstable_batchedUpdates =\n \"You don’t need to pass unstable_batchedUpdates to RoomProvider anymore, since you’re on React 18+ already.\";\n\nfunction useSyncExternalStore<Snapshot>(\n s: (onStoreChange: () => void) => () => void,\n gs: () => Snapshot,\n gss: undefined | null | (() => Snapshot)\n): Snapshot {\n return useSyncExternalStoreWithSelector(s, gs, gss, identity);\n}\n\nconst EMPTY_OTHERS =\n // NOTE: asArrayWithLegacyMethods() wrapping should no longer be necessary in 0.19\n asArrayWithLegacyMethods([]);\n\nfunction getEmptyOthers() {\n return EMPTY_OTHERS;\n}\n\nfunction makeMutationContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject,\n TUserMeta extends BaseUserMeta,\n TRoomEvent extends Json,\n>(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n): MutationContext<TPresence, TStorage, TUserMeta> {\n const errmsg =\n \"This mutation cannot be used until connected to the Liveblocks room\";\n\n return {\n get storage() {\n const mutableRoot = room.getStorageSnapshot();\n if (mutableRoot === null) {\n throw new Error(errmsg);\n }\n return mutableRoot;\n },\n\n get self() {\n const self = room.getSelf();\n if (self === null) {\n throw new Error(errmsg);\n }\n return self;\n },\n\n get others() {\n const others = room.getOthers();\n if (room.getSelf() === null) {\n throw new Error(errmsg);\n }\n return others;\n },\n\n setMyPresence: room.updatePresence,\n };\n}\n\ntype Options<TUserMeta extends BaseUserMeta> = {\n /**\n * An asynchronous function that returns user info from a user ID.\n */\n resolveUser?: (userId: string) => Promise<TUserMeta[\"info\"] | undefined>;\n\n /**\n * An asynchronous function that returns a list of user IDs matching a string.\n */\n resolveMentionSuggestions?: (search: string) => Promise<string[]>;\n\n /**\n * @internal Internal endpoint\n */\n serverEndpoint?: string;\n};\n\nlet hasWarnedIfNoResolveUser = false;\nlet hasWarnedIfNoResolveMentionSuggestions = false;\n\nfunction warnIfNoResolveUser(usersCache?: AsyncCache<unknown, unknown>) {\n if (\n !hasWarnedIfNoResolveUser &&\n !usersCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\"The resolveUser option wasn't set in createRoomContext.\");\n hasWarnedIfNoResolveUser = true;\n }\n}\n\nfunction warnIfNoResolveMentionSuggestions(\n mentionSuggestionsCache?: AsyncCache<unknown, unknown>\n) {\n if (\n !hasWarnedIfNoResolveMentionSuggestions &&\n !mentionSuggestionsCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\n \"The resolveMentionSuggestions option wasn't set in createRoomContext.\"\n );\n hasWarnedIfNoResolveMentionSuggestions = true;\n }\n}\n\nconst ContextBundle = React.createContext<RoomContextBundle<\n JsonObject,\n LsonObject,\n BaseUserMeta,\n never,\n BaseMetadata\n> | null>(null);\n\n// TODO: Internal?\nexport function useRoomContextBundle() {\n return React.useContext(ContextBundle)!;\n}\n\nexport function createRoomContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject = LsonObject,\n TUserMeta extends BaseUserMeta = BaseUserMeta,\n TRoomEvent extends Json = never,\n TThreadMetadata extends BaseMetadata = never,\n>(\n client: Client,\n options?: Options<TUserMeta>\n): RoomContextBundle<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent,\n TThreadMetadata\n> {\n const RoomContext = React.createContext<Room<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent\n > | null>(null);\n\n function RoomProvider(props: RoomProviderProps<TPresence, TStorage>) {\n const {\n id: roomId,\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect,\n } = props;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!roomId) {\n throw new Error(\n \"RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required\"\n );\n }\n\n if (typeof roomId !== \"string\") {\n throw new Error(\"RoomProvider id property should be a string.\");\n }\n\n const majorReactVersion = parseInt(React.version) || 1;\n const oldReactVersion = majorReactVersion < 18;\n errorIf(\n oldReactVersion && props.unstable_batchedUpdates === undefined,\n missing_unstable_batchedUpdates(majorReactVersion, roomId)\n );\n deprecateIf(\n !oldReactVersion && props.unstable_batchedUpdates !== undefined,\n superfluous_unstable_batchedUpdates\n );\n }\n\n // Note: We'll hold on to the initial value given here, and ignore any\n // changes to this argument in subsequent renders\n const frozen = useInitial({\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect:\n shouldInitiallyConnect === undefined\n ? typeof window !== \"undefined\"\n : shouldInitiallyConnect,\n });\n\n const [room, setRoom] = React.useState<\n Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n >(() =>\n client.enter(roomId, {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n })\n );\n\n React.useEffect(() => {\n const room = client.enter<TPresence, TStorage, TUserMeta, TRoomEvent>(\n roomId,\n {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n }\n );\n\n setRoom(room);\n\n const unsubscribe = getCommentsRoom(room).subscribe();\n\n return () => {\n unsubscribe();\n commentsRooms.delete(room.id);\n client.leave(roomId);\n };\n }, [roomId, frozen]);\n\n return (\n <RoomContext.Provider value={room}>\n <ContextBundle.Provider value={bundle as any}>\n {props.children}\n </ContextBundle.Provider>\n </RoomContext.Provider>\n );\n }\n\n function connectionIdSelector(\n others: Others<TPresence, TUserMeta>\n ): number[] {\n return others.map((user) => user.connectionId);\n }\n\n function useRoom(): Room<TPresence, TStorage, TUserMeta, TRoomEvent> {\n const room = React.useContext(RoomContext);\n if (room === null) {\n throw new Error(\"RoomProvider is missing from the React tree.\");\n }\n return room;\n }\n\n function useStatus(): Status {\n const room = useRoom();\n const subscribe = room.events.status.subscribe;\n const getSnapshot = room.getStatus;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n function useMyPresence(): [\n TPresence,\n (patch: Partial<TPresence>, options?: { addToHistory: boolean }) => void,\n ] {\n const room = useRoom();\n const subscribe = room.events.myPresence.subscribe;\n const getSnapshot = room.getPresence;\n const presence = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setPresence = room.updatePresence;\n return [presence, setPresence];\n }\n\n function useUpdateMyPresence(): (\n patch: Partial<TPresence>,\n options?: { addToHistory: boolean }\n ) => void {\n return useRoom().updatePresence;\n }\n\n function useOthers(): Others<TPresence, TUserMeta>;\n function useOthers<T>(\n selector: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useOthers<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n const room = useRoom();\n const subscribe = room.events.others.subscribe;\n const getSnapshot = room.getOthers;\n const getServerSnapshot = getEmptyOthers;\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n selector ?? (identity as (others: Others<TPresence, TUserMeta>) => T),\n isEqual\n );\n }\n\n function useOthersConnectionIds(): readonly number[] {\n return useOthers(connectionIdSelector, shallow);\n }\n\n function useOthersMapped<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) =>\n others.map(\n (other) => [other.connectionId, itemSelector(other)] as const\n ),\n [itemSelector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (\n a: ReadonlyArray<readonly [connectionId: number, data: T]>,\n b: ReadonlyArray<readonly [connectionId: number, data: T]>\n ): boolean => {\n const eq = itemIsEqual ?? Object.is;\n return (\n a.length === b.length &&\n a.every((atuple, index) => {\n const btuple = b[index];\n return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);\n })\n );\n },\n [itemIsEqual]\n );\n\n return useOthers(wrappedSelector, wrappedIsEqual);\n }\n\n const NOT_FOUND = Symbol();\n\n type NotFound = typeof NOT_FOUND;\n\n function useOther<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) => {\n // TODO: Make this O(1) instead of O(n)?\n const other = others.find(\n (other) => other.connectionId === connectionId\n );\n return other !== undefined ? selector(other) : NOT_FOUND;\n },\n [connectionId, selector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (prev: T | NotFound, curr: T | NotFound): boolean => {\n if (prev === NOT_FOUND || curr === NOT_FOUND) {\n return prev === curr;\n }\n\n const eq = isEqual ?? Object.is;\n return eq(prev, curr);\n },\n [isEqual]\n );\n\n const other = useOthers(wrappedSelector, wrappedIsEqual);\n if (other === NOT_FOUND) {\n throw new Error(\n `No such other user with connection id ${connectionId} exists`\n );\n }\n\n return other;\n }\n\n function useBroadcastEvent(): (\n event: TRoomEvent,\n options?: BroadcastOptions\n ) => void {\n const room = useRoom();\n\n return React.useCallback(\n (\n event: TRoomEvent,\n options: BroadcastOptions = { shouldQueueEventIfNotReady: false }\n ) => {\n room.broadcastEvent(event, options);\n },\n [room]\n );\n }\n\n function useLostConnectionListener(\n callback: (event: LostConnectionEvent) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () =>\n room.events.lostConnection.subscribe((event: LostConnectionEvent) =>\n savedCallback.current(event)\n ),\n [room]\n );\n }\n\n function useErrorListener(callback: (err: Error) => void): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () => room.events.error.subscribe((e: Error) => savedCallback.current(e)),\n [room]\n );\n }\n\n function useEventListener(\n callback: (eventData: { connectionId: number; event: TRoomEvent }) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (eventData: {\n connectionId: number;\n event: TRoomEvent;\n }) => {\n savedCallback.current(eventData);\n };\n\n return room.events.customEvent.subscribe(listener);\n }, [room]);\n }\n\n function useSelf(): User<TPresence, TUserMeta> | null;\n function useSelf<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null;\n function useSelf<T>(\n maybeSelector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | User<TPresence, TUserMeta> | null {\n type Snapshot = User<TPresence, TUserMeta> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const subscribe = room.events.self.subscribe;\n const getSnapshot: () => Snapshot = room.getSelf;\n\n const selector =\n maybeSelector ?? (identity as (me: User<TPresence, TUserMeta>) => T);\n const wrappedSelector = React.useCallback(\n (me: Snapshot): Selection => (me !== null ? selector(me) : null),\n [selector]\n );\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function useMutableStorageRoot(): LiveObject<TStorage> | null {\n type Snapshot = LiveObject<TStorage> | null;\n const room = useRoom();\n const subscribe = room.events.storageDidLoad.subscribeOnce;\n const getSnapshot = room.getStorageSnapshot;\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n }\n\n // NOTE: This API exists for backward compatible reasons\n function useStorageRoot(): [root: LiveObject<TStorage> | null] {\n return [useMutableStorageRoot()];\n }\n\n function useHistory(): History {\n return useRoom().history;\n }\n\n function useUndo(): () => void {\n return useHistory().undo;\n }\n\n function useRedo(): () => void {\n return useHistory().redo;\n }\n\n function useCanUndo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canUndo = room.history.canUndo;\n return useSyncExternalStore(subscribe, canUndo, canUndo);\n }\n\n function useCanRedo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canRedo = room.history.canRedo;\n return useSyncExternalStore(subscribe, canRedo, canRedo);\n }\n\n function useBatch<T>(): (callback: () => T) => T {\n return useRoom().batch;\n }\n\n function useLegacyKey<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] | null {\n const room = useRoom();\n const root = useMutableStorageRoot();\n const rerender = useRerender();\n\n React.useEffect(() => {\n if (root === null) {\n return;\n }\n\n let liveValue = root.get(key);\n\n function onRootChange() {\n const newCrdt = root!.get(key);\n if (newCrdt !== liveValue) {\n unsubscribeCrdt();\n liveValue = newCrdt;\n unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n rerender();\n }\n }\n\n let unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n const unsubscribeRoot = room.subscribe(\n root as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n onRootChange\n );\n\n rerender();\n\n return () => {\n unsubscribeRoot();\n unsubscribeCrdt();\n };\n }, [root, room, key, rerender]);\n\n if (root === null) {\n return null;\n } else {\n return root.get(key);\n }\n }\n\n function useStorage<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null {\n type Snapshot = ToImmutable<TStorage> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const rootOrNull = useMutableStorageRoot();\n\n const wrappedSelector = React.useCallback(\n (rootOrNull: Snapshot): Selection =>\n rootOrNull !== null ? selector(rootOrNull) : null,\n [selector]\n );\n\n const subscribe = React.useCallback(\n (onStoreChange: () => void) =>\n rootOrNull !== null\n ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true })\n : noop,\n [room, rootOrNull]\n );\n\n const getSnapshot = React.useCallback((): Snapshot => {\n if (rootOrNull === null) {\n return null;\n } else {\n const root = rootOrNull;\n const imm = root.toImmutable();\n return imm;\n }\n }, [rootOrNull]);\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function ensureNotServerSide(): void {\n // Error early if suspense is used in a server-side context\n if (typeof window === \"undefined\") {\n throw new Error(\n \"You cannot use the Suspense version of this hook on the server side. Make sure to only call them on the client side.\\nFor tips, see https://liveblocks.io/docs/api-reference/liveblocks-react#suspense-avoid-ssr\"\n );\n }\n }\n\n function useSuspendUntilStorageLoaded(): void {\n const room = useRoom();\n if (room.getStorageSnapshot() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.storageDidLoad.subscribeOnce(() => res());\n });\n }\n\n function useSuspendUntilPresenceLoaded(): void {\n const room = useRoom();\n if (room.getSelf() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.status.subscribeOnce(() => res());\n });\n }\n\n function useMutation<\n F extends (\n context: MutationContext<TPresence, TStorage, TUserMeta>,\n ...args: any[]\n ) => any,\n >(callback: F, deps: readonly unknown[]): OmitFirstArg<F> {\n const room = useRoom();\n return React.useMemo(\n () => {\n return ((...args) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n room.batch(() =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n callback(\n makeMutationContext(room),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n ...args\n )\n )) as OmitFirstArg<F>;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [room, ...deps]\n );\n }\n\n function useStorageSuspense<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilStorageLoaded();\n return useStorage(\n selector,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T;\n }\n\n function useSelfSuspense(): User<TPresence, TUserMeta>;\n function useSelfSuspense<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useSelfSuspense<T>(\n selector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | User<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useSelf(\n selector as (me: User<TPresence, TUserMeta>) => T,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T | User<TPresence, TUserMeta>;\n }\n\n function useOthersSuspense<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useOthers(\n selector as (others: Others<TPresence, TUserMeta>) => T,\n isEqual as (prev: T, curr: T) => boolean\n ) as T | Others<TPresence, TUserMeta>;\n }\n\n function useOthersConnectionIdsSuspense(): readonly number[] {\n useSuspendUntilPresenceLoaded();\n return useOthersConnectionIds();\n }\n\n function useOthersMappedSuspense<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n useSuspendUntilPresenceLoaded();\n return useOthersMapped(itemSelector, itemIsEqual);\n }\n\n function useOtherSuspense<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilPresenceLoaded();\n return useOther(connectionId, selector, isEqual);\n }\n\n function useLegacyKeySuspense<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] {\n useSuspendUntilStorageLoaded();\n return useLegacyKey(key) as TStorage[TKey];\n }\n\n /*\n * START COMMMENTS\n */\n\n const errorEventSource = makeEventSource<CommentsApiError<TThreadMetadata>>();\n\n const commentsRooms = new Map<string, CommentsRoom<TThreadMetadata>>();\n\n function getCommentsRoom(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n ) {\n let commentsRoom = commentsRooms.get(room.id);\n if (commentsRoom === undefined) {\n commentsRoom = createCommentsRoom(room, errorEventSource);\n commentsRooms.set(room.id, commentsRoom);\n }\n return commentsRoom;\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n const room = useRoom();\n return getCommentsRoom(room).useThreads();\n }\n\n function useThreadsSuspense() {\n const room = useRoom();\n return getCommentsRoom(room).useThreadsSuspense();\n }\n\n function useCreateThread() {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateThreadOptions<TThreadMetadata>) =>\n getCommentsRoom(room).createThread(options),\n [room]\n );\n }\n\n function useEditThreadMetadata() {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditThreadMetadataOptions<TThreadMetadata>) =>\n getCommentsRoom(room).editThreadMetadata(options),\n [room]\n );\n }\n\n function useCreateComment(): (options: CreateCommentOptions) => CommentData {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateCommentOptions) =>\n getCommentsRoom(room).createComment(options),\n [room]\n );\n }\n\n function useEditComment(): (options: EditCommentOptions) => void {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditCommentOptions) =>\n getCommentsRoom(room).editComment(options),\n [room]\n );\n }\n\n function useDeleteComment() {\n const room = useRoom();\n\n return React.useCallback(\n (options: DeleteCommentOptions) =>\n getCommentsRoom(room).deleteComment(options),\n [room]\n );\n }\n\n const { resolveUser, resolveMentionSuggestions } = options ?? {};\n\n const usersCache = resolveUser ? createAsyncCache(resolveUser) : undefined;\n\n function useUser(userId: string) {\n const state = useAsyncCache(usersCache, userId);\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n if (state.isLoading) {\n return {\n isLoading: true,\n } as UserState<TUserMeta[\"info\"]>;\n } else {\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserState<TUserMeta[\"info\"]>;\n }\n }\n\n function useUserSuspense(userId: string) {\n const state = useAsyncCache(usersCache, userId, {\n suspense: true,\n });\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserStateSuspense<TUserMeta[\"info\"]>;\n }\n\n const mentionSuggestionsCache = createAsyncCache<string[], unknown>(\n resolveMentionSuggestions ?? (() => Promise.resolve([]))\n );\n\n function useMentionSuggestions(search?: string) {\n const debouncedSearch = useDebounce(search, 500);\n const { data } = useAsyncCache(\n mentionSuggestionsCache,\n debouncedSearch ?? null,\n {\n keepPreviousDataWhileLoading: true,\n }\n );\n\n React.useEffect(\n () => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),\n []\n );\n\n return data;\n }\n\n /*\n * END COMMENTS\n */\n\n const bundle = {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // These are just aliases. The passed-in key will define their return values.\n useList: useLegacyKey,\n useMap: useLegacyKey,\n useObject: useLegacyKey,\n\n useStorageRoot,\n useStorage,\n\n useSelf,\n useMyPresence,\n useUpdateMyPresence,\n useOthers,\n useOthersMapped,\n useOthersConnectionIds,\n useOther,\n\n useMutation,\n\n useThreads,\n useUser,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n\n useMentionSuggestions,\n\n suspense: {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // Legacy hooks\n useList: useLegacyKeySuspense,\n useMap: useLegacyKeySuspense,\n useObject: useLegacyKeySuspense,\n\n useStorageRoot,\n useStorage: useStorageSuspense,\n\n useSelf: useSelfSuspense,\n useMyPresence,\n useUpdateMyPresence,\n useOthers: useOthersSuspense,\n useOthersMapped: useOthersMappedSuspense,\n useOthersConnectionIds: useOthersConnectionIdsSuspense,\n useOther: useOtherSuspense,\n\n useMutation,\n\n useThreads: useThreadsSuspense,\n useUser: useUserSuspense,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n },\n };\n\n return bundle;\n}\n","import type {\n BaseMetadata,\n BaseUserMeta,\n CommentBody,\n CommentData,\n EventSource,\n Json,\n JsonObject,\n LsonObject,\n Room,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { makePoller } from \"@liveblocks/core\";\nimport { nanoid } from \"nanoid\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport type { CommentsApiError } from \"./errors\";\nimport {\n CreateCommentError,\n CreateThreadError,\n DeleteCommentError,\n EditCommentError,\n EditThreadMetadataError,\n} from \"./errors\";\nimport { createStore } from \"./lib/store\";\n\nconst POLLING_INTERVAL_REALTIME = 30000;\nconst POLLING_INTERVAL = 5000;\nconst THREAD_ID_PREFIX = \"th\";\nconst COMMENT_ID_PREFIX = \"cm\";\n\nexport type CommentsRoom<TThreadMetadata extends BaseMetadata> = {\n useThreads(): RoomThreads<TThreadMetadata>;\n useThreadsSuspense(): ThreadData<TThreadMetadata>[];\n createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata>;\n editThreadMetadata(options: EditThreadMetadataOptions<TThreadMetadata>): void;\n createComment(options: CreateCommentOptions): CommentData;\n editComment(options: EditCommentOptions): void;\n deleteComment(options: DeleteCommentOptions): void;\n subscribe(): () => void;\n};\n\nexport type CreateThreadOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n body: CommentBody;\n }\n : { body: CommentBody; metadata: TMetadata };\n\nexport type EditThreadMetadataOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n threadId: string;\n }\n : { threadId: string; metadata: Partial<TMetadata> };\n\nexport type CreateCommentOptions = {\n threadId: string;\n body: CommentBody;\n};\n\nexport type EditCommentOptions = {\n threadId: string;\n commentId: string;\n body: CommentBody;\n};\n\nexport type DeleteCommentOptions = {\n threadId: string;\n commentId: string;\n};\n\nfunction createOptimisticId(prefix: string) {\n return `${prefix}_${nanoid()}`;\n}\n\nexport type RoomThreads<TThreadMetadata extends BaseMetadata> =\n | {\n isLoading: true;\n threads?: never;\n error?: never;\n }\n | {\n isLoading: false;\n threads?: never;\n error: Error;\n }\n | {\n isLoading: false;\n threads: ThreadData<TThreadMetadata>[];\n error?: never;\n };\n\nexport function createCommentsRoom<TThreadMetadata extends BaseMetadata>(\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>,\n errorEventSource: EventSource<CommentsApiError<TThreadMetadata>>\n): CommentsRoom<TThreadMetadata> {\n const store = createStore<RoomThreads<TThreadMetadata>>({\n isLoading: true,\n });\n\n // Temporary solution\n // The most basic conflict resolution\n // If there are any pending mutation, we simply ignore any threads coming from the server\n // When all mutations are finished, we pull the source of truth from the backend\n\n let numberOfMutations = 0;\n function endMutation() {\n numberOfMutations--;\n if (numberOfMutations === 0) {\n revalidateThreads();\n }\n }\n\n function startMutation() {\n pollingHub.threads.stop();\n numberOfMutations++;\n }\n\n const pollingHub = {\n // TODO: If there's an error, it will currently infinitely retry at the current polling rate → add retry logic\n threads: makePoller(revalidateThreads),\n };\n let unsubscribeRealtimeEvents: (() => void) | undefined;\n let unsubscribeRealtimeConnection: (() => void) | undefined;\n let realtimeClientConnected = false;\n\n function getPollingInterval() {\n return realtimeClientConnected\n ? POLLING_INTERVAL_REALTIME\n : POLLING_INTERVAL;\n }\n\n function ensureThreadsAreLoadedForMutations() {\n const state = store.get();\n if (state.isLoading || state.error) {\n throw new Error(\n \"Cannot update threads or comments before they are loaded\"\n );\n }\n return state.threads;\n }\n\n async function revalidateThreads() {\n pollingHub.threads.pause();\n\n if (numberOfMutations === 0) {\n setThreads(await room.getThreads());\n }\n\n pollingHub.threads.resume();\n }\n\n function subscribe() {\n if (!unsubscribeRealtimeEvents) {\n unsubscribeRealtimeEvents = room.events.comments.subscribe(() => {\n pollingHub.threads.restart(getPollingInterval());\n revalidateThreads();\n });\n }\n\n if (!unsubscribeRealtimeConnection) {\n unsubscribeRealtimeConnection = room.events.status.subscribe((status) => {\n const nextRealtimeClientConnected = status === \"connected\";\n\n if (nextRealtimeClientConnected !== realtimeClientConnected) {\n realtimeClientConnected = nextRealtimeClientConnected;\n pollingHub.threads.restart(getPollingInterval());\n }\n });\n }\n\n // Will only start if not already started\n pollingHub.threads.start(getPollingInterval());\n\n // TODO: improve thread revalidation\n revalidateThreads();\n\n return () => {\n pollingHub.threads.stop();\n unsubscribeRealtimeEvents?.();\n unsubscribeRealtimeEvents = undefined;\n unsubscribeRealtimeConnection?.();\n unsubscribeRealtimeConnection = undefined;\n };\n }\n\n function setThreads(newThreads: ThreadData<TThreadMetadata>[]) {\n store.set({\n threads: newThreads,\n isLoading: false,\n });\n }\n\n function getCurrentUserId() {\n const self = room.getSelf();\n if (self === null || self.id === undefined) {\n return \"anonymous\";\n } else {\n return self.id;\n }\n }\n\n function createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata> {\n const body = options.body;\n const metadata: TThreadMetadata =\n \"metadata\" in options ? options.metadata : ({} as TThreadMetadata);\n const threads = ensureThreadsAreLoadedForMutations();\n\n const threadId = createOptimisticId(THREAD_ID_PREFIX);\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const newThread = {\n id: threadId,\n type: \"thread\",\n createdAt: now,\n roomId: room.id,\n metadata,\n comments: [\n {\n id: commentId,\n createdAt: now,\n type: \"comment\",\n userId: getCurrentUserId(),\n body,\n },\n ],\n } as ThreadData<TThreadMetadata>; // TODO: Figure out metadata typing\n\n setThreads([...threads, newThread]);\n\n startMutation();\n room\n .createThread({ threadId, commentId, body, metadata })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateThreadError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n metadata,\n })\n )\n )\n .finally(endMutation);\n\n return newThread;\n }\n\n function editThreadMetadata(\n options: EditThreadMetadataOptions<TThreadMetadata>\n ): void {\n const threadId = options.threadId;\n const metadata: Partial<TThreadMetadata> =\n \"metadata\" in options ? options.metadata : {};\n const threads = ensureThreadsAreLoadedForMutations();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n metadata: {\n ...thread.metadata,\n ...metadata,\n },\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editThreadMetadata({ metadata, threadId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditThreadMetadataError(er, {\n roomId: room.id,\n threadId,\n metadata,\n })\n )\n )\n .finally(endMutation);\n }\n\n function createComment({\n threadId,\n body,\n }: CreateCommentOptions): CommentData {\n const threads = ensureThreadsAreLoadedForMutations();\n\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const comment: CommentData = {\n id: commentId,\n threadId,\n roomId: room.id,\n type: \"comment\",\n createdAt: now,\n userId: getCurrentUserId(),\n mentionedIds: [],\n body,\n };\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: [...thread.comments, comment],\n }\n : thread\n )\n );\n\n startMutation();\n room\n .createComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n\n return comment;\n }\n\n function editComment({ threadId, commentId, body }: EditCommentOptions) {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? ({\n ...comment,\n editedAt: now,\n body,\n } as CommentData)\n : comment\n ),\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n }\n\n function deleteComment({ threadId, commentId }: DeleteCommentOptions): void {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n const newThreads: ThreadData<TThreadMetadata>[] = [];\n\n for (const thread of threads) {\n if (thread.id === threadId) {\n const newThread: ThreadData<TThreadMetadata> = {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n deletedAt: now,\n body: undefined,\n mentionedIds: [],\n }\n : comment\n ),\n };\n\n if (\n newThread.comments.some((comment) => comment.deletedAt === undefined)\n ) {\n newThreads.push(newThread);\n }\n } else {\n newThreads.push(thread);\n }\n }\n\n setThreads(newThreads);\n\n startMutation();\n room\n .deleteComment({ threadId, commentId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new DeleteCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n })\n )\n )\n .finally(endMutation);\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n return useSyncExternalStore<RoomThreads<TThreadMetadata>>(\n store.subscribe,\n store.get,\n store.get\n );\n }\n\n function useThreadsSuspense() {\n const result = useThreads();\n\n if (result.isLoading) {\n throw new Promise(store.subscribeOnce);\n }\n\n if (result.error) {\n throw result.error;\n }\n\n return result.threads;\n }\n\n return {\n useThreads,\n useThreadsSuspense,\n createThread,\n editThreadMetadata,\n createComment,\n editComment,\n deleteComment,\n subscribe,\n };\n}\n","import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes -= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size -= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n","import type { BaseMetadata, CommentBody } from \"@liveblocks/core\";\n\nexport class CreateThreadError<TMetadata extends BaseMetadata> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n metadata: TMetadata;\n }\n ) {\n super(\"Create thread failed.\");\n this.name = \"CreateThreadError\";\n }\n}\n\nexport class EditThreadMetadataError<\n TMetadata extends BaseMetadata,\n> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n metadata: Partial<TMetadata>;\n }\n ) {\n super(\"Edit thread metadata failed.\");\n this.name = \"EditThreadMetadataError\";\n }\n}\n\nexport class CreateCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Create comment failed.\");\n this.name = \"CreateCommentError\";\n }\n}\n\nexport class EditCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Edit comment failed.\");\n this.name = \"EditCommentError\";\n }\n}\n\nexport class DeleteCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n }\n ) {\n super(\"Delete comment failed.\");\n this.name = \"DeleteCommentError\";\n }\n}\n\nexport type CommentsApiError<TThreadMetadata extends BaseMetadata> =\n | CreateThreadError<TThreadMetadata>\n | EditThreadMetadataError<TThreadMetadata>\n | CreateCommentError\n | EditCommentError\n | DeleteCommentError;\n","import type { UnsubscribeCallback } from \"@liveblocks/core\";\nimport { makeEventSource } from \"@liveblocks/core\";\n\n/**\n * Create a store that keep a state and let consumers subscribe to updates\n * The store assume that the provided state is immutable\n */\nexport function createStore<T>(initialState: T) {\n let state = initialState;\n const eventSource = makeEventSource<T>();\n\n return {\n get(): T {\n return state;\n },\n set(newState: T) {\n state = newState;\n eventSource.notify(state);\n },\n subscribe(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribe(callback);\n },\n subscribeOnce(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribeOnce(callback);\n },\n subscribersCount() {\n return eventSource.count();\n },\n destroy() {\n return eventSource.clear();\n },\n };\n}\n","import type {\n AsyncCache,\n AsyncState,\n AsyncStateInitial,\n AsyncStateResolved,\n} from \"@liveblocks/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport { useInitial } from \"./use-initial\";\n\nconst INITIAL_ASYNC_STATE: AsyncStateInitial = {\n isLoading: false,\n data: undefined,\n error: undefined,\n};\n\ntype AsyncFunction<T, A extends any[] = any[]> = (...args: A) => Promise<T>;\n\nexport type UseAsyncCacheOptions<T> = {\n overrideFunction?: AsyncFunction<T, [string]>;\n keepPreviousDataWhileLoading?: boolean;\n suspense?: boolean;\n};\n\ntype UseAsyncCacheState<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = O extends {\n suspense: true;\n}\n ? Exclude<AsyncState<T, E>, { isLoading: true }>\n : AsyncState<T, E>;\n\nexport type UseAsyncCacheResponse<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = UseAsyncCacheState<T, E, O> & {\n /**\n * Returns the current state of the key synchronously.\n */\n getState: () => AsyncState<T, E>;\n\n /**\n * Revalidates the key.\n */\n revalidate(): Promise<AsyncStateResolved<T, E>>;\n};\n\ntype PreviousData<T> = {\n key: string | null;\n data?: T;\n};\n\nconst noop = () => {};\n\nexport function useAsyncCache<T, E, O extends UseAsyncCacheOptions<T>>(\n cache: AsyncCache<T, E> | undefined,\n key: string | null,\n options?: O\n): UseAsyncCacheResponse<T, E, O> {\n const frozenOptions = useInitial(options);\n const cacheItem = useMemo(() => {\n if (key === null || !cache) {\n return null;\n }\n\n const cacheItem = cache.create(key, frozenOptions?.overrideFunction);\n void cacheItem.get();\n\n return cacheItem;\n }, [cache, frozenOptions, key]);\n\n const subscribe = useCallback(\n (callback: () => void) => cacheItem?.subscribe(callback) ?? noop,\n [cacheItem]\n );\n\n const getState = useCallback(\n () => cacheItem?.getState() ?? INITIAL_ASYNC_STATE,\n [cacheItem]\n );\n\n const revalidate = useCallback(() => cacheItem?.revalidate(), [cacheItem]);\n\n const state = useSyncExternalStore(subscribe, getState, getState);\n const previousData = useRef<PreviousData<T>>();\n let data = state.data;\n\n useEffect(() => {\n previousData.current = { key, data: state.data };\n }, [key, state]);\n\n if (frozenOptions?.suspense && state.isLoading && cacheItem) {\n throw new Promise<void>((resolve) => {\n cacheItem.subscribeOnce(() => resolve());\n });\n }\n\n if (\n state.isLoading &&\n frozenOptions?.keepPreviousDataWhileLoading &&\n typeof state.data === \"undefined\" &&\n previousData.current?.key !== key &&\n typeof previousData.current?.data !== \"undefined\"\n ) {\n data = previousData.current.data;\n }\n\n return {\n isLoading: state.isLoading,\n data,\n error: state.error,\n getState,\n revalidate,\n } as UseAsyncCacheResponse<T, E, O>;\n}\n","import { useRef } from \"react\";\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T | (() => T)): T {\n return useRef(value instanceof Function ? value() : value).current;\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nconst DEFAULT_DELAY = 500;\n\nexport function useDebounce<T>(\n value: T,\n delay: number | false = DEFAULT_DELAY\n): T {\n const timeout = useRef<number>();\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n if (delay === false) {\n return;\n }\n\n if (timeout.current === undefined) {\n setDebouncedValue(value);\n }\n\n timeout.current = window.setTimeout(() => {\n setDebouncedValue(value);\n timeout.current = undefined;\n }, delay);\n\n return () => {\n window.clearTimeout(timeout.current);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { useReducer, useRef } from \"react\";\n\n/**\n * Trigger a re-render programmatically, without changing the component's\n * state.\n *\n * @example\n * const rerender = useRerender();\n *\n * return (\n * <button onClick={rerender}>\n * {Math.random()}\n * </button>\n * )\n */\nexport function useRerender(): () => void {\n const [, update] = useReducer(\n // This implementation works by incrementing a hidden counter value that is\n // never consumed. Simply incrementing the counter changes the component's\n // state and, thus, trigger a re-render.\n (x: number): number => x + 1,\n 0\n );\n return update;\n}\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T): T {\n return useRef(value).current;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/ClientSideSuspense.tsx","../src/factory.tsx","../src/comments/CommentsRoom.ts","../../../node_modules/nanoid/index.js","../../../node_modules/nanoid/url-alphabet/index.js","../src/comments/errors.ts","../src/comments/lib/store.ts","../src/comments/lib/use-async-cache.ts","../src/comments/lib/use-initial.ts","../src/comments/lib/use-debounce.ts","../src/hooks.ts"],"names":["makeEventSource","React","useEffect","useRef","useSyncExternalStore","cacheItem","useState","useInitial","noop","room","other","options","rootOrNull","shallow"],"mappings":"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","sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { ClientSideSuspense } from \"./ClientSideSuspense\";\nexport { createRoomContext, useRoomContextBundle } from \"./factory\";\nexport type {\n MutationContext,\n ResolveMentionSuggestionsOptions,\n ResolveUserOptions,\n} from \"./types\";\n\n// Re-exports from @liveblocks/client, for convenience\nexport type { Json, JsonObject } from \"@liveblocks/client\";\nexport { shallow } from \"@liveblocks/client\";\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n","import type { ReactElement, ReactNode } from \"react\";\nimport * as React from \"react\";\n\ntype Props = {\n fallback: NonNullable<ReactNode> | null;\n children: () => ReactNode | undefined;\n};\n\n/**\n * Almost like a normal <Suspense> component, except that for server-side\n * renders, the fallback will be used.\n *\n * The child props will have to be provided in a function, i.e. change:\n *\n * <Suspense fallback={<Loading />}>\n * <MyRealComponent a={1} />\n * </Suspense>\n *\n * To:\n *\n * <ClientSideSuspense fallback={<Loading />}>\n * {() => <MyRealComponent a={1} />}\n * </ClientSideSuspense>\n *\n */\nexport function ClientSideSuspense(props: Props): ReactElement {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n // Effects are never executed on the server side. The point of this is to\n // delay the flipping of this boolean until after hydration has happened.\n setMounted(true);\n }, []);\n\n return (\n <React.Suspense fallback={props.fallback}>\n {mounted ? props.children() : props.fallback}\n </React.Suspense>\n );\n}\n","import type {\n BaseUserMeta,\n BroadcastOptions,\n Client,\n History,\n Json,\n JsonObject,\n LiveObject,\n LostConnectionEvent,\n LsonObject,\n Others,\n Room,\n Status,\n User,\n} from \"@liveblocks/client\";\nimport { shallow } from \"@liveblocks/client\";\nimport type {\n AsyncCache,\n BaseMetadata,\n CommentData,\n ToImmutable,\n} from \"@liveblocks/core\";\nimport {\n asArrayWithLegacyMethods,\n createAsyncCache,\n deprecateIf,\n errorIf,\n makeEventSource,\n} from \"@liveblocks/core\";\nimport * as React from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector.js\";\n\nimport type {\n CommentsRoom,\n CreateCommentOptions,\n CreateThreadOptions,\n DeleteCommentOptions,\n EditCommentOptions,\n EditThreadMetadataOptions,\n RoomThreads,\n} from \"./comments/CommentsRoom\";\nimport { createCommentsRoom } from \"./comments/CommentsRoom\";\nimport type { CommentsApiError } from \"./comments/errors\";\nimport { useAsyncCache } from \"./comments/lib/use-async-cache\";\nimport { useDebounce } from \"./comments/lib/use-debounce\";\nimport { useInitial, useRerender } from \"./hooks\";\nimport type {\n MutationContext,\n OmitFirstArg,\n ResolveMentionSuggestionsOptions,\n ResolveUserOptions,\n RoomContextBundle,\n RoomProviderProps,\n UserState,\n UserStateSuspense,\n} from \"./types\";\n\nconst noop = () => {};\nconst identity: <T>(x: T) => T = (x) => x;\n\nconst missing_unstable_batchedUpdates = (\n reactVersion: number,\n roomId: string\n) =>\n `We noticed you’re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you’re ready to upgrade to React 18:\n\n import { unstable_batchedUpdates } from \"react-dom\"; // or \"react-native\"\n\n <RoomProvider id=${JSON.stringify(\n roomId\n )} ... unstable_batchedUpdates={unstable_batchedUpdates}>\n ...\n </RoomProvider>\n\nWhy? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;\n\nconst superfluous_unstable_batchedUpdates =\n \"You don’t need to pass unstable_batchedUpdates to RoomProvider anymore, since you’re on React 18+ already.\";\n\nfunction useSyncExternalStore<Snapshot>(\n s: (onStoreChange: () => void) => () => void,\n gs: () => Snapshot,\n gss: undefined | null | (() => Snapshot)\n): Snapshot {\n return useSyncExternalStoreWithSelector(s, gs, gss, identity);\n}\n\nconst EMPTY_OTHERS =\n // NOTE: asArrayWithLegacyMethods() wrapping should no longer be necessary in 0.19\n asArrayWithLegacyMethods([]);\n\nfunction getEmptyOthers() {\n return EMPTY_OTHERS;\n}\n\nfunction makeMutationContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject,\n TUserMeta extends BaseUserMeta,\n TRoomEvent extends Json,\n>(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n): MutationContext<TPresence, TStorage, TUserMeta> {\n const errmsg =\n \"This mutation cannot be used until connected to the Liveblocks room\";\n\n return {\n get storage() {\n const mutableRoot = room.getStorageSnapshot();\n if (mutableRoot === null) {\n throw new Error(errmsg);\n }\n return mutableRoot;\n },\n\n get self() {\n const self = room.getSelf();\n if (self === null) {\n throw new Error(errmsg);\n }\n return self;\n },\n\n get others() {\n const others = room.getOthers();\n if (room.getSelf() === null) {\n throw new Error(errmsg);\n }\n return others;\n },\n\n setMyPresence: room.updatePresence,\n };\n}\n\ntype Options<TUserMeta extends BaseUserMeta> = {\n /**\n * An asynchronous function that returns user info from a user ID.\n */\n resolveUser?: (\n options: ResolveUserOptions\n ) => Promise<TUserMeta[\"info\"] | undefined>;\n\n /**\n * An asynchronous function that returns a list of user IDs matching a string.\n */\n resolveMentionSuggestions?: (\n options: ResolveMentionSuggestionsOptions\n ) => Promise<string[]>;\n\n /**\n * @internal Internal endpoint\n */\n serverEndpoint?: string;\n};\n\nlet hasWarnedIfNoResolveUser = false;\nlet hasWarnedIfNoResolveMentionSuggestions = false;\n\nfunction warnIfNoResolveUser(usersCache?: AsyncCache<unknown, unknown>) {\n if (\n !hasWarnedIfNoResolveUser &&\n !usersCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\"The resolveUser option wasn't set in createRoomContext.\");\n hasWarnedIfNoResolveUser = true;\n }\n}\n\nfunction warnIfNoResolveMentionSuggestions(\n mentionSuggestionsCache?: AsyncCache<unknown, unknown>\n) {\n if (\n !hasWarnedIfNoResolveMentionSuggestions &&\n !mentionSuggestionsCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\n \"The resolveMentionSuggestions option wasn't set in createRoomContext.\"\n );\n hasWarnedIfNoResolveMentionSuggestions = true;\n }\n}\n\nconst ContextBundle = React.createContext<RoomContextBundle<\n JsonObject,\n LsonObject,\n BaseUserMeta,\n never,\n BaseMetadata\n> | null>(null);\n\n// TODO: Internal?\nexport function useRoomContextBundle() {\n return React.useContext(ContextBundle)!;\n}\n\nexport function createRoomContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject = LsonObject,\n TUserMeta extends BaseUserMeta = BaseUserMeta,\n TRoomEvent extends Json = never,\n TThreadMetadata extends BaseMetadata = never,\n>(\n client: Client,\n options?: Options<TUserMeta>\n): RoomContextBundle<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent,\n TThreadMetadata\n> {\n const RoomContext = React.createContext<Room<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent\n > | null>(null);\n\n function RoomProvider(props: RoomProviderProps<TPresence, TStorage>) {\n const {\n id: roomId,\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect,\n } = props;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!roomId) {\n throw new Error(\n \"RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required\"\n );\n }\n\n if (typeof roomId !== \"string\") {\n throw new Error(\"RoomProvider id property should be a string.\");\n }\n\n const majorReactVersion = parseInt(React.version) || 1;\n const oldReactVersion = majorReactVersion < 18;\n errorIf(\n oldReactVersion && props.unstable_batchedUpdates === undefined,\n missing_unstable_batchedUpdates(majorReactVersion, roomId)\n );\n deprecateIf(\n !oldReactVersion && props.unstable_batchedUpdates !== undefined,\n superfluous_unstable_batchedUpdates\n );\n }\n\n // Note: We'll hold on to the initial value given here, and ignore any\n // changes to this argument in subsequent renders\n const frozen = useInitial({\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect:\n shouldInitiallyConnect === undefined\n ? typeof window !== \"undefined\"\n : shouldInitiallyConnect,\n });\n\n const [room, setRoom] = React.useState<\n Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n >(() =>\n client.enter(roomId, {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n })\n );\n\n React.useEffect(() => {\n const room = client.enter<TPresence, TStorage, TUserMeta, TRoomEvent>(\n roomId,\n {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n }\n );\n\n setRoom(room);\n\n const unsubscribe = getCommentsRoom(room).subscribe();\n\n return () => {\n unsubscribe();\n commentsRooms.delete(room.id);\n client.leave(roomId);\n };\n }, [roomId, frozen]);\n\n return (\n <RoomContext.Provider value={room}>\n <ContextBundle.Provider value={bundle as any}>\n {props.children}\n </ContextBundle.Provider>\n </RoomContext.Provider>\n );\n }\n\n function connectionIdSelector(\n others: Others<TPresence, TUserMeta>\n ): number[] {\n return others.map((user) => user.connectionId);\n }\n\n function useRoom(): Room<TPresence, TStorage, TUserMeta, TRoomEvent> {\n const room = React.useContext(RoomContext);\n if (room === null) {\n throw new Error(\"RoomProvider is missing from the React tree.\");\n }\n return room;\n }\n\n function useStatus(): Status {\n const room = useRoom();\n const subscribe = room.events.status.subscribe;\n const getSnapshot = room.getStatus;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n function useMyPresence(): [\n TPresence,\n (patch: Partial<TPresence>, options?: { addToHistory: boolean }) => void,\n ] {\n const room = useRoom();\n const subscribe = room.events.myPresence.subscribe;\n const getSnapshot = room.getPresence;\n const presence = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setPresence = room.updatePresence;\n return [presence, setPresence];\n }\n\n function useUpdateMyPresence(): (\n patch: Partial<TPresence>,\n options?: { addToHistory: boolean }\n ) => void {\n return useRoom().updatePresence;\n }\n\n function useOthers(): Others<TPresence, TUserMeta>;\n function useOthers<T>(\n selector: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useOthers<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n const room = useRoom();\n const subscribe = room.events.others.subscribe;\n const getSnapshot = room.getOthers;\n const getServerSnapshot = getEmptyOthers;\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n selector ?? (identity as (others: Others<TPresence, TUserMeta>) => T),\n isEqual\n );\n }\n\n function useOthersConnectionIds(): readonly number[] {\n return useOthers(connectionIdSelector, shallow);\n }\n\n function useOthersMapped<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) =>\n others.map(\n (other) => [other.connectionId, itemSelector(other)] as const\n ),\n [itemSelector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (\n a: ReadonlyArray<readonly [connectionId: number, data: T]>,\n b: ReadonlyArray<readonly [connectionId: number, data: T]>\n ): boolean => {\n const eq = itemIsEqual ?? Object.is;\n return (\n a.length === b.length &&\n a.every((atuple, index) => {\n const btuple = b[index];\n return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);\n })\n );\n },\n [itemIsEqual]\n );\n\n return useOthers(wrappedSelector, wrappedIsEqual);\n }\n\n const NOT_FOUND = Symbol();\n\n type NotFound = typeof NOT_FOUND;\n\n function useOther<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) => {\n // TODO: Make this O(1) instead of O(n)?\n const other = others.find(\n (other) => other.connectionId === connectionId\n );\n return other !== undefined ? selector(other) : NOT_FOUND;\n },\n [connectionId, selector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (prev: T | NotFound, curr: T | NotFound): boolean => {\n if (prev === NOT_FOUND || curr === NOT_FOUND) {\n return prev === curr;\n }\n\n const eq = isEqual ?? Object.is;\n return eq(prev, curr);\n },\n [isEqual]\n );\n\n const other = useOthers(wrappedSelector, wrappedIsEqual);\n if (other === NOT_FOUND) {\n throw new Error(\n `No such other user with connection id ${connectionId} exists`\n );\n }\n\n return other;\n }\n\n function useBroadcastEvent(): (\n event: TRoomEvent,\n options?: BroadcastOptions\n ) => void {\n const room = useRoom();\n\n return React.useCallback(\n (\n event: TRoomEvent,\n options: BroadcastOptions = { shouldQueueEventIfNotReady: false }\n ) => {\n room.broadcastEvent(event, options);\n },\n [room]\n );\n }\n\n function useLostConnectionListener(\n callback: (event: LostConnectionEvent) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () =>\n room.events.lostConnection.subscribe((event: LostConnectionEvent) =>\n savedCallback.current(event)\n ),\n [room]\n );\n }\n\n function useErrorListener(callback: (err: Error) => void): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () => room.events.error.subscribe((e: Error) => savedCallback.current(e)),\n [room]\n );\n }\n\n function useEventListener(\n callback: (eventData: { connectionId: number; event: TRoomEvent }) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (eventData: {\n connectionId: number;\n event: TRoomEvent;\n }) => {\n savedCallback.current(eventData);\n };\n\n return room.events.customEvent.subscribe(listener);\n }, [room]);\n }\n\n function useSelf(): User<TPresence, TUserMeta> | null;\n function useSelf<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null;\n function useSelf<T>(\n maybeSelector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | User<TPresence, TUserMeta> | null {\n type Snapshot = User<TPresence, TUserMeta> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const subscribe = room.events.self.subscribe;\n const getSnapshot: () => Snapshot = room.getSelf;\n\n const selector =\n maybeSelector ?? (identity as (me: User<TPresence, TUserMeta>) => T);\n const wrappedSelector = React.useCallback(\n (me: Snapshot): Selection => (me !== null ? selector(me) : null),\n [selector]\n );\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function useMutableStorageRoot(): LiveObject<TStorage> | null {\n type Snapshot = LiveObject<TStorage> | null;\n const room = useRoom();\n const subscribe = room.events.storageDidLoad.subscribeOnce;\n const getSnapshot = room.getStorageSnapshot;\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n }\n\n // NOTE: This API exists for backward compatible reasons\n function useStorageRoot(): [root: LiveObject<TStorage> | null] {\n return [useMutableStorageRoot()];\n }\n\n function useHistory(): History {\n return useRoom().history;\n }\n\n function useUndo(): () => void {\n return useHistory().undo;\n }\n\n function useRedo(): () => void {\n return useHistory().redo;\n }\n\n function useCanUndo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canUndo = room.history.canUndo;\n return useSyncExternalStore(subscribe, canUndo, canUndo);\n }\n\n function useCanRedo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canRedo = room.history.canRedo;\n return useSyncExternalStore(subscribe, canRedo, canRedo);\n }\n\n function useBatch<T>(): (callback: () => T) => T {\n return useRoom().batch;\n }\n\n function useLegacyKey<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] | null {\n const room = useRoom();\n const root = useMutableStorageRoot();\n const rerender = useRerender();\n\n React.useEffect(() => {\n if (root === null) {\n return;\n }\n\n let liveValue = root.get(key);\n\n function onRootChange() {\n const newCrdt = root!.get(key);\n if (newCrdt !== liveValue) {\n unsubscribeCrdt();\n liveValue = newCrdt;\n unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n rerender();\n }\n }\n\n let unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n const unsubscribeRoot = room.subscribe(\n root as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n onRootChange\n );\n\n rerender();\n\n return () => {\n unsubscribeRoot();\n unsubscribeCrdt();\n };\n }, [root, room, key, rerender]);\n\n if (root === null) {\n return null;\n } else {\n return root.get(key);\n }\n }\n\n function useStorage<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null {\n type Snapshot = ToImmutable<TStorage> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const rootOrNull = useMutableStorageRoot();\n\n const wrappedSelector = React.useCallback(\n (rootOrNull: Snapshot): Selection =>\n rootOrNull !== null ? selector(rootOrNull) : null,\n [selector]\n );\n\n const subscribe = React.useCallback(\n (onStoreChange: () => void) =>\n rootOrNull !== null\n ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true })\n : noop,\n [room, rootOrNull]\n );\n\n const getSnapshot = React.useCallback((): Snapshot => {\n if (rootOrNull === null) {\n return null;\n } else {\n const root = rootOrNull;\n const imm = root.toImmutable();\n return imm;\n }\n }, [rootOrNull]);\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function ensureNotServerSide(): void {\n // Error early if suspense is used in a server-side context\n if (typeof window === \"undefined\") {\n throw new Error(\n \"You cannot use the Suspense version of this hook on the server side. Make sure to only call them on the client side.\\nFor tips, see https://liveblocks.io/docs/api-reference/liveblocks-react#suspense-avoid-ssr\"\n );\n }\n }\n\n function useSuspendUntilStorageLoaded(): void {\n const room = useRoom();\n if (room.getStorageSnapshot() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.storageDidLoad.subscribeOnce(() => res());\n });\n }\n\n function useSuspendUntilPresenceLoaded(): void {\n const room = useRoom();\n if (room.getSelf() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.status.subscribeOnce(() => res());\n });\n }\n\n function useMutation<\n F extends (\n context: MutationContext<TPresence, TStorage, TUserMeta>,\n ...args: any[]\n ) => any,\n >(callback: F, deps: readonly unknown[]): OmitFirstArg<F> {\n const room = useRoom();\n return React.useMemo(\n () => {\n return ((...args) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n room.batch(() =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n callback(\n makeMutationContext(room),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n ...args\n )\n )) as OmitFirstArg<F>;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [room, ...deps]\n );\n }\n\n function useStorageSuspense<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilStorageLoaded();\n return useStorage(\n selector,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T;\n }\n\n function useSelfSuspense(): User<TPresence, TUserMeta>;\n function useSelfSuspense<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useSelfSuspense<T>(\n selector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | User<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useSelf(\n selector as (me: User<TPresence, TUserMeta>) => T,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T | User<TPresence, TUserMeta>;\n }\n\n function useOthersSuspense<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useOthers(\n selector as (others: Others<TPresence, TUserMeta>) => T,\n isEqual as (prev: T, curr: T) => boolean\n ) as T | Others<TPresence, TUserMeta>;\n }\n\n function useOthersConnectionIdsSuspense(): readonly number[] {\n useSuspendUntilPresenceLoaded();\n return useOthersConnectionIds();\n }\n\n function useOthersMappedSuspense<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n useSuspendUntilPresenceLoaded();\n return useOthersMapped(itemSelector, itemIsEqual);\n }\n\n function useOtherSuspense<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilPresenceLoaded();\n return useOther(connectionId, selector, isEqual);\n }\n\n function useLegacyKeySuspense<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] {\n useSuspendUntilStorageLoaded();\n return useLegacyKey(key) as TStorage[TKey];\n }\n\n /*\n * START COMMMENTS\n */\n\n const errorEventSource = makeEventSource<CommentsApiError<TThreadMetadata>>();\n\n const commentsRooms = new Map<string, CommentsRoom<TThreadMetadata>>();\n\n function getCommentsRoom(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n ) {\n let commentsRoom = commentsRooms.get(room.id);\n if (commentsRoom === undefined) {\n commentsRoom = createCommentsRoom(room, errorEventSource);\n commentsRooms.set(room.id, commentsRoom);\n }\n return commentsRoom;\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n const room = useRoom();\n return getCommentsRoom(room).useThreads();\n }\n\n function useThreadsSuspense() {\n const room = useRoom();\n return getCommentsRoom(room).useThreadsSuspense();\n }\n\n function useCreateThread() {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateThreadOptions<TThreadMetadata>) =>\n getCommentsRoom(room).createThread(options),\n [room]\n );\n }\n\n function useEditThreadMetadata() {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditThreadMetadataOptions<TThreadMetadata>) =>\n getCommentsRoom(room).editThreadMetadata(options),\n [room]\n );\n }\n\n function useCreateComment(): (options: CreateCommentOptions) => CommentData {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateCommentOptions) =>\n getCommentsRoom(room).createComment(options),\n [room]\n );\n }\n\n function useEditComment(): (options: EditCommentOptions) => void {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditCommentOptions) =>\n getCommentsRoom(room).editComment(options),\n [room]\n );\n }\n\n function useDeleteComment() {\n const room = useRoom();\n\n return React.useCallback(\n (options: DeleteCommentOptions) =>\n getCommentsRoom(room).deleteComment(options),\n [room]\n );\n }\n\n const { resolveUser, resolveMentionSuggestions } = options ?? {};\n\n const usersCache = resolveUser\n ? createAsyncCache((stringifiedOptions: string) => {\n return resolveUser(\n JSON.parse(stringifiedOptions) as ResolveUserOptions\n );\n })\n : undefined;\n\n function useUser(userId: string) {\n const resolverKey = React.useMemo(\n () => JSON.stringify({ userId }),\n [userId]\n );\n const state = useAsyncCache(usersCache, resolverKey);\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n if (state.isLoading) {\n return {\n isLoading: true,\n } as UserState<TUserMeta[\"info\"]>;\n } else {\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserState<TUserMeta[\"info\"]>;\n }\n }\n\n function useUserSuspense(userId: string) {\n const resolverKey = React.useMemo(\n () => JSON.stringify({ userId }),\n [userId]\n );\n const state = useAsyncCache(usersCache, resolverKey, {\n suspense: true,\n });\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserStateSuspense<TUserMeta[\"info\"]>;\n }\n\n const mentionSuggestionsCache = createAsyncCache<string[], unknown>(\n resolveMentionSuggestions\n ? (stringifiedOptions: string) => {\n return resolveMentionSuggestions(\n JSON.parse(stringifiedOptions) as ResolveMentionSuggestionsOptions\n );\n }\n : () => Promise.resolve([])\n );\n\n function useMentionSuggestions(search?: string) {\n const room = useRoom();\n const debouncedSearch = useDebounce(search, 500);\n const resolverKey = React.useMemo(\n () =>\n debouncedSearch !== undefined\n ? JSON.stringify({ text: debouncedSearch, roomId: room.id })\n : null,\n [debouncedSearch, room.id]\n );\n const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {\n keepPreviousDataWhileLoading: true,\n });\n\n React.useEffect(\n () => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),\n []\n );\n\n return data;\n }\n\n /*\n * END COMMENTS\n */\n\n const bundle = {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // These are just aliases. The passed-in key will define their return values.\n useList: useLegacyKey,\n useMap: useLegacyKey,\n useObject: useLegacyKey,\n\n useStorageRoot,\n useStorage,\n\n useSelf,\n useMyPresence,\n useUpdateMyPresence,\n useOthers,\n useOthersMapped,\n useOthersConnectionIds,\n useOther,\n\n useMutation,\n\n useThreads,\n useUser,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n\n useMentionSuggestions,\n\n suspense: {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // Legacy hooks\n useList: useLegacyKeySuspense,\n useMap: useLegacyKeySuspense,\n useObject: useLegacyKeySuspense,\n\n useStorageRoot,\n useStorage: useStorageSuspense,\n\n useSelf: useSelfSuspense,\n useMyPresence,\n useUpdateMyPresence,\n useOthers: useOthersSuspense,\n useOthersMapped: useOthersMappedSuspense,\n useOthersConnectionIds: useOthersConnectionIdsSuspense,\n useOther: useOtherSuspense,\n\n useMutation,\n\n useThreads: useThreadsSuspense,\n useUser: useUserSuspense,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n },\n };\n\n return bundle;\n}\n","import type {\n BaseMetadata,\n BaseUserMeta,\n CommentBody,\n CommentData,\n EventSource,\n Json,\n JsonObject,\n LsonObject,\n Room,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { makePoller } from \"@liveblocks/core\";\nimport { nanoid } from \"nanoid\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport type { CommentsApiError } from \"./errors\";\nimport {\n CreateCommentError,\n CreateThreadError,\n DeleteCommentError,\n EditCommentError,\n EditThreadMetadataError,\n} from \"./errors\";\nimport { createStore } from \"./lib/store\";\n\nconst POLLING_INTERVAL_REALTIME = 30000;\nconst POLLING_INTERVAL = 5000;\nconst THREAD_ID_PREFIX = \"th\";\nconst COMMENT_ID_PREFIX = \"cm\";\n\nexport type CommentsRoom<TThreadMetadata extends BaseMetadata> = {\n useThreads(): RoomThreads<TThreadMetadata>;\n useThreadsSuspense(): ThreadData<TThreadMetadata>[];\n createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata>;\n editThreadMetadata(options: EditThreadMetadataOptions<TThreadMetadata>): void;\n createComment(options: CreateCommentOptions): CommentData;\n editComment(options: EditCommentOptions): void;\n deleteComment(options: DeleteCommentOptions): void;\n subscribe(): () => void;\n};\n\nexport type CreateThreadOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n body: CommentBody;\n }\n : { body: CommentBody; metadata: TMetadata };\n\nexport type EditThreadMetadataOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n threadId: string;\n }\n : { threadId: string; metadata: Partial<TMetadata> };\n\nexport type CreateCommentOptions = {\n threadId: string;\n body: CommentBody;\n};\n\nexport type EditCommentOptions = {\n threadId: string;\n commentId: string;\n body: CommentBody;\n};\n\nexport type DeleteCommentOptions = {\n threadId: string;\n commentId: string;\n};\n\nfunction createOptimisticId(prefix: string) {\n return `${prefix}_${nanoid()}`;\n}\n\nexport type RoomThreads<TThreadMetadata extends BaseMetadata> =\n | {\n isLoading: true;\n threads?: never;\n error?: never;\n }\n | {\n isLoading: false;\n threads?: never;\n error: Error;\n }\n | {\n isLoading: false;\n threads: ThreadData<TThreadMetadata>[];\n error?: never;\n };\n\nexport function createCommentsRoom<TThreadMetadata extends BaseMetadata>(\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>,\n errorEventSource: EventSource<CommentsApiError<TThreadMetadata>>\n): CommentsRoom<TThreadMetadata> {\n const store = createStore<RoomThreads<TThreadMetadata>>({\n isLoading: true,\n });\n\n // Temporary solution\n // The most basic conflict resolution\n // If there are any pending mutation, we simply ignore any threads coming from the server\n // When all mutations are finished, we pull the source of truth from the backend\n\n let numberOfMutations = 0;\n function endMutation() {\n numberOfMutations--;\n if (numberOfMutations === 0) {\n revalidateThreads();\n }\n }\n\n function startMutation() {\n pollingHub.threads.stop();\n numberOfMutations++;\n }\n\n const pollingHub = {\n // TODO: If there's an error, it will currently infinitely retry at the current polling rate → add retry logic\n threads: makePoller(revalidateThreads),\n };\n let unsubscribeRealtimeEvents: (() => void) | undefined;\n let unsubscribeRealtimeConnection: (() => void) | undefined;\n let realtimeClientConnected = false;\n\n function getPollingInterval() {\n return realtimeClientConnected\n ? POLLING_INTERVAL_REALTIME\n : POLLING_INTERVAL;\n }\n\n function ensureThreadsAreLoadedForMutations() {\n const state = store.get();\n if (state.isLoading || state.error) {\n throw new Error(\n \"Cannot update threads or comments before they are loaded\"\n );\n }\n return state.threads;\n }\n\n async function revalidateThreads() {\n pollingHub.threads.pause();\n\n if (numberOfMutations === 0) {\n setThreads(await room.getThreads());\n }\n\n pollingHub.threads.resume();\n }\n\n function subscribe() {\n if (!unsubscribeRealtimeEvents) {\n unsubscribeRealtimeEvents = room.events.comments.subscribe(() => {\n pollingHub.threads.restart(getPollingInterval());\n revalidateThreads();\n });\n }\n\n if (!unsubscribeRealtimeConnection) {\n unsubscribeRealtimeConnection = room.events.status.subscribe((status) => {\n const nextRealtimeClientConnected = status === \"connected\";\n\n if (nextRealtimeClientConnected !== realtimeClientConnected) {\n realtimeClientConnected = nextRealtimeClientConnected;\n pollingHub.threads.restart(getPollingInterval());\n }\n });\n }\n\n // Will only start if not already started\n pollingHub.threads.start(getPollingInterval());\n\n // TODO: improve thread revalidation\n revalidateThreads();\n\n return () => {\n pollingHub.threads.stop();\n unsubscribeRealtimeEvents?.();\n unsubscribeRealtimeEvents = undefined;\n unsubscribeRealtimeConnection?.();\n unsubscribeRealtimeConnection = undefined;\n };\n }\n\n function setThreads(newThreads: ThreadData<TThreadMetadata>[]) {\n store.set({\n threads: newThreads,\n isLoading: false,\n });\n }\n\n function getCurrentUserId() {\n const self = room.getSelf();\n if (self === null || self.id === undefined) {\n return \"anonymous\";\n } else {\n return self.id;\n }\n }\n\n function createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata> {\n const body = options.body;\n const metadata: TThreadMetadata =\n \"metadata\" in options ? options.metadata : ({} as TThreadMetadata);\n const threads = ensureThreadsAreLoadedForMutations();\n\n const threadId = createOptimisticId(THREAD_ID_PREFIX);\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const newThread = {\n id: threadId,\n type: \"thread\",\n createdAt: now,\n roomId: room.id,\n metadata,\n comments: [\n {\n id: commentId,\n createdAt: now,\n type: \"comment\",\n userId: getCurrentUserId(),\n body,\n },\n ],\n } as ThreadData<TThreadMetadata>; // TODO: Figure out metadata typing\n\n setThreads([...threads, newThread]);\n\n startMutation();\n room\n .createThread({ threadId, commentId, body, metadata })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateThreadError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n metadata,\n })\n )\n )\n .finally(endMutation);\n\n return newThread;\n }\n\n function editThreadMetadata(\n options: EditThreadMetadataOptions<TThreadMetadata>\n ): void {\n const threadId = options.threadId;\n const metadata: Partial<TThreadMetadata> =\n \"metadata\" in options ? options.metadata : {};\n const threads = ensureThreadsAreLoadedForMutations();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n metadata: {\n ...thread.metadata,\n ...metadata,\n },\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editThreadMetadata({ metadata, threadId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditThreadMetadataError(er, {\n roomId: room.id,\n threadId,\n metadata,\n })\n )\n )\n .finally(endMutation);\n }\n\n function createComment({\n threadId,\n body,\n }: CreateCommentOptions): CommentData {\n const threads = ensureThreadsAreLoadedForMutations();\n\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const comment: CommentData = {\n id: commentId,\n threadId,\n roomId: room.id,\n type: \"comment\",\n createdAt: now,\n userId: getCurrentUserId(),\n body,\n };\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: [...thread.comments, comment],\n }\n : thread\n )\n );\n\n startMutation();\n room\n .createComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n\n return comment;\n }\n\n function editComment({ threadId, commentId, body }: EditCommentOptions) {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? ({\n ...comment,\n editedAt: now,\n body,\n } as CommentData)\n : comment\n ),\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n }\n\n function deleteComment({ threadId, commentId }: DeleteCommentOptions): void {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n const newThreads: ThreadData<TThreadMetadata>[] = [];\n\n for (const thread of threads) {\n if (thread.id === threadId) {\n const newThread: ThreadData<TThreadMetadata> = {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n deletedAt: now,\n body: undefined,\n }\n : comment\n ),\n };\n\n if (\n newThread.comments.some((comment) => comment.deletedAt === undefined)\n ) {\n newThreads.push(newThread);\n }\n } else {\n newThreads.push(thread);\n }\n }\n\n setThreads(newThreads);\n\n startMutation();\n room\n .deleteComment({ threadId, commentId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new DeleteCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n })\n )\n )\n .finally(endMutation);\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n return useSyncExternalStore<RoomThreads<TThreadMetadata>>(\n store.subscribe,\n store.get,\n store.get\n );\n }\n\n function useThreadsSuspense() {\n const result = useThreads();\n\n if (result.isLoading) {\n throw new Promise(store.subscribeOnce);\n }\n\n if (result.error) {\n throw result.error;\n }\n\n return result.threads;\n }\n\n return {\n useThreads,\n useThreadsSuspense,\n createThread,\n editThreadMetadata,\n createComment,\n editComment,\n deleteComment,\n subscribe,\n };\n}\n","import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes -= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size -= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n","import type { BaseMetadata, CommentBody } from \"@liveblocks/core\";\n\nexport class CreateThreadError<TMetadata extends BaseMetadata> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n metadata: TMetadata;\n }\n ) {\n super(\"Create thread failed.\");\n this.name = \"CreateThreadError\";\n }\n}\n\nexport class EditThreadMetadataError<\n TMetadata extends BaseMetadata,\n> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n metadata: Partial<TMetadata>;\n }\n ) {\n super(\"Edit thread metadata failed.\");\n this.name = \"EditThreadMetadataError\";\n }\n}\n\nexport class CreateCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Create comment failed.\");\n this.name = \"CreateCommentError\";\n }\n}\n\nexport class EditCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Edit comment failed.\");\n this.name = \"EditCommentError\";\n }\n}\n\nexport class DeleteCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n }\n ) {\n super(\"Delete comment failed.\");\n this.name = \"DeleteCommentError\";\n }\n}\n\nexport type CommentsApiError<TThreadMetadata extends BaseMetadata> =\n | CreateThreadError<TThreadMetadata>\n | EditThreadMetadataError<TThreadMetadata>\n | CreateCommentError\n | EditCommentError\n | DeleteCommentError;\n","import type { UnsubscribeCallback } from \"@liveblocks/core\";\nimport { makeEventSource } from \"@liveblocks/core\";\n\n/**\n * Create a store that keep a state and let consumers subscribe to updates\n * The store assume that the provided state is immutable\n */\nexport function createStore<T>(initialState: T) {\n let state = initialState;\n const eventSource = makeEventSource<T>();\n\n return {\n get(): T {\n return state;\n },\n set(newState: T) {\n state = newState;\n eventSource.notify(state);\n },\n subscribe(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribe(callback);\n },\n subscribeOnce(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribeOnce(callback);\n },\n subscribersCount() {\n return eventSource.count();\n },\n destroy() {\n return eventSource.clear();\n },\n };\n}\n","import type {\n AsyncCache,\n AsyncState,\n AsyncStateInitial,\n AsyncStateResolved,\n} from \"@liveblocks/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport { useInitial } from \"./use-initial\";\n\nconst INITIAL_ASYNC_STATE: AsyncStateInitial = {\n isLoading: false,\n data: undefined,\n error: undefined,\n};\n\ntype AsyncFunction<T, A extends any[] = any[]> = (...args: A) => Promise<T>;\n\nexport type UseAsyncCacheOptions<T> = {\n overrideFunction?: AsyncFunction<T, [string]>;\n keepPreviousDataWhileLoading?: boolean;\n suspense?: boolean;\n};\n\ntype UseAsyncCacheState<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = O extends {\n suspense: true;\n}\n ? Exclude<AsyncState<T, E>, { isLoading: true }>\n : AsyncState<T, E>;\n\nexport type UseAsyncCacheResponse<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = UseAsyncCacheState<T, E, O> & {\n /**\n * Returns the current state of the key synchronously.\n */\n getState: () => AsyncState<T, E>;\n\n /**\n * Revalidates the key.\n */\n revalidate(): Promise<AsyncStateResolved<T, E>>;\n};\n\ntype PreviousData<T> = {\n key: string | null;\n data?: T;\n};\n\nconst noop = () => {};\n\nexport function useAsyncCache<T, E, O extends UseAsyncCacheOptions<T>>(\n cache: AsyncCache<T, E> | undefined,\n key: string | null,\n options?: O\n): UseAsyncCacheResponse<T, E, O> {\n const frozenOptions = useInitial(options);\n const cacheItem = useMemo(() => {\n if (key === null || !cache) {\n return null;\n }\n\n const cacheItem = cache.create(key, frozenOptions?.overrideFunction);\n void cacheItem.get();\n\n return cacheItem;\n }, [cache, frozenOptions, key]);\n\n const subscribe = useCallback(\n (callback: () => void) => cacheItem?.subscribe(callback) ?? noop,\n [cacheItem]\n );\n\n const getState = useCallback(\n () => cacheItem?.getState() ?? INITIAL_ASYNC_STATE,\n [cacheItem]\n );\n\n const revalidate = useCallback(() => cacheItem?.revalidate(), [cacheItem]);\n\n const state = useSyncExternalStore(subscribe, getState, getState);\n const previousData = useRef<PreviousData<T>>();\n let data = state.data;\n\n useEffect(() => {\n previousData.current = { key, data: state.data };\n }, [key, state]);\n\n if (frozenOptions?.suspense && state.isLoading && cacheItem) {\n throw new Promise<void>((resolve) => {\n cacheItem.subscribeOnce(() => resolve());\n });\n }\n\n if (\n state.isLoading &&\n frozenOptions?.keepPreviousDataWhileLoading &&\n typeof state.data === \"undefined\" &&\n previousData.current?.key !== key &&\n typeof previousData.current?.data !== \"undefined\"\n ) {\n data = previousData.current.data;\n }\n\n return {\n isLoading: state.isLoading,\n data,\n error: state.error,\n getState,\n revalidate,\n } as UseAsyncCacheResponse<T, E, O>;\n}\n","import { useRef } from \"react\";\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T | (() => T)): T {\n return useRef(value instanceof Function ? value() : value).current;\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nconst DEFAULT_DELAY = 500;\n\nexport function useDebounce<T>(\n value: T,\n delay: number | false = DEFAULT_DELAY\n): T {\n const timeout = useRef<number>();\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n if (delay === false) {\n return;\n }\n\n if (timeout.current === undefined) {\n setDebouncedValue(value);\n }\n\n timeout.current = window.setTimeout(() => {\n setDebouncedValue(value);\n timeout.current = undefined;\n }, delay);\n\n return () => {\n window.clearTimeout(timeout.current);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { useReducer, useRef } from \"react\";\n\n/**\n * Trigger a re-render programmatically, without changing the component's\n * state.\n *\n * @example\n * const rerender = useRerender();\n *\n * return (\n * <button onClick={rerender}>\n * {Math.random()}\n * </button>\n * )\n */\nexport function useRerender(): () => void {\n const [, update] = useReducer(\n // This implementation works by incrementing a hidden counter value that is\n // never consumed. Simply incrementing the counter changes the component's\n // state and, thus, trigger a re-render.\n (x: number): number => x + 1,\n 0\n );\n return update;\n}\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T): T {\n return useRef(value).current;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { detectDupes } from "@liveblocks/core";
|
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
7
|
var PKG_NAME = "@liveblocks/react";
|
|
8
|
-
var PKG_VERSION = "1.2.2-
|
|
8
|
+
var PKG_VERSION = "1.2.2-comments2";
|
|
9
9
|
var PKG_FORMAT = "esm";
|
|
10
10
|
|
|
11
11
|
// src/ClientSideSuspense.tsx
|
|
@@ -303,7 +303,6 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
303
303
|
type: "comment",
|
|
304
304
|
createdAt: now,
|
|
305
305
|
userId: getCurrentUserId(),
|
|
306
|
-
mentionedIds: [],
|
|
307
306
|
body
|
|
308
307
|
};
|
|
309
308
|
setThreads(
|
|
@@ -368,8 +367,7 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
368
367
|
(comment) => comment.id === commentId ? {
|
|
369
368
|
...comment,
|
|
370
369
|
deletedAt: now,
|
|
371
|
-
body: void 0
|
|
372
|
-
mentionedIds: []
|
|
370
|
+
body: void 0
|
|
373
371
|
} : comment
|
|
374
372
|
)
|
|
375
373
|
};
|
|
@@ -1059,9 +1057,17 @@ function createRoomContext(client, options) {
|
|
|
1059
1057
|
);
|
|
1060
1058
|
}
|
|
1061
1059
|
const { resolveUser, resolveMentionSuggestions } = options ?? {};
|
|
1062
|
-
const usersCache = resolveUser ? createAsyncCache(
|
|
1060
|
+
const usersCache = resolveUser ? createAsyncCache((stringifiedOptions) => {
|
|
1061
|
+
return resolveUser(
|
|
1062
|
+
JSON.parse(stringifiedOptions)
|
|
1063
|
+
);
|
|
1064
|
+
}) : void 0;
|
|
1063
1065
|
function useUser(userId) {
|
|
1064
|
-
const
|
|
1066
|
+
const resolverKey = React2.useMemo(
|
|
1067
|
+
() => JSON.stringify({ userId }),
|
|
1068
|
+
[userId]
|
|
1069
|
+
);
|
|
1070
|
+
const state = useAsyncCache(usersCache, resolverKey);
|
|
1065
1071
|
React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
|
|
1066
1072
|
if (state.isLoading) {
|
|
1067
1073
|
return {
|
|
@@ -1076,7 +1082,11 @@ function createRoomContext(client, options) {
|
|
|
1076
1082
|
}
|
|
1077
1083
|
}
|
|
1078
1084
|
function useUserSuspense(userId) {
|
|
1079
|
-
const
|
|
1085
|
+
const resolverKey = React2.useMemo(
|
|
1086
|
+
() => JSON.stringify({ userId }),
|
|
1087
|
+
[userId]
|
|
1088
|
+
);
|
|
1089
|
+
const state = useAsyncCache(usersCache, resolverKey, {
|
|
1080
1090
|
suspense: true
|
|
1081
1091
|
});
|
|
1082
1092
|
React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
|
|
@@ -1087,17 +1097,22 @@ function createRoomContext(client, options) {
|
|
|
1087
1097
|
};
|
|
1088
1098
|
}
|
|
1089
1099
|
const mentionSuggestionsCache = createAsyncCache(
|
|
1090
|
-
resolveMentionSuggestions
|
|
1100
|
+
resolveMentionSuggestions ? (stringifiedOptions) => {
|
|
1101
|
+
return resolveMentionSuggestions(
|
|
1102
|
+
JSON.parse(stringifiedOptions)
|
|
1103
|
+
);
|
|
1104
|
+
} : () => Promise.resolve([])
|
|
1091
1105
|
);
|
|
1092
1106
|
function useMentionSuggestions(search) {
|
|
1107
|
+
const room = useRoom();
|
|
1093
1108
|
const debouncedSearch = useDebounce(search, 500);
|
|
1094
|
-
const
|
|
1095
|
-
|
|
1096
|
-
debouncedSearch
|
|
1097
|
-
{
|
|
1098
|
-
keepPreviousDataWhileLoading: true
|
|
1099
|
-
}
|
|
1109
|
+
const resolverKey = React2.useMemo(
|
|
1110
|
+
() => debouncedSearch !== void 0 ? JSON.stringify({ text: debouncedSearch, roomId: room.id }) : null,
|
|
1111
|
+
[debouncedSearch, room.id]
|
|
1100
1112
|
);
|
|
1113
|
+
const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {
|
|
1114
|
+
keepPreviousDataWhileLoading: true
|
|
1115
|
+
});
|
|
1101
1116
|
React2.useEffect(
|
|
1102
1117
|
() => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),
|
|
1103
1118
|
[]
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/ClientSideSuspense.tsx","../src/factory.tsx","../src/comments/CommentsRoom.ts","../../../node_modules/nanoid/index.js","../../../node_modules/nanoid/url-alphabet/index.js","../src/comments/errors.ts","../src/comments/lib/store.ts","../src/comments/lib/use-async-cache.ts","../src/comments/lib/use-initial.ts","../src/comments/lib/use-debounce.ts","../src/hooks.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { ClientSideSuspense } from \"./ClientSideSuspense\";\nexport { createRoomContext, useRoomContextBundle } from \"./factory\";\nexport type { MutationContext } from \"./types\";\n\n// Re-exports from @liveblocks/client, for convenience\nexport type { Json, JsonObject } from \"@liveblocks/client\";\nexport { shallow } from \"@liveblocks/client\";\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n","import type { ReactElement, ReactNode } from \"react\";\nimport * as React from \"react\";\n\ntype Props = {\n fallback: NonNullable<ReactNode> | null;\n children: () => ReactNode | undefined;\n};\n\n/**\n * Almost like a normal <Suspense> component, except that for server-side\n * renders, the fallback will be used.\n *\n * The child props will have to be provided in a function, i.e. change:\n *\n * <Suspense fallback={<Loading />}>\n * <MyRealComponent a={1} />\n * </Suspense>\n *\n * To:\n *\n * <ClientSideSuspense fallback={<Loading />}>\n * {() => <MyRealComponent a={1} />}\n * </ClientSideSuspense>\n *\n */\nexport function ClientSideSuspense(props: Props): ReactElement {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n // Effects are never executed on the server side. The point of this is to\n // delay the flipping of this boolean until after hydration has happened.\n setMounted(true);\n }, []);\n\n return (\n <React.Suspense fallback={props.fallback}>\n {mounted ? props.children() : props.fallback}\n </React.Suspense>\n );\n}\n","import type {\n BaseUserMeta,\n BroadcastOptions,\n Client,\n History,\n Json,\n JsonObject,\n LiveObject,\n LostConnectionEvent,\n LsonObject,\n Others,\n Room,\n Status,\n User,\n} from \"@liveblocks/client\";\nimport { shallow } from \"@liveblocks/client\";\nimport type {\n AsyncCache,\n BaseMetadata,\n CommentData,\n ToImmutable,\n} from \"@liveblocks/core\";\nimport {\n asArrayWithLegacyMethods,\n createAsyncCache,\n deprecateIf,\n errorIf,\n makeEventSource,\n} from \"@liveblocks/core\";\nimport * as React from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector.js\";\n\nimport type {\n CommentsRoom,\n CreateCommentOptions,\n CreateThreadOptions,\n DeleteCommentOptions,\n EditCommentOptions,\n EditThreadMetadataOptions,\n RoomThreads,\n} from \"./comments/CommentsRoom\";\nimport { createCommentsRoom } from \"./comments/CommentsRoom\";\nimport type { CommentsApiError } from \"./comments/errors\";\nimport { useAsyncCache } from \"./comments/lib/use-async-cache\";\nimport { useDebounce } from \"./comments/lib/use-debounce\";\nimport { useInitial, useRerender } from \"./hooks\";\nimport type {\n MutationContext,\n OmitFirstArg,\n RoomContextBundle,\n RoomProviderProps,\n UserState,\n UserStateSuspense,\n} from \"./types\";\n\nconst noop = () => {};\nconst identity: <T>(x: T) => T = (x) => x;\n\nconst missing_unstable_batchedUpdates = (\n reactVersion: number,\n roomId: string\n) =>\n `We noticed you’re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you’re ready to upgrade to React 18:\n\n import { unstable_batchedUpdates } from \"react-dom\"; // or \"react-native\"\n\n <RoomProvider id=${JSON.stringify(\n roomId\n )} ... unstable_batchedUpdates={unstable_batchedUpdates}>\n ...\n </RoomProvider>\n\nWhy? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;\n\nconst superfluous_unstable_batchedUpdates =\n \"You don’t need to pass unstable_batchedUpdates to RoomProvider anymore, since you’re on React 18+ already.\";\n\nfunction useSyncExternalStore<Snapshot>(\n s: (onStoreChange: () => void) => () => void,\n gs: () => Snapshot,\n gss: undefined | null | (() => Snapshot)\n): Snapshot {\n return useSyncExternalStoreWithSelector(s, gs, gss, identity);\n}\n\nconst EMPTY_OTHERS =\n // NOTE: asArrayWithLegacyMethods() wrapping should no longer be necessary in 0.19\n asArrayWithLegacyMethods([]);\n\nfunction getEmptyOthers() {\n return EMPTY_OTHERS;\n}\n\nfunction makeMutationContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject,\n TUserMeta extends BaseUserMeta,\n TRoomEvent extends Json,\n>(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n): MutationContext<TPresence, TStorage, TUserMeta> {\n const errmsg =\n \"This mutation cannot be used until connected to the Liveblocks room\";\n\n return {\n get storage() {\n const mutableRoot = room.getStorageSnapshot();\n if (mutableRoot === null) {\n throw new Error(errmsg);\n }\n return mutableRoot;\n },\n\n get self() {\n const self = room.getSelf();\n if (self === null) {\n throw new Error(errmsg);\n }\n return self;\n },\n\n get others() {\n const others = room.getOthers();\n if (room.getSelf() === null) {\n throw new Error(errmsg);\n }\n return others;\n },\n\n setMyPresence: room.updatePresence,\n };\n}\n\ntype Options<TUserMeta extends BaseUserMeta> = {\n /**\n * An asynchronous function that returns user info from a user ID.\n */\n resolveUser?: (userId: string) => Promise<TUserMeta[\"info\"] | undefined>;\n\n /**\n * An asynchronous function that returns a list of user IDs matching a string.\n */\n resolveMentionSuggestions?: (search: string) => Promise<string[]>;\n\n /**\n * @internal Internal endpoint\n */\n serverEndpoint?: string;\n};\n\nlet hasWarnedIfNoResolveUser = false;\nlet hasWarnedIfNoResolveMentionSuggestions = false;\n\nfunction warnIfNoResolveUser(usersCache?: AsyncCache<unknown, unknown>) {\n if (\n !hasWarnedIfNoResolveUser &&\n !usersCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\"The resolveUser option wasn't set in createRoomContext.\");\n hasWarnedIfNoResolveUser = true;\n }\n}\n\nfunction warnIfNoResolveMentionSuggestions(\n mentionSuggestionsCache?: AsyncCache<unknown, unknown>\n) {\n if (\n !hasWarnedIfNoResolveMentionSuggestions &&\n !mentionSuggestionsCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\n \"The resolveMentionSuggestions option wasn't set in createRoomContext.\"\n );\n hasWarnedIfNoResolveMentionSuggestions = true;\n }\n}\n\nconst ContextBundle = React.createContext<RoomContextBundle<\n JsonObject,\n LsonObject,\n BaseUserMeta,\n never,\n BaseMetadata\n> | null>(null);\n\n// TODO: Internal?\nexport function useRoomContextBundle() {\n return React.useContext(ContextBundle)!;\n}\n\nexport function createRoomContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject = LsonObject,\n TUserMeta extends BaseUserMeta = BaseUserMeta,\n TRoomEvent extends Json = never,\n TThreadMetadata extends BaseMetadata = never,\n>(\n client: Client,\n options?: Options<TUserMeta>\n): RoomContextBundle<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent,\n TThreadMetadata\n> {\n const RoomContext = React.createContext<Room<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent\n > | null>(null);\n\n function RoomProvider(props: RoomProviderProps<TPresence, TStorage>) {\n const {\n id: roomId,\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect,\n } = props;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!roomId) {\n throw new Error(\n \"RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required\"\n );\n }\n\n if (typeof roomId !== \"string\") {\n throw new Error(\"RoomProvider id property should be a string.\");\n }\n\n const majorReactVersion = parseInt(React.version) || 1;\n const oldReactVersion = majorReactVersion < 18;\n errorIf(\n oldReactVersion && props.unstable_batchedUpdates === undefined,\n missing_unstable_batchedUpdates(majorReactVersion, roomId)\n );\n deprecateIf(\n !oldReactVersion && props.unstable_batchedUpdates !== undefined,\n superfluous_unstable_batchedUpdates\n );\n }\n\n // Note: We'll hold on to the initial value given here, and ignore any\n // changes to this argument in subsequent renders\n const frozen = useInitial({\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect:\n shouldInitiallyConnect === undefined\n ? typeof window !== \"undefined\"\n : shouldInitiallyConnect,\n });\n\n const [room, setRoom] = React.useState<\n Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n >(() =>\n client.enter(roomId, {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n })\n );\n\n React.useEffect(() => {\n const room = client.enter<TPresence, TStorage, TUserMeta, TRoomEvent>(\n roomId,\n {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n }\n );\n\n setRoom(room);\n\n const unsubscribe = getCommentsRoom(room).subscribe();\n\n return () => {\n unsubscribe();\n commentsRooms.delete(room.id);\n client.leave(roomId);\n };\n }, [roomId, frozen]);\n\n return (\n <RoomContext.Provider value={room}>\n <ContextBundle.Provider value={bundle as any}>\n {props.children}\n </ContextBundle.Provider>\n </RoomContext.Provider>\n );\n }\n\n function connectionIdSelector(\n others: Others<TPresence, TUserMeta>\n ): number[] {\n return others.map((user) => user.connectionId);\n }\n\n function useRoom(): Room<TPresence, TStorage, TUserMeta, TRoomEvent> {\n const room = React.useContext(RoomContext);\n if (room === null) {\n throw new Error(\"RoomProvider is missing from the React tree.\");\n }\n return room;\n }\n\n function useStatus(): Status {\n const room = useRoom();\n const subscribe = room.events.status.subscribe;\n const getSnapshot = room.getStatus;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n function useMyPresence(): [\n TPresence,\n (patch: Partial<TPresence>, options?: { addToHistory: boolean }) => void,\n ] {\n const room = useRoom();\n const subscribe = room.events.myPresence.subscribe;\n const getSnapshot = room.getPresence;\n const presence = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setPresence = room.updatePresence;\n return [presence, setPresence];\n }\n\n function useUpdateMyPresence(): (\n patch: Partial<TPresence>,\n options?: { addToHistory: boolean }\n ) => void {\n return useRoom().updatePresence;\n }\n\n function useOthers(): Others<TPresence, TUserMeta>;\n function useOthers<T>(\n selector: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useOthers<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n const room = useRoom();\n const subscribe = room.events.others.subscribe;\n const getSnapshot = room.getOthers;\n const getServerSnapshot = getEmptyOthers;\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n selector ?? (identity as (others: Others<TPresence, TUserMeta>) => T),\n isEqual\n );\n }\n\n function useOthersConnectionIds(): readonly number[] {\n return useOthers(connectionIdSelector, shallow);\n }\n\n function useOthersMapped<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) =>\n others.map(\n (other) => [other.connectionId, itemSelector(other)] as const\n ),\n [itemSelector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (\n a: ReadonlyArray<readonly [connectionId: number, data: T]>,\n b: ReadonlyArray<readonly [connectionId: number, data: T]>\n ): boolean => {\n const eq = itemIsEqual ?? Object.is;\n return (\n a.length === b.length &&\n a.every((atuple, index) => {\n const btuple = b[index];\n return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);\n })\n );\n },\n [itemIsEqual]\n );\n\n return useOthers(wrappedSelector, wrappedIsEqual);\n }\n\n const NOT_FOUND = Symbol();\n\n type NotFound = typeof NOT_FOUND;\n\n function useOther<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) => {\n // TODO: Make this O(1) instead of O(n)?\n const other = others.find(\n (other) => other.connectionId === connectionId\n );\n return other !== undefined ? selector(other) : NOT_FOUND;\n },\n [connectionId, selector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (prev: T | NotFound, curr: T | NotFound): boolean => {\n if (prev === NOT_FOUND || curr === NOT_FOUND) {\n return prev === curr;\n }\n\n const eq = isEqual ?? Object.is;\n return eq(prev, curr);\n },\n [isEqual]\n );\n\n const other = useOthers(wrappedSelector, wrappedIsEqual);\n if (other === NOT_FOUND) {\n throw new Error(\n `No such other user with connection id ${connectionId} exists`\n );\n }\n\n return other;\n }\n\n function useBroadcastEvent(): (\n event: TRoomEvent,\n options?: BroadcastOptions\n ) => void {\n const room = useRoom();\n\n return React.useCallback(\n (\n event: TRoomEvent,\n options: BroadcastOptions = { shouldQueueEventIfNotReady: false }\n ) => {\n room.broadcastEvent(event, options);\n },\n [room]\n );\n }\n\n function useLostConnectionListener(\n callback: (event: LostConnectionEvent) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () =>\n room.events.lostConnection.subscribe((event: LostConnectionEvent) =>\n savedCallback.current(event)\n ),\n [room]\n );\n }\n\n function useErrorListener(callback: (err: Error) => void): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () => room.events.error.subscribe((e: Error) => savedCallback.current(e)),\n [room]\n );\n }\n\n function useEventListener(\n callback: (eventData: { connectionId: number; event: TRoomEvent }) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (eventData: {\n connectionId: number;\n event: TRoomEvent;\n }) => {\n savedCallback.current(eventData);\n };\n\n return room.events.customEvent.subscribe(listener);\n }, [room]);\n }\n\n function useSelf(): User<TPresence, TUserMeta> | null;\n function useSelf<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null;\n function useSelf<T>(\n maybeSelector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | User<TPresence, TUserMeta> | null {\n type Snapshot = User<TPresence, TUserMeta> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const subscribe = room.events.self.subscribe;\n const getSnapshot: () => Snapshot = room.getSelf;\n\n const selector =\n maybeSelector ?? (identity as (me: User<TPresence, TUserMeta>) => T);\n const wrappedSelector = React.useCallback(\n (me: Snapshot): Selection => (me !== null ? selector(me) : null),\n [selector]\n );\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function useMutableStorageRoot(): LiveObject<TStorage> | null {\n type Snapshot = LiveObject<TStorage> | null;\n const room = useRoom();\n const subscribe = room.events.storageDidLoad.subscribeOnce;\n const getSnapshot = room.getStorageSnapshot;\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n }\n\n // NOTE: This API exists for backward compatible reasons\n function useStorageRoot(): [root: LiveObject<TStorage> | null] {\n return [useMutableStorageRoot()];\n }\n\n function useHistory(): History {\n return useRoom().history;\n }\n\n function useUndo(): () => void {\n return useHistory().undo;\n }\n\n function useRedo(): () => void {\n return useHistory().redo;\n }\n\n function useCanUndo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canUndo = room.history.canUndo;\n return useSyncExternalStore(subscribe, canUndo, canUndo);\n }\n\n function useCanRedo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canRedo = room.history.canRedo;\n return useSyncExternalStore(subscribe, canRedo, canRedo);\n }\n\n function useBatch<T>(): (callback: () => T) => T {\n return useRoom().batch;\n }\n\n function useLegacyKey<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] | null {\n const room = useRoom();\n const root = useMutableStorageRoot();\n const rerender = useRerender();\n\n React.useEffect(() => {\n if (root === null) {\n return;\n }\n\n let liveValue = root.get(key);\n\n function onRootChange() {\n const newCrdt = root!.get(key);\n if (newCrdt !== liveValue) {\n unsubscribeCrdt();\n liveValue = newCrdt;\n unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n rerender();\n }\n }\n\n let unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n const unsubscribeRoot = room.subscribe(\n root as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n onRootChange\n );\n\n rerender();\n\n return () => {\n unsubscribeRoot();\n unsubscribeCrdt();\n };\n }, [root, room, key, rerender]);\n\n if (root === null) {\n return null;\n } else {\n return root.get(key);\n }\n }\n\n function useStorage<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null {\n type Snapshot = ToImmutable<TStorage> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const rootOrNull = useMutableStorageRoot();\n\n const wrappedSelector = React.useCallback(\n (rootOrNull: Snapshot): Selection =>\n rootOrNull !== null ? selector(rootOrNull) : null,\n [selector]\n );\n\n const subscribe = React.useCallback(\n (onStoreChange: () => void) =>\n rootOrNull !== null\n ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true })\n : noop,\n [room, rootOrNull]\n );\n\n const getSnapshot = React.useCallback((): Snapshot => {\n if (rootOrNull === null) {\n return null;\n } else {\n const root = rootOrNull;\n const imm = root.toImmutable();\n return imm;\n }\n }, [rootOrNull]);\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function ensureNotServerSide(): void {\n // Error early if suspense is used in a server-side context\n if (typeof window === \"undefined\") {\n throw new Error(\n \"You cannot use the Suspense version of this hook on the server side. Make sure to only call them on the client side.\\nFor tips, see https://liveblocks.io/docs/api-reference/liveblocks-react#suspense-avoid-ssr\"\n );\n }\n }\n\n function useSuspendUntilStorageLoaded(): void {\n const room = useRoom();\n if (room.getStorageSnapshot() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.storageDidLoad.subscribeOnce(() => res());\n });\n }\n\n function useSuspendUntilPresenceLoaded(): void {\n const room = useRoom();\n if (room.getSelf() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.status.subscribeOnce(() => res());\n });\n }\n\n function useMutation<\n F extends (\n context: MutationContext<TPresence, TStorage, TUserMeta>,\n ...args: any[]\n ) => any,\n >(callback: F, deps: readonly unknown[]): OmitFirstArg<F> {\n const room = useRoom();\n return React.useMemo(\n () => {\n return ((...args) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n room.batch(() =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n callback(\n makeMutationContext(room),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n ...args\n )\n )) as OmitFirstArg<F>;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [room, ...deps]\n );\n }\n\n function useStorageSuspense<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilStorageLoaded();\n return useStorage(\n selector,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T;\n }\n\n function useSelfSuspense(): User<TPresence, TUserMeta>;\n function useSelfSuspense<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useSelfSuspense<T>(\n selector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | User<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useSelf(\n selector as (me: User<TPresence, TUserMeta>) => T,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T | User<TPresence, TUserMeta>;\n }\n\n function useOthersSuspense<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useOthers(\n selector as (others: Others<TPresence, TUserMeta>) => T,\n isEqual as (prev: T, curr: T) => boolean\n ) as T | Others<TPresence, TUserMeta>;\n }\n\n function useOthersConnectionIdsSuspense(): readonly number[] {\n useSuspendUntilPresenceLoaded();\n return useOthersConnectionIds();\n }\n\n function useOthersMappedSuspense<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n useSuspendUntilPresenceLoaded();\n return useOthersMapped(itemSelector, itemIsEqual);\n }\n\n function useOtherSuspense<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilPresenceLoaded();\n return useOther(connectionId, selector, isEqual);\n }\n\n function useLegacyKeySuspense<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] {\n useSuspendUntilStorageLoaded();\n return useLegacyKey(key) as TStorage[TKey];\n }\n\n /*\n * START COMMMENTS\n */\n\n const errorEventSource = makeEventSource<CommentsApiError<TThreadMetadata>>();\n\n const commentsRooms = new Map<string, CommentsRoom<TThreadMetadata>>();\n\n function getCommentsRoom(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n ) {\n let commentsRoom = commentsRooms.get(room.id);\n if (commentsRoom === undefined) {\n commentsRoom = createCommentsRoom(room, errorEventSource);\n commentsRooms.set(room.id, commentsRoom);\n }\n return commentsRoom;\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n const room = useRoom();\n return getCommentsRoom(room).useThreads();\n }\n\n function useThreadsSuspense() {\n const room = useRoom();\n return getCommentsRoom(room).useThreadsSuspense();\n }\n\n function useCreateThread() {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateThreadOptions<TThreadMetadata>) =>\n getCommentsRoom(room).createThread(options),\n [room]\n );\n }\n\n function useEditThreadMetadata() {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditThreadMetadataOptions<TThreadMetadata>) =>\n getCommentsRoom(room).editThreadMetadata(options),\n [room]\n );\n }\n\n function useCreateComment(): (options: CreateCommentOptions) => CommentData {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateCommentOptions) =>\n getCommentsRoom(room).createComment(options),\n [room]\n );\n }\n\n function useEditComment(): (options: EditCommentOptions) => void {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditCommentOptions) =>\n getCommentsRoom(room).editComment(options),\n [room]\n );\n }\n\n function useDeleteComment() {\n const room = useRoom();\n\n return React.useCallback(\n (options: DeleteCommentOptions) =>\n getCommentsRoom(room).deleteComment(options),\n [room]\n );\n }\n\n const { resolveUser, resolveMentionSuggestions } = options ?? {};\n\n const usersCache = resolveUser ? createAsyncCache(resolveUser) : undefined;\n\n function useUser(userId: string) {\n const state = useAsyncCache(usersCache, userId);\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n if (state.isLoading) {\n return {\n isLoading: true,\n } as UserState<TUserMeta[\"info\"]>;\n } else {\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserState<TUserMeta[\"info\"]>;\n }\n }\n\n function useUserSuspense(userId: string) {\n const state = useAsyncCache(usersCache, userId, {\n suspense: true,\n });\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserStateSuspense<TUserMeta[\"info\"]>;\n }\n\n const mentionSuggestionsCache = createAsyncCache<string[], unknown>(\n resolveMentionSuggestions ?? (() => Promise.resolve([]))\n );\n\n function useMentionSuggestions(search?: string) {\n const debouncedSearch = useDebounce(search, 500);\n const { data } = useAsyncCache(\n mentionSuggestionsCache,\n debouncedSearch ?? null,\n {\n keepPreviousDataWhileLoading: true,\n }\n );\n\n React.useEffect(\n () => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),\n []\n );\n\n return data;\n }\n\n /*\n * END COMMENTS\n */\n\n const bundle = {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // These are just aliases. The passed-in key will define their return values.\n useList: useLegacyKey,\n useMap: useLegacyKey,\n useObject: useLegacyKey,\n\n useStorageRoot,\n useStorage,\n\n useSelf,\n useMyPresence,\n useUpdateMyPresence,\n useOthers,\n useOthersMapped,\n useOthersConnectionIds,\n useOther,\n\n useMutation,\n\n useThreads,\n useUser,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n\n useMentionSuggestions,\n\n suspense: {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // Legacy hooks\n useList: useLegacyKeySuspense,\n useMap: useLegacyKeySuspense,\n useObject: useLegacyKeySuspense,\n\n useStorageRoot,\n useStorage: useStorageSuspense,\n\n useSelf: useSelfSuspense,\n useMyPresence,\n useUpdateMyPresence,\n useOthers: useOthersSuspense,\n useOthersMapped: useOthersMappedSuspense,\n useOthersConnectionIds: useOthersConnectionIdsSuspense,\n useOther: useOtherSuspense,\n\n useMutation,\n\n useThreads: useThreadsSuspense,\n useUser: useUserSuspense,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n },\n };\n\n return bundle;\n}\n","import type {\n BaseMetadata,\n BaseUserMeta,\n CommentBody,\n CommentData,\n EventSource,\n Json,\n JsonObject,\n LsonObject,\n Room,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { makePoller } from \"@liveblocks/core\";\nimport { nanoid } from \"nanoid\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport type { CommentsApiError } from \"./errors\";\nimport {\n CreateCommentError,\n CreateThreadError,\n DeleteCommentError,\n EditCommentError,\n EditThreadMetadataError,\n} from \"./errors\";\nimport { createStore } from \"./lib/store\";\n\nconst POLLING_INTERVAL_REALTIME = 30000;\nconst POLLING_INTERVAL = 5000;\nconst THREAD_ID_PREFIX = \"th\";\nconst COMMENT_ID_PREFIX = \"cm\";\n\nexport type CommentsRoom<TThreadMetadata extends BaseMetadata> = {\n useThreads(): RoomThreads<TThreadMetadata>;\n useThreadsSuspense(): ThreadData<TThreadMetadata>[];\n createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata>;\n editThreadMetadata(options: EditThreadMetadataOptions<TThreadMetadata>): void;\n createComment(options: CreateCommentOptions): CommentData;\n editComment(options: EditCommentOptions): void;\n deleteComment(options: DeleteCommentOptions): void;\n subscribe(): () => void;\n};\n\nexport type CreateThreadOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n body: CommentBody;\n }\n : { body: CommentBody; metadata: TMetadata };\n\nexport type EditThreadMetadataOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n threadId: string;\n }\n : { threadId: string; metadata: Partial<TMetadata> };\n\nexport type CreateCommentOptions = {\n threadId: string;\n body: CommentBody;\n};\n\nexport type EditCommentOptions = {\n threadId: string;\n commentId: string;\n body: CommentBody;\n};\n\nexport type DeleteCommentOptions = {\n threadId: string;\n commentId: string;\n};\n\nfunction createOptimisticId(prefix: string) {\n return `${prefix}_${nanoid()}`;\n}\n\nexport type RoomThreads<TThreadMetadata extends BaseMetadata> =\n | {\n isLoading: true;\n threads?: never;\n error?: never;\n }\n | {\n isLoading: false;\n threads?: never;\n error: Error;\n }\n | {\n isLoading: false;\n threads: ThreadData<TThreadMetadata>[];\n error?: never;\n };\n\nexport function createCommentsRoom<TThreadMetadata extends BaseMetadata>(\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>,\n errorEventSource: EventSource<CommentsApiError<TThreadMetadata>>\n): CommentsRoom<TThreadMetadata> {\n const store = createStore<RoomThreads<TThreadMetadata>>({\n isLoading: true,\n });\n\n // Temporary solution\n // The most basic conflict resolution\n // If there are any pending mutation, we simply ignore any threads coming from the server\n // When all mutations are finished, we pull the source of truth from the backend\n\n let numberOfMutations = 0;\n function endMutation() {\n numberOfMutations--;\n if (numberOfMutations === 0) {\n revalidateThreads();\n }\n }\n\n function startMutation() {\n pollingHub.threads.stop();\n numberOfMutations++;\n }\n\n const pollingHub = {\n // TODO: If there's an error, it will currently infinitely retry at the current polling rate → add retry logic\n threads: makePoller(revalidateThreads),\n };\n let unsubscribeRealtimeEvents: (() => void) | undefined;\n let unsubscribeRealtimeConnection: (() => void) | undefined;\n let realtimeClientConnected = false;\n\n function getPollingInterval() {\n return realtimeClientConnected\n ? POLLING_INTERVAL_REALTIME\n : POLLING_INTERVAL;\n }\n\n function ensureThreadsAreLoadedForMutations() {\n const state = store.get();\n if (state.isLoading || state.error) {\n throw new Error(\n \"Cannot update threads or comments before they are loaded\"\n );\n }\n return state.threads;\n }\n\n async function revalidateThreads() {\n pollingHub.threads.pause();\n\n if (numberOfMutations === 0) {\n setThreads(await room.getThreads());\n }\n\n pollingHub.threads.resume();\n }\n\n function subscribe() {\n if (!unsubscribeRealtimeEvents) {\n unsubscribeRealtimeEvents = room.events.comments.subscribe(() => {\n pollingHub.threads.restart(getPollingInterval());\n revalidateThreads();\n });\n }\n\n if (!unsubscribeRealtimeConnection) {\n unsubscribeRealtimeConnection = room.events.status.subscribe((status) => {\n const nextRealtimeClientConnected = status === \"connected\";\n\n if (nextRealtimeClientConnected !== realtimeClientConnected) {\n realtimeClientConnected = nextRealtimeClientConnected;\n pollingHub.threads.restart(getPollingInterval());\n }\n });\n }\n\n // Will only start if not already started\n pollingHub.threads.start(getPollingInterval());\n\n // TODO: improve thread revalidation\n revalidateThreads();\n\n return () => {\n pollingHub.threads.stop();\n unsubscribeRealtimeEvents?.();\n unsubscribeRealtimeEvents = undefined;\n unsubscribeRealtimeConnection?.();\n unsubscribeRealtimeConnection = undefined;\n };\n }\n\n function setThreads(newThreads: ThreadData<TThreadMetadata>[]) {\n store.set({\n threads: newThreads,\n isLoading: false,\n });\n }\n\n function getCurrentUserId() {\n const self = room.getSelf();\n if (self === null || self.id === undefined) {\n return \"anonymous\";\n } else {\n return self.id;\n }\n }\n\n function createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata> {\n const body = options.body;\n const metadata: TThreadMetadata =\n \"metadata\" in options ? options.metadata : ({} as TThreadMetadata);\n const threads = ensureThreadsAreLoadedForMutations();\n\n const threadId = createOptimisticId(THREAD_ID_PREFIX);\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const newThread = {\n id: threadId,\n type: \"thread\",\n createdAt: now,\n roomId: room.id,\n metadata,\n comments: [\n {\n id: commentId,\n createdAt: now,\n type: \"comment\",\n userId: getCurrentUserId(),\n body,\n },\n ],\n } as ThreadData<TThreadMetadata>; // TODO: Figure out metadata typing\n\n setThreads([...threads, newThread]);\n\n startMutation();\n room\n .createThread({ threadId, commentId, body, metadata })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateThreadError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n metadata,\n })\n )\n )\n .finally(endMutation);\n\n return newThread;\n }\n\n function editThreadMetadata(\n options: EditThreadMetadataOptions<TThreadMetadata>\n ): void {\n const threadId = options.threadId;\n const metadata: Partial<TThreadMetadata> =\n \"metadata\" in options ? options.metadata : {};\n const threads = ensureThreadsAreLoadedForMutations();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n metadata: {\n ...thread.metadata,\n ...metadata,\n },\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editThreadMetadata({ metadata, threadId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditThreadMetadataError(er, {\n roomId: room.id,\n threadId,\n metadata,\n })\n )\n )\n .finally(endMutation);\n }\n\n function createComment({\n threadId,\n body,\n }: CreateCommentOptions): CommentData {\n const threads = ensureThreadsAreLoadedForMutations();\n\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const comment: CommentData = {\n id: commentId,\n threadId,\n roomId: room.id,\n type: \"comment\",\n createdAt: now,\n userId: getCurrentUserId(),\n mentionedIds: [],\n body,\n };\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: [...thread.comments, comment],\n }\n : thread\n )\n );\n\n startMutation();\n room\n .createComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n\n return comment;\n }\n\n function editComment({ threadId, commentId, body }: EditCommentOptions) {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? ({\n ...comment,\n editedAt: now,\n body,\n } as CommentData)\n : comment\n ),\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n }\n\n function deleteComment({ threadId, commentId }: DeleteCommentOptions): void {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n const newThreads: ThreadData<TThreadMetadata>[] = [];\n\n for (const thread of threads) {\n if (thread.id === threadId) {\n const newThread: ThreadData<TThreadMetadata> = {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n deletedAt: now,\n body: undefined,\n mentionedIds: [],\n }\n : comment\n ),\n };\n\n if (\n newThread.comments.some((comment) => comment.deletedAt === undefined)\n ) {\n newThreads.push(newThread);\n }\n } else {\n newThreads.push(thread);\n }\n }\n\n setThreads(newThreads);\n\n startMutation();\n room\n .deleteComment({ threadId, commentId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new DeleteCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n })\n )\n )\n .finally(endMutation);\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n return useSyncExternalStore<RoomThreads<TThreadMetadata>>(\n store.subscribe,\n store.get,\n store.get\n );\n }\n\n function useThreadsSuspense() {\n const result = useThreads();\n\n if (result.isLoading) {\n throw new Promise(store.subscribeOnce);\n }\n\n if (result.error) {\n throw result.error;\n }\n\n return result.threads;\n }\n\n return {\n useThreads,\n useThreadsSuspense,\n createThread,\n editThreadMetadata,\n createComment,\n editComment,\n deleteComment,\n subscribe,\n };\n}\n","import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes -= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size -= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n","import type { BaseMetadata, CommentBody } from \"@liveblocks/core\";\n\nexport class CreateThreadError<TMetadata extends BaseMetadata> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n metadata: TMetadata;\n }\n ) {\n super(\"Create thread failed.\");\n this.name = \"CreateThreadError\";\n }\n}\n\nexport class EditThreadMetadataError<\n TMetadata extends BaseMetadata,\n> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n metadata: Partial<TMetadata>;\n }\n ) {\n super(\"Edit thread metadata failed.\");\n this.name = \"EditThreadMetadataError\";\n }\n}\n\nexport class CreateCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Create comment failed.\");\n this.name = \"CreateCommentError\";\n }\n}\n\nexport class EditCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Edit comment failed.\");\n this.name = \"EditCommentError\";\n }\n}\n\nexport class DeleteCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n }\n ) {\n super(\"Delete comment failed.\");\n this.name = \"DeleteCommentError\";\n }\n}\n\nexport type CommentsApiError<TThreadMetadata extends BaseMetadata> =\n | CreateThreadError<TThreadMetadata>\n | EditThreadMetadataError<TThreadMetadata>\n | CreateCommentError\n | EditCommentError\n | DeleteCommentError;\n","import type { UnsubscribeCallback } from \"@liveblocks/core\";\nimport { makeEventSource } from \"@liveblocks/core\";\n\n/**\n * Create a store that keep a state and let consumers subscribe to updates\n * The store assume that the provided state is immutable\n */\nexport function createStore<T>(initialState: T) {\n let state = initialState;\n const eventSource = makeEventSource<T>();\n\n return {\n get(): T {\n return state;\n },\n set(newState: T) {\n state = newState;\n eventSource.notify(state);\n },\n subscribe(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribe(callback);\n },\n subscribeOnce(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribeOnce(callback);\n },\n subscribersCount() {\n return eventSource.count();\n },\n destroy() {\n return eventSource.clear();\n },\n };\n}\n","import type {\n AsyncCache,\n AsyncState,\n AsyncStateInitial,\n AsyncStateResolved,\n} from \"@liveblocks/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport { useInitial } from \"./use-initial\";\n\nconst INITIAL_ASYNC_STATE: AsyncStateInitial = {\n isLoading: false,\n data: undefined,\n error: undefined,\n};\n\ntype AsyncFunction<T, A extends any[] = any[]> = (...args: A) => Promise<T>;\n\nexport type UseAsyncCacheOptions<T> = {\n overrideFunction?: AsyncFunction<T, [string]>;\n keepPreviousDataWhileLoading?: boolean;\n suspense?: boolean;\n};\n\ntype UseAsyncCacheState<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = O extends {\n suspense: true;\n}\n ? Exclude<AsyncState<T, E>, { isLoading: true }>\n : AsyncState<T, E>;\n\nexport type UseAsyncCacheResponse<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = UseAsyncCacheState<T, E, O> & {\n /**\n * Returns the current state of the key synchronously.\n */\n getState: () => AsyncState<T, E>;\n\n /**\n * Revalidates the key.\n */\n revalidate(): Promise<AsyncStateResolved<T, E>>;\n};\n\ntype PreviousData<T> = {\n key: string | null;\n data?: T;\n};\n\nconst noop = () => {};\n\nexport function useAsyncCache<T, E, O extends UseAsyncCacheOptions<T>>(\n cache: AsyncCache<T, E> | undefined,\n key: string | null,\n options?: O\n): UseAsyncCacheResponse<T, E, O> {\n const frozenOptions = useInitial(options);\n const cacheItem = useMemo(() => {\n if (key === null || !cache) {\n return null;\n }\n\n const cacheItem = cache.create(key, frozenOptions?.overrideFunction);\n void cacheItem.get();\n\n return cacheItem;\n }, [cache, frozenOptions, key]);\n\n const subscribe = useCallback(\n (callback: () => void) => cacheItem?.subscribe(callback) ?? noop,\n [cacheItem]\n );\n\n const getState = useCallback(\n () => cacheItem?.getState() ?? INITIAL_ASYNC_STATE,\n [cacheItem]\n );\n\n const revalidate = useCallback(() => cacheItem?.revalidate(), [cacheItem]);\n\n const state = useSyncExternalStore(subscribe, getState, getState);\n const previousData = useRef<PreviousData<T>>();\n let data = state.data;\n\n useEffect(() => {\n previousData.current = { key, data: state.data };\n }, [key, state]);\n\n if (frozenOptions?.suspense && state.isLoading && cacheItem) {\n throw new Promise<void>((resolve) => {\n cacheItem.subscribeOnce(() => resolve());\n });\n }\n\n if (\n state.isLoading &&\n frozenOptions?.keepPreviousDataWhileLoading &&\n typeof state.data === \"undefined\" &&\n previousData.current?.key !== key &&\n typeof previousData.current?.data !== \"undefined\"\n ) {\n data = previousData.current.data;\n }\n\n return {\n isLoading: state.isLoading,\n data,\n error: state.error,\n getState,\n revalidate,\n } as UseAsyncCacheResponse<T, E, O>;\n}\n","import { useRef } from \"react\";\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T | (() => T)): T {\n return useRef(value instanceof Function ? value() : value).current;\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nconst DEFAULT_DELAY = 500;\n\nexport function useDebounce<T>(\n value: T,\n delay: number | false = DEFAULT_DELAY\n): T {\n const timeout = useRef<number>();\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n if (delay === false) {\n return;\n }\n\n if (timeout.current === undefined) {\n setDebouncedValue(value);\n }\n\n timeout.current = window.setTimeout(() => {\n setDebouncedValue(value);\n timeout.current = undefined;\n }, delay);\n\n return () => {\n window.clearTimeout(timeout.current);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { useReducer, useRef } from \"react\";\n\n/**\n * Trigger a re-render programmatically, without changing the component's\n * state.\n *\n * @example\n * const rerender = useRerender();\n *\n * return (\n * <button onClick={rerender}>\n * {Math.random()}\n * </button>\n * )\n */\nexport function useRerender(): () => void {\n const [, update] = useReducer(\n // This implementation works by incrementing a hidden counter value that is\n // never consumed. Simply incrementing the counter changes the component's\n // state and, thus, trigger a re-render.\n (x: number): number => x + 1,\n 0\n );\n return update;\n}\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T): T {\n return useRef(value).current;\n}\n"],"mappings":"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","names":["makeEventSource","React","useEffect","useRef","useSyncExternalStore","cacheItem","useSyncExternalStore","useRef","useEffect","useEffect","useRef","useState","useRef","useInitial","noop","useSyncExternalStore","useInitial","room","other","options","rootOrNull","makeEventSource","shallow"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/ClientSideSuspense.tsx","../src/factory.tsx","../src/comments/CommentsRoom.ts","../../../node_modules/nanoid/index.js","../../../node_modules/nanoid/url-alphabet/index.js","../src/comments/errors.ts","../src/comments/lib/store.ts","../src/comments/lib/use-async-cache.ts","../src/comments/lib/use-initial.ts","../src/comments/lib/use-debounce.ts","../src/hooks.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { ClientSideSuspense } from \"./ClientSideSuspense\";\nexport { createRoomContext, useRoomContextBundle } from \"./factory\";\nexport type {\n MutationContext,\n ResolveMentionSuggestionsOptions,\n ResolveUserOptions,\n} from \"./types\";\n\n// Re-exports from @liveblocks/client, for convenience\nexport type { Json, JsonObject } from \"@liveblocks/client\";\nexport { shallow } from \"@liveblocks/client\";\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n","import type { ReactElement, ReactNode } from \"react\";\nimport * as React from \"react\";\n\ntype Props = {\n fallback: NonNullable<ReactNode> | null;\n children: () => ReactNode | undefined;\n};\n\n/**\n * Almost like a normal <Suspense> component, except that for server-side\n * renders, the fallback will be used.\n *\n * The child props will have to be provided in a function, i.e. change:\n *\n * <Suspense fallback={<Loading />}>\n * <MyRealComponent a={1} />\n * </Suspense>\n *\n * To:\n *\n * <ClientSideSuspense fallback={<Loading />}>\n * {() => <MyRealComponent a={1} />}\n * </ClientSideSuspense>\n *\n */\nexport function ClientSideSuspense(props: Props): ReactElement {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n // Effects are never executed on the server side. The point of this is to\n // delay the flipping of this boolean until after hydration has happened.\n setMounted(true);\n }, []);\n\n return (\n <React.Suspense fallback={props.fallback}>\n {mounted ? props.children() : props.fallback}\n </React.Suspense>\n );\n}\n","import type {\n BaseUserMeta,\n BroadcastOptions,\n Client,\n History,\n Json,\n JsonObject,\n LiveObject,\n LostConnectionEvent,\n LsonObject,\n Others,\n Room,\n Status,\n User,\n} from \"@liveblocks/client\";\nimport { shallow } from \"@liveblocks/client\";\nimport type {\n AsyncCache,\n BaseMetadata,\n CommentData,\n ToImmutable,\n} from \"@liveblocks/core\";\nimport {\n asArrayWithLegacyMethods,\n createAsyncCache,\n deprecateIf,\n errorIf,\n makeEventSource,\n} from \"@liveblocks/core\";\nimport * as React from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector.js\";\n\nimport type {\n CommentsRoom,\n CreateCommentOptions,\n CreateThreadOptions,\n DeleteCommentOptions,\n EditCommentOptions,\n EditThreadMetadataOptions,\n RoomThreads,\n} from \"./comments/CommentsRoom\";\nimport { createCommentsRoom } from \"./comments/CommentsRoom\";\nimport type { CommentsApiError } from \"./comments/errors\";\nimport { useAsyncCache } from \"./comments/lib/use-async-cache\";\nimport { useDebounce } from \"./comments/lib/use-debounce\";\nimport { useInitial, useRerender } from \"./hooks\";\nimport type {\n MutationContext,\n OmitFirstArg,\n ResolveMentionSuggestionsOptions,\n ResolveUserOptions,\n RoomContextBundle,\n RoomProviderProps,\n UserState,\n UserStateSuspense,\n} from \"./types\";\n\nconst noop = () => {};\nconst identity: <T>(x: T) => T = (x) => x;\n\nconst missing_unstable_batchedUpdates = (\n reactVersion: number,\n roomId: string\n) =>\n `We noticed you’re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you’re ready to upgrade to React 18:\n\n import { unstable_batchedUpdates } from \"react-dom\"; // or \"react-native\"\n\n <RoomProvider id=${JSON.stringify(\n roomId\n )} ... unstable_batchedUpdates={unstable_batchedUpdates}>\n ...\n </RoomProvider>\n\nWhy? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;\n\nconst superfluous_unstable_batchedUpdates =\n \"You don’t need to pass unstable_batchedUpdates to RoomProvider anymore, since you’re on React 18+ already.\";\n\nfunction useSyncExternalStore<Snapshot>(\n s: (onStoreChange: () => void) => () => void,\n gs: () => Snapshot,\n gss: undefined | null | (() => Snapshot)\n): Snapshot {\n return useSyncExternalStoreWithSelector(s, gs, gss, identity);\n}\n\nconst EMPTY_OTHERS =\n // NOTE: asArrayWithLegacyMethods() wrapping should no longer be necessary in 0.19\n asArrayWithLegacyMethods([]);\n\nfunction getEmptyOthers() {\n return EMPTY_OTHERS;\n}\n\nfunction makeMutationContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject,\n TUserMeta extends BaseUserMeta,\n TRoomEvent extends Json,\n>(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n): MutationContext<TPresence, TStorage, TUserMeta> {\n const errmsg =\n \"This mutation cannot be used until connected to the Liveblocks room\";\n\n return {\n get storage() {\n const mutableRoot = room.getStorageSnapshot();\n if (mutableRoot === null) {\n throw new Error(errmsg);\n }\n return mutableRoot;\n },\n\n get self() {\n const self = room.getSelf();\n if (self === null) {\n throw new Error(errmsg);\n }\n return self;\n },\n\n get others() {\n const others = room.getOthers();\n if (room.getSelf() === null) {\n throw new Error(errmsg);\n }\n return others;\n },\n\n setMyPresence: room.updatePresence,\n };\n}\n\ntype Options<TUserMeta extends BaseUserMeta> = {\n /**\n * An asynchronous function that returns user info from a user ID.\n */\n resolveUser?: (\n options: ResolveUserOptions\n ) => Promise<TUserMeta[\"info\"] | undefined>;\n\n /**\n * An asynchronous function that returns a list of user IDs matching a string.\n */\n resolveMentionSuggestions?: (\n options: ResolveMentionSuggestionsOptions\n ) => Promise<string[]>;\n\n /**\n * @internal Internal endpoint\n */\n serverEndpoint?: string;\n};\n\nlet hasWarnedIfNoResolveUser = false;\nlet hasWarnedIfNoResolveMentionSuggestions = false;\n\nfunction warnIfNoResolveUser(usersCache?: AsyncCache<unknown, unknown>) {\n if (\n !hasWarnedIfNoResolveUser &&\n !usersCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\"The resolveUser option wasn't set in createRoomContext.\");\n hasWarnedIfNoResolveUser = true;\n }\n}\n\nfunction warnIfNoResolveMentionSuggestions(\n mentionSuggestionsCache?: AsyncCache<unknown, unknown>\n) {\n if (\n !hasWarnedIfNoResolveMentionSuggestions &&\n !mentionSuggestionsCache &&\n process.env.NODE_ENV !== \"production\"\n ) {\n console.warn(\n \"The resolveMentionSuggestions option wasn't set in createRoomContext.\"\n );\n hasWarnedIfNoResolveMentionSuggestions = true;\n }\n}\n\nconst ContextBundle = React.createContext<RoomContextBundle<\n JsonObject,\n LsonObject,\n BaseUserMeta,\n never,\n BaseMetadata\n> | null>(null);\n\n// TODO: Internal?\nexport function useRoomContextBundle() {\n return React.useContext(ContextBundle)!;\n}\n\nexport function createRoomContext<\n TPresence extends JsonObject,\n TStorage extends LsonObject = LsonObject,\n TUserMeta extends BaseUserMeta = BaseUserMeta,\n TRoomEvent extends Json = never,\n TThreadMetadata extends BaseMetadata = never,\n>(\n client: Client,\n options?: Options<TUserMeta>\n): RoomContextBundle<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent,\n TThreadMetadata\n> {\n const RoomContext = React.createContext<Room<\n TPresence,\n TStorage,\n TUserMeta,\n TRoomEvent\n > | null>(null);\n\n function RoomProvider(props: RoomProviderProps<TPresence, TStorage>) {\n const {\n id: roomId,\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect,\n } = props;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!roomId) {\n throw new Error(\n \"RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required\"\n );\n }\n\n if (typeof roomId !== \"string\") {\n throw new Error(\"RoomProvider id property should be a string.\");\n }\n\n const majorReactVersion = parseInt(React.version) || 1;\n const oldReactVersion = majorReactVersion < 18;\n errorIf(\n oldReactVersion && props.unstable_batchedUpdates === undefined,\n missing_unstable_batchedUpdates(majorReactVersion, roomId)\n );\n deprecateIf(\n !oldReactVersion && props.unstable_batchedUpdates !== undefined,\n superfluous_unstable_batchedUpdates\n );\n }\n\n // Note: We'll hold on to the initial value given here, and ignore any\n // changes to this argument in subsequent renders\n const frozen = useInitial({\n initialPresence,\n initialStorage,\n unstable_batchedUpdates,\n shouldInitiallyConnect:\n shouldInitiallyConnect === undefined\n ? typeof window !== \"undefined\"\n : shouldInitiallyConnect,\n });\n\n const [room, setRoom] = React.useState<\n Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n >(() =>\n client.enter(roomId, {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n })\n );\n\n React.useEffect(() => {\n const room = client.enter<TPresence, TStorage, TUserMeta, TRoomEvent>(\n roomId,\n {\n initialPresence: frozen.initialPresence,\n initialStorage: frozen.initialStorage,\n shouldInitiallyConnect: frozen.shouldInitiallyConnect,\n unstable_batchedUpdates: frozen.unstable_batchedUpdates,\n }\n );\n\n setRoom(room);\n\n const unsubscribe = getCommentsRoom(room).subscribe();\n\n return () => {\n unsubscribe();\n commentsRooms.delete(room.id);\n client.leave(roomId);\n };\n }, [roomId, frozen]);\n\n return (\n <RoomContext.Provider value={room}>\n <ContextBundle.Provider value={bundle as any}>\n {props.children}\n </ContextBundle.Provider>\n </RoomContext.Provider>\n );\n }\n\n function connectionIdSelector(\n others: Others<TPresence, TUserMeta>\n ): number[] {\n return others.map((user) => user.connectionId);\n }\n\n function useRoom(): Room<TPresence, TStorage, TUserMeta, TRoomEvent> {\n const room = React.useContext(RoomContext);\n if (room === null) {\n throw new Error(\"RoomProvider is missing from the React tree.\");\n }\n return room;\n }\n\n function useStatus(): Status {\n const room = useRoom();\n const subscribe = room.events.status.subscribe;\n const getSnapshot = room.getStatus;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n function useMyPresence(): [\n TPresence,\n (patch: Partial<TPresence>, options?: { addToHistory: boolean }) => void,\n ] {\n const room = useRoom();\n const subscribe = room.events.myPresence.subscribe;\n const getSnapshot = room.getPresence;\n const presence = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setPresence = room.updatePresence;\n return [presence, setPresence];\n }\n\n function useUpdateMyPresence(): (\n patch: Partial<TPresence>,\n options?: { addToHistory: boolean }\n ) => void {\n return useRoom().updatePresence;\n }\n\n function useOthers(): Others<TPresence, TUserMeta>;\n function useOthers<T>(\n selector: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useOthers<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n const room = useRoom();\n const subscribe = room.events.others.subscribe;\n const getSnapshot = room.getOthers;\n const getServerSnapshot = getEmptyOthers;\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n selector ?? (identity as (others: Others<TPresence, TUserMeta>) => T),\n isEqual\n );\n }\n\n function useOthersConnectionIds(): readonly number[] {\n return useOthers(connectionIdSelector, shallow);\n }\n\n function useOthersMapped<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) =>\n others.map(\n (other) => [other.connectionId, itemSelector(other)] as const\n ),\n [itemSelector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (\n a: ReadonlyArray<readonly [connectionId: number, data: T]>,\n b: ReadonlyArray<readonly [connectionId: number, data: T]>\n ): boolean => {\n const eq = itemIsEqual ?? Object.is;\n return (\n a.length === b.length &&\n a.every((atuple, index) => {\n const btuple = b[index];\n return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);\n })\n );\n },\n [itemIsEqual]\n );\n\n return useOthers(wrappedSelector, wrappedIsEqual);\n }\n\n const NOT_FOUND = Symbol();\n\n type NotFound = typeof NOT_FOUND;\n\n function useOther<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n const wrappedSelector = React.useCallback(\n (others: Others<TPresence, TUserMeta>) => {\n // TODO: Make this O(1) instead of O(n)?\n const other = others.find(\n (other) => other.connectionId === connectionId\n );\n return other !== undefined ? selector(other) : NOT_FOUND;\n },\n [connectionId, selector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (prev: T | NotFound, curr: T | NotFound): boolean => {\n if (prev === NOT_FOUND || curr === NOT_FOUND) {\n return prev === curr;\n }\n\n const eq = isEqual ?? Object.is;\n return eq(prev, curr);\n },\n [isEqual]\n );\n\n const other = useOthers(wrappedSelector, wrappedIsEqual);\n if (other === NOT_FOUND) {\n throw new Error(\n `No such other user with connection id ${connectionId} exists`\n );\n }\n\n return other;\n }\n\n function useBroadcastEvent(): (\n event: TRoomEvent,\n options?: BroadcastOptions\n ) => void {\n const room = useRoom();\n\n return React.useCallback(\n (\n event: TRoomEvent,\n options: BroadcastOptions = { shouldQueueEventIfNotReady: false }\n ) => {\n room.broadcastEvent(event, options);\n },\n [room]\n );\n }\n\n function useLostConnectionListener(\n callback: (event: LostConnectionEvent) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () =>\n room.events.lostConnection.subscribe((event: LostConnectionEvent) =>\n savedCallback.current(event)\n ),\n [room]\n );\n }\n\n function useErrorListener(callback: (err: Error) => void): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(\n () => room.events.error.subscribe((e: Error) => savedCallback.current(e)),\n [room]\n );\n }\n\n function useEventListener(\n callback: (eventData: { connectionId: number; event: TRoomEvent }) => void\n ): void {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (eventData: {\n connectionId: number;\n event: TRoomEvent;\n }) => {\n savedCallback.current(eventData);\n };\n\n return room.events.customEvent.subscribe(listener);\n }, [room]);\n }\n\n function useSelf(): User<TPresence, TUserMeta> | null;\n function useSelf<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null;\n function useSelf<T>(\n maybeSelector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | User<TPresence, TUserMeta> | null {\n type Snapshot = User<TPresence, TUserMeta> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const subscribe = room.events.self.subscribe;\n const getSnapshot: () => Snapshot = room.getSelf;\n\n const selector =\n maybeSelector ?? (identity as (me: User<TPresence, TUserMeta>) => T);\n const wrappedSelector = React.useCallback(\n (me: Snapshot): Selection => (me !== null ? selector(me) : null),\n [selector]\n );\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function useMutableStorageRoot(): LiveObject<TStorage> | null {\n type Snapshot = LiveObject<TStorage> | null;\n const room = useRoom();\n const subscribe = room.events.storageDidLoad.subscribeOnce;\n const getSnapshot = room.getStorageSnapshot;\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n }\n\n // NOTE: This API exists for backward compatible reasons\n function useStorageRoot(): [root: LiveObject<TStorage> | null] {\n return [useMutableStorageRoot()];\n }\n\n function useHistory(): History {\n return useRoom().history;\n }\n\n function useUndo(): () => void {\n return useHistory().undo;\n }\n\n function useRedo(): () => void {\n return useHistory().redo;\n }\n\n function useCanUndo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canUndo = room.history.canUndo;\n return useSyncExternalStore(subscribe, canUndo, canUndo);\n }\n\n function useCanRedo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canRedo = room.history.canRedo;\n return useSyncExternalStore(subscribe, canRedo, canRedo);\n }\n\n function useBatch<T>(): (callback: () => T) => T {\n return useRoom().batch;\n }\n\n function useLegacyKey<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] | null {\n const room = useRoom();\n const root = useMutableStorageRoot();\n const rerender = useRerender();\n\n React.useEffect(() => {\n if (root === null) {\n return;\n }\n\n let liveValue = root.get(key);\n\n function onRootChange() {\n const newCrdt = root!.get(key);\n if (newCrdt !== liveValue) {\n unsubscribeCrdt();\n liveValue = newCrdt;\n unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n rerender();\n }\n }\n\n let unsubscribeCrdt = room.subscribe(\n liveValue as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n rerender\n );\n const unsubscribeRoot = room.subscribe(\n root as any /* AbstractCrdt */, // TODO: This is hiding a bug! If `liveValue` happens to be the string `\"event\"` this actually subscribes an event handler!\n onRootChange\n );\n\n rerender();\n\n return () => {\n unsubscribeRoot();\n unsubscribeCrdt();\n };\n }, [root, room, key, rerender]);\n\n if (root === null) {\n return null;\n } else {\n return root.get(key);\n }\n }\n\n function useStorage<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n ): T | null {\n type Snapshot = ToImmutable<TStorage> | null;\n type Selection = T | null;\n\n const room = useRoom();\n const rootOrNull = useMutableStorageRoot();\n\n const wrappedSelector = React.useCallback(\n (rootOrNull: Snapshot): Selection =>\n rootOrNull !== null ? selector(rootOrNull) : null,\n [selector]\n );\n\n const subscribe = React.useCallback(\n (onStoreChange: () => void) =>\n rootOrNull !== null\n ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true })\n : noop,\n [room, rootOrNull]\n );\n\n const getSnapshot = React.useCallback((): Snapshot => {\n if (rootOrNull === null) {\n return null;\n } else {\n const root = rootOrNull;\n const imm = root.toImmutable();\n return imm;\n }\n }, [rootOrNull]);\n\n const getServerSnapshot = React.useCallback((): Snapshot => null, []);\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n }\n\n function ensureNotServerSide(): void {\n // Error early if suspense is used in a server-side context\n if (typeof window === \"undefined\") {\n throw new Error(\n \"You cannot use the Suspense version of this hook on the server side. Make sure to only call them on the client side.\\nFor tips, see https://liveblocks.io/docs/api-reference/liveblocks-react#suspense-avoid-ssr\"\n );\n }\n }\n\n function useSuspendUntilStorageLoaded(): void {\n const room = useRoom();\n if (room.getStorageSnapshot() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.storageDidLoad.subscribeOnce(() => res());\n });\n }\n\n function useSuspendUntilPresenceLoaded(): void {\n const room = useRoom();\n if (room.getSelf() !== null) {\n return;\n }\n\n ensureNotServerSide();\n\n // Throw a _promise_. Suspense will suspend the component tree until this\n // promise resolves (aka until storage has loaded). After that, it will\n // render this component tree again.\n throw new Promise<void>((res) => {\n room.events.status.subscribeOnce(() => res());\n });\n }\n\n function useMutation<\n F extends (\n context: MutationContext<TPresence, TStorage, TUserMeta>,\n ...args: any[]\n ) => any,\n >(callback: F, deps: readonly unknown[]): OmitFirstArg<F> {\n const room = useRoom();\n return React.useMemo(\n () => {\n return ((...args) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n room.batch(() =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n callback(\n makeMutationContext(room),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n ...args\n )\n )) as OmitFirstArg<F>;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [room, ...deps]\n );\n }\n\n function useStorageSuspense<T>(\n selector: (root: ToImmutable<TStorage>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilStorageLoaded();\n return useStorage(\n selector,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T;\n }\n\n function useSelfSuspense(): User<TPresence, TUserMeta>;\n function useSelfSuspense<T>(\n selector: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T;\n function useSelfSuspense<T>(\n selector?: (me: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | User<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useSelf(\n selector as (me: User<TPresence, TUserMeta>) => T,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T | User<TPresence, TUserMeta>;\n }\n\n function useOthersSuspense<T>(\n selector?: (others: Others<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T | Others<TPresence, TUserMeta> {\n useSuspendUntilPresenceLoaded();\n return useOthers(\n selector as (others: Others<TPresence, TUserMeta>) => T,\n isEqual as (prev: T, curr: T) => boolean\n ) as T | Others<TPresence, TUserMeta>;\n }\n\n function useOthersConnectionIdsSuspense(): readonly number[] {\n useSuspendUntilPresenceLoaded();\n return useOthersConnectionIds();\n }\n\n function useOthersMappedSuspense<T>(\n itemSelector: (other: User<TPresence, TUserMeta>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n ): ReadonlyArray<readonly [connectionId: number, data: T]> {\n useSuspendUntilPresenceLoaded();\n return useOthersMapped(itemSelector, itemIsEqual);\n }\n\n function useOtherSuspense<T>(\n connectionId: number,\n selector: (other: User<TPresence, TUserMeta>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n ): T {\n useSuspendUntilPresenceLoaded();\n return useOther(connectionId, selector, isEqual);\n }\n\n function useLegacyKeySuspense<TKey extends Extract<keyof TStorage, string>>(\n key: TKey\n ): TStorage[TKey] {\n useSuspendUntilStorageLoaded();\n return useLegacyKey(key) as TStorage[TKey];\n }\n\n /*\n * START COMMMENTS\n */\n\n const errorEventSource = makeEventSource<CommentsApiError<TThreadMetadata>>();\n\n const commentsRooms = new Map<string, CommentsRoom<TThreadMetadata>>();\n\n function getCommentsRoom(\n room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>\n ) {\n let commentsRoom = commentsRooms.get(room.id);\n if (commentsRoom === undefined) {\n commentsRoom = createCommentsRoom(room, errorEventSource);\n commentsRooms.set(room.id, commentsRoom);\n }\n return commentsRoom;\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n const room = useRoom();\n return getCommentsRoom(room).useThreads();\n }\n\n function useThreadsSuspense() {\n const room = useRoom();\n return getCommentsRoom(room).useThreadsSuspense();\n }\n\n function useCreateThread() {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateThreadOptions<TThreadMetadata>) =>\n getCommentsRoom(room).createThread(options),\n [room]\n );\n }\n\n function useEditThreadMetadata() {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditThreadMetadataOptions<TThreadMetadata>) =>\n getCommentsRoom(room).editThreadMetadata(options),\n [room]\n );\n }\n\n function useCreateComment(): (options: CreateCommentOptions) => CommentData {\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateCommentOptions) =>\n getCommentsRoom(room).createComment(options),\n [room]\n );\n }\n\n function useEditComment(): (options: EditCommentOptions) => void {\n const room = useRoom();\n\n return React.useCallback(\n (options: EditCommentOptions) =>\n getCommentsRoom(room).editComment(options),\n [room]\n );\n }\n\n function useDeleteComment() {\n const room = useRoom();\n\n return React.useCallback(\n (options: DeleteCommentOptions) =>\n getCommentsRoom(room).deleteComment(options),\n [room]\n );\n }\n\n const { resolveUser, resolveMentionSuggestions } = options ?? {};\n\n const usersCache = resolveUser\n ? createAsyncCache((stringifiedOptions: string) => {\n return resolveUser(\n JSON.parse(stringifiedOptions) as ResolveUserOptions\n );\n })\n : undefined;\n\n function useUser(userId: string) {\n const resolverKey = React.useMemo(\n () => JSON.stringify({ userId }),\n [userId]\n );\n const state = useAsyncCache(usersCache, resolverKey);\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n if (state.isLoading) {\n return {\n isLoading: true,\n } as UserState<TUserMeta[\"info\"]>;\n } else {\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserState<TUserMeta[\"info\"]>;\n }\n }\n\n function useUserSuspense(userId: string) {\n const resolverKey = React.useMemo(\n () => JSON.stringify({ userId }),\n [userId]\n );\n const state = useAsyncCache(usersCache, resolverKey, {\n suspense: true,\n });\n\n React.useEffect(() => warnIfNoResolveUser(usersCache), []);\n\n return {\n user: state.data,\n error: state.error,\n isLoading: false,\n } as UserStateSuspense<TUserMeta[\"info\"]>;\n }\n\n const mentionSuggestionsCache = createAsyncCache<string[], unknown>(\n resolveMentionSuggestions\n ? (stringifiedOptions: string) => {\n return resolveMentionSuggestions(\n JSON.parse(stringifiedOptions) as ResolveMentionSuggestionsOptions\n );\n }\n : () => Promise.resolve([])\n );\n\n function useMentionSuggestions(search?: string) {\n const room = useRoom();\n const debouncedSearch = useDebounce(search, 500);\n const resolverKey = React.useMemo(\n () =>\n debouncedSearch !== undefined\n ? JSON.stringify({ text: debouncedSearch, roomId: room.id })\n : null,\n [debouncedSearch, room.id]\n );\n const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {\n keepPreviousDataWhileLoading: true,\n });\n\n React.useEffect(\n () => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),\n []\n );\n\n return data;\n }\n\n /*\n * END COMMENTS\n */\n\n const bundle = {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // These are just aliases. The passed-in key will define their return values.\n useList: useLegacyKey,\n useMap: useLegacyKey,\n useObject: useLegacyKey,\n\n useStorageRoot,\n useStorage,\n\n useSelf,\n useMyPresence,\n useUpdateMyPresence,\n useOthers,\n useOthersMapped,\n useOthersConnectionIds,\n useOther,\n\n useMutation,\n\n useThreads,\n useUser,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n\n useMentionSuggestions,\n\n suspense: {\n RoomContext,\n RoomProvider,\n\n useRoom,\n useStatus,\n\n useBatch,\n useBroadcastEvent,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n // Legacy hooks\n useList: useLegacyKeySuspense,\n useMap: useLegacyKeySuspense,\n useObject: useLegacyKeySuspense,\n\n useStorageRoot,\n useStorage: useStorageSuspense,\n\n useSelf: useSelfSuspense,\n useMyPresence,\n useUpdateMyPresence,\n useOthers: useOthersSuspense,\n useOthersMapped: useOthersMappedSuspense,\n useOthersConnectionIds: useOthersConnectionIdsSuspense,\n useOther: useOtherSuspense,\n\n useMutation,\n\n useThreads: useThreadsSuspense,\n useUser: useUserSuspense,\n\n useCreateThread,\n useEditThreadMetadata,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n },\n };\n\n return bundle;\n}\n","import type {\n BaseMetadata,\n BaseUserMeta,\n CommentBody,\n CommentData,\n EventSource,\n Json,\n JsonObject,\n LsonObject,\n Room,\n ThreadData,\n} from \"@liveblocks/core\";\nimport { makePoller } from \"@liveblocks/core\";\nimport { nanoid } from \"nanoid\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport type { CommentsApiError } from \"./errors\";\nimport {\n CreateCommentError,\n CreateThreadError,\n DeleteCommentError,\n EditCommentError,\n EditThreadMetadataError,\n} from \"./errors\";\nimport { createStore } from \"./lib/store\";\n\nconst POLLING_INTERVAL_REALTIME = 30000;\nconst POLLING_INTERVAL = 5000;\nconst THREAD_ID_PREFIX = \"th\";\nconst COMMENT_ID_PREFIX = \"cm\";\n\nexport type CommentsRoom<TThreadMetadata extends BaseMetadata> = {\n useThreads(): RoomThreads<TThreadMetadata>;\n useThreadsSuspense(): ThreadData<TThreadMetadata>[];\n createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata>;\n editThreadMetadata(options: EditThreadMetadataOptions<TThreadMetadata>): void;\n createComment(options: CreateCommentOptions): CommentData;\n editComment(options: EditCommentOptions): void;\n deleteComment(options: DeleteCommentOptions): void;\n subscribe(): () => void;\n};\n\nexport type CreateThreadOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n body: CommentBody;\n }\n : { body: CommentBody; metadata: TMetadata };\n\nexport type EditThreadMetadataOptions<TMetadata extends BaseMetadata> = [\n TMetadata,\n] extends [never]\n ? {\n threadId: string;\n }\n : { threadId: string; metadata: Partial<TMetadata> };\n\nexport type CreateCommentOptions = {\n threadId: string;\n body: CommentBody;\n};\n\nexport type EditCommentOptions = {\n threadId: string;\n commentId: string;\n body: CommentBody;\n};\n\nexport type DeleteCommentOptions = {\n threadId: string;\n commentId: string;\n};\n\nfunction createOptimisticId(prefix: string) {\n return `${prefix}_${nanoid()}`;\n}\n\nexport type RoomThreads<TThreadMetadata extends BaseMetadata> =\n | {\n isLoading: true;\n threads?: never;\n error?: never;\n }\n | {\n isLoading: false;\n threads?: never;\n error: Error;\n }\n | {\n isLoading: false;\n threads: ThreadData<TThreadMetadata>[];\n error?: never;\n };\n\nexport function createCommentsRoom<TThreadMetadata extends BaseMetadata>(\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>,\n errorEventSource: EventSource<CommentsApiError<TThreadMetadata>>\n): CommentsRoom<TThreadMetadata> {\n const store = createStore<RoomThreads<TThreadMetadata>>({\n isLoading: true,\n });\n\n // Temporary solution\n // The most basic conflict resolution\n // If there are any pending mutation, we simply ignore any threads coming from the server\n // When all mutations are finished, we pull the source of truth from the backend\n\n let numberOfMutations = 0;\n function endMutation() {\n numberOfMutations--;\n if (numberOfMutations === 0) {\n revalidateThreads();\n }\n }\n\n function startMutation() {\n pollingHub.threads.stop();\n numberOfMutations++;\n }\n\n const pollingHub = {\n // TODO: If there's an error, it will currently infinitely retry at the current polling rate → add retry logic\n threads: makePoller(revalidateThreads),\n };\n let unsubscribeRealtimeEvents: (() => void) | undefined;\n let unsubscribeRealtimeConnection: (() => void) | undefined;\n let realtimeClientConnected = false;\n\n function getPollingInterval() {\n return realtimeClientConnected\n ? POLLING_INTERVAL_REALTIME\n : POLLING_INTERVAL;\n }\n\n function ensureThreadsAreLoadedForMutations() {\n const state = store.get();\n if (state.isLoading || state.error) {\n throw new Error(\n \"Cannot update threads or comments before they are loaded\"\n );\n }\n return state.threads;\n }\n\n async function revalidateThreads() {\n pollingHub.threads.pause();\n\n if (numberOfMutations === 0) {\n setThreads(await room.getThreads());\n }\n\n pollingHub.threads.resume();\n }\n\n function subscribe() {\n if (!unsubscribeRealtimeEvents) {\n unsubscribeRealtimeEvents = room.events.comments.subscribe(() => {\n pollingHub.threads.restart(getPollingInterval());\n revalidateThreads();\n });\n }\n\n if (!unsubscribeRealtimeConnection) {\n unsubscribeRealtimeConnection = room.events.status.subscribe((status) => {\n const nextRealtimeClientConnected = status === \"connected\";\n\n if (nextRealtimeClientConnected !== realtimeClientConnected) {\n realtimeClientConnected = nextRealtimeClientConnected;\n pollingHub.threads.restart(getPollingInterval());\n }\n });\n }\n\n // Will only start if not already started\n pollingHub.threads.start(getPollingInterval());\n\n // TODO: improve thread revalidation\n revalidateThreads();\n\n return () => {\n pollingHub.threads.stop();\n unsubscribeRealtimeEvents?.();\n unsubscribeRealtimeEvents = undefined;\n unsubscribeRealtimeConnection?.();\n unsubscribeRealtimeConnection = undefined;\n };\n }\n\n function setThreads(newThreads: ThreadData<TThreadMetadata>[]) {\n store.set({\n threads: newThreads,\n isLoading: false,\n });\n }\n\n function getCurrentUserId() {\n const self = room.getSelf();\n if (self === null || self.id === undefined) {\n return \"anonymous\";\n } else {\n return self.id;\n }\n }\n\n function createThread(\n options: CreateThreadOptions<TThreadMetadata>\n ): ThreadData<TThreadMetadata> {\n const body = options.body;\n const metadata: TThreadMetadata =\n \"metadata\" in options ? options.metadata : ({} as TThreadMetadata);\n const threads = ensureThreadsAreLoadedForMutations();\n\n const threadId = createOptimisticId(THREAD_ID_PREFIX);\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const newThread = {\n id: threadId,\n type: \"thread\",\n createdAt: now,\n roomId: room.id,\n metadata,\n comments: [\n {\n id: commentId,\n createdAt: now,\n type: \"comment\",\n userId: getCurrentUserId(),\n body,\n },\n ],\n } as ThreadData<TThreadMetadata>; // TODO: Figure out metadata typing\n\n setThreads([...threads, newThread]);\n\n startMutation();\n room\n .createThread({ threadId, commentId, body, metadata })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateThreadError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n metadata,\n })\n )\n )\n .finally(endMutation);\n\n return newThread;\n }\n\n function editThreadMetadata(\n options: EditThreadMetadataOptions<TThreadMetadata>\n ): void {\n const threadId = options.threadId;\n const metadata: Partial<TThreadMetadata> =\n \"metadata\" in options ? options.metadata : {};\n const threads = ensureThreadsAreLoadedForMutations();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n metadata: {\n ...thread.metadata,\n ...metadata,\n },\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editThreadMetadata({ metadata, threadId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditThreadMetadataError(er, {\n roomId: room.id,\n threadId,\n metadata,\n })\n )\n )\n .finally(endMutation);\n }\n\n function createComment({\n threadId,\n body,\n }: CreateCommentOptions): CommentData {\n const threads = ensureThreadsAreLoadedForMutations();\n\n const commentId = createOptimisticId(COMMENT_ID_PREFIX);\n const now = new Date().toISOString();\n\n const comment: CommentData = {\n id: commentId,\n threadId,\n roomId: room.id,\n type: \"comment\",\n createdAt: now,\n userId: getCurrentUserId(),\n body,\n };\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: [...thread.comments, comment],\n }\n : thread\n )\n );\n\n startMutation();\n room\n .createComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new CreateCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n\n return comment;\n }\n\n function editComment({ threadId, commentId, body }: EditCommentOptions) {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n setThreads(\n threads.map((thread) =>\n thread.id === threadId\n ? {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? ({\n ...comment,\n editedAt: now,\n body,\n } as CommentData)\n : comment\n ),\n }\n : thread\n )\n );\n\n startMutation();\n room\n .editComment({ threadId, commentId, body })\n .catch((er: Error) =>\n errorEventSource.notify(\n new EditCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n )\n .finally(endMutation);\n }\n\n function deleteComment({ threadId, commentId }: DeleteCommentOptions): void {\n const threads = ensureThreadsAreLoadedForMutations();\n const now = new Date().toISOString();\n\n const newThreads: ThreadData<TThreadMetadata>[] = [];\n\n for (const thread of threads) {\n if (thread.id === threadId) {\n const newThread: ThreadData<TThreadMetadata> = {\n ...thread,\n comments: thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n deletedAt: now,\n body: undefined,\n }\n : comment\n ),\n };\n\n if (\n newThread.comments.some((comment) => comment.deletedAt === undefined)\n ) {\n newThreads.push(newThread);\n }\n } else {\n newThreads.push(thread);\n }\n }\n\n setThreads(newThreads);\n\n startMutation();\n room\n .deleteComment({ threadId, commentId })\n .catch((er: Error) =>\n errorEventSource.notify(\n new DeleteCommentError(er, {\n roomId: room.id,\n threadId,\n commentId,\n })\n )\n )\n .finally(endMutation);\n }\n\n function useThreads(): RoomThreads<TThreadMetadata> {\n return useSyncExternalStore<RoomThreads<TThreadMetadata>>(\n store.subscribe,\n store.get,\n store.get\n );\n }\n\n function useThreadsSuspense() {\n const result = useThreads();\n\n if (result.isLoading) {\n throw new Promise(store.subscribeOnce);\n }\n\n if (result.error) {\n throw result.error;\n }\n\n return result.threads;\n }\n\n return {\n useThreads,\n useThreadsSuspense,\n createThread,\n editThreadMetadata,\n createComment,\n editComment,\n deleteComment,\n subscribe,\n };\n}\n","import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes -= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size -= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n","import type { BaseMetadata, CommentBody } from \"@liveblocks/core\";\n\nexport class CreateThreadError<TMetadata extends BaseMetadata> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n metadata: TMetadata;\n }\n ) {\n super(\"Create thread failed.\");\n this.name = \"CreateThreadError\";\n }\n}\n\nexport class EditThreadMetadataError<\n TMetadata extends BaseMetadata,\n> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n metadata: Partial<TMetadata>;\n }\n ) {\n super(\"Edit thread metadata failed.\");\n this.name = \"EditThreadMetadataError\";\n }\n}\n\nexport class CreateCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Create comment failed.\");\n this.name = \"CreateCommentError\";\n }\n}\n\nexport class EditCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Edit comment failed.\");\n this.name = \"EditCommentError\";\n }\n}\n\nexport class DeleteCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n }\n ) {\n super(\"Delete comment failed.\");\n this.name = \"DeleteCommentError\";\n }\n}\n\nexport type CommentsApiError<TThreadMetadata extends BaseMetadata> =\n | CreateThreadError<TThreadMetadata>\n | EditThreadMetadataError<TThreadMetadata>\n | CreateCommentError\n | EditCommentError\n | DeleteCommentError;\n","import type { UnsubscribeCallback } from \"@liveblocks/core\";\nimport { makeEventSource } from \"@liveblocks/core\";\n\n/**\n * Create a store that keep a state and let consumers subscribe to updates\n * The store assume that the provided state is immutable\n */\nexport function createStore<T>(initialState: T) {\n let state = initialState;\n const eventSource = makeEventSource<T>();\n\n return {\n get(): T {\n return state;\n },\n set(newState: T) {\n state = newState;\n eventSource.notify(state);\n },\n subscribe(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribe(callback);\n },\n subscribeOnce(callback: (state: T) => void): UnsubscribeCallback {\n return eventSource.subscribeOnce(callback);\n },\n subscribersCount() {\n return eventSource.count();\n },\n destroy() {\n return eventSource.clear();\n },\n };\n}\n","import type {\n AsyncCache,\n AsyncState,\n AsyncStateInitial,\n AsyncStateResolved,\n} from \"@liveblocks/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport { useInitial } from \"./use-initial\";\n\nconst INITIAL_ASYNC_STATE: AsyncStateInitial = {\n isLoading: false,\n data: undefined,\n error: undefined,\n};\n\ntype AsyncFunction<T, A extends any[] = any[]> = (...args: A) => Promise<T>;\n\nexport type UseAsyncCacheOptions<T> = {\n overrideFunction?: AsyncFunction<T, [string]>;\n keepPreviousDataWhileLoading?: boolean;\n suspense?: boolean;\n};\n\ntype UseAsyncCacheState<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = O extends {\n suspense: true;\n}\n ? Exclude<AsyncState<T, E>, { isLoading: true }>\n : AsyncState<T, E>;\n\nexport type UseAsyncCacheResponse<\n T,\n E,\n O extends UseAsyncCacheOptions<T> = UseAsyncCacheOptions<T>,\n> = UseAsyncCacheState<T, E, O> & {\n /**\n * Returns the current state of the key synchronously.\n */\n getState: () => AsyncState<T, E>;\n\n /**\n * Revalidates the key.\n */\n revalidate(): Promise<AsyncStateResolved<T, E>>;\n};\n\ntype PreviousData<T> = {\n key: string | null;\n data?: T;\n};\n\nconst noop = () => {};\n\nexport function useAsyncCache<T, E, O extends UseAsyncCacheOptions<T>>(\n cache: AsyncCache<T, E> | undefined,\n key: string | null,\n options?: O\n): UseAsyncCacheResponse<T, E, O> {\n const frozenOptions = useInitial(options);\n const cacheItem = useMemo(() => {\n if (key === null || !cache) {\n return null;\n }\n\n const cacheItem = cache.create(key, frozenOptions?.overrideFunction);\n void cacheItem.get();\n\n return cacheItem;\n }, [cache, frozenOptions, key]);\n\n const subscribe = useCallback(\n (callback: () => void) => cacheItem?.subscribe(callback) ?? noop,\n [cacheItem]\n );\n\n const getState = useCallback(\n () => cacheItem?.getState() ?? INITIAL_ASYNC_STATE,\n [cacheItem]\n );\n\n const revalidate = useCallback(() => cacheItem?.revalidate(), [cacheItem]);\n\n const state = useSyncExternalStore(subscribe, getState, getState);\n const previousData = useRef<PreviousData<T>>();\n let data = state.data;\n\n useEffect(() => {\n previousData.current = { key, data: state.data };\n }, [key, state]);\n\n if (frozenOptions?.suspense && state.isLoading && cacheItem) {\n throw new Promise<void>((resolve) => {\n cacheItem.subscribeOnce(() => resolve());\n });\n }\n\n if (\n state.isLoading &&\n frozenOptions?.keepPreviousDataWhileLoading &&\n typeof state.data === \"undefined\" &&\n previousData.current?.key !== key &&\n typeof previousData.current?.data !== \"undefined\"\n ) {\n data = previousData.current.data;\n }\n\n return {\n isLoading: state.isLoading,\n data,\n error: state.error,\n getState,\n revalidate,\n } as UseAsyncCacheResponse<T, E, O>;\n}\n","import { useRef } from \"react\";\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T | (() => T)): T {\n return useRef(value instanceof Function ? value() : value).current;\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nconst DEFAULT_DELAY = 500;\n\nexport function useDebounce<T>(\n value: T,\n delay: number | false = DEFAULT_DELAY\n): T {\n const timeout = useRef<number>();\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n if (delay === false) {\n return;\n }\n\n if (timeout.current === undefined) {\n setDebouncedValue(value);\n }\n\n timeout.current = window.setTimeout(() => {\n setDebouncedValue(value);\n timeout.current = undefined;\n }, delay);\n\n return () => {\n window.clearTimeout(timeout.current);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { useReducer, useRef } from \"react\";\n\n/**\n * Trigger a re-render programmatically, without changing the component's\n * state.\n *\n * @example\n * const rerender = useRerender();\n *\n * return (\n * <button onClick={rerender}>\n * {Math.random()}\n * </button>\n * )\n */\nexport function useRerender(): () => void {\n const [, update] = useReducer(\n // This implementation works by incrementing a hidden counter value that is\n // never consumed. Simply incrementing the counter changes the component's\n // state and, thus, trigger a re-render.\n (x: number): number => x + 1,\n 0\n );\n return update;\n}\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T): T {\n return useRef(value).current;\n}\n"],"mappings":"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","names":["makeEventSource","React","useEffect","useRef","useSyncExternalStore","cacheItem","useSyncExternalStore","useRef","useEffect","useEffect","useRef","useState","useRef","useInitial","noop","useSyncExternalStore","useInitial","room","other","options","rootOrNull","makeEventSource","shallow"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/react",
|
|
3
|
-
"version": "1.2.2-
|
|
3
|
+
"version": "1.2.2-comments2",
|
|
4
4
|
"description": "A set of React hooks and providers to use Liveblocks declaratively. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"test:watch": "jest --silent --verbose --color=always --watch"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@liveblocks/client": "1.2.2-
|
|
38
|
-
"@liveblocks/core": "1.2.2-
|
|
37
|
+
"@liveblocks/client": "1.2.2-comments2",
|
|
38
|
+
"@liveblocks/core": "1.2.2-comments2",
|
|
39
39
|
"use-sync-external-store": "^1.2.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|