@liveblocks/react 1.4.4 → 1.4.6-test1

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 CHANGED
@@ -28,6 +28,9 @@ declare type Props = {
28
28
  */
29
29
  declare function ClientSideSuspense(props: Props): ReactElement;
30
30
 
31
+ declare type PartialNullable<T> = {
32
+ [P in keyof T]?: T[P] | null | undefined;
33
+ };
31
34
  declare type CreateThreadOptions<TMetadata extends BaseMetadata> = [
32
35
  TMetadata
33
36
  ] extends [never] ? {
@@ -42,7 +45,7 @@ declare type EditThreadMetadataOptions<TMetadata extends BaseMetadata> = [
42
45
  threadId: string;
43
46
  } : {
44
47
  threadId: string;
45
- metadata: Partial<TMetadata>;
48
+ metadata: Resolve<PartialNullable<TMetadata>>;
46
49
  };
47
50
  declare type CreateCommentOptions = {
48
51
  threadId: string;
@@ -79,11 +82,25 @@ declare type ThreadsStateSuccess<TThreadMetadata extends BaseMetadata> = {
79
82
  };
80
83
  declare type ThreadsState<TThreadMetadata extends BaseMetadata> = ThreadsStateLoading | ThreadsStateError | ThreadsStateSuccess<TThreadMetadata>;
81
84
 
82
- declare type ResolveUserOptions = {
83
- userId: string;
85
+ declare type PromiseOrNot<T> = T | Promise<T>;
86
+ declare type ResolveUsersArgs = {
87
+ /**
88
+ * The ID of the current room.
89
+ */
90
+ roomId: string;
91
+ /**
92
+ * The ID of the users to resolve.
93
+ */
94
+ userIds: string;
84
95
  };
85
- declare type ResolveMentionSuggestionsOptions = {
96
+ declare type ResolveMentionSuggestionsArgs = {
97
+ /**
98
+ * The ID of the current room.
99
+ */
86
100
  roomId: string;
101
+ /**
102
+ * The text to search for.
103
+ */
87
104
  text: string;
88
105
  };
89
106
  declare type UserStateLoading = {
@@ -439,6 +456,7 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
439
456
  * @beta
440
457
  *
441
458
  * Returns a function that edits a thread's metadata.
459
+ * To delete an existing metadata property, set its value to `null`.
442
460
  *
443
461
  * @example
444
462
  * const editThreadMetadata = useEditThreadMetadata();
@@ -742,15 +760,15 @@ declare type Options<TUserMeta extends BaseUserMeta> = {
742
760
  /**
743
761
  * @beta
744
762
  *
745
- * An asynchronous function that returns user info from a user ID.
763
+ * A function that returns user info from user IDs.
746
764
  */
747
- resolveUser?: (options: ResolveUserOptions) => Promise<TUserMeta["info"] | undefined>;
765
+ resolveUsers?: (args: ResolveUsersArgs) => PromiseOrNot<TUserMeta["info"] | undefined>;
748
766
  /**
749
767
  * @beta
750
768
  *
751
- * An asynchronous function that returns a list of user IDs matching a string.
769
+ * A function that returns a list of user IDs matching a string.
752
770
  */
753
- resolveMentionSuggestions?: (options: ResolveMentionSuggestionsOptions) => Promise<string[]>;
771
+ resolveMentionSuggestions?: (args: ResolveMentionSuggestionsArgs) => PromiseOrNot<string[]>;
754
772
  };
755
773
  /**
756
774
  * @private
@@ -800,7 +818,9 @@ declare function useRoomContextBundle(): {
800
818
  }) => _liveblocks_core.ThreadData<BaseMetadata>;
801
819
  useEditThreadMetadata: () => (options: {
802
820
  threadId: string;
803
- metadata: Partial<BaseMetadata>;
821
+ metadata: {
822
+ [x: string]: string | number | boolean | null | undefined;
823
+ };
804
824
  }) => void;
805
825
  useCreateComment: () => (options: CreateCommentOptions) => CommentData;
806
826
  useEditComment: () => (options: EditCommentOptions) => void;
@@ -1154,7 +1174,9 @@ declare function useRoomContextBundle(): {
1154
1174
  }) => _liveblocks_core.ThreadData<BaseMetadata>;
1155
1175
  useEditThreadMetadata: () => (options: {
1156
1176
  threadId: string;
1157
- metadata: Partial<BaseMetadata>;
1177
+ metadata: {
1178
+ [x: string]: string | number | boolean | null | undefined;
1179
+ };
1158
1180
  }) => void;
1159
1181
  useCreateComment: () => (options: CreateCommentOptions) => CommentData;
1160
1182
  useEditComment: () => (options: EditCommentOptions) => void;
@@ -1471,4 +1493,4 @@ declare function useRoomContextBundle(): {
1471
1493
  };
1472
1494
  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>;
1473
1495
 
1474
- export { ClientSideSuspense, MutationContext, ResolveMentionSuggestionsOptions, ResolveUserOptions, createRoomContext, useRoomContextBundle };
1496
+ export { ClientSideSuspense, MutationContext, ResolveMentionSuggestionsArgs, ResolveUsersArgs, createRoomContext, useRoomContextBundle };
package/dist/index.d.ts CHANGED
@@ -28,6 +28,9 @@ declare type Props = {
28
28
  */
29
29
  declare function ClientSideSuspense(props: Props): ReactElement;
30
30
 
31
+ declare type PartialNullable<T> = {
32
+ [P in keyof T]?: T[P] | null | undefined;
33
+ };
31
34
  declare type CreateThreadOptions<TMetadata extends BaseMetadata> = [
32
35
  TMetadata
33
36
  ] extends [never] ? {
@@ -42,7 +45,7 @@ declare type EditThreadMetadataOptions<TMetadata extends BaseMetadata> = [
42
45
  threadId: string;
43
46
  } : {
44
47
  threadId: string;
45
- metadata: Partial<TMetadata>;
48
+ metadata: Resolve<PartialNullable<TMetadata>>;
46
49
  };
47
50
  declare type CreateCommentOptions = {
48
51
  threadId: string;
@@ -79,11 +82,25 @@ declare type ThreadsStateSuccess<TThreadMetadata extends BaseMetadata> = {
79
82
  };
80
83
  declare type ThreadsState<TThreadMetadata extends BaseMetadata> = ThreadsStateLoading | ThreadsStateError | ThreadsStateSuccess<TThreadMetadata>;
81
84
 
82
- declare type ResolveUserOptions = {
83
- userId: string;
85
+ declare type PromiseOrNot<T> = T | Promise<T>;
86
+ declare type ResolveUsersArgs = {
87
+ /**
88
+ * The ID of the current room.
89
+ */
90
+ roomId: string;
91
+ /**
92
+ * The ID of the users to resolve.
93
+ */
94
+ userIds: string;
84
95
  };
85
- declare type ResolveMentionSuggestionsOptions = {
96
+ declare type ResolveMentionSuggestionsArgs = {
97
+ /**
98
+ * The ID of the current room.
99
+ */
86
100
  roomId: string;
101
+ /**
102
+ * The text to search for.
103
+ */
87
104
  text: string;
88
105
  };
89
106
  declare type UserStateLoading = {
@@ -439,6 +456,7 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
439
456
  * @beta
440
457
  *
441
458
  * Returns a function that edits a thread's metadata.
459
+ * To delete an existing metadata property, set its value to `null`.
442
460
  *
443
461
  * @example
444
462
  * const editThreadMetadata = useEditThreadMetadata();
@@ -742,15 +760,15 @@ declare type Options<TUserMeta extends BaseUserMeta> = {
742
760
  /**
743
761
  * @beta
744
762
  *
745
- * An asynchronous function that returns user info from a user ID.
763
+ * A function that returns user info from user IDs.
746
764
  */
747
- resolveUser?: (options: ResolveUserOptions) => Promise<TUserMeta["info"] | undefined>;
765
+ resolveUsers?: (args: ResolveUsersArgs) => PromiseOrNot<TUserMeta["info"] | undefined>;
748
766
  /**
749
767
  * @beta
750
768
  *
751
- * An asynchronous function that returns a list of user IDs matching a string.
769
+ * A function that returns a list of user IDs matching a string.
752
770
  */
753
- resolveMentionSuggestions?: (options: ResolveMentionSuggestionsOptions) => Promise<string[]>;
771
+ resolveMentionSuggestions?: (args: ResolveMentionSuggestionsArgs) => PromiseOrNot<string[]>;
754
772
  };
755
773
  /**
756
774
  * @private
@@ -800,7 +818,9 @@ declare function useRoomContextBundle(): {
800
818
  }) => _liveblocks_core.ThreadData<BaseMetadata>;
801
819
  useEditThreadMetadata: () => (options: {
802
820
  threadId: string;
803
- metadata: Partial<BaseMetadata>;
821
+ metadata: {
822
+ [x: string]: string | number | boolean | null | undefined;
823
+ };
804
824
  }) => void;
805
825
  useCreateComment: () => (options: CreateCommentOptions) => CommentData;
806
826
  useEditComment: () => (options: EditCommentOptions) => void;
@@ -1154,7 +1174,9 @@ declare function useRoomContextBundle(): {
1154
1174
  }) => _liveblocks_core.ThreadData<BaseMetadata>;
1155
1175
  useEditThreadMetadata: () => (options: {
1156
1176
  threadId: string;
1157
- metadata: Partial<BaseMetadata>;
1177
+ metadata: {
1178
+ [x: string]: string | number | boolean | null | undefined;
1179
+ };
1158
1180
  }) => void;
1159
1181
  useCreateComment: () => (options: CreateCommentOptions) => CommentData;
1160
1182
  useEditComment: () => (options: EditCommentOptions) => void;
@@ -1471,4 +1493,4 @@ declare function useRoomContextBundle(): {
1471
1493
  };
1472
1494
  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>;
1473
1495
 
1474
- export { ClientSideSuspense, MutationContext, ResolveMentionSuggestionsOptions, ResolveUserOptions, createRoomContext, useRoomContextBundle };
1496
+ export { ClientSideSuspense, MutationContext, ResolveMentionSuggestionsArgs, ResolveUsersArgs, 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.4.4";
8
+ var PKG_VERSION = "1.4.6-test1";
9
9
  var PKG_FORMAT = "cjs";
10
10
 
11
11
  // src/ClientSideSuspense.tsx
@@ -28,6 +28,7 @@ var _client = require('@liveblocks/client');
28
28
 
29
29
 
30
30
 
31
+
31
32
  var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
32
33
 
33
34
  // src/comments/CommentsRoom.ts
@@ -257,21 +258,23 @@ function createCommentsRoom(room, errorEventSource) {
257
258
  const threadId = createOptimisticId(THREAD_ID_PREFIX);
258
259
  const commentId = createOptimisticId(COMMENT_ID_PREFIX);
259
260
  const now = (/* @__PURE__ */ new Date()).toISOString();
261
+ const newComment = {
262
+ id: commentId,
263
+ threadId,
264
+ roomId: room.id,
265
+ createdAt: now,
266
+ type: "comment",
267
+ userId: getCurrentUserId(),
268
+ body,
269
+ reactions: []
270
+ };
260
271
  const newThread = {
261
272
  id: threadId,
262
273
  type: "thread",
263
274
  createdAt: now,
264
275
  roomId: room.id,
265
276
  metadata,
266
- comments: [
267
- {
268
- id: commentId,
269
- createdAt: now,
270
- type: "comment",
271
- userId: getCurrentUserId(),
272
- body
273
- }
274
- ]
277
+ comments: [newComment]
275
278
  };
276
279
  mutate(room.createThread({ threadId, commentId, body, metadata }), {
277
280
  optimisticData: [...threads, newThread]
@@ -624,18 +627,6 @@ function useDebounce(value, delay = DEFAULT_DELAY) {
624
627
  return debouncedValue;
625
628
  }
626
629
 
627
- // src/lib/stable-stringify.ts
628
- function stableStringify(object, ...args) {
629
- const sortedObject = Object.keys(object).sort().reduce(
630
- (sortedObject2, key) => {
631
- sortedObject2[key] = object[key];
632
- return sortedObject2;
633
- },
634
- {}
635
- );
636
- return JSON.stringify(sortedObject, ...args);
637
- }
638
-
639
630
  // src/lib/use-async-cache.ts
640
631
 
641
632
 
@@ -660,35 +651,50 @@ function useAsyncCache(cache, key, options) {
660
651
  if (key === null || !cache) {
661
652
  return null;
662
653
  }
663
- const cacheItem2 = cache.create(key, _optionalChain([frozenOptions, 'optionalAccess', _2 => _2.overrideFunction]));
654
+ const cacheItem2 = cache.create(key);
664
655
  void cacheItem2.get();
665
656
  return cacheItem2;
666
- }, [cache, frozenOptions, key]);
657
+ }, [cache, key]);
667
658
  const subscribe = _react.useCallback.call(void 0,
668
- (callback) => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _3 => _3.subscribe, 'call', _4 => _4(callback)]), () => ( noop)),
659
+ (callback) => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _2 => _2.subscribe, 'call', _3 => _3(callback)]), () => ( noop)),
669
660
  [cacheItem]
670
661
  );
671
662
  const getState = _react.useCallback.call(void 0,
672
- () => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _5 => _5.getState, 'call', _6 => _6()]), () => ( INITIAL_ASYNC_STATE)),
663
+ () => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _4 => _4.getState, 'call', _5 => _5()]), () => ( INITIAL_ASYNC_STATE)),
673
664
  [cacheItem]
674
665
  );
675
- const revalidate = _react.useCallback.call(void 0, () => _optionalChain([cacheItem, 'optionalAccess', _7 => _7.revalidate, 'call', _8 => _8()]), [cacheItem]);
666
+ const revalidate = _react.useCallback.call(void 0, () => _optionalChain([cacheItem, 'optionalAccess', _6 => _6.revalidate, 'call', _7 => _7()]), [cacheItem]);
676
667
  const state = _indexjs.useSyncExternalStore.call(void 0, subscribe, getState, getState);
677
668
  const previousData = _react.useRef.call(void 0, );
678
669
  let data = state.data;
679
670
  _react.useEffect.call(void 0, () => {
680
671
  previousData.current = { key, data: state.data };
681
- }, [key, state]);
682
- if (_optionalChain([frozenOptions, 'optionalAccess', _9 => _9.suspense]) && state.isLoading && cacheItem) {
683
- throw new Promise((resolve) => {
684
- cacheItem.subscribeOnce(() => resolve());
685
- });
672
+ }, [key, state.data]);
673
+ if (!cacheItem) {
674
+ return {
675
+ isLoading: false,
676
+ data: void 0,
677
+ error: void 0,
678
+ getState,
679
+ revalidate
680
+ };
686
681
  }
687
- if (state.isLoading && _optionalChain([frozenOptions, 'optionalAccess', _10 => _10.keepPreviousDataWhileLoading]) && typeof state.data === "undefined" && _optionalChain([previousData, 'access', _11 => _11.current, 'optionalAccess', _12 => _12.key]) !== key && typeof _optionalChain([previousData, 'access', _13 => _13.current, 'optionalAccess', _14 => _14.data]) !== "undefined") {
688
- data = previousData.current.data;
682
+ if (_optionalChain([frozenOptions, 'optionalAccess', _8 => _8.suspense])) {
683
+ const error = getState().error;
684
+ if (error) {
685
+ throw error;
686
+ } else if (getState().isLoading) {
687
+ throw new Promise((resolve) => {
688
+ cacheItem.subscribeOnce((state2) => {
689
+ if (!state2.isLoading) {
690
+ resolve();
691
+ }
692
+ });
693
+ });
694
+ }
689
695
  }
690
- if (_optionalChain([frozenOptions, 'optionalAccess', _15 => _15.suspense]) && state.error) {
691
- throw state.error;
696
+ if (state.isLoading && _optionalChain([frozenOptions, 'optionalAccess', _9 => _9.keepPreviousDataWhileLoading]) && typeof state.data === "undefined" && _optionalChain([previousData, 'access', _10 => _10.current, 'optionalAccess', _11 => _11.key]) !== key && typeof _optionalChain([previousData, 'access', _12 => _12.current, 'optionalAccess', _13 => _13.data]) !== "undefined") {
697
+ data = previousData.current.data;
692
698
  }
693
699
  return {
694
700
  isLoading: state.isLoading,
@@ -738,6 +744,9 @@ function alwaysEmptyList() {
738
744
  function alwaysNull() {
739
745
  return null;
740
746
  }
747
+ function alwaysConnecting() {
748
+ return "connecting";
749
+ }
741
750
  function makeMutationContext(room) {
742
751
  const errmsg = "This mutation cannot be used until connected to the Liveblocks room";
743
752
  return {
@@ -765,13 +774,13 @@ function makeMutationContext(room) {
765
774
  setMyPresence: room.updatePresence
766
775
  };
767
776
  }
768
- var hasWarnedIfNoResolveUser = false;
769
- function warnIfNoResolveUser(usersCache) {
770
- if (!hasWarnedIfNoResolveUser && !usersCache && process.env.NODE_ENV !== "production") {
777
+ var hasWarnedIfNoResolveUsers = false;
778
+ function warnIfNoResolveUsers(usersCache) {
779
+ if (!hasWarnedIfNoResolveUsers && !usersCache && process.env.NODE_ENV !== "production") {
771
780
  console.warn(
772
- "Set the resolveUser option in createRoomContext to specify user info."
781
+ "Set the resolveUsers option in createRoomContext to specify user info."
773
782
  );
774
- hasWarnedIfNoResolveUser = true;
783
+ hasWarnedIfNoResolveUsers = true;
775
784
  }
776
785
  }
777
786
  var hasWarnedAboutCommentsBeta = false;
@@ -876,7 +885,8 @@ function createRoomContext(client, options) {
876
885
  const room = useRoom();
877
886
  const subscribe = room.events.status.subscribe;
878
887
  const getSnapshot = room.getStatus;
879
- return useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
888
+ const getServerSnapshot = alwaysConnecting;
889
+ return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot);
880
890
  }
881
891
  function useMyPresence() {
882
892
  const room = useRoom();
@@ -1068,7 +1078,7 @@ function createRoomContext(client, options) {
1068
1078
  function onRootChange() {
1069
1079
  const newValue = root.get(key);
1070
1080
  if (newValue !== curr) {
1071
- _optionalChain([unsubCurr, 'optionalCall', _16 => _16()]);
1081
+ _optionalChain([unsubCurr, 'optionalCall', _14 => _14()]);
1072
1082
  curr = newValue;
1073
1083
  subscribeToCurr();
1074
1084
  rerender();
@@ -1079,7 +1089,7 @@ function createRoomContext(client, options) {
1079
1089
  const unsubscribeRoot = room.subscribe(root, onRootChange);
1080
1090
  return () => {
1081
1091
  unsubscribeRoot();
1082
- _optionalChain([unsubCurr, 'optionalCall', _17 => _17()]);
1092
+ _optionalChain([unsubCurr, 'optionalCall', _15 => _15()]);
1083
1093
  };
1084
1094
  }, [rootOrNull, room, key, rerender]);
1085
1095
  if (rootOrNull === null) {
@@ -1141,6 +1151,7 @@ function createRoomContext(client, options) {
1141
1151
  }
1142
1152
  ensureNotServerSide();
1143
1153
  throw new Promise((res) => {
1154
+ room.events.self.subscribeOnce(() => res());
1144
1155
  room.events.status.subscribeOnce(() => res());
1145
1156
  });
1146
1157
  }
@@ -1296,19 +1307,21 @@ function createRoomContext(client, options) {
1296
1307
  [room]
1297
1308
  );
1298
1309
  }
1299
- const { resolveUser, resolveMentionSuggestions } = _nullishCoalesce(options, () => ( {}));
1300
- const usersCache = resolveUser ? _core.createAsyncCache.call(void 0, (stringifiedOptions) => {
1301
- return resolveUser(
1310
+ const { resolveUsers, resolveMentionSuggestions } = _nullishCoalesce(options, () => ( {}));
1311
+ const usersCache = resolveUsers ? _core.createAsyncCache.call(void 0, async (stringifiedOptions) => {
1312
+ const users = await resolveUsers(
1302
1313
  JSON.parse(stringifiedOptions)
1303
1314
  );
1315
+ return _optionalChain([users, 'optionalAccess', _16 => _16[0]]);
1304
1316
  }) : void 0;
1305
1317
  function useUser(userId) {
1318
+ const room = useRoom();
1306
1319
  const resolverKey = React2.useMemo(
1307
- () => stableStringify({ userId }),
1308
- [userId]
1320
+ () => _core.stringify.call(void 0, { userIds: [userId], roomId: room.id }),
1321
+ [userId, room.id]
1309
1322
  );
1310
1323
  const state = useAsyncCache(usersCache, resolverKey);
1311
- React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
1324
+ React2.useEffect(() => warnIfNoResolveUsers(usersCache), []);
1312
1325
  if (state.isLoading) {
1313
1326
  return {
1314
1327
  isLoading: true
@@ -1322,14 +1335,15 @@ function createRoomContext(client, options) {
1322
1335
  }
1323
1336
  }
1324
1337
  function useUserSuspense(userId) {
1338
+ const room = useRoom();
1325
1339
  const resolverKey = React2.useMemo(
1326
- () => stableStringify({ userId }),
1327
- [userId]
1340
+ () => _core.stringify.call(void 0, { userIds: [userId], roomId: room.id }),
1341
+ [userId, room.id]
1328
1342
  );
1329
1343
  const state = useAsyncCache(usersCache, resolverKey, {
1330
1344
  suspense: true
1331
1345
  });
1332
- React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
1346
+ React2.useEffect(() => warnIfNoResolveUsers(usersCache), []);
1333
1347
  return {
1334
1348
  user: state.data,
1335
1349
  isLoading: false
@@ -1346,7 +1360,7 @@ function createRoomContext(client, options) {
1346
1360
  const room = useRoom();
1347
1361
  const debouncedSearch = useDebounce(search, 500);
1348
1362
  const resolverKey = React2.useMemo(
1349
- () => debouncedSearch !== void 0 ? stableStringify({ text: debouncedSearch, roomId: room.id }) : null,
1363
+ () => debouncedSearch !== void 0 ? _core.stringify.call(void 0, { text: debouncedSearch, roomId: room.id }) : null,
1350
1364
  [debouncedSearch, room.id]
1351
1365
  );
1352
1366
  const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {