@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.d.mts CHANGED
@@ -2,7 +2,7 @@ import * as React$1 from 'react';
2
2
  import { ReactElement, ReactNode } from 'react';
3
3
  import * as _liveblocks_core from '@liveblocks/core';
4
4
  import { CommentBody, BaseMetadata, ThreadData, Resolve, ToImmutable, RoomEventMessage, CommentData, RoomInitializers } from '@liveblocks/core';
5
- import { JsonObject, LsonObject, BaseUserMeta, LiveObject, User, Others, Json, Room, Status, BroadcastOptions, LostConnectionEvent, History, Client } from '@liveblocks/client';
5
+ import { JsonObject, LsonObject, BaseUserMeta, LiveObject, User, Json, Room, Status, BroadcastOptions, OthersEvent, LostConnectionEvent, History, Client } from '@liveblocks/client';
6
6
  export { Json, JsonObject, shallow } from '@liveblocks/client';
7
7
 
8
8
  declare type Props = {
@@ -133,6 +133,8 @@ declare type RoomProviderProps<TPresence extends JsonObject, TStorage extends Ls
133
133
  * meaning the RoomProvider tries to connect to Liveblocks servers
134
134
  * only on the client side.
135
135
  */
136
+ autoConnect?: boolean;
137
+ /** @deprecated Renamed to `autoConnect` */
136
138
  shouldInitiallyConnect?: boolean;
137
139
  /**
138
140
  * If you're on React 17 or lower, pass in a reference to
@@ -158,7 +160,7 @@ declare type OmitFirstArg<F> = F extends (first: any, ...rest: infer A) => infer
158
160
  declare type MutationContext<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta> = {
159
161
  storage: LiveObject<TStorage>;
160
162
  self: User<TPresence, TUserMeta>;
161
- others: Others<TPresence, TUserMeta>;
163
+ others: readonly User<TPresence, TUserMeta>[];
162
164
  setMyPresence: (patch: Partial<TPresence>, options?: {
163
165
  addToHistory: boolean;
164
166
  }) => void;
@@ -202,6 +204,19 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
202
204
  * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
203
205
  */
204
206
  useBroadcastEvent(): (event: TRoomEvent, options?: BroadcastOptions) => void;
207
+ /**
208
+ * Get informed when users enter or leave the room, as an event.
209
+ *
210
+ * @example
211
+ * useOthersListener({ type, user, others }) => {
212
+ * if (type === 'enter') {
213
+ * // `user` has joined the room
214
+ * } else if (type === 'leave') {
215
+ * // `user` has left the room
216
+ * }
217
+ * })
218
+ */
219
+ useOthersListener(callback: (event: OthersEvent<TPresence, TUserMeta>) => void): void;
205
220
  /**
206
221
  * Get informed when reconnecting to the Liveblocks servers is taking
207
222
  * longer than usual. This typically is a sign of a client that has lost
@@ -224,7 +239,8 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
224
239
  */
225
240
  useLostConnectionListener(callback: (event: LostConnectionEvent) => void): void;
226
241
  /**
227
- * useErrorListener is a react hook that lets you react to potential room connection errors.
242
+ * useErrorListener is a React hook that allows you to respond to potential room
243
+ * connection errors.
228
244
  *
229
245
  * @example
230
246
  * useErrorListener(er => {
@@ -233,7 +249,8 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
233
249
  */
234
250
  useErrorListener(callback: (err: Error) => void): void;
235
251
  /**
236
- * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.
252
+ * useEventListener is a React hook that allows you to respond to events broadcast
253
+ * by other users in the room.
237
254
  *
238
255
  * @example
239
256
  * useEventListener(({ connectionId, event }) => {
@@ -369,7 +386,7 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
369
386
  * </>
370
387
  * )
371
388
  */
372
- useOthers(): Others<TPresence, TUserMeta>;
389
+ useOthers(): readonly User<TPresence, TUserMeta>[];
373
390
  /**
374
391
  * Extract arbitrary data based on all the users currently connected in the
375
392
  * room (except yourself).
@@ -391,7 +408,7 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
391
408
  * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));
392
409
  *
393
410
  */
394
- useOthers<T>(selector: (others: Others<TPresence, TUserMeta>) => T, isEqual?: (prev: T, curr: T) => boolean): T;
411
+ useOthers<T>(selector: (others: readonly User<TPresence, TUserMeta>[]) => T, isEqual?: (prev: T, curr: T) => boolean): T;
395
412
  /**
396
413
  * Returns an array of connection IDs. This matches the values you'll get by
397
414
  * using the `useOthers()` hook.
@@ -780,6 +797,7 @@ declare function useRoomContextBundle(): {
780
797
  RoomProvider: (props: {
781
798
  id: string;
782
799
  children: React$1.ReactNode;
800
+ autoConnect?: boolean | undefined;
783
801
  shouldInitiallyConnect?: boolean | undefined;
784
802
  unstable_batchedUpdates?: ((cb: () => void) => void) | undefined;
785
803
  initialPresence: JsonObject | ((roomId: string) => JsonObject);
@@ -789,6 +807,7 @@ declare function useRoomContextBundle(): {
789
807
  useStatus: () => Status;
790
808
  useBatch: <T>() => (callback: () => T) => T;
791
809
  useBroadcastEvent: () => (event: never, options?: BroadcastOptions | undefined) => void;
810
+ useOthersListener: (callback: (event: OthersEvent<JsonObject, BaseUserMeta>) => void) => void;
792
811
  useLostConnectionListener: (callback: (event: LostConnectionEvent) => void) => void;
793
812
  useErrorListener: (callback: (err: Error) => void) => void;
794
813
  useEventListener: (callback: (data: RoomEventMessage<JsonObject, BaseUserMeta, never>) => void) => void;
@@ -806,8 +825,8 @@ declare function useRoomContextBundle(): {
806
825
  } | undefined) => void;
807
826
  useMutation: <F extends (context: MutationContext<JsonObject, LsonObject, BaseUserMeta>, ...args: any[]) => any>(callback: F, deps: readonly unknown[]) => OmitFirstArg<F>;
808
827
  useOthers: {
809
- (): _liveblocks_core.Others<JsonObject, BaseUserMeta>;
810
- <T_1>(selector: (others: _liveblocks_core.Others<JsonObject, BaseUserMeta>) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
828
+ (): readonly User<JsonObject, BaseUserMeta>[];
829
+ <T_1>(selector: (others: readonly User<JsonObject, BaseUserMeta>[]) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
811
830
  };
812
831
  useOthersConnectionIds: () => readonly number[];
813
832
  useOthersMapped: <T_2>(itemSelector: (other: User<JsonObject, BaseUserMeta>) => T_2, itemIsEqual?: ((prev: T_2, curr: T_2) => boolean) | undefined) => readonly (readonly [connectionId: number, data: T_2])[];
@@ -1136,6 +1155,7 @@ declare function useRoomContextBundle(): {
1136
1155
  RoomProvider: (props: {
1137
1156
  id: string;
1138
1157
  children: React$1.ReactNode;
1158
+ autoConnect?: boolean | undefined;
1139
1159
  shouldInitiallyConnect?: boolean | undefined;
1140
1160
  unstable_batchedUpdates?: ((cb: () => void) => void) | undefined;
1141
1161
  initialPresence: JsonObject | ((roomId: string) => JsonObject);
@@ -1145,6 +1165,7 @@ declare function useRoomContextBundle(): {
1145
1165
  useStatus: () => Status;
1146
1166
  useBatch: <T>() => (callback: () => T) => T;
1147
1167
  useBroadcastEvent: () => (event: never, options?: BroadcastOptions | undefined) => void;
1168
+ useOthersListener: (callback: (event: OthersEvent<JsonObject, BaseUserMeta>) => void) => void;
1148
1169
  useLostConnectionListener: (callback: (event: LostConnectionEvent) => void) => void;
1149
1170
  useErrorListener: (callback: (err: Error) => void) => void;
1150
1171
  useEventListener: (callback: (data: RoomEventMessage<JsonObject, BaseUserMeta, never>) => void) => void;
@@ -1162,8 +1183,8 @@ declare function useRoomContextBundle(): {
1162
1183
  } | undefined) => void;
1163
1184
  useMutation: <F extends (context: MutationContext<JsonObject, LsonObject, BaseUserMeta>, ...args: any[]) => any>(callback: F, deps: readonly unknown[]) => OmitFirstArg<F>;
1164
1185
  useOthers: {
1165
- (): _liveblocks_core.Others<JsonObject, BaseUserMeta>;
1166
- <T_1>(selector: (others: _liveblocks_core.Others<JsonObject, BaseUserMeta>) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
1186
+ (): readonly User<JsonObject, BaseUserMeta>[];
1187
+ <T_1>(selector: (others: readonly User<JsonObject, BaseUserMeta>[]) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
1167
1188
  };
1168
1189
  useOthersConnectionIds: () => readonly number[];
1169
1190
  useOthersMapped: <T_2>(itemSelector: (other: User<JsonObject, BaseUserMeta>) => T_2, itemIsEqual?: ((prev: T_2, curr: T_2) => boolean) | undefined) => readonly (readonly [connectionId: number, data: T_2])[];
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as React$1 from 'react';
2
2
  import { ReactElement, ReactNode } from 'react';
3
3
  import * as _liveblocks_core from '@liveblocks/core';
4
4
  import { CommentBody, BaseMetadata, ThreadData, Resolve, ToImmutable, RoomEventMessage, CommentData, RoomInitializers } from '@liveblocks/core';
5
- import { JsonObject, LsonObject, BaseUserMeta, LiveObject, User, Others, Json, Room, Status, BroadcastOptions, LostConnectionEvent, History, Client } from '@liveblocks/client';
5
+ import { JsonObject, LsonObject, BaseUserMeta, LiveObject, User, Json, Room, Status, BroadcastOptions, OthersEvent, LostConnectionEvent, History, Client } from '@liveblocks/client';
6
6
  export { Json, JsonObject, shallow } from '@liveblocks/client';
7
7
 
8
8
  declare type Props = {
@@ -133,6 +133,8 @@ declare type RoomProviderProps<TPresence extends JsonObject, TStorage extends Ls
133
133
  * meaning the RoomProvider tries to connect to Liveblocks servers
134
134
  * only on the client side.
135
135
  */
136
+ autoConnect?: boolean;
137
+ /** @deprecated Renamed to `autoConnect` */
136
138
  shouldInitiallyConnect?: boolean;
137
139
  /**
138
140
  * If you're on React 17 or lower, pass in a reference to
@@ -158,7 +160,7 @@ declare type OmitFirstArg<F> = F extends (first: any, ...rest: infer A) => infer
158
160
  declare type MutationContext<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta> = {
159
161
  storage: LiveObject<TStorage>;
160
162
  self: User<TPresence, TUserMeta>;
161
- others: Others<TPresence, TUserMeta>;
163
+ others: readonly User<TPresence, TUserMeta>[];
162
164
  setMyPresence: (patch: Partial<TPresence>, options?: {
163
165
  addToHistory: boolean;
164
166
  }) => void;
@@ -202,6 +204,19 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
202
204
  * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
203
205
  */
204
206
  useBroadcastEvent(): (event: TRoomEvent, options?: BroadcastOptions) => void;
207
+ /**
208
+ * Get informed when users enter or leave the room, as an event.
209
+ *
210
+ * @example
211
+ * useOthersListener({ type, user, others }) => {
212
+ * if (type === 'enter') {
213
+ * // `user` has joined the room
214
+ * } else if (type === 'leave') {
215
+ * // `user` has left the room
216
+ * }
217
+ * })
218
+ */
219
+ useOthersListener(callback: (event: OthersEvent<TPresence, TUserMeta>) => void): void;
205
220
  /**
206
221
  * Get informed when reconnecting to the Liveblocks servers is taking
207
222
  * longer than usual. This typically is a sign of a client that has lost
@@ -224,7 +239,8 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
224
239
  */
225
240
  useLostConnectionListener(callback: (event: LostConnectionEvent) => void): void;
226
241
  /**
227
- * useErrorListener is a react hook that lets you react to potential room connection errors.
242
+ * useErrorListener is a React hook that allows you to respond to potential room
243
+ * connection errors.
228
244
  *
229
245
  * @example
230
246
  * useErrorListener(er => {
@@ -233,7 +249,8 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
233
249
  */
234
250
  useErrorListener(callback: (err: Error) => void): void;
235
251
  /**
236
- * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.
252
+ * useEventListener is a React hook that allows you to respond to events broadcast
253
+ * by other users in the room.
237
254
  *
238
255
  * @example
239
256
  * useEventListener(({ connectionId, event }) => {
@@ -369,7 +386,7 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
369
386
  * </>
370
387
  * )
371
388
  */
372
- useOthers(): Others<TPresence, TUserMeta>;
389
+ useOthers(): readonly User<TPresence, TUserMeta>[];
373
390
  /**
374
391
  * Extract arbitrary data based on all the users currently connected in the
375
392
  * room (except yourself).
@@ -391,7 +408,7 @@ declare type RoomContextBundleShared<TPresence extends JsonObject, TStorage exte
391
408
  * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));
392
409
  *
393
410
  */
394
- useOthers<T>(selector: (others: Others<TPresence, TUserMeta>) => T, isEqual?: (prev: T, curr: T) => boolean): T;
411
+ useOthers<T>(selector: (others: readonly User<TPresence, TUserMeta>[]) => T, isEqual?: (prev: T, curr: T) => boolean): T;
395
412
  /**
396
413
  * Returns an array of connection IDs. This matches the values you'll get by
397
414
  * using the `useOthers()` hook.
@@ -780,6 +797,7 @@ declare function useRoomContextBundle(): {
780
797
  RoomProvider: (props: {
781
798
  id: string;
782
799
  children: React$1.ReactNode;
800
+ autoConnect?: boolean | undefined;
783
801
  shouldInitiallyConnect?: boolean | undefined;
784
802
  unstable_batchedUpdates?: ((cb: () => void) => void) | undefined;
785
803
  initialPresence: JsonObject | ((roomId: string) => JsonObject);
@@ -789,6 +807,7 @@ declare function useRoomContextBundle(): {
789
807
  useStatus: () => Status;
790
808
  useBatch: <T>() => (callback: () => T) => T;
791
809
  useBroadcastEvent: () => (event: never, options?: BroadcastOptions | undefined) => void;
810
+ useOthersListener: (callback: (event: OthersEvent<JsonObject, BaseUserMeta>) => void) => void;
792
811
  useLostConnectionListener: (callback: (event: LostConnectionEvent) => void) => void;
793
812
  useErrorListener: (callback: (err: Error) => void) => void;
794
813
  useEventListener: (callback: (data: RoomEventMessage<JsonObject, BaseUserMeta, never>) => void) => void;
@@ -806,8 +825,8 @@ declare function useRoomContextBundle(): {
806
825
  } | undefined) => void;
807
826
  useMutation: <F extends (context: MutationContext<JsonObject, LsonObject, BaseUserMeta>, ...args: any[]) => any>(callback: F, deps: readonly unknown[]) => OmitFirstArg<F>;
808
827
  useOthers: {
809
- (): _liveblocks_core.Others<JsonObject, BaseUserMeta>;
810
- <T_1>(selector: (others: _liveblocks_core.Others<JsonObject, BaseUserMeta>) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
828
+ (): readonly User<JsonObject, BaseUserMeta>[];
829
+ <T_1>(selector: (others: readonly User<JsonObject, BaseUserMeta>[]) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
811
830
  };
812
831
  useOthersConnectionIds: () => readonly number[];
813
832
  useOthersMapped: <T_2>(itemSelector: (other: User<JsonObject, BaseUserMeta>) => T_2, itemIsEqual?: ((prev: T_2, curr: T_2) => boolean) | undefined) => readonly (readonly [connectionId: number, data: T_2])[];
@@ -1136,6 +1155,7 @@ declare function useRoomContextBundle(): {
1136
1155
  RoomProvider: (props: {
1137
1156
  id: string;
1138
1157
  children: React$1.ReactNode;
1158
+ autoConnect?: boolean | undefined;
1139
1159
  shouldInitiallyConnect?: boolean | undefined;
1140
1160
  unstable_batchedUpdates?: ((cb: () => void) => void) | undefined;
1141
1161
  initialPresence: JsonObject | ((roomId: string) => JsonObject);
@@ -1145,6 +1165,7 @@ declare function useRoomContextBundle(): {
1145
1165
  useStatus: () => Status;
1146
1166
  useBatch: <T>() => (callback: () => T) => T;
1147
1167
  useBroadcastEvent: () => (event: never, options?: BroadcastOptions | undefined) => void;
1168
+ useOthersListener: (callback: (event: OthersEvent<JsonObject, BaseUserMeta>) => void) => void;
1148
1169
  useLostConnectionListener: (callback: (event: LostConnectionEvent) => void) => void;
1149
1170
  useErrorListener: (callback: (err: Error) => void) => void;
1150
1171
  useEventListener: (callback: (data: RoomEventMessage<JsonObject, BaseUserMeta, never>) => void) => void;
@@ -1162,8 +1183,8 @@ declare function useRoomContextBundle(): {
1162
1183
  } | undefined) => void;
1163
1184
  useMutation: <F extends (context: MutationContext<JsonObject, LsonObject, BaseUserMeta>, ...args: any[]) => any>(callback: F, deps: readonly unknown[]) => OmitFirstArg<F>;
1164
1185
  useOthers: {
1165
- (): _liveblocks_core.Others<JsonObject, BaseUserMeta>;
1166
- <T_1>(selector: (others: _liveblocks_core.Others<JsonObject, BaseUserMeta>) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
1186
+ (): readonly User<JsonObject, BaseUserMeta>[];
1187
+ <T_1>(selector: (others: readonly User<JsonObject, BaseUserMeta>[]) => T_1, isEqual?: ((prev: T_1, curr: T_1) => boolean) | undefined): T_1;
1167
1188
  };
1168
1189
  useOthersConnectionIds: () => readonly number[];
1169
1190
  useOthersMapped: <T_2>(itemSelector: (other: User<JsonObject, BaseUserMeta>) => T_2, itemIsEqual?: ((prev: T_2, curr: T_2) => boolean) | undefined) => readonly (readonly [connectionId: number, data: T_2])[];
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.8";
8
+ var PKG_VERSION = "1.5.0-subdoc";
9
9
  var PKG_FORMAT = "cjs";
10
10
 
11
11
  // src/ClientSideSuspense.tsx
@@ -634,7 +634,7 @@ function useDebounce(value, delay = DEFAULT_DELAY) {
634
634
  // src/lib/use-initial.ts
635
635
 
636
636
  function useInitial(value) {
637
- return _react.useRef.call(void 0, value).current;
637
+ return _react.useState.call(void 0, value)[0];
638
638
  }
639
639
 
640
640
  // src/lib/use-async-cache.ts
@@ -705,6 +705,16 @@ function useAsyncCache(cache, key, options) {
705
705
  };
706
706
  }
707
707
 
708
+ // src/lib/use-latest.ts
709
+
710
+ function useLatest(value) {
711
+ const ref = _react.useRef.call(void 0, value);
712
+ _react.useEffect.call(void 0, () => {
713
+ ref.current = value;
714
+ }, [value]);
715
+ return ref;
716
+ }
717
+
708
718
  // src/lib/use-rerender.ts
709
719
 
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 _withselectorjs.useSyncExternalStoreWithSelector.call(void 0, 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: _nullishCoalesce(_nullishCoalesce(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,