@liveblocks/react 1.2.2-comments4 → 1.2.2-comments6

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
@@ -530,10 +530,6 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
530
530
  * const { user, error, isLoading } = useUser("user-id");
531
531
  */
532
532
  useUser(userId: string): UserState<TUserMeta["info"]>;
533
- /**
534
- * @private
535
- */
536
- useMentionSuggestions(search?: string): string[] | undefined;
537
533
  /**
538
534
  * Returns the LiveList associated with the provided key. The hook triggers
539
535
  * a re-render if the LiveList is updated, however it does not triggers
@@ -686,6 +682,11 @@ declare type Options<TUserMeta extends BaseUserMeta> = {
686
682
  */
687
683
  resolveMentionSuggestions?: (options: ResolveMentionSuggestionsOptions) => Promise<string[]>;
688
684
  };
685
+ /**
686
+ * @private
687
+ *
688
+ * This is an internal API, use `createRoomContext` instead.
689
+ */
689
690
  declare function useRoomContextBundle(): {
690
691
  RoomContext: React$1.Context<Room<JsonObject, LsonObject, BaseUserMeta, never> | null>;
691
692
  RoomProvider: (props: {
@@ -1038,7 +1039,6 @@ declare function useRoomContextBundle(): {
1038
1039
  name?: string | undefined;
1039
1040
  avatar?: string | undefined;
1040
1041
  } | undefined>;
1041
- useMentionSuggestions: (search?: string | undefined) => string[] | undefined;
1042
1042
  useList: <TKey extends string>(key: TKey) => _liveblocks_core.Lson | undefined;
1043
1043
  useMap: <TKey_1 extends string>(key: TKey_1) => _liveblocks_core.Lson | undefined;
1044
1044
  useObject: <TKey_2 extends string>(key: TKey_2) => _liveblocks_core.Lson | undefined;
@@ -1402,6 +1402,8 @@ declare function useRoomContextBundle(): {
1402
1402
  useMap: <TKey_4 extends string>(key: TKey_4) => _liveblocks_core.Lson | undefined;
1403
1403
  useObject: <TKey_5 extends string>(key: TKey_5) => _liveblocks_core.Lson | undefined;
1404
1404
  };
1405
+ hasResolveMentionSuggestions: boolean;
1406
+ useMentionSuggestions: (search?: string | undefined) => string[] | undefined;
1405
1407
  };
1406
1408
  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>;
1407
1409
 
package/dist/index.d.ts CHANGED
@@ -530,10 +530,6 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
530
530
  * const { user, error, isLoading } = useUser("user-id");
531
531
  */
532
532
  useUser(userId: string): UserState<TUserMeta["info"]>;
533
- /**
534
- * @private
535
- */
536
- useMentionSuggestions(search?: string): string[] | undefined;
537
533
  /**
538
534
  * Returns the LiveList associated with the provided key. The hook triggers
539
535
  * a re-render if the LiveList is updated, however it does not triggers
@@ -686,6 +682,11 @@ declare type Options<TUserMeta extends BaseUserMeta> = {
686
682
  */
687
683
  resolveMentionSuggestions?: (options: ResolveMentionSuggestionsOptions) => Promise<string[]>;
688
684
  };
685
+ /**
686
+ * @private
687
+ *
688
+ * This is an internal API, use `createRoomContext` instead.
689
+ */
689
690
  declare function useRoomContextBundle(): {
690
691
  RoomContext: React$1.Context<Room<JsonObject, LsonObject, BaseUserMeta, never> | null>;
691
692
  RoomProvider: (props: {
@@ -1038,7 +1039,6 @@ declare function useRoomContextBundle(): {
1038
1039
  name?: string | undefined;
1039
1040
  avatar?: string | undefined;
1040
1041
  } | undefined>;
1041
- useMentionSuggestions: (search?: string | undefined) => string[] | undefined;
1042
1042
  useList: <TKey extends string>(key: TKey) => _liveblocks_core.Lson | undefined;
1043
1043
  useMap: <TKey_1 extends string>(key: TKey_1) => _liveblocks_core.Lson | undefined;
1044
1044
  useObject: <TKey_2 extends string>(key: TKey_2) => _liveblocks_core.Lson | undefined;
@@ -1402,6 +1402,8 @@ declare function useRoomContextBundle(): {
1402
1402
  useMap: <TKey_4 extends string>(key: TKey_4) => _liveblocks_core.Lson | undefined;
1403
1403
  useObject: <TKey_5 extends string>(key: TKey_5) => _liveblocks_core.Lson | undefined;
1404
1404
  };
1405
+ hasResolveMentionSuggestions: boolean;
1406
+ useMentionSuggestions: (search?: string | undefined) => string[] | undefined;
1405
1407
  };
1406
1408
  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>;
1407
1409
 
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
2
 
3
3
  // src/index.ts
4
4
  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-comments4";
8
+ var PKG_VERSION = "1.2.2-comments6";
9
9
  var PKG_FORMAT = "cjs";
10
10
 
11
11
  // src/ClientSideSuspense.tsx
@@ -32,38 +32,7 @@ var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
32
32
 
33
33
  // src/comments/CommentsRoom.ts
34
34
 
35
-
36
- // ../../node_modules/nanoid/index.js
37
- var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
38
-
39
- // ../../node_modules/nanoid/url-alphabet/index.js
40
- var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
41
-
42
- // ../../node_modules/nanoid/index.js
43
- var POOL_SIZE_MULTIPLIER = 128;
44
- var pool;
45
- var poolOffset;
46
- var fillPool = (bytes) => {
47
- if (!pool || pool.length < bytes) {
48
- pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
49
- _crypto2.default.randomFillSync(pool);
50
- poolOffset = 0;
51
- } else if (poolOffset + bytes > pool.length) {
52
- _crypto2.default.randomFillSync(pool);
53
- poolOffset = 0;
54
- }
55
- poolOffset += bytes;
56
- };
57
- var nanoid = (size = 21) => {
58
- fillPool(size -= 0);
59
- let id = "";
60
- for (let i = poolOffset - size; i < poolOffset; i++) {
61
- id += urlAlphabet[pool[i] & 63];
62
- }
63
- return id;
64
- };
65
-
66
- // src/comments/CommentsRoom.ts
35
+ var _nanoid = require('nanoid');
67
36
  var _indexjs = require('use-sync-external-store/shim/index.js');
68
37
 
69
38
  // src/comments/errors.ts
@@ -137,17 +106,19 @@ function createStore(initialState) {
137
106
  }
138
107
 
139
108
  // src/comments/CommentsRoom.ts
109
+
140
110
  var POLLING_INTERVAL_REALTIME = 3e4;
141
111
  var POLLING_INTERVAL = 5e3;
142
112
  var THREAD_ID_PREFIX = "th";
143
113
  var COMMENT_ID_PREFIX = "cm";
144
114
  function createOptimisticId(prefix) {
145
- return `${prefix}_${nanoid()}`;
115
+ return `${prefix}_${_nanoid.nanoid.call(void 0, )}`;
146
116
  }
147
117
  function createCommentsRoom(room, errorEventSource) {
148
118
  const store = createStore({
149
119
  isLoading: true
150
120
  });
121
+ let fetchThreadsPromise = null;
151
122
  let numberOfMutations = 0;
152
123
  function endMutation() {
153
124
  numberOfMutations--;
@@ -181,7 +152,11 @@ function createCommentsRoom(room, errorEventSource) {
181
152
  async function revalidateThreads() {
182
153
  pollingHub.threads.pause();
183
154
  if (numberOfMutations === 0) {
184
- setThreads(await room.getThreads());
155
+ if (fetchThreadsPromise === null) {
156
+ fetchThreadsPromise = room.getThreads();
157
+ }
158
+ setThreads(await fetchThreadsPromise);
159
+ fetchThreadsPromise = null;
185
160
  }
186
161
  pollingHub.threads.resume();
187
162
  }
@@ -202,8 +177,10 @@ function createCommentsRoom(room, errorEventSource) {
202
177
  });
203
178
  }
204
179
  pollingHub.threads.start(getPollingInterval());
205
- revalidateThreads();
206
180
  return () => {
181
+ if (store.subscribersCount() > 1) {
182
+ return;
183
+ }
207
184
  pollingHub.threads.stop();
208
185
  _optionalChain([unsubscribeRealtimeEvents, 'optionalCall', _ => _()]);
209
186
  unsubscribeRealtimeEvents = void 0;
@@ -217,6 +194,30 @@ function createCommentsRoom(room, errorEventSource) {
217
194
  isLoading: false
218
195
  });
219
196
  }
197
+ function useThreadsInternal() {
198
+ _react.useEffect.call(void 0, subscribe, []);
199
+ return _indexjs.useSyncExternalStore.call(void 0,
200
+ store.subscribe,
201
+ store.get,
202
+ store.get
203
+ );
204
+ }
205
+ function useThreads() {
206
+ _react.useEffect.call(void 0, () => {
207
+ void revalidateThreads();
208
+ }, []);
209
+ return useThreadsInternal();
210
+ }
211
+ function useThreadsSuspense() {
212
+ const result = useThreadsInternal();
213
+ if (result.isLoading) {
214
+ throw revalidateThreads();
215
+ }
216
+ if (result.error) {
217
+ throw result.error;
218
+ }
219
+ return result.threads;
220
+ }
220
221
  function getCurrentUserId() {
221
222
  const self = room.getSelf();
222
223
  if (self === null || self.id === void 0) {
@@ -390,23 +391,6 @@ function createCommentsRoom(room, errorEventSource) {
390
391
  )
391
392
  ).finally(endMutation);
392
393
  }
393
- function useThreads() {
394
- return _indexjs.useSyncExternalStore.call(void 0,
395
- store.subscribe,
396
- store.get,
397
- store.get
398
- );
399
- }
400
- function useThreadsSuspense() {
401
- const result = useThreads();
402
- if (result.isLoading) {
403
- throw new Promise(store.subscribeOnce);
404
- }
405
- if (result.error) {
406
- throw result.error;
407
- }
408
- return result.threads;
409
- }
410
394
  return {
411
395
  useThreads,
412
396
  useThreadsSuspense,
@@ -414,8 +398,7 @@ function createCommentsRoom(room, errorEventSource) {
414
398
  editThreadMetadata,
415
399
  createComment,
416
400
  editComment,
417
- deleteComment,
418
- subscribe
401
+ deleteComment
419
402
  };
420
403
  }
421
404
 
@@ -519,6 +502,18 @@ function useInitial2(value) {
519
502
  return _react.useRef.call(void 0, value).current;
520
503
  }
521
504
 
505
+ // src/lib/stable-stringify.ts
506
+ function stableStringify(object, ...args) {
507
+ const sortedObject = Object.keys(object).sort().reduce(
508
+ (sortedObject2, key) => {
509
+ sortedObject2[key] = object[key];
510
+ return sortedObject2;
511
+ },
512
+ {}
513
+ );
514
+ return JSON.stringify(sortedObject, ...args);
515
+ }
516
+
522
517
  // src/factory.tsx
523
518
  var noop2 = () => {
524
519
  };
@@ -573,24 +568,21 @@ function makeMutationContext(room) {
573
568
  };
574
569
  }
575
570
  var hasWarnedIfNoResolveUser = false;
576
- var hasWarnedIfNoResolveMentionSuggestions = false;
577
571
  function warnIfNoResolveUser(usersCache) {
578
572
  if (!hasWarnedIfNoResolveUser && !usersCache && process.env.NODE_ENV !== "production") {
579
- console.warn("The resolveUser option wasn't set in createRoomContext.");
580
- hasWarnedIfNoResolveUser = true;
581
- }
582
- }
583
- function warnIfNoResolveMentionSuggestions(mentionSuggestionsCache) {
584
- if (!hasWarnedIfNoResolveMentionSuggestions && !mentionSuggestionsCache && process.env.NODE_ENV !== "production") {
585
573
  console.warn(
586
- "The resolveMentionSuggestions option wasn't set in createRoomContext."
574
+ "Set the resolveUser option in createRoomContext to specify user info."
587
575
  );
588
- hasWarnedIfNoResolveMentionSuggestions = true;
576
+ hasWarnedIfNoResolveUser = true;
589
577
  }
590
578
  }
591
579
  var ContextBundle = React2.createContext(null);
592
580
  function useRoomContextBundle() {
593
- return React2.useContext(ContextBundle);
581
+ const bundle = React2.useContext(ContextBundle);
582
+ if (bundle === null) {
583
+ throw new Error("RoomProvider is missing from the React tree.");
584
+ }
585
+ return bundle;
594
586
  }
595
587
  function createRoomContext(client, options) {
596
588
  const RoomContext = React2.createContext(null);
@@ -647,14 +639,21 @@ function createRoomContext(client, options) {
647
639
  }
648
640
  );
649
641
  setRoom(room2);
650
- const unsubscribe = getCommentsRoom(room2).subscribe();
651
642
  return () => {
652
- unsubscribe();
653
- commentsRooms.delete(room2.id);
643
+ const commentsRoom = commentsRooms.get(roomId);
644
+ if (commentsRoom) {
645
+ commentsRooms.delete(roomId);
646
+ }
654
647
  client.leave(roomId);
655
648
  };
656
649
  }, [roomId, frozen]);
657
- return /* @__PURE__ */ React2.createElement(RoomContext.Provider, { value: room }, /* @__PURE__ */ React2.createElement(ContextBundle.Provider, { value: bundle }, props.children));
650
+ return /* @__PURE__ */ React2.createElement(RoomContext.Provider, { value: room }, /* @__PURE__ */ React2.createElement(
651
+ ContextBundle.Provider,
652
+ {
653
+ value: internalBundle
654
+ },
655
+ props.children
656
+ ));
658
657
  }
659
658
  function connectionIdSelector(others) {
660
659
  return others.map((user) => user.connectionId);
@@ -1064,7 +1063,7 @@ function createRoomContext(client, options) {
1064
1063
  }) : void 0;
1065
1064
  function useUser(userId) {
1066
1065
  const resolverKey = React2.useMemo(
1067
- () => JSON.stringify({ userId }),
1066
+ () => stableStringify({ userId }),
1068
1067
  [userId]
1069
1068
  );
1070
1069
  const state = useAsyncCache(usersCache, resolverKey);
@@ -1083,7 +1082,7 @@ function createRoomContext(client, options) {
1083
1082
  }
1084
1083
  function useUserSuspense(userId) {
1085
1084
  const resolverKey = React2.useMemo(
1086
- () => JSON.stringify({ userId }),
1085
+ () => stableStringify({ userId }),
1087
1086
  [userId]
1088
1087
  );
1089
1088
  const state = useAsyncCache(usersCache, resolverKey, {
@@ -1107,16 +1106,12 @@ function createRoomContext(client, options) {
1107
1106
  const room = useRoom();
1108
1107
  const debouncedSearch = useDebounce(search, 500);
1109
1108
  const resolverKey = React2.useMemo(
1110
- () => debouncedSearch !== void 0 ? JSON.stringify({ text: debouncedSearch, roomId: room.id }) : null,
1109
+ () => debouncedSearch !== void 0 ? stableStringify({ text: debouncedSearch, roomId: room.id }) : null,
1111
1110
  [debouncedSearch, room.id]
1112
1111
  );
1113
1112
  const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {
1114
1113
  keepPreviousDataWhileLoading: true
1115
1114
  });
1116
- React2.useEffect(
1117
- () => warnIfNoResolveMentionSuggestions(mentionSuggestionsCache),
1118
- []
1119
- );
1120
1115
  return data;
1121
1116
  }
1122
1117
  const bundle = {
@@ -1155,7 +1150,6 @@ function createRoomContext(client, options) {
1155
1150
  useCreateComment,
1156
1151
  useEditComment,
1157
1152
  useDeleteComment,
1158
- useMentionSuggestions,
1159
1153
  suspense: {
1160
1154
  RoomContext,
1161
1155
  RoomProvider,
@@ -1194,6 +1188,11 @@ function createRoomContext(client, options) {
1194
1188
  useDeleteComment
1195
1189
  }
1196
1190
  };
1191
+ const internalBundle = {
1192
+ ...bundle,
1193
+ hasResolveMentionSuggestions: resolveMentionSuggestions !== void 0,
1194
+ useMentionSuggestions
1195
+ };
1197
1196
  return bundle;
1198
1197
  }
1199
1198