@liveblocks/react 1.9.3 → 1.9.5

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.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.9.3";
8
+ var PKG_VERSION = "1.9.5";
9
9
  var PKG_FORMAT = "cjs";
10
10
 
11
11
  // src/ClientSideSuspense.tsx
@@ -41,6 +41,7 @@ var _nanoid = require('nanoid');
41
41
 
42
42
 
43
43
 
44
+ var _shim = require('use-sync-external-store/shim');
44
45
 
45
46
 
46
47
  // src/comments/errors.ts
@@ -103,6 +104,53 @@ var RemoveReactionError = class extends Error {
103
104
 
104
105
  // src/comments/lib/revalidation.ts
105
106
 
107
+
108
+ // src/comments/lib/use-is-document-visible.ts
109
+ var _indexjs = require('use-sync-external-store/shim/index.js');
110
+ function useIsDocumentVisible() {
111
+ const isVisible = _indexjs.useSyncExternalStore.call(void 0, subscribe, getSnapshot, getSnapshot);
112
+ return isVisible;
113
+ }
114
+ function subscribe(onStoreChange) {
115
+ document.addEventListener("visibilitychange", onStoreChange);
116
+ return () => {
117
+ document.removeEventListener("visibilitychange", onStoreChange);
118
+ };
119
+ }
120
+ function getSnapshot() {
121
+ const isDocumentDefined = typeof document !== "undefined";
122
+ return isDocumentDefined ? document.visibilityState === "visible" : true;
123
+ }
124
+
125
+ // src/comments/lib/use-is-online.ts
126
+
127
+
128
+ function useIsOnline() {
129
+ const isOnlineRef = _react.useRef.call(void 0, true);
130
+ const subscribe2 = _react.useCallback.call(void 0, (onStoreChange) => {
131
+ function handleIsOnline() {
132
+ isOnlineRef.current = true;
133
+ onStoreChange();
134
+ }
135
+ function handleIsOffline() {
136
+ isOnlineRef.current = false;
137
+ onStoreChange();
138
+ }
139
+ window.addEventListener("online", handleIsOnline);
140
+ window.addEventListener("offline", handleIsOffline);
141
+ return () => {
142
+ window.removeEventListener("online", handleIsOnline);
143
+ window.removeEventListener("offline", handleIsOffline);
144
+ };
145
+ }, []);
146
+ const getSnapshot2 = _react.useCallback.call(void 0, () => {
147
+ return isOnlineRef.current;
148
+ }, []);
149
+ const isOnline = _indexjs.useSyncExternalStore.call(void 0, subscribe2, getSnapshot2, getSnapshot2);
150
+ return isOnline;
151
+ }
152
+
153
+ // src/comments/lib/revalidation.ts
106
154
  var DEFAULT_ERROR_RETRY_INTERVAL = 5e3;
107
155
  var DEFAULT_MAX_ERROR_RETRY_COUNT = 5;
108
156
  var DEFAULT_DEDUPING_INTERVAL = 2e3;
@@ -239,6 +287,8 @@ function useMutate(manager, revalidateCache) {
239
287
  // src/comments/CommentsRoom.tsx
240
288
  var THREAD_ID_PREFIX = "th";
241
289
  var COMMENT_ID_PREFIX = "cm";
290
+ var POLLING_INTERVAL_REALTIME = 3e4;
291
+ var POLLING_INTERVAL = 5e3;
242
292
  function createCommentsRoom(errorEventSource) {
243
293
  const store = createClientCacheStore();
244
294
  const FetcherContext = _react.createContext.call(void 0, null);
@@ -275,6 +325,70 @@ function createCommentsRoom(errorEventSource) {
275
325
  return threads;
276
326
  }, [room, manager]);
277
327
  const revalidateCache = useRevalidateCache(manager, fetcher);
328
+ const status = _shim.useSyncExternalStore.call(void 0,
329
+ room.events.status.subscribe,
330
+ room.getStatus,
331
+ room.getStatus
332
+ );
333
+ const isOnline = useIsOnline();
334
+ const isDocumentVisible = useIsDocumentVisible();
335
+ const refreshInterval = getPollingInterval(
336
+ isOnline,
337
+ isDocumentVisible,
338
+ status === "connected"
339
+ );
340
+ _react.useEffect.call(void 0, () => {
341
+ let revalidationTimerId;
342
+ function scheduleRevalidation() {
343
+ if (refreshInterval === 0)
344
+ return;
345
+ revalidationTimerId = window.setTimeout(() => {
346
+ if (isOnline && isDocumentVisible && !manager.getError() && manager.getTotalReferenceCount() > 0) {
347
+ void revalidateCache({ shouldDedupe: true }).then(
348
+ scheduleRevalidation
349
+ );
350
+ return;
351
+ }
352
+ scheduleRevalidation();
353
+ }, refreshInterval);
354
+ }
355
+ scheduleRevalidation();
356
+ return () => {
357
+ window.clearTimeout(revalidationTimerId);
358
+ };
359
+ }, [
360
+ revalidateCache,
361
+ refreshInterval,
362
+ isOnline,
363
+ isDocumentVisible,
364
+ manager
365
+ ]);
366
+ _react.useEffect.call(void 0, () => {
367
+ function handleIsOnline() {
368
+ if (isDocumentVisible) {
369
+ void revalidateCache({ shouldDedupe: true });
370
+ }
371
+ }
372
+ window.addEventListener("online", handleIsOnline);
373
+ return () => {
374
+ window.removeEventListener("online", handleIsOnline);
375
+ };
376
+ }, [revalidateCache, isDocumentVisible]);
377
+ _react.useEffect.call(void 0, () => {
378
+ function handleVisibilityChange() {
379
+ const isVisible = document.visibilityState === "visible";
380
+ if (isVisible && isOnline) {
381
+ void revalidateCache({ shouldDedupe: true });
382
+ }
383
+ }
384
+ document.addEventListener("visibilitychange", handleVisibilityChange);
385
+ return () => {
386
+ document.removeEventListener(
387
+ "visibilitychange",
388
+ handleVisibilityChange
389
+ );
390
+ };
391
+ }, [revalidateCache, isOnline]);
278
392
  _react.useEffect.call(void 0, () => {
279
393
  const unsubscribe = room.events.comments.subscribe(() => {
280
394
  void revalidateCache({ shouldDedupe: false });
@@ -338,38 +452,9 @@ function createCommentsRoom(errorEventSource) {
338
452
  return () => {
339
453
  manager.decrementReferenceCount(key);
340
454
  };
341
- });
342
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
343
- store.subscribe,
344
- () => store.getThreads(),
345
- () => store.getThreads(),
346
- (state) => {
347
- const isLoading = useThreadsRevalidationManager.getIsLoading();
348
- if (isLoading) {
349
- return {
350
- isLoading: true
351
- };
352
- }
353
- const options2 = useThreadsRevalidationManager.getOptions();
354
- const error = useThreadsRevalidationManager.getError();
355
- const filtered = state.filter((thread) => {
356
- if (thread.roomId !== room.id)
357
- return false;
358
- const query = _nullishCoalesce(options2.query, () => ( {}));
359
- for (const key2 in query.metadata) {
360
- if (thread.metadata[key2] !== query.metadata[key2]) {
361
- return false;
362
- }
363
- }
364
- return true;
365
- });
366
- return {
367
- isLoading: false,
368
- threads: filtered,
369
- error
370
- };
371
- }
372
- );
455
+ }, [manager, key]);
456
+ const cache = _useThreads(room, options);
457
+ return cache;
373
458
  }
374
459
  function useThreadsSuspense(room, options = { query: { metadata: {} } }) {
375
460
  const key = _react.useMemo.call(void 0, () => _core.stringify.call(void 0, options), [options]);
@@ -397,8 +482,29 @@ function createCommentsRoom(errorEventSource) {
397
482
  return () => {
398
483
  manager.decrementReferenceCount(key);
399
484
  };
400
- });
401
- const cache = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
485
+ }, [manager, key]);
486
+ const cache = _useThreads(room, options);
487
+ if (cache.error) {
488
+ throw cache.error;
489
+ }
490
+ if (cache.isLoading || !cache.threads) {
491
+ throw revalidateCache({
492
+ shouldDedupe: true
493
+ });
494
+ }
495
+ return {
496
+ isLoading: false,
497
+ threads: cache.threads,
498
+ error: cache.error
499
+ };
500
+ }
501
+ function _useThreads(room, options) {
502
+ const manager = useRoomManager();
503
+ const useThreadsRevalidationManager = getUseThreadsRevalidationManager(
504
+ options,
505
+ manager
506
+ );
507
+ return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
402
508
  store.subscribe,
403
509
  () => store.getThreads(),
404
510
  () => store.getThreads(),
@@ -415,8 +521,8 @@ function createCommentsRoom(errorEventSource) {
415
521
  if (thread.roomId !== room.id)
416
522
  return false;
417
523
  const query = _nullishCoalesce(options2.query, () => ( {}));
418
- for (const key2 in query.metadata) {
419
- if (thread.metadata[key2] !== query.metadata[key2]) {
524
+ for (const key in query.metadata) {
525
+ if (thread.metadata[key] !== query.metadata[key]) {
420
526
  return false;
421
527
  }
422
528
  }
@@ -429,19 +535,6 @@ function createCommentsRoom(errorEventSource) {
429
535
  };
430
536
  }
431
537
  );
432
- if (cache.error) {
433
- throw cache.error;
434
- }
435
- if (cache.isLoading || !cache.threads) {
436
- throw revalidateCache({
437
- shouldDedupe: true
438
- });
439
- }
440
- return {
441
- isLoading: false,
442
- threads: cache.threads,
443
- error: cache.error
444
- };
445
538
  }
446
539
  function useEditThreadMetadata(room) {
447
540
  const manager = useRoomManager();
@@ -492,8 +585,8 @@ function createCommentsRoom(errorEventSource) {
492
585
  const body = options.body;
493
586
  const metadata = "metadata" in options ? options.metadata : {};
494
587
  const threads = getThreads(manager);
495
- const threadId = createOptimisticId(THREAD_ID_PREFIX);
496
- const commentId = createOptimisticId(COMMENT_ID_PREFIX);
588
+ const threadId = createThreadId();
589
+ const commentId = createCommentId();
497
590
  const now = /* @__PURE__ */ new Date();
498
591
  const newComment = {
499
592
  id: commentId,
@@ -544,7 +637,7 @@ function createCommentsRoom(errorEventSource) {
544
637
  const createComment = _react.useCallback.call(void 0,
545
638
  ({ threadId, body }) => {
546
639
  const threads = getThreads(manager);
547
- const commentId = createOptimisticId(COMMENT_ID_PREFIX);
640
+ const commentId = createCommentId();
548
641
  const now = /* @__PURE__ */ new Date();
549
642
  const comment = {
550
643
  id: commentId,
@@ -821,6 +914,12 @@ function createCommentsRoom(errorEventSource) {
821
914
  function createOptimisticId(prefix) {
822
915
  return `${prefix}_${_nanoid.nanoid.call(void 0, )}`;
823
916
  }
917
+ function createThreadId() {
918
+ return createOptimisticId(THREAD_ID_PREFIX);
919
+ }
920
+ function createCommentId() {
921
+ return createOptimisticId(COMMENT_ID_PREFIX);
922
+ }
824
923
  function getCurrentUserId(room) {
825
924
  const self = room.getSelf();
826
925
  if (self === null || self.id === void 0) {
@@ -897,6 +996,12 @@ function createRoomRevalidationManager(roomId, {
897
996
  setRevalidationmanager(key, manager) {
898
997
  revalidationManagerByOptions.set(key, manager);
899
998
  },
999
+ getTotalReferenceCount() {
1000
+ return Array.from(referenceCountByOptions.values()).reduce(
1001
+ (acc, count) => acc + count,
1002
+ 0
1003
+ );
1004
+ },
900
1005
  incrementReferenceCount(key) {
901
1006
  const count = _nullishCoalesce(referenceCountByOptions.get(key), () => ( 0));
902
1007
  referenceCountByOptions.set(key, count + 1);
@@ -930,7 +1035,6 @@ function createUseThreadsRevalidationManager(options, manager) {
930
1035
  let isLoading = true;
931
1036
  let request;
932
1037
  let error;
933
- const errorEventSource = _core.makeEventSource.call(void 0, );
934
1038
  return {
935
1039
  // Cache
936
1040
  getCache() {
@@ -959,7 +1063,9 @@ function createUseThreadsRevalidationManager(options, manager) {
959
1063
  },
960
1064
  setError(err) {
961
1065
  error = err;
962
- errorEventSource.notify(err);
1066
+ isLoading = false;
1067
+ const cache = manager.getCache();
1068
+ manager.setCache(cache);
963
1069
  },
964
1070
  // Mutation
965
1071
  getMutation() {
@@ -979,6 +1085,13 @@ function createUseThreadsRevalidationManager(options, manager) {
979
1085
  }
980
1086
  };
981
1087
  }
1088
+ function getPollingInterval(isBrowserOnline, isDocumentVisible, isRoomConnected) {
1089
+ if (!isBrowserOnline || !isDocumentVisible)
1090
+ return;
1091
+ if (isRoomConnected)
1092
+ return POLLING_INTERVAL_REALTIME;
1093
+ return POLLING_INTERVAL;
1094
+ }
982
1095
 
983
1096
  // src/comments/lib/use-debounce.ts
984
1097
 
@@ -1006,7 +1119,7 @@ function useDebounce(value, delay = DEFAULT_DELAY) {
1006
1119
 
1007
1120
  // src/lib/use-async-cache.ts
1008
1121
 
1009
- var _indexjs = require('use-sync-external-store/shim/index.js');
1122
+
1010
1123
 
1011
1124
  // src/lib/use-initial.ts
1012
1125
 
@@ -1032,7 +1145,7 @@ function useAsyncCache(cache, key, options) {
1032
1145
  void cacheItem2.get();
1033
1146
  return cacheItem2;
1034
1147
  }, [cache, key]);
1035
- const subscribe = _react.useCallback.call(void 0,
1148
+ const subscribe2 = _react.useCallback.call(void 0,
1036
1149
  (callback) => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _4 => _4.subscribe, 'call', _5 => _5(callback)]), () => ( noop)),
1037
1150
  [cacheItem]
1038
1151
  );
@@ -1041,7 +1154,7 @@ function useAsyncCache(cache, key, options) {
1041
1154
  [cacheItem]
1042
1155
  );
1043
1156
  const revalidate = _react.useCallback.call(void 0, () => _optionalChain([cacheItem, 'optionalAccess', _8 => _8.revalidate, 'call', _9 => _9()]), [cacheItem]);
1044
- const state = _indexjs.useSyncExternalStore.call(void 0, subscribe, getState, getState);
1157
+ const state = _indexjs.useSyncExternalStore.call(void 0, subscribe2, getState, getState);
1045
1158
  const previousData = _react.useRef.call(void 0, );
1046
1159
  let data = state.data;
1047
1160
  _react.useEffect.call(void 0, () => {
@@ -1121,7 +1234,7 @@ var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\
1121
1234
 
1122
1235
  Why? Please see https://liveblocks.io/docs/platform/troubleshooting#stale-props-zombie-child for more information`;
1123
1236
  var superfluous_unstable_batchedUpdates = "You don\u2019t need to pass unstable_batchedUpdates to RoomProvider anymore, since you\u2019re on React 18+ already.";
1124
- function useSyncExternalStore2(s, gs, gss) {
1237
+ function useSyncExternalStore5(s, gs, gss) {
1125
1238
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0, s, gs, gss, identity);
1126
1239
  }
1127
1240
  var STABLE_EMPTY_LIST = Object.freeze([]);
@@ -1270,16 +1383,16 @@ function createRoomContext(client, options) {
1270
1383
  }
1271
1384
  function useStatus() {
1272
1385
  const room = useRoom();
1273
- const subscribe = room.events.status.subscribe;
1274
- const getSnapshot = room.getStatus;
1386
+ const subscribe2 = room.events.status.subscribe;
1387
+ const getSnapshot2 = room.getStatus;
1275
1388
  const getServerSnapshot = room.getStatus;
1276
- return useSyncExternalStore2(subscribe, getSnapshot, getServerSnapshot);
1389
+ return useSyncExternalStore5(subscribe2, getSnapshot2, getServerSnapshot);
1277
1390
  }
1278
1391
  function useMyPresence() {
1279
1392
  const room = useRoom();
1280
- const subscribe = room.events.myPresence.subscribe;
1281
- const getSnapshot = room.getPresence;
1282
- const presence = useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
1393
+ const subscribe2 = room.events.myPresence.subscribe;
1394
+ const getSnapshot2 = room.getPresence;
1395
+ const presence = useSyncExternalStore5(subscribe2, getSnapshot2, getSnapshot2);
1283
1396
  const setPresence = room.updatePresence;
1284
1397
  return [presence, setPresence];
1285
1398
  }
@@ -1288,12 +1401,12 @@ function createRoomContext(client, options) {
1288
1401
  }
1289
1402
  function useOthers(selector, isEqual) {
1290
1403
  const room = useRoom();
1291
- const subscribe = room.events.others.subscribe;
1292
- const getSnapshot = room.getOthers;
1404
+ const subscribe2 = room.events.others.subscribe;
1405
+ const getSnapshot2 = room.getOthers;
1293
1406
  const getServerSnapshot = alwaysEmptyList;
1294
1407
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1295
- subscribe,
1296
- getSnapshot,
1408
+ subscribe2,
1409
+ getSnapshot2,
1297
1410
  getServerSnapshot,
1298
1411
  _nullishCoalesce(selector, () => ( identity)),
1299
1412
  isEqual
@@ -1397,8 +1510,8 @@ function createRoomContext(client, options) {
1397
1510
  }
1398
1511
  function useSelf(maybeSelector, isEqual) {
1399
1512
  const room = useRoom();
1400
- const subscribe = room.events.self.subscribe;
1401
- const getSnapshot = room.getSelf;
1513
+ const subscribe2 = room.events.self.subscribe;
1514
+ const getSnapshot2 = room.getSelf;
1402
1515
  const selector = _nullishCoalesce(maybeSelector, () => ( identity));
1403
1516
  const wrappedSelector = React3.useCallback(
1404
1517
  (me) => me !== null ? selector(me) : null,
@@ -1406,8 +1519,8 @@ function createRoomContext(client, options) {
1406
1519
  );
1407
1520
  const getServerSnapshot = alwaysNull;
1408
1521
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1409
- subscribe,
1410
- getSnapshot,
1522
+ subscribe2,
1523
+ getSnapshot2,
1411
1524
  getServerSnapshot,
1412
1525
  wrappedSelector,
1413
1526
  isEqual
@@ -1415,10 +1528,10 @@ function createRoomContext(client, options) {
1415
1528
  }
1416
1529
  function useMutableStorageRoot() {
1417
1530
  const room = useRoom();
1418
- const subscribe = room.events.storageDidLoad.subscribeOnce;
1419
- const getSnapshot = room.getStorageSnapshot;
1531
+ const subscribe2 = room.events.storageDidLoad.subscribeOnce;
1532
+ const getSnapshot2 = room.getStorageSnapshot;
1420
1533
  const getServerSnapshot = alwaysNull;
1421
- return useSyncExternalStore2(subscribe, getSnapshot, getServerSnapshot);
1534
+ return useSyncExternalStore5(subscribe2, getSnapshot2, getServerSnapshot);
1422
1535
  }
1423
1536
  function useStorageRoot() {
1424
1537
  return [useMutableStorageRoot()];
@@ -1434,15 +1547,15 @@ function createRoomContext(client, options) {
1434
1547
  }
1435
1548
  function useCanUndo() {
1436
1549
  const room = useRoom();
1437
- const subscribe = room.events.history.subscribe;
1550
+ const subscribe2 = room.events.history.subscribe;
1438
1551
  const canUndo = room.history.canUndo;
1439
- return useSyncExternalStore2(subscribe, canUndo, canUndo);
1552
+ return useSyncExternalStore5(subscribe2, canUndo, canUndo);
1440
1553
  }
1441
1554
  function useCanRedo() {
1442
1555
  const room = useRoom();
1443
- const subscribe = room.events.history.subscribe;
1556
+ const subscribe2 = room.events.history.subscribe;
1444
1557
  const canRedo = room.history.canRedo;
1445
- return useSyncExternalStore2(subscribe, canRedo, canRedo);
1558
+ return useSyncExternalStore5(subscribe2, canRedo, canRedo);
1446
1559
  }
1447
1560
  function useBatch() {
1448
1561
  return useRoom().batch;
@@ -1491,11 +1604,11 @@ function createRoomContext(client, options) {
1491
1604
  (rootOrNull2) => rootOrNull2 !== null ? selector(rootOrNull2) : null,
1492
1605
  [selector]
1493
1606
  );
1494
- const subscribe = React3.useCallback(
1607
+ const subscribe2 = React3.useCallback(
1495
1608
  (onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop2,
1496
1609
  [room, rootOrNull]
1497
1610
  );
1498
- const getSnapshot = React3.useCallback(() => {
1611
+ const getSnapshot2 = React3.useCallback(() => {
1499
1612
  if (rootOrNull === null) {
1500
1613
  return null;
1501
1614
  } else {
@@ -1506,8 +1619,8 @@ function createRoomContext(client, options) {
1506
1619
  }, [rootOrNull]);
1507
1620
  const getServerSnapshot = alwaysNull;
1508
1621
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1509
- subscribe,
1510
- getSnapshot,
1622
+ subscribe2,
1623
+ getSnapshot2,
1511
1624
  getServerSnapshot,
1512
1625
  wrappedSelector,
1513
1626
  isEqual