@liveblocks/react 0.16.2 → 0.16.4-beta2

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/index.d.ts CHANGED
@@ -16,7 +16,7 @@ declare function LiveblocksProvider(props: LiveblocksProviderProps): JSX.Element
16
16
  */
17
17
  declare function useClient(): Client;
18
18
 
19
- declare type RoomProviderProps<TStorageRoot> = {
19
+ declare type RoomProviderProps<TStorage> = {
20
20
  /**
21
21
  * The id of the room you want to connect to
22
22
  */
@@ -26,7 +26,7 @@ declare type RoomProviderProps<TStorageRoot> = {
26
26
  * If ommited, the default presence will be an empty object
27
27
  */
28
28
  defaultPresence?: () => Presence;
29
- defaultStorageRoot?: TStorageRoot;
29
+ defaultStorageRoot?: TStorage;
30
30
  children: React.ReactNode;
31
31
  };
32
32
  /**
@@ -34,7 +34,7 @@ declare type RoomProviderProps<TStorageRoot> = {
34
34
  * When this component is unmounted, the current user leave the room.
35
35
  * That means that you can't have 2 RoomProvider with the same room id in your react tree.
36
36
  */
37
- declare function RoomProvider<TStorageRoot>({ id, children, defaultPresence, defaultStorageRoot, }: RoomProviderProps<TStorageRoot>): JSX.Element;
37
+ declare function RoomProvider<TStorage>(props: RoomProviderProps<TStorage>): JSX.Element;
38
38
  /**
39
39
  * Returns the Room of the nearest RoomProvider above in the React component
40
40
  * tree.
@@ -142,8 +142,8 @@ declare function useEventListener<TEvent extends Json>(callback: ({ connectionId
142
142
  * const user = useSelf();
143
143
  */
144
144
  declare function useSelf<TPresence extends Presence = Presence>(): User<TPresence> | null;
145
- declare function useStorage<TRoot extends Record<string, any>>(): [
146
- root: LiveObject<TRoot> | null
145
+ declare function useStorage<TStorage extends Record<string, any>>(): [
146
+ root: LiveObject<TStorage> | null
147
147
  ];
148
148
  /**
149
149
  * Returns the LiveMap associated with the provided key. If the LiveMap does not exist, a new empty LiveMap will be created.
package/index.js CHANGED
@@ -87,18 +87,17 @@ function useRerender() {
87
87
  }
88
88
 
89
89
  var RoomContext = React__namespace.createContext(null);
90
- function RoomProvider(_ref) {
91
- var id = _ref.id,
92
- children = _ref.children,
93
- defaultPresence = _ref.defaultPresence,
94
- defaultStorageRoot = _ref.defaultStorageRoot;
90
+ function RoomProvider(props) {
91
+ var roomId = props.id,
92
+ defaultPresence = props.defaultPresence,
93
+ defaultStorageRoot = props.defaultStorageRoot;
95
94
 
96
95
  if (process.env.NODE_ENV !== "production") {
97
- if (id == null) {
96
+ if (roomId == null) {
98
97
  throw new Error("RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required");
99
98
  }
100
99
 
101
- if (typeof id !== "string") {
100
+ if (typeof roomId !== "string") {
102
101
  throw new Error("RoomProvider id property should be a string.");
103
102
  }
104
103
  }
@@ -106,7 +105,7 @@ function RoomProvider(_ref) {
106
105
  var client = useClient();
107
106
 
108
107
  var _React$useState = React__namespace.useState(function () {
109
- return client.enter(id, {
108
+ return client.enter(roomId, {
110
109
  defaultPresence: defaultPresence ? defaultPresence() : undefined,
111
110
  defaultStorageRoot: defaultStorageRoot,
112
111
  DO_NOT_USE_withoutConnecting: typeof window === "undefined"
@@ -116,18 +115,18 @@ function RoomProvider(_ref) {
116
115
  setRoom = _React$useState[1];
117
116
 
118
117
  React__namespace.useEffect(function () {
119
- setRoom(client.enter(id, {
118
+ setRoom(client.enter(roomId, {
120
119
  defaultPresence: defaultPresence ? defaultPresence() : undefined,
121
120
  defaultStorageRoot: defaultStorageRoot,
122
121
  DO_NOT_USE_withoutConnecting: typeof window === "undefined"
123
122
  }));
124
123
  return function () {
125
- client.leave(id);
124
+ client.leave(roomId);
126
125
  };
127
- }, [client, id]);
126
+ }, [client, roomId]);
128
127
  return React__namespace.createElement(RoomContext.Provider, {
129
128
  value: room
130
- }, children);
129
+ }, props.children);
131
130
  }
132
131
  function useRoom() {
133
132
  var room = React__namespace.useContext(RoomContext);
package/index.mjs ADDED
@@ -0,0 +1,409 @@
1
+ import * as React from 'react';
2
+ import { useReducer } from 'react';
3
+ import { LiveMap, LiveList, LiveObject } from '@liveblocks/client';
4
+
5
+ const ClientContext = React.createContext(null);
6
+ /**
7
+ * Makes the Liveblocks client available in the component hierarchy below.
8
+ */
9
+ function LiveblocksProvider(props) {
10
+ return (React.createElement(ClientContext.Provider, { value: props.client }, props.children));
11
+ }
12
+ /**
13
+ * Returns the Client of the nearest LiveblocksProvider above in the React
14
+ * component tree.
15
+ */
16
+ function useClient() {
17
+ const client = React.useContext(ClientContext);
18
+ if (client == null) {
19
+ throw new Error("LiveblocksProvider is missing from the react tree");
20
+ }
21
+ return client;
22
+ }
23
+
24
+ /*! *****************************************************************************
25
+ Copyright (c) Microsoft Corporation.
26
+
27
+ Permission to use, copy, modify, and/or distribute this software for any
28
+ purpose with or without fee is hereby granted.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
31
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
32
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
33
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
34
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
35
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
36
+ PERFORMANCE OF THIS SOFTWARE.
37
+ ***************************************************************************** */
38
+
39
+ function __awaiter(thisArg, _arguments, P, generator) {
40
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
41
+ return new (P || (P = Promise))(function (resolve, reject) {
42
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
43
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
44
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
45
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Trigger a re-render programmatically, without changing the component's
51
+ * state.
52
+ *
53
+ * Usage:
54
+ *
55
+ * const rerender = useRerender();
56
+ * return (
57
+ * <button onClick={rerender}>
58
+ * {Math.random()}
59
+ * </button>
60
+ * )
61
+ *
62
+ */
63
+ function useRerender() {
64
+ const [, update] = useReducer(
65
+ // This implementation works by incrementing a hidden counter value that is
66
+ // never consumed. Simply incrementing the counter changes the component's
67
+ // state and, thus, trigger a re-render.
68
+ (x) => x + 1, 0);
69
+ return update;
70
+ }
71
+
72
+ const RoomContext = React.createContext(null);
73
+ /**
74
+ * Makes a Room available in the component hierarchy below.
75
+ * When this component is unmounted, the current user leave the room.
76
+ * That means that you can't have 2 RoomProvider with the same room id in your react tree.
77
+ */
78
+ function RoomProvider(props) {
79
+ const { id: roomId, defaultPresence, defaultStorageRoot } = props;
80
+ if (process.env.NODE_ENV !== "production") {
81
+ if (roomId == null) {
82
+ throw new Error("RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required");
83
+ }
84
+ if (typeof roomId !== "string") {
85
+ throw new Error("RoomProvider id property should be a string.");
86
+ }
87
+ }
88
+ const client = useClient();
89
+ const [room, setRoom] = React.useState(() => client.enter(roomId, {
90
+ defaultPresence: defaultPresence ? defaultPresence() : undefined,
91
+ defaultStorageRoot,
92
+ DO_NOT_USE_withoutConnecting: typeof window === "undefined",
93
+ }));
94
+ React.useEffect(() => {
95
+ setRoom(client.enter(roomId, {
96
+ defaultPresence: defaultPresence ? defaultPresence() : undefined,
97
+ defaultStorageRoot,
98
+ DO_NOT_USE_withoutConnecting: typeof window === "undefined",
99
+ }));
100
+ return () => {
101
+ client.leave(roomId);
102
+ };
103
+ }, [client, roomId]);
104
+ return (React.createElement(RoomContext.Provider, { value: room }, props.children));
105
+ }
106
+ /**
107
+ * Returns the Room of the nearest RoomProvider above in the React component
108
+ * tree.
109
+ */
110
+ function useRoom() {
111
+ const room = React.useContext(RoomContext);
112
+ if (room == null) {
113
+ throw new Error("RoomProvider is missing from the react tree");
114
+ }
115
+ return room;
116
+ }
117
+ /**
118
+ * Returns the presence of the current user of the current room, and a function to update it.
119
+ * It is different from the setState function returned by the useState hook from React.
120
+ * You don't need to pass the full presence object to update it.
121
+ *
122
+ * @example
123
+ * import { useMyPresence } from "@liveblocks/react";
124
+ *
125
+ * const [myPresence, updateMyPresence] = useMyPresence();
126
+ * updateMyPresence({ x: 0 });
127
+ * updateMyPresence({ y: 0 });
128
+ *
129
+ * // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }"
130
+ */
131
+ function useMyPresence() {
132
+ const room = useRoom();
133
+ const presence = room.getPresence();
134
+ const rerender = useRerender();
135
+ React.useEffect(() => {
136
+ const unsubscribe = room.subscribe("my-presence", rerender);
137
+ return () => {
138
+ unsubscribe();
139
+ };
140
+ }, [room]);
141
+ const setPresence = React.useCallback((overrides, options) => room.updatePresence(overrides, options), [room]);
142
+ return [presence, setPresence];
143
+ }
144
+ /**
145
+ * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.
146
+ * If you don't use the current user presence in your component, but you need to update it (e.g. live cursor), it's better to use useUpdateMyPresence to avoid unnecessary renders.
147
+ *
148
+ * @example
149
+ * import { useUpdateMyPresence } from "@liveblocks/react";
150
+ *
151
+ * const updateMyPresence = useUpdateMyPresence();
152
+ * updateMyPresence({ x: 0 });
153
+ * updateMyPresence({ y: 0 });
154
+ *
155
+ * // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }"
156
+ */
157
+ function useUpdateMyPresence() {
158
+ const room = useRoom();
159
+ return React.useCallback((overrides, options) => {
160
+ room.updatePresence(overrides, options);
161
+ }, [room]);
162
+ }
163
+ /**
164
+ * Returns an object that lets you get information about all the the users currently connected in the room.
165
+ *
166
+ * @example
167
+ * import { useOthers } from "@liveblocks/react";
168
+ *
169
+ * const others = useOthers();
170
+ *
171
+ * // Example to map all cursors in jsx
172
+ * {
173
+ * others.map(({ connectionId, presence }) => {
174
+ * if(presence == null || presence.cursor == null) {
175
+ * return null;
176
+ * }
177
+ * return <Cursor key={connectionId} cursor={presence.cursor} />
178
+ * })
179
+ * }
180
+ */
181
+ function useOthers() {
182
+ const room = useRoom();
183
+ const rerender = useRerender();
184
+ React.useEffect(() => {
185
+ const unsubscribe = room.subscribe("others", rerender);
186
+ return () => {
187
+ unsubscribe();
188
+ };
189
+ }, [room]);
190
+ return room.getOthers();
191
+ }
192
+ /**
193
+ * Returns a callback that lets you broadcast custom events to other users in the room
194
+ *
195
+ * @example
196
+ * import { useBroadcastEvent } from "@liveblocks/react";
197
+ *
198
+ * const broadcast = useBroadcastEvent();
199
+ *
200
+ * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
201
+ */
202
+ function useBroadcastEvent() {
203
+ const room = useRoom();
204
+ return React.useCallback((event, options = { shouldQueueEventIfNotReady: false }) => {
205
+ room.broadcastEvent(event, options);
206
+ }, [room]);
207
+ }
208
+ /**
209
+ * useErrorListener is a react hook that lets you react to potential room connection errors.
210
+ *
211
+ * @example
212
+ * import { useErrorListener } from "@liveblocks/react";
213
+ *
214
+ * useErrorListener(er => {
215
+ * console.error(er);
216
+ * })
217
+ */
218
+ function useErrorListener(callback) {
219
+ const room = useRoom();
220
+ const savedCallback = React.useRef(callback);
221
+ React.useEffect(() => {
222
+ savedCallback.current = callback;
223
+ });
224
+ React.useEffect(() => {
225
+ const listener = (e) => savedCallback.current(e);
226
+ const unsubscribe = room.subscribe("error", listener);
227
+ return () => {
228
+ unsubscribe();
229
+ };
230
+ }, [room]);
231
+ }
232
+ /**
233
+ * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.
234
+ *
235
+ * @example
236
+ * import { useEventListener } from "@liveblocks/react";
237
+ *
238
+ * useEventListener(({ connectionId, event }) => {
239
+ * if (event.type === "CUSTOM_EVENT") {
240
+ * // Do something
241
+ * }
242
+ * });
243
+ */
244
+ function useEventListener(callback) {
245
+ const room = useRoom();
246
+ const savedCallback = React.useRef(callback);
247
+ React.useEffect(() => {
248
+ savedCallback.current = callback;
249
+ });
250
+ React.useEffect(() => {
251
+ const listener = (e) => savedCallback.current(e);
252
+ const unsubscribe = room.subscribe("event", listener);
253
+ return () => {
254
+ unsubscribe();
255
+ };
256
+ }, [room]);
257
+ }
258
+ /**
259
+ * Gets the current user once it is connected to the room.
260
+ *
261
+ * @example
262
+ * import { useSelf } from "@liveblocks/react";
263
+ *
264
+ * const user = useSelf();
265
+ */
266
+ function useSelf() {
267
+ const room = useRoom();
268
+ const rerender = useRerender();
269
+ React.useEffect(() => {
270
+ const unsubscribePresence = room.subscribe("my-presence", rerender);
271
+ const unsubscribeConnection = room.subscribe("connection", rerender);
272
+ return () => {
273
+ unsubscribePresence();
274
+ unsubscribeConnection();
275
+ };
276
+ }, [room]);
277
+ return room.getSelf();
278
+ }
279
+ function useStorage() {
280
+ const room = useRoom();
281
+ const [root, setState] = React.useState(null);
282
+ React.useEffect(() => {
283
+ let didCancel = false;
284
+ function fetchStorage() {
285
+ return __awaiter(this, void 0, void 0, function* () {
286
+ const storage = yield room.getStorage();
287
+ if (!didCancel) {
288
+ setState(storage.root);
289
+ }
290
+ });
291
+ }
292
+ fetchStorage();
293
+ return () => {
294
+ didCancel = true;
295
+ };
296
+ }, [room]);
297
+ return [root];
298
+ }
299
+ /**
300
+ * Returns the LiveMap associated with the provided key. If the LiveMap does not exist, a new empty LiveMap will be created.
301
+ * The hook triggers a re-render if the LiveMap is updated, however it does not triggers a re-render if a nested CRDT is updated.
302
+ *
303
+ * @param key The storage key associated with the LiveMap
304
+ * @param entries Optional entries that are used to create the LiveMap for the first time
305
+ * @returns null while the storage is loading, otherwise, returns the LiveMap associated to the storage
306
+ *
307
+ * @example
308
+ * const emptyMap = useMap("mapA");
309
+ * const mapWithItems = useMap("mapB", [["keyA", "valueA"], ["keyB", "valueB"]]);
310
+ */
311
+ function useMap(key, entries) {
312
+ return useCrdt(key, new LiveMap(entries));
313
+ }
314
+ /**
315
+ * Returns the LiveList associated with the provided key. If the LiveList does not exist, a new LiveList will be created.
316
+ * The hook triggers a re-render if the LiveList is updated, however it does not triggers a re-render if a nested CRDT is updated.
317
+ *
318
+ * @param key The storage key associated with the LiveList
319
+ * @param items Optional items that are used to create the LiveList for the first time
320
+ * @returns null while the storage is loading, otherwise, returns the LiveList associated to the storage
321
+ *
322
+ * @example
323
+ * const emptyList = useList("listA");
324
+ * const listWithItems = useList("listB", ["a", "b", "c"]);
325
+ */
326
+ function useList(key, items) {
327
+ return useCrdt(key, new LiveList(items));
328
+ }
329
+ /**
330
+ * Returns the LiveObject associated with the provided key. If the LiveObject does not exist, it will be created with the initialData parameter.
331
+ * The hook triggers a re-render if the LiveObject is updated, however it does not triggers a re-render if a nested CRDT is updated.
332
+ *
333
+ * @param key The storage key associated with the LiveObject
334
+ * @param initialData Optional data that is used to create the LiveObject for the first time
335
+ * @returns null while the storage is loading, otherwise, returns the LveObject associated to the storage
336
+ *
337
+ * @example
338
+ * const object = useObject("obj", {
339
+ * company: "Liveblocks",
340
+ * website: "https://liveblocks.io"
341
+ * });
342
+ */
343
+ function useObject(key, initialData) {
344
+ return useCrdt(key, new LiveObject(initialData));
345
+ }
346
+ /**
347
+ * Returns a function that undoes the last operation executed by the current client.
348
+ * It does not impact operations made by other clients.
349
+ */
350
+ function useUndo() {
351
+ return useRoom().history.undo;
352
+ }
353
+ /**
354
+ * Returns a function that redoes the last operation executed by the current client.
355
+ * It does not impact operations made by other clients.
356
+ */
357
+ function useRedo() {
358
+ return useRoom().history.redo;
359
+ }
360
+ /**
361
+ * Returns a function that batches modifications made during the given function.
362
+ * All the modifications are sent to other clients in a single message.
363
+ * All the modifications are merged in a single history item (undo/redo).
364
+ * All the subscribers are called only after the batch is over.
365
+ */
366
+ function useBatch() {
367
+ return useRoom().batch;
368
+ }
369
+ /**
370
+ * Returns the room.history
371
+ */
372
+ function useHistory() {
373
+ return useRoom().history;
374
+ }
375
+ function useCrdt(key, initialCrdt) {
376
+ var _a;
377
+ const room = useRoom();
378
+ const [root] = useStorage();
379
+ const rerender = useRerender();
380
+ React.useEffect(() => {
381
+ if (root == null) {
382
+ return;
383
+ }
384
+ let crdt = root.get(key);
385
+ if (crdt == null) {
386
+ crdt = initialCrdt;
387
+ root.set(key, crdt);
388
+ }
389
+ function onRootChange() {
390
+ const newCrdt = root.get(key);
391
+ if (newCrdt !== crdt) {
392
+ unsubscribeCrdt();
393
+ crdt = newCrdt;
394
+ unsubscribeCrdt = room.subscribe(crdt /* AbstractCrdt */, rerender);
395
+ rerender();
396
+ }
397
+ }
398
+ let unsubscribeCrdt = room.subscribe(crdt /* AbstractCrdt */, rerender);
399
+ const unsubscribeRoot = room.subscribe(root /* AbstractCrdt */, onRootChange);
400
+ rerender();
401
+ return () => {
402
+ unsubscribeRoot();
403
+ unsubscribeCrdt();
404
+ };
405
+ }, [root, room]);
406
+ return (_a = root === null || root === void 0 ? void 0 : root.get(key)) !== null && _a !== void 0 ? _a : null;
407
+ }
408
+
409
+ export { LiveblocksProvider, RoomProvider, useBatch, useBroadcastEvent, useClient, useErrorListener, useEventListener, useHistory, useList, useMap, useMyPresence, useObject, useOthers, useRedo, useRoom, useSelf, useStorage, useUndo, useUpdateMyPresence };
package/package.json CHANGED
@@ -1,21 +1,13 @@
1
1
  {
2
2
  "name": "@liveblocks/react",
3
- "version": "0.16.2",
3
+ "version": "0.16.4-beta2",
4
4
  "description": "A set of React hooks and providers to use Liveblocks declaratively.",
5
5
  "main": "./index.js",
6
+ "module": "./index.mjs",
6
7
  "types": "./index.d.ts",
7
8
  "files": [
8
9
  "**"
9
10
  ],
10
- "exports": {
11
- "./package.json": "./package.json",
12
- ".": {
13
- "types": "./index.d.ts",
14
- "module": "./esm/index.js",
15
- "import": "./esm/index.mjs",
16
- "default": "./index.js"
17
- }
18
- },
19
11
  "keywords": [
20
12
  "react",
21
13
  "liveblocks",
@@ -29,11 +21,13 @@
29
21
  "scripts": {
30
22
  "build": "rollup -c && cp ./package.json ./README.md ./lib",
31
23
  "start": "rollup -c -w",
32
- "test": "jest --watch"
24
+ "lint": "eslint src/",
25
+ "test": "jest --watch",
26
+ "test-ci": "jest"
33
27
  },
34
28
  "license": "Apache-2.0",
35
29
  "peerDependencies": {
36
- "@liveblocks/client": "0.16.2",
30
+ "@liveblocks/client": "0.16.4-beta2",
37
31
  "react": "^16.14.0 || ^17 || ^18"
38
32
  },
39
33
  "devDependencies": {
@@ -43,6 +37,7 @@
43
37
  "@babel/preset-typescript": "^7.12.16",
44
38
  "@rollup/plugin-babel": "^5.3.1",
45
39
  "@rollup/plugin-node-resolve": "^11.2.1",
40
+ "@rollup/plugin-replace": "^4.0.0",
46
41
  "@rollup/plugin-typescript": "^8.3.1",
47
42
  "@testing-library/jest-dom": "^5.11.9",
48
43
  "@testing-library/react": "^13.1.1",
@@ -59,8 +54,8 @@
59
54
  "msw": "^0.27.1",
60
55
  "react-error-boundary": "^3.1.1",
61
56
  "rollup": "^2.39.0",
57
+ "rollup-plugin-command": "^1.1.3",
62
58
  "rollup-plugin-dts": "^4.2.0",
63
- "rollup-plugin-esbuild": "^4.8.2",
64
59
  "typescript": "^4.1.5",
65
60
  "whatwg-fetch": "^3.6.2"
66
61
  },
@@ -68,5 +63,6 @@
68
63
  "type": "git",
69
64
  "url": "https://github.com/liveblocks/liveblocks.git",
70
65
  "directory": "packages/liveblocks-react"
71
- }
66
+ },
67
+ "sideEffects": false
72
68
  }
package/esm/index.js DELETED
@@ -1,216 +0,0 @@
1
- import * as React from 'react';
2
- import { useReducer } from 'react';
3
- import { LiveMap, LiveList, LiveObject } from '@liveblocks/client';
4
-
5
- const ClientContext = React.createContext(null);
6
- function LiveblocksProvider(props) {
7
- return /* @__PURE__ */ React.createElement(ClientContext.Provider, {
8
- value: props.client
9
- }, props.children);
10
- }
11
- function useClient() {
12
- const client = React.useContext(ClientContext);
13
- if (client == null) {
14
- throw new Error("LiveblocksProvider is missing from the react tree");
15
- }
16
- return client;
17
- }
18
-
19
- function useRerender() {
20
- const [, update] = useReducer((x) => x + 1, 0);
21
- return update;
22
- }
23
-
24
- const RoomContext = React.createContext(null);
25
- function RoomProvider({
26
- id,
27
- children,
28
- defaultPresence,
29
- defaultStorageRoot
30
- }) {
31
- if (process.env.NODE_ENV !== "production") {
32
- if (id == null) {
33
- throw new Error("RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required");
34
- }
35
- if (typeof id !== "string") {
36
- throw new Error("RoomProvider id property should be a string.");
37
- }
38
- }
39
- const client = useClient();
40
- const [room, setRoom] = React.useState(() => client.enter(id, {
41
- defaultPresence: defaultPresence ? defaultPresence() : void 0,
42
- defaultStorageRoot,
43
- DO_NOT_USE_withoutConnecting: typeof window === "undefined"
44
- }));
45
- React.useEffect(() => {
46
- setRoom(client.enter(id, {
47
- defaultPresence: defaultPresence ? defaultPresence() : void 0,
48
- defaultStorageRoot,
49
- DO_NOT_USE_withoutConnecting: typeof window === "undefined"
50
- }));
51
- return () => {
52
- client.leave(id);
53
- };
54
- }, [client, id]);
55
- return /* @__PURE__ */ React.createElement(RoomContext.Provider, {
56
- value: room
57
- }, children);
58
- }
59
- function useRoom() {
60
- const room = React.useContext(RoomContext);
61
- if (room == null) {
62
- throw new Error("RoomProvider is missing from the react tree");
63
- }
64
- return room;
65
- }
66
- function useMyPresence() {
67
- const room = useRoom();
68
- const presence = room.getPresence();
69
- const rerender = useRerender();
70
- React.useEffect(() => {
71
- const unsubscribe = room.subscribe("my-presence", rerender);
72
- return () => {
73
- unsubscribe();
74
- };
75
- }, [room]);
76
- const setPresence = React.useCallback((overrides, options) => room.updatePresence(overrides, options), [room]);
77
- return [presence, setPresence];
78
- }
79
- function useUpdateMyPresence() {
80
- const room = useRoom();
81
- return React.useCallback((overrides, options) => {
82
- room.updatePresence(overrides, options);
83
- }, [room]);
84
- }
85
- function useOthers() {
86
- const room = useRoom();
87
- const rerender = useRerender();
88
- React.useEffect(() => {
89
- const unsubscribe = room.subscribe("others", rerender);
90
- return () => {
91
- unsubscribe();
92
- };
93
- }, [room]);
94
- return room.getOthers();
95
- }
96
- function useBroadcastEvent() {
97
- const room = useRoom();
98
- return React.useCallback((event, options = { shouldQueueEventIfNotReady: false }) => {
99
- room.broadcastEvent(event, options);
100
- }, [room]);
101
- }
102
- function useErrorListener(callback) {
103
- const room = useRoom();
104
- const savedCallback = React.useRef(callback);
105
- React.useEffect(() => {
106
- savedCallback.current = callback;
107
- });
108
- React.useEffect(() => {
109
- const listener = (e) => savedCallback.current(e);
110
- const unsubscribe = room.subscribe("error", listener);
111
- return () => {
112
- unsubscribe();
113
- };
114
- }, [room]);
115
- }
116
- function useEventListener(callback) {
117
- const room = useRoom();
118
- const savedCallback = React.useRef(callback);
119
- React.useEffect(() => {
120
- savedCallback.current = callback;
121
- });
122
- React.useEffect(() => {
123
- const listener = (e) => savedCallback.current(e);
124
- const unsubscribe = room.subscribe("event", listener);
125
- return () => {
126
- unsubscribe();
127
- };
128
- }, [room]);
129
- }
130
- function useSelf() {
131
- const room = useRoom();
132
- const rerender = useRerender();
133
- React.useEffect(() => {
134
- const unsubscribePresence = room.subscribe("my-presence", rerender);
135
- const unsubscribeConnection = room.subscribe("connection", rerender);
136
- return () => {
137
- unsubscribePresence();
138
- unsubscribeConnection();
139
- };
140
- }, [room]);
141
- return room.getSelf();
142
- }
143
- function useStorage() {
144
- const room = useRoom();
145
- const [root, setState] = React.useState(null);
146
- React.useEffect(() => {
147
- let didCancel = false;
148
- async function fetchStorage() {
149
- const storage = await room.getStorage();
150
- if (!didCancel) {
151
- setState(storage.root);
152
- }
153
- }
154
- fetchStorage();
155
- return () => {
156
- didCancel = true;
157
- };
158
- }, [room]);
159
- return [root];
160
- }
161
- function useMap(key, entries) {
162
- return useCrdt(key, new LiveMap(entries));
163
- }
164
- function useList(key, items) {
165
- return useCrdt(key, new LiveList(items));
166
- }
167
- function useObject(key, initialData) {
168
- return useCrdt(key, new LiveObject(initialData));
169
- }
170
- function useUndo() {
171
- return useRoom().history.undo;
172
- }
173
- function useRedo() {
174
- return useRoom().history.redo;
175
- }
176
- function useBatch() {
177
- return useRoom().batch;
178
- }
179
- function useHistory() {
180
- return useRoom().history;
181
- }
182
- function useCrdt(key, initialCrdt) {
183
- var _a;
184
- const room = useRoom();
185
- const [root] = useStorage();
186
- const rerender = useRerender();
187
- React.useEffect(() => {
188
- if (root == null) {
189
- return;
190
- }
191
- let crdt = root.get(key);
192
- if (crdt == null) {
193
- crdt = initialCrdt;
194
- root.set(key, crdt);
195
- }
196
- function onRootChange() {
197
- const newCrdt = root.get(key);
198
- if (newCrdt !== crdt) {
199
- unsubscribeCrdt();
200
- crdt = newCrdt;
201
- unsubscribeCrdt = room.subscribe(crdt, rerender);
202
- rerender();
203
- }
204
- }
205
- let unsubscribeCrdt = room.subscribe(crdt, rerender);
206
- const unsubscribeRoot = room.subscribe(root, onRootChange);
207
- rerender();
208
- return () => {
209
- unsubscribeRoot();
210
- unsubscribeCrdt();
211
- };
212
- }, [root, room]);
213
- return (_a = root == null ? void 0 : root.get(key)) != null ? _a : null;
214
- }
215
-
216
- export { LiveblocksProvider, RoomProvider, useBatch, useBroadcastEvent, useClient, useErrorListener, useEventListener, useHistory, useList, useMap, useMyPresence, useObject, useOthers, useRedo, useRoom, useSelf, useStorage, useUndo, useUpdateMyPresence };
package/esm/index.mjs DELETED
@@ -1,216 +0,0 @@
1
- import * as React from 'react';
2
- import { useReducer } from 'react';
3
- import { LiveMap, LiveList, LiveObject } from '@liveblocks/client';
4
-
5
- const ClientContext = React.createContext(null);
6
- function LiveblocksProvider(props) {
7
- return /* @__PURE__ */ React.createElement(ClientContext.Provider, {
8
- value: props.client
9
- }, props.children);
10
- }
11
- function useClient() {
12
- const client = React.useContext(ClientContext);
13
- if (client == null) {
14
- throw new Error("LiveblocksProvider is missing from the react tree");
15
- }
16
- return client;
17
- }
18
-
19
- function useRerender() {
20
- const [, update] = useReducer((x) => x + 1, 0);
21
- return update;
22
- }
23
-
24
- const RoomContext = React.createContext(null);
25
- function RoomProvider({
26
- id,
27
- children,
28
- defaultPresence,
29
- defaultStorageRoot
30
- }) {
31
- if (process.env.NODE_ENV !== "production") {
32
- if (id == null) {
33
- throw new Error("RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required");
34
- }
35
- if (typeof id !== "string") {
36
- throw new Error("RoomProvider id property should be a string.");
37
- }
38
- }
39
- const client = useClient();
40
- const [room, setRoom] = React.useState(() => client.enter(id, {
41
- defaultPresence: defaultPresence ? defaultPresence() : void 0,
42
- defaultStorageRoot,
43
- DO_NOT_USE_withoutConnecting: typeof window === "undefined"
44
- }));
45
- React.useEffect(() => {
46
- setRoom(client.enter(id, {
47
- defaultPresence: defaultPresence ? defaultPresence() : void 0,
48
- defaultStorageRoot,
49
- DO_NOT_USE_withoutConnecting: typeof window === "undefined"
50
- }));
51
- return () => {
52
- client.leave(id);
53
- };
54
- }, [client, id]);
55
- return /* @__PURE__ */ React.createElement(RoomContext.Provider, {
56
- value: room
57
- }, children);
58
- }
59
- function useRoom() {
60
- const room = React.useContext(RoomContext);
61
- if (room == null) {
62
- throw new Error("RoomProvider is missing from the react tree");
63
- }
64
- return room;
65
- }
66
- function useMyPresence() {
67
- const room = useRoom();
68
- const presence = room.getPresence();
69
- const rerender = useRerender();
70
- React.useEffect(() => {
71
- const unsubscribe = room.subscribe("my-presence", rerender);
72
- return () => {
73
- unsubscribe();
74
- };
75
- }, [room]);
76
- const setPresence = React.useCallback((overrides, options) => room.updatePresence(overrides, options), [room]);
77
- return [presence, setPresence];
78
- }
79
- function useUpdateMyPresence() {
80
- const room = useRoom();
81
- return React.useCallback((overrides, options) => {
82
- room.updatePresence(overrides, options);
83
- }, [room]);
84
- }
85
- function useOthers() {
86
- const room = useRoom();
87
- const rerender = useRerender();
88
- React.useEffect(() => {
89
- const unsubscribe = room.subscribe("others", rerender);
90
- return () => {
91
- unsubscribe();
92
- };
93
- }, [room]);
94
- return room.getOthers();
95
- }
96
- function useBroadcastEvent() {
97
- const room = useRoom();
98
- return React.useCallback((event, options = { shouldQueueEventIfNotReady: false }) => {
99
- room.broadcastEvent(event, options);
100
- }, [room]);
101
- }
102
- function useErrorListener(callback) {
103
- const room = useRoom();
104
- const savedCallback = React.useRef(callback);
105
- React.useEffect(() => {
106
- savedCallback.current = callback;
107
- });
108
- React.useEffect(() => {
109
- const listener = (e) => savedCallback.current(e);
110
- const unsubscribe = room.subscribe("error", listener);
111
- return () => {
112
- unsubscribe();
113
- };
114
- }, [room]);
115
- }
116
- function useEventListener(callback) {
117
- const room = useRoom();
118
- const savedCallback = React.useRef(callback);
119
- React.useEffect(() => {
120
- savedCallback.current = callback;
121
- });
122
- React.useEffect(() => {
123
- const listener = (e) => savedCallback.current(e);
124
- const unsubscribe = room.subscribe("event", listener);
125
- return () => {
126
- unsubscribe();
127
- };
128
- }, [room]);
129
- }
130
- function useSelf() {
131
- const room = useRoom();
132
- const rerender = useRerender();
133
- React.useEffect(() => {
134
- const unsubscribePresence = room.subscribe("my-presence", rerender);
135
- const unsubscribeConnection = room.subscribe("connection", rerender);
136
- return () => {
137
- unsubscribePresence();
138
- unsubscribeConnection();
139
- };
140
- }, [room]);
141
- return room.getSelf();
142
- }
143
- function useStorage() {
144
- const room = useRoom();
145
- const [root, setState] = React.useState(null);
146
- React.useEffect(() => {
147
- let didCancel = false;
148
- async function fetchStorage() {
149
- const storage = await room.getStorage();
150
- if (!didCancel) {
151
- setState(storage.root);
152
- }
153
- }
154
- fetchStorage();
155
- return () => {
156
- didCancel = true;
157
- };
158
- }, [room]);
159
- return [root];
160
- }
161
- function useMap(key, entries) {
162
- return useCrdt(key, new LiveMap(entries));
163
- }
164
- function useList(key, items) {
165
- return useCrdt(key, new LiveList(items));
166
- }
167
- function useObject(key, initialData) {
168
- return useCrdt(key, new LiveObject(initialData));
169
- }
170
- function useUndo() {
171
- return useRoom().history.undo;
172
- }
173
- function useRedo() {
174
- return useRoom().history.redo;
175
- }
176
- function useBatch() {
177
- return useRoom().batch;
178
- }
179
- function useHistory() {
180
- return useRoom().history;
181
- }
182
- function useCrdt(key, initialCrdt) {
183
- var _a;
184
- const room = useRoom();
185
- const [root] = useStorage();
186
- const rerender = useRerender();
187
- React.useEffect(() => {
188
- if (root == null) {
189
- return;
190
- }
191
- let crdt = root.get(key);
192
- if (crdt == null) {
193
- crdt = initialCrdt;
194
- root.set(key, crdt);
195
- }
196
- function onRootChange() {
197
- const newCrdt = root.get(key);
198
- if (newCrdt !== crdt) {
199
- unsubscribeCrdt();
200
- crdt = newCrdt;
201
- unsubscribeCrdt = room.subscribe(crdt, rerender);
202
- rerender();
203
- }
204
- }
205
- let unsubscribeCrdt = room.subscribe(crdt, rerender);
206
- const unsubscribeRoot = room.subscribe(root, onRootChange);
207
- rerender();
208
- return () => {
209
- unsubscribeRoot();
210
- unsubscribeCrdt();
211
- };
212
- }, [root, room]);
213
- return (_a = root == null ? void 0 : root.get(key)) != null ? _a : null;
214
- }
215
-
216
- export { LiveblocksProvider, RoomProvider, useBatch, useBroadcastEvent, useClient, useErrorListener, useEventListener, useHistory, useList, useMap, useMyPresence, useObject, useOthers, useRedo, useRoom, useSelf, useStorage, useUndo, useUpdateMyPresence };