@liveblocks/react 1.4.8 → 1.5.0-subdoc

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.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.4.8";
8
+ var PKG_VERSION = "1.5.0-subdoc";
9
9
  var PKG_FORMAT = "esm";
10
10
 
11
11
  // src/ClientSideSuspense.tsx
@@ -628,13 +628,13 @@ function useDebounce(value, delay = DEFAULT_DELAY) {
628
628
  }
629
629
 
630
630
  // src/lib/use-async-cache.ts
631
- import { useCallback, useEffect as useEffect4, useMemo, useRef as useRef3 } from "react";
631
+ import { useCallback, useEffect as useEffect4, useMemo, useRef as useRef2 } from "react";
632
632
  import { useSyncExternalStore as useSyncExternalStore2 } from "use-sync-external-store/shim/index.js";
633
633
 
634
634
  // src/lib/use-initial.ts
635
- import { useRef as useRef2 } from "react";
635
+ import { useState as useState3 } from "react";
636
636
  function useInitial(value) {
637
- return useRef2(value).current;
637
+ return useState3(value)[0];
638
638
  }
639
639
 
640
640
  // src/lib/use-async-cache.ts
@@ -665,7 +665,7 @@ function useAsyncCache(cache, key, options) {
665
665
  );
666
666
  const revalidate = useCallback(() => cacheItem?.revalidate(), [cacheItem]);
667
667
  const state = useSyncExternalStore2(subscribe, getState, getState);
668
- const previousData = useRef3();
668
+ const previousData = useRef2();
669
669
  let data = state.data;
670
670
  useEffect4(() => {
671
671
  previousData.current = { key, data: state.data };
@@ -705,6 +705,16 @@ function useAsyncCache(cache, key, options) {
705
705
  };
706
706
  }
707
707
 
708
+ // src/lib/use-latest.ts
709
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
710
+ function useLatest(value) {
711
+ const ref = useRef3(value);
712
+ useEffect5(() => {
713
+ ref.current = value;
714
+ }, [value]);
715
+ return ref;
716
+ }
717
+
708
718
  // src/lib/use-rerender.ts
709
719
  import { useReducer } from "react";
710
720
  function useRerender() {
@@ -732,7 +742,7 @@ var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\
732
742
  ...
733
743
  </RoomProvider>
734
744
 
735
- Why? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;
745
+ Why? Please see https://liveblocks.io/docs/platform/troubleshooting#stale-props-zombie-child for more information`;
736
746
  var superfluous_unstable_batchedUpdates = "You don\u2019t need to pass unstable_batchedUpdates to RoomProvider anymore, since you\u2019re on React 18+ already.";
737
747
  function useSyncExternalStore3(s, gs, gss) {
738
748
  return useSyncExternalStoreWithSelector(s, gs, gss, identity);
@@ -744,9 +754,6 @@ function alwaysEmptyList() {
744
754
  function alwaysNull() {
745
755
  return null;
746
756
  }
747
- function alwaysConnecting() {
748
- return "connecting";
749
- }
750
757
  function makeMutationContext(room) {
751
758
  const errmsg = "This mutation cannot be used until connected to the Liveblocks room";
752
759
  return {
@@ -802,14 +809,33 @@ function useRoomContextBundle() {
802
809
  }
803
810
  function createRoomContext(client, options) {
804
811
  const RoomContext = React2.createContext(null);
805
- function RoomProvider(props) {
806
- const {
807
- id: roomId,
808
- initialPresence,
809
- initialStorage,
810
- unstable_batchedUpdates,
811
- shouldInitiallyConnect
812
- } = props;
812
+ function RoomProviderOuter(props) {
813
+ const [cache] = React2.useState(
814
+ () => /* @__PURE__ */ new Map()
815
+ );
816
+ const stableEnterRoom = React2.useCallback(
817
+ (roomId, options2) => {
818
+ const cached = cache.get(roomId);
819
+ if (cached)
820
+ return cached;
821
+ const rv = client.enterRoom(
822
+ roomId,
823
+ options2
824
+ );
825
+ const origLeave = rv.leave;
826
+ rv.leave = () => {
827
+ origLeave();
828
+ cache.delete(roomId);
829
+ };
830
+ cache.set(roomId, rv);
831
+ return rv;
832
+ },
833
+ [cache]
834
+ );
835
+ return /* @__PURE__ */ React2.createElement(RoomProviderInner, { ...props, stableEnterRoom });
836
+ }
837
+ function RoomProviderInner(props) {
838
+ const { id: roomId, stableEnterRoom } = props;
813
839
  if (process.env.NODE_ENV !== "production") {
814
840
  if (!roomId) {
815
841
  throw new Error(
@@ -830,39 +856,34 @@ function createRoomContext(client, options) {
830
856
  superfluous_unstable_batchedUpdates
831
857
  );
832
858
  }
833
- const frozen = useInitial({
834
- initialPresence,
835
- initialStorage,
836
- unstable_batchedUpdates,
837
- shouldInitiallyConnect: shouldInitiallyConnect === void 0 ? typeof window !== "undefined" : shouldInitiallyConnect
859
+ const frozenProps = useInitial({
860
+ initialPresence: props.initialPresence,
861
+ initialStorage: props.initialStorage,
862
+ unstable_batchedUpdates: props.unstable_batchedUpdates,
863
+ autoConnect: props.autoConnect ?? props.shouldInitiallyConnect ?? typeof window !== "undefined"
838
864
  });
839
- const [room, setRoom] = React2.useState(
840
- () => client.enter(roomId, {
841
- initialPresence: frozen.initialPresence,
842
- initialStorage: frozen.initialStorage,
843
- shouldInitiallyConnect: frozen.shouldInitiallyConnect,
844
- unstable_batchedUpdates: frozen.unstable_batchedUpdates
865
+ const [{ room }, setRoomLeavePair] = React2.useState(
866
+ () => stableEnterRoom(roomId, {
867
+ ...frozenProps,
868
+ autoConnect: false
869
+ // Deliberately using false here on the first render, see below
845
870
  })
846
871
  );
847
872
  React2.useEffect(() => {
848
- const room2 = client.enter(
849
- roomId,
850
- {
851
- initialPresence: frozen.initialPresence,
852
- initialStorage: frozen.initialStorage,
853
- shouldInitiallyConnect: frozen.shouldInitiallyConnect,
854
- unstable_batchedUpdates: frozen.unstable_batchedUpdates
855
- }
856
- );
857
- setRoom(room2);
873
+ const pair = stableEnterRoom(roomId, frozenProps);
874
+ setRoomLeavePair(pair);
875
+ const { room: room2, leave } = pair;
876
+ if (frozenProps.autoConnect) {
877
+ room2.connect();
878
+ }
858
879
  return () => {
859
880
  const commentsRoom = commentsRooms.get(room2);
860
881
  if (commentsRoom) {
861
882
  commentsRooms.delete(room2);
862
883
  }
863
- client.leave(roomId);
884
+ leave();
864
885
  };
865
- }, [roomId, frozen]);
886
+ }, [roomId, frozenProps, stableEnterRoom]);
866
887
  return /* @__PURE__ */ React2.createElement(RoomContext.Provider, { value: room }, /* @__PURE__ */ React2.createElement(
867
888
  ContextBundle.Provider,
868
889
  {
@@ -885,7 +906,7 @@ function createRoomContext(client, options) {
885
906
  const room = useRoom();
886
907
  const subscribe = room.events.status.subscribe;
887
908
  const getSnapshot = room.getStatus;
888
- const getServerSnapshot = alwaysConnecting;
909
+ const getServerSnapshot = room.getStatus;
889
910
  return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot);
890
911
  }
891
912
  function useMyPresence() {
@@ -972,42 +993,41 @@ function createRoomContext(client, options) {
972
993
  [room]
973
994
  );
974
995
  }
996
+ function useOthersListener(callback) {
997
+ const room = useRoom();
998
+ const savedCallback = useLatest(callback);
999
+ React2.useEffect(
1000
+ () => room.events.others.subscribe((event) => savedCallback.current(event)),
1001
+ [room, savedCallback]
1002
+ );
1003
+ }
975
1004
  function useLostConnectionListener(callback) {
976
1005
  const room = useRoom();
977
- const savedCallback = React2.useRef(callback);
978
- React2.useEffect(() => {
979
- savedCallback.current = callback;
980
- });
1006
+ const savedCallback = useLatest(callback);
981
1007
  React2.useEffect(
982
1008
  () => room.events.lostConnection.subscribe(
983
1009
  (event) => savedCallback.current(event)
984
1010
  ),
985
- [room]
1011
+ [room, savedCallback]
986
1012
  );
987
1013
  }
988
1014
  function useErrorListener(callback) {
989
1015
  const room = useRoom();
990
- const savedCallback = React2.useRef(callback);
991
- React2.useEffect(() => {
992
- savedCallback.current = callback;
993
- });
1016
+ const savedCallback = useLatest(callback);
994
1017
  React2.useEffect(
995
1018
  () => room.events.error.subscribe((e) => savedCallback.current(e)),
996
- [room]
1019
+ [room, savedCallback]
997
1020
  );
998
1021
  }
999
1022
  function useEventListener(callback) {
1000
1023
  const room = useRoom();
1001
- const savedCallback = React2.useRef(callback);
1002
- React2.useEffect(() => {
1003
- savedCallback.current = callback;
1004
- });
1024
+ const savedCallback = useLatest(callback);
1005
1025
  React2.useEffect(() => {
1006
1026
  const listener = (eventData) => {
1007
1027
  savedCallback.current(eventData);
1008
1028
  };
1009
1029
  return room.events.customEvent.subscribe(listener);
1010
- }, [room]);
1030
+ }, [room, savedCallback]);
1011
1031
  }
1012
1032
  function useSelf(maybeSelector, isEqual) {
1013
1033
  const room = useRoom();
@@ -1370,11 +1390,12 @@ function createRoomContext(client, options) {
1370
1390
  }
1371
1391
  const bundle = {
1372
1392
  RoomContext,
1373
- RoomProvider,
1393
+ RoomProvider: RoomProviderOuter,
1374
1394
  useRoom,
1375
1395
  useStatus,
1376
1396
  useBatch,
1377
1397
  useBroadcastEvent,
1398
+ useOthersListener,
1378
1399
  useLostConnectionListener,
1379
1400
  useErrorListener,
1380
1401
  useEventListener,
@@ -1408,11 +1429,12 @@ function createRoomContext(client, options) {
1408
1429
  useRemoveReaction,
1409
1430
  suspense: {
1410
1431
  RoomContext,
1411
- RoomProvider,
1432
+ RoomProvider: RoomProviderOuter,
1412
1433
  useRoom,
1413
1434
  useStatus,
1414
1435
  useBatch,
1415
1436
  useBroadcastEvent,
1437
+ useOthersListener,
1416
1438
  useLostConnectionListener,
1417
1439
  useErrorListener,
1418
1440
  useEventListener,