@liveblocks/react 0.18.0-beta3 → 0.18.0

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.
@@ -1 +1 @@
1
- ee7b9e79d3549611f64024b4247e9a862cfddd34
1
+ ab4dc80c03188cfbc87c124cad9c824347a785b0
package/index.d.ts CHANGED
@@ -39,7 +39,7 @@ declare type RoomProviderProps<TPresence extends JsonObject, TStorage extends Ls
39
39
  */
40
40
  declare type OmitFirstArg<F> = F extends (first: any, ...rest: infer A) => infer R ? (...args: A) => R : never;
41
41
  declare type MutationContext<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta> = {
42
- root: LiveObject<TStorage>;
42
+ storage: LiveObject<TStorage>;
43
43
  self: User<TPresence, TUserMeta>;
44
44
  others: Others<TPresence, TUserMeta>;
45
45
  setMyPresence: (patch: Partial<TPresence>, options?: {
@@ -166,13 +166,6 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
166
166
  * const [root] = useStorageRoot();
167
167
  */
168
168
  useStorageRoot(): [root: LiveObject<TStorage> | null];
169
- /**
170
- * Returns your entire Liveblocks Storage as an immutable data structure.
171
- *
172
- * @example
173
- * const root = useStorage();
174
- */
175
- useStorage(): ToImmutable<TStorage> | null;
176
169
  /**
177
170
  * Extract arbitrary data from the Liveblocks Storage state, using an
178
171
  * arbitrary selector function.
@@ -192,7 +185,7 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
192
185
  * return the result of a .map() or .filter() call from the selector. In
193
186
  * those cases, you'll probably want to use a `shallow` comparison check.
194
187
  */
195
- useStorage<T>(selector: (root: ToImmutable<TStorage>) => T, isEqual?: (prev: T, curr: T) => boolean): T | null;
188
+ useStorage<T>(selector: (root: ToImmutable<TStorage>) => T, isEqual?: (prev: T | null, curr: T | null) => boolean): T | null;
196
189
  /**
197
190
  * Gets the current user once it is connected to the room.
198
191
  *
@@ -296,10 +289,10 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
296
289
  * for each user in the room, e.g. cursors.
297
290
  *
298
291
  * @example
299
- * const ids = useConnectionIds();
292
+ * const ids = useOthersConnectionIds();
300
293
  * // [2, 4, 7]
301
294
  */
302
- useConnectionIds(): readonly number[];
295
+ useOthersConnectionIds(): readonly number[];
303
296
  /**
304
297
  * Related to useOthers(), but optimized for selecting only "subsets" of
305
298
  * others. This is useful for performance reasons in particular, because
@@ -307,11 +300,11 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
307
300
  * re-renders that will be triggered.
308
301
  *
309
302
  * @example
310
- * const avatars = useOthersWithData(user => user.info.avatar);
303
+ * const avatars = useOthersMapped(user => user.info.avatar);
311
304
  * // ^^^^^^^
312
305
  * // { connectionId: number; data: string }[]
313
306
  *
314
- * The selector function you pass to useOthersWithData() is called an "item
307
+ * The selector function you pass to useOthersMapped() is called an "item
315
308
  * selector", and operates on a single user at a time. If you provide an
316
309
  * (optional) "item comparison" function, it will be used to compare each
317
310
  * item pairwise.
@@ -319,17 +312,14 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
319
312
  * For example, to select multiple properties:
320
313
  *
321
314
  * @example
322
- * const avatarsAndCursors = useOthersWithData(
315
+ * const avatarsAndCursors = useOthersMapped(
323
316
  * user => [u.info.avatar, u.presence.cursor],
324
317
  * shallow, // 👈
325
318
  * );
326
319
  */
327
- useOthersWithData<T>(itemSelector: (other: User<TPresence, TUserMeta>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): readonly {
328
- readonly connectionId: number;
329
- readonly data: T;
330
- }[];
320
+ useOthersMapped<T>(itemSelector: (other: User<TPresence, TUserMeta>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): ReadonlyArray<readonly [connectionId: number, data: T]>;
331
321
  /**
332
- * Given a connection ID (as obtained by using `useConnectionIds()`), you can
322
+ * Given a connection ID (as obtained by using `useOthersConnectionIds`), you can
333
323
  * call this selector deep down in your component stack to only have the
334
324
  * component re-render if properties for this particular user change.
335
325
  *
@@ -339,8 +329,8 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
339
329
  */
340
330
  useOther(connectionId: number): User<TPresence, TUserMeta>;
341
331
  /**
342
- * Given a connection ID (as obtained by using `useConnectionIds()`), you can
343
- * call this selector deep down in your component stack to only have the
332
+ * Given a connection ID (as obtained by using `useOthersConnectionIds`), you
333
+ * can call this selector deep down in your component stack to only have the
344
334
  * component re-render if properties for this particular user change.
345
335
  *
346
336
  * @example
@@ -363,7 +353,7 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
363
353
  addToHistory: boolean;
364
354
  }) => void;
365
355
  /**
366
- * Create a callback function that can be called to mutate Liveblocks state.
356
+ * Create a callback function that lets you mutate Liveblocks state.
367
357
  *
368
358
  * The first argument that gets passed into your callback will be a "mutation
369
359
  * context", which exposes the following:
@@ -493,13 +483,6 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
493
483
  * const [root] = useStorageRoot();
494
484
  */
495
485
  useStorageRoot(): [root: LiveObject<TStorage> | null];
496
- /**
497
- * Returns your entire Liveblocks Storage as an immutable data structure.
498
- *
499
- * @example
500
- * const root = useStorage();
501
- */
502
- useStorage(): ToImmutable<TStorage>;
503
486
  /**
504
487
  * Extract arbitrary data from the Liveblocks Storage state, using an
505
488
  * arbitrary selector function.
@@ -623,10 +606,10 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
623
606
  * for each user in the room, e.g. cursors.
624
607
  *
625
608
  * @example
626
- * const ids = useConnectionIds();
609
+ * const ids = useOthersConnectionIds();
627
610
  * // [2, 4, 7]
628
611
  */
629
- useConnectionIds(): readonly number[];
612
+ useOthersConnectionIds(): readonly number[];
630
613
  /**
631
614
  * Related to useOthers(), but optimized for selecting only "subsets" of
632
615
  * others. This is useful for performance reasons in particular, because
@@ -634,11 +617,11 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
634
617
  * re-renders that will be triggered.
635
618
  *
636
619
  * @example
637
- * const avatars = useOthersWithData(user => user.info.avatar);
620
+ * const avatars = useOthersMapped(user => user.info.avatar);
638
621
  * // ^^^^^^^
639
622
  * // { connectionId: number; data: string }[]
640
623
  *
641
- * The selector function you pass to useOthersWithData() is called an "item
624
+ * The selector function you pass to useOthersMapped() is called an "item
642
625
  * selector", and operates on a single user at a time. If you provide an
643
626
  * (optional) "item comparison" function, it will be used to compare each
644
627
  * item pairwise.
@@ -646,19 +629,17 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
646
629
  * For example, to select multiple properties:
647
630
  *
648
631
  * @example
649
- * const avatarsAndCursors = useOthersWithData(
632
+ * const avatarsAndCursors = useOthersMapped(
650
633
  * user => [u.info.avatar, u.presence.cursor],
651
634
  * shallow, // 👈
652
635
  * );
653
636
  */
654
- useOthersWithData<T>(itemSelector: (other: User<TPresence, TUserMeta>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): readonly {
655
- readonly connectionId: number;
656
- readonly data: T;
657
- }[];
637
+ useOthersMapped<T>(itemSelector: (other: User<TPresence, TUserMeta>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): ReadonlyArray<readonly [connectionId: number, data: T]>;
658
638
  /**
659
- * Given a connection ID (as obtained by using `useConnectionIds()`), you
660
- * can call this selector deep down in your component stack to only have
661
- * the component re-render if properties for this particular user change.
639
+ * Given a connection ID (as obtained by using `useOthersConnectionIds`),
640
+ * you can call this selector deep down in your component stack to only
641
+ * have the component re-render if properties for this particular user
642
+ * change.
662
643
  *
663
644
  * @example
664
645
  * // Returns full user and re-renders whenever anything on the user changes
@@ -666,9 +647,10 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
666
647
  */
667
648
  useOther(connectionId: number): User<TPresence, TUserMeta>;
668
649
  /**
669
- * Given a connection ID (as obtained by using `useConnectionIds()`), you
670
- * can call this selector deep down in your component stack to only have
671
- * the component re-render if properties for this particular user change.
650
+ * Given a connection ID (as obtained by using `useOthersConnectionIds`),
651
+ * you can call this selector deep down in your component stack to only
652
+ * have the component re-render if properties for this particular user
653
+ * change.
672
654
  *
673
655
  * @example
674
656
  * // Returns only the selected values re-renders whenever that selection changes)
@@ -690,8 +672,7 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
690
672
  addToHistory: boolean;
691
673
  }) => void;
692
674
  /**
693
- * Create a callback function that can be called to mutate Liveblocks
694
- * state.
675
+ * Create a callback function that lets you mutate Liveblocks state.
695
676
  *
696
677
  * The first argument that gets passed into your callback will be
697
678
  * a "mutation context", which exposes the following:
package/index.js CHANGED
@@ -43,12 +43,12 @@ function getEmptyOthers() {
43
43
  function makeMutationContext(room) {
44
44
  const errmsg = "This mutation cannot be used until connected to the Liveblocks room";
45
45
  return {
46
- get root() {
47
- const root = room.getStorageSnapshot();
48
- if (root === null) {
46
+ get storage() {
47
+ const mutableRoot = room.getStorageSnapshot();
48
+ if (mutableRoot === null) {
49
49
  throw new Error(errmsg);
50
50
  }
51
- return root;
51
+ return mutableRoot;
52
52
  },
53
53
  get self() {
54
54
  const self = room.getSelf();
@@ -142,15 +142,14 @@ function createRoomContext(client) {
142
142
  isEqual
143
143
  );
144
144
  }
145
- function useConnectionIds() {
145
+ function useOthersConnectionIds() {
146
146
  return useOthers(connectionIdSelector, _client.shallow);
147
147
  }
148
- function useOthersWithData(itemSelector, itemIsEqual) {
148
+ function useOthersMapped(itemSelector, itemIsEqual) {
149
149
  const wrappedSelector = React2.useCallback(
150
- (others) => others.map((other) => ({
151
- connectionId: other.connectionId,
152
- data: itemSelector(other)
153
- })),
150
+ (others) => others.map(
151
+ (other) => [other.connectionId, itemSelector(other)]
152
+ ),
154
153
  [itemSelector]
155
154
  );
156
155
  const wrappedIsEqual = React2.useCallback(
@@ -158,7 +157,7 @@ function createRoomContext(client) {
158
157
  const eq = itemIsEqual != null ? itemIsEqual : Object.is;
159
158
  return a.length === b.length && a.every((atuple, index) => {
160
159
  const btuple = b[index];
161
- return atuple.connectionId === btuple.connectionId && eq(atuple.data, btuple.data);
160
+ return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);
162
161
  });
163
162
  },
164
163
  [itemIsEqual]
@@ -346,10 +345,9 @@ function createRoomContext(client) {
346
345
  return root.get(key);
347
346
  }
348
347
  }
349
- function useStorage(maybeSelector, isEqual) {
348
+ function useStorage(selector, isEqual) {
350
349
  const room = useRoom();
351
350
  const rootOrNull = useMutableStorageRoot();
352
- const selector = maybeSelector != null ? maybeSelector : identity;
353
351
  const wrappedSelector = React2.useCallback(
354
352
  (rootOrNull2) => rootOrNull2 !== null ? selector(rootOrNull2) : null,
355
353
  [selector]
@@ -379,7 +377,7 @@ function createRoomContext(client) {
379
377
  function ensureNotServerSide() {
380
378
  if (typeof window === "undefined") {
381
379
  throw new Error(
382
- "You cannot call the Suspense version of this hook on the server side. Make sure to only call them on the client side.\nFor tips for structuring your app, see XXX"
380
+ "You cannot use the Suspense version of this hook on the server side. Make sure to only call them on the client side.\nFor tips, see https://liveblocks.io/docs/api-reference/liveblocks-react#suspense-avoid-ssr"
383
381
  );
384
382
  }
385
383
  }
@@ -435,9 +433,13 @@ function createRoomContext(client) {
435
433
  isEqual
436
434
  );
437
435
  }
438
- function useOthersWithDataSuspense(itemSelector, itemIsEqual) {
436
+ function useOthersConnectionIdsSuspense() {
437
+ useSuspendUntilPresenceLoaded();
438
+ return useOthersConnectionIds();
439
+ }
440
+ function useOthersMappedSuspense(itemSelector, itemIsEqual) {
439
441
  useSuspendUntilPresenceLoaded();
440
- return useOthersWithData(itemSelector, itemIsEqual);
442
+ return useOthersMapped(itemSelector, itemIsEqual);
441
443
  }
442
444
  function useOtherSuspense(connectionId, selector, isEqual) {
443
445
  useSuspendUntilPresenceLoaded();
@@ -473,8 +475,8 @@ function createRoomContext(client) {
473
475
  useMyPresence,
474
476
  useUpdateMyPresence,
475
477
  useOthers,
476
- useOthersWithData,
477
- useConnectionIds,
478
+ useOthersMapped,
479
+ useOthersConnectionIds,
478
480
  useOther,
479
481
  useMutation,
480
482
  suspense: {
@@ -499,8 +501,8 @@ function createRoomContext(client) {
499
501
  useMyPresence,
500
502
  useUpdateMyPresence,
501
503
  useOthers: useOthersSuspense,
502
- useOthersWithData: useOthersWithDataSuspense,
503
- useConnectionIds,
504
+ useOthersMapped: useOthersMappedSuspense,
505
+ useOthersConnectionIds: useOthersConnectionIdsSuspense,
504
506
  useOther: useOtherSuspense,
505
507
  useMutation
506
508
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/react",
3
- "version": "0.18.0-beta3",
3
+ "version": "0.18.0",
4
4
  "description": "A set of React hooks and providers to use Liveblocks declaratively.",
5
5
  "main": "./index.js",
6
6
  "module": "./index.mjs",
@@ -27,7 +27,7 @@
27
27
  "use-sync-external-store": "^1.2.0"
28
28
  },
29
29
  "peerDependencies": {
30
- "@liveblocks/client": "0.18.0-beta3",
30
+ "@liveblocks/client": "0.18.0",
31
31
  "react": "^16.14.0 || ^17 || ^18"
32
32
  },
33
33
  "repository": {