@liveblocks/react 0.11.0 → 0.12.0-beta.12

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/README.md CHANGED
@@ -12,16 +12,6 @@ Liveblocks helps you create performant and reliable collaborative experiences.
12
12
 
13
13
  ## Examples
14
14
 
15
- Try it live on [liveblocks.io](https://liveblocks.io/examples)
15
+ Try it live on [liveblocks.io](https://liveblocks.io/examples).
16
16
 
17
- ### Next.js
18
-
19
- Clone this [github repository](https://github.com/liveblocks/next-js-examples) or try it directly on [CodeSandbox](https://codesandbox.io/s/github/liveblocks/next-js-examples?file=/pages/presence.tsx)
20
-
21
- ### Nuxt.js
22
-
23
- Clone this [github repository](https://github.com/liveblocks/nuxt-js-examples) or try it directly on [CodeSandbox](https://codesandbox.io/s/github/liveblocks/nuxt-js-examples?file=/pages/presence.vue)
24
-
25
- ### Vanilla JavaScript + Express.js
26
-
27
- Clone this [github repository](https://github.com/liveblocks/javascript-examples)
17
+ Clone one of our [examples](https://github.com/liveblocks/liveblocks/tree/main/examples).
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Client, RecordData, Others, Presence, Record, InitialStorageFactory, Room, User } from "@liveblocks/client";
1
+ import { Client, Others, Presence, LiveObject, LiveMap, User, LiveList } from "@liveblocks/client";
2
2
  import * as React from "react";
3
3
  declare type LiveblocksProviderProps = {
4
4
  children: React.ReactNode;
@@ -8,7 +8,7 @@ declare type LiveblocksProviderProps = {
8
8
  * Makes the Liveblocks client available in the component hierarchy below.
9
9
  */
10
10
  export declare function LiveblocksProvider(props: LiveblocksProviderProps): JSX.Element;
11
- declare type RoomProviderProps = {
11
+ declare type RoomProviderProps<TStorageRoot> = {
12
12
  /**
13
13
  * The id of the room you want to connect to
14
14
  */
@@ -18,6 +18,7 @@ declare type RoomProviderProps = {
18
18
  * If ommited, the default presence will be an empty object
19
19
  */
20
20
  defaultPresence?: () => Presence;
21
+ defaultStorageRoot?: TStorageRoot;
21
22
  children: React.ReactNode;
22
23
  };
23
24
  /**
@@ -25,14 +26,13 @@ declare type RoomProviderProps = {
25
26
  * When this component is unmounted, the current user leave the room.
26
27
  * That means that you can't have 2 RoomProvider with the same room id in your react tree.
27
28
  */
28
- export declare function RoomProvider({ id, children, defaultPresence, }: RoomProviderProps): JSX.Element;
29
+ export declare function RoomProvider<TStorageRoot>({ id, children, defaultPresence, defaultStorageRoot, }: RoomProviderProps<TStorageRoot>): JSX.Element;
29
30
  /**
30
31
  * Returns the presence of the current user of the current room, and a function to update it.
31
32
  * It is different from the setState function returned by the useState hook from React.
32
33
  * You don't need to pass the full presence object to update it.
33
34
  *
34
- * ### Example
35
- * ``` typescript
35
+ * @example
36
36
  * import { useMyPresence } from "@liveblocks/react";
37
37
  *
38
38
  * const [myPresence, updateMyPresence] = useMyPresence();
@@ -40,7 +40,6 @@ export declare function RoomProvider({ id, children, defaultPresence, }: RoomPro
40
40
  * updateMyPresence({ y: 0 });
41
41
  *
42
42
  * // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }"
43
- * ```
44
43
  */
45
44
  export declare function useMyPresence<T extends Presence>(): [
46
45
  T,
@@ -50,8 +49,7 @@ export declare function useMyPresence<T extends Presence>(): [
50
49
  * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.
51
50
  * 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.
52
51
  *
53
- * ### Example
54
- * ``` typescript
52
+ * @example
55
53
  * import { useUpdateMyPresence } from "@liveblocks/react";
56
54
  *
57
55
  * const updateMyPresence = useUpdateMyPresence();
@@ -59,14 +57,12 @@ export declare function useMyPresence<T extends Presence>(): [
59
57
  * updateMyPresence({ y: 0 });
60
58
  *
61
59
  * // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }"
62
- * ```
63
60
  */
64
61
  export declare function useUpdateMyPresence<T extends Presence>(): (overrides: Partial<T>) => void;
65
62
  /**
66
63
  * Returns an object that lets you get information about all the the users currently connected in the room.
67
64
  *
68
- * ### Example
69
- * ``` typescript
65
+ * @example
70
66
  * import { useOthers } from "@liveblocks/react";
71
67
  *
72
68
  * const others = useOthers();
@@ -80,40 +76,34 @@ export declare function useUpdateMyPresence<T extends Presence>(): (overrides: P
80
76
  * return <Cursor key={connectionId} cursor={presence.cursor} />
81
77
  * })
82
78
  * }
83
- * ```
84
79
  */
85
80
  export declare function useOthers<T extends Presence>(): Others<T>;
86
81
  /**
87
82
  * Returns a callback that lets you broadcast custom events to other users in the room
88
83
  *
89
- * ### Example
90
- * ``` typescript
84
+ * @example
91
85
  * import { useBroadcastEvent } from "@liveblocks/react";
92
86
  *
93
87
  * const broadcast = useBroadcastEvent();
94
88
  *
95
89
  * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
96
- * ```
97
90
  */
98
91
  export declare function useBroadcastEvent(): (event: any) => void;
99
92
  /**
100
93
  * useErrorListener is a react hook that lets you react to potential room connection errors.
101
94
  *
102
- * ### Example
103
- * ``` typescript
95
+ * @example
104
96
  * import { useErrorListener } from "@liveblocks/react";
105
97
  *
106
98
  * useErrorListener(er => {
107
99
  * console.error(er);
108
100
  * })
109
- * ```
110
101
  */
111
102
  export declare function useErrorListener(callback: (er: Error) => void): void;
112
103
  /**
113
104
  * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.
114
105
  *
115
- * ### Example
116
- * ``` typescript
106
+ * @example
117
107
  * import { useEventListener } from "@liveblocks/react";
118
108
  *
119
109
  * useEventListener(({ connectionId, event }) => {
@@ -121,7 +111,6 @@ export declare function useErrorListener(callback: (er: Error) => void): void;
121
111
  * // Do something
122
112
  * }
123
113
  * });
124
- * ```
125
114
  */
126
115
  export declare function useEventListener<TEvent>(callback: ({ connectionId, event, }: {
127
116
  connectionId: number;
@@ -130,23 +119,16 @@ export declare function useEventListener<TEvent>(callback: ({ connectionId, even
130
119
  /**
131
120
  * Gets the current user once it is connected to the room.
132
121
  *
133
- * ### Example
134
- * ``` typescript
122
+ * @example
135
123
  * import { useSelf } from "@liveblocks/react";
136
124
  *
137
125
  * const user = useSelf();
138
- * ```
139
126
  */
140
127
  export declare function useSelf<TPresence extends Presence = Presence>(): User<TPresence> | null;
141
- declare type StorageActions = {
142
- createRecord: Room["createRecord"];
143
- updateRecord: Room["updateRecord"];
144
- createList: Room["createList"];
145
- moveItem: Room["moveItem"];
146
- deleteItem: Room["deleteItem"];
147
- deleteItemById: Room["deleteItemById"];
148
- pushItem: Room["pushItem"];
149
- };
150
- export declare function useStorage<TRoot extends RecordData>(initialStorage: InitialStorageFactory<TRoot>): [root: Record<TRoot> | null, actions: StorageActions];
151
- export declare function useStorageActions(): StorageActions;
128
+ export declare function useStorage<TRoot extends Record<string, any>>(): [
129
+ root: LiveObject<TRoot> | null
130
+ ];
131
+ export declare function useMap<TKey extends string, TValue>(key: string): LiveMap<TKey, TValue> | null;
132
+ export declare function useList<TValue>(key: string): LiveList<TValue> | null;
133
+ export declare function useObject<TData>(key: string): LiveObject<TData> | null;
152
134
  export {};
package/lib/index.js CHANGED
@@ -1,75 +1,60 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
+ var client = require('@liveblocks/client');
3
4
  var React = require('react');
4
5
 
5
- var ServerMessageType;
6
- (function (ServerMessageType) {
7
- ServerMessageType[ServerMessageType["UpdatePresence"] = 100] = "UpdatePresence";
8
- ServerMessageType[ServerMessageType["UserJoined"] = 101] = "UserJoined";
9
- ServerMessageType[ServerMessageType["UserLeft"] = 102] = "UserLeft";
10
- ServerMessageType[ServerMessageType["Event"] = 103] = "Event";
11
- ServerMessageType[ServerMessageType["RoomState"] = 104] = "RoomState";
12
- ServerMessageType[ServerMessageType["InitialStorageState"] = 200] = "InitialStorageState";
13
- ServerMessageType[ServerMessageType["UpdateStorage"] = 201] = "UpdateStorage";
14
- })(ServerMessageType || (ServerMessageType = {}));
15
- var ClientMessageType;
16
- (function (ClientMessageType) {
17
- ClientMessageType[ClientMessageType["UpdatePresence"] = 100] = "UpdatePresence";
18
- ClientMessageType[ClientMessageType["ClientEvent"] = 103] = "ClientEvent";
19
- ClientMessageType[ClientMessageType["FetchStorage"] = 200] = "FetchStorage";
20
- ClientMessageType[ClientMessageType["UpdateStorage"] = 201] = "UpdateStorage";
21
- })(ClientMessageType || (ClientMessageType = {}));
22
- var CrdtType;
23
- (function (CrdtType) {
24
- CrdtType[CrdtType["Record"] = 0] = "Record";
25
- CrdtType[CrdtType["List"] = 1] = "List";
26
- CrdtType[CrdtType["Register"] = 2] = "Register";
27
- })(CrdtType || (CrdtType = {}));
28
- var OpType;
29
- (function (OpType) {
30
- OpType[OpType["Init"] = 100] = "Init";
31
- OpType[OpType["ListInsert"] = 200] = "ListInsert";
32
- OpType[OpType["ListMove"] = 201] = "ListMove";
33
- OpType[OpType["ListRemove"] = 202] = "ListRemove";
34
- OpType[OpType["RecordUpdate"] = 300] = "RecordUpdate";
35
- })(OpType || (OpType = {}));
36
- var WebsocketCloseCodes;
37
- (function (WebsocketCloseCodes) {
38
- WebsocketCloseCodes[WebsocketCloseCodes["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
39
- WebsocketCloseCodes[WebsocketCloseCodes["INVALID_MESSAGE_FORMAT"] = 4000] = "INVALID_MESSAGE_FORMAT";
40
- WebsocketCloseCodes[WebsocketCloseCodes["NOT_ALLOWED"] = 4001] = "NOT_ALLOWED";
41
- WebsocketCloseCodes[WebsocketCloseCodes["MAX_NUMBER_OF_MESSAGES_PER_SECONDS"] = 4002] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS";
42
- WebsocketCloseCodes[WebsocketCloseCodes["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"] = 4003] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS";
43
- WebsocketCloseCodes[WebsocketCloseCodes["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP";
44
- WebsocketCloseCodes[WebsocketCloseCodes["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM";
45
- })(WebsocketCloseCodes || (WebsocketCloseCodes = {}));
46
-
47
- var LiveStorageState;
48
- (function (LiveStorageState) {
49
- LiveStorageState[LiveStorageState["NotInitialized"] = 0] = "NotInitialized";
50
- LiveStorageState[LiveStorageState["Loading"] = 1] = "Loading";
51
- LiveStorageState[LiveStorageState["Loaded"] = 2] = "Loaded";
52
- })(LiveStorageState || (LiveStorageState = {}));
53
-
54
- (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
55
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
56
- return new (P || (P = Promise))(function (resolve, reject) {
57
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
58
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
59
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
60
- step((generator = generator.apply(thisArg, _arguments || [])).next());
61
- });
62
- };
63
-
64
- (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
65
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
66
- return new (P || (P = Promise))(function (resolve, reject) {
67
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
68
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
69
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
70
- step((generator = generator.apply(thisArg, _arguments || [])).next());
71
- });
72
- };
6
+ /*! *****************************************************************************
7
+ Copyright (c) Microsoft Corporation.
8
+
9
+ Permission to use, copy, modify, and/or distribute this software for any
10
+ purpose with or without fee is hereby granted.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
13
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
15
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18
+ PERFORMANCE OF THIS SOFTWARE.
19
+ ***************************************************************************** */
20
+
21
+ function __awaiter(thisArg, _arguments, P, generator) {
22
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
+ return new (P || (P = Promise))(function (resolve, reject) {
24
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
25
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
26
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
28
+ });
29
+ }
30
+
31
+ function __generator(thisArg, body) {
32
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
33
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
34
+ function verb(n) { return function (v) { return step([n, v]); }; }
35
+ function step(op) {
36
+ if (f) throw new TypeError("Generator is already executing.");
37
+ while (_) try {
38
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
39
+ if (y = 0, t) op = [op[0] & 2, t.value];
40
+ switch (op[0]) {
41
+ case 0: case 1: t = op; break;
42
+ case 4: _.label++; return { value: op[1], done: false };
43
+ case 5: _.label++; y = op[1]; op = [0]; continue;
44
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
45
+ default:
46
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
47
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
48
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
49
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
50
+ if (t[2]) _.ops.pop();
51
+ _.trys.pop(); continue;
52
+ }
53
+ op = body.call(thisArg, _);
54
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
55
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
56
+ }
57
+ }
73
58
 
74
59
  var ClientContext = React.createContext(null);
75
60
  var RoomContext = React.createContext(null);
@@ -95,7 +80,7 @@ function useClient() {
95
80
  * That means that you can't have 2 RoomProvider with the same room id in your react tree.
96
81
  */
97
82
  function RoomProvider(_a) {
98
- var id = _a.id, children = _a.children, defaultPresence = _a.defaultPresence;
83
+ var id = _a.id, children = _a.children, defaultPresence = _a.defaultPresence, defaultStorageRoot = _a.defaultStorageRoot;
99
84
  var client = useClient();
100
85
  React.useEffect(function () {
101
86
  return function () {
@@ -103,7 +88,10 @@ function RoomProvider(_a) {
103
88
  };
104
89
  }, [client, id]);
105
90
  var room = client.getRoom(id) ||
106
- client.enter(id, defaultPresence ? defaultPresence() : undefined);
91
+ client.enter(id, {
92
+ defaultPresence: defaultPresence ? defaultPresence() : undefined,
93
+ defaultStorageRoot: defaultStorageRoot,
94
+ });
107
95
  return React.createElement(RoomContext.Provider, { value: room }, children);
108
96
  }
109
97
  /**
@@ -121,8 +109,7 @@ function useRoom() {
121
109
  * It is different from the setState function returned by the useState hook from React.
122
110
  * You don't need to pass the full presence object to update it.
123
111
  *
124
- * ### Example
125
- * ``` typescript
112
+ * @example
126
113
  * import { useMyPresence } from "@liveblocks/react";
127
114
  *
128
115
  * const [myPresence, updateMyPresence] = useMyPresence();
@@ -130,7 +117,6 @@ function useRoom() {
130
117
  * updateMyPresence({ y: 0 });
131
118
  *
132
119
  * // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }"
133
- * ```
134
120
  */
135
121
  function useMyPresence() {
136
122
  var room = useRoom();
@@ -152,8 +138,7 @@ function useMyPresence() {
152
138
  * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.
153
139
  * 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.
154
140
  *
155
- * ### Example
156
- * ``` typescript
141
+ * @example
157
142
  * import { useUpdateMyPresence } from "@liveblocks/react";
158
143
  *
159
144
  * const updateMyPresence = useUpdateMyPresence();
@@ -161,7 +146,6 @@ function useMyPresence() {
161
146
  * updateMyPresence({ y: 0 });
162
147
  *
163
148
  * // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }"
164
- * ```
165
149
  */
166
150
  function useUpdateMyPresence() {
167
151
  var room = useRoom();
@@ -172,8 +156,7 @@ function useUpdateMyPresence() {
172
156
  /**
173
157
  * Returns an object that lets you get information about all the the users currently connected in the room.
174
158
  *
175
- * ### Example
176
- * ``` typescript
159
+ * @example
177
160
  * import { useOthers } from "@liveblocks/react";
178
161
  *
179
162
  * const others = useOthers();
@@ -187,7 +170,6 @@ function useUpdateMyPresence() {
187
170
  * return <Cursor key={connectionId} cursor={presence.cursor} />
188
171
  * })
189
172
  * }
190
- * ```
191
173
  */
192
174
  function useOthers() {
193
175
  var room = useRoom();
@@ -206,14 +188,12 @@ function useOthers() {
206
188
  /**
207
189
  * Returns a callback that lets you broadcast custom events to other users in the room
208
190
  *
209
- * ### Example
210
- * ``` typescript
191
+ * @example
211
192
  * import { useBroadcastEvent } from "@liveblocks/react";
212
193
  *
213
194
  * const broadcast = useBroadcastEvent();
214
195
  *
215
196
  * broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } });
216
- * ```
217
197
  */
218
198
  function useBroadcastEvent() {
219
199
  var room = useRoom();
@@ -224,14 +204,12 @@ function useBroadcastEvent() {
224
204
  /**
225
205
  * useErrorListener is a react hook that lets you react to potential room connection errors.
226
206
  *
227
- * ### Example
228
- * ``` typescript
207
+ * @example
229
208
  * import { useErrorListener } from "@liveblocks/react";
230
209
  *
231
210
  * useErrorListener(er => {
232
211
  * console.error(er);
233
212
  * })
234
- * ```
235
213
  */
236
214
  function useErrorListener(callback) {
237
215
  var room = useRoom();
@@ -250,8 +228,7 @@ function useErrorListener(callback) {
250
228
  /**
251
229
  * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.
252
230
  *
253
- * ### Example
254
- * ``` typescript
231
+ * @example
255
232
  * import { useEventListener } from "@liveblocks/react";
256
233
  *
257
234
  * useEventListener(({ connectionId, event }) => {
@@ -259,7 +236,6 @@ function useErrorListener(callback) {
259
236
  * // Do something
260
237
  * }
261
238
  * });
262
- * ```
263
239
  */
264
240
  function useEventListener(callback) {
265
241
  var room = useRoom();
@@ -280,12 +256,10 @@ function useEventListener(callback) {
280
256
  /**
281
257
  * Gets the current user once it is connected to the room.
282
258
  *
283
- * ### Example
284
- * ``` typescript
259
+ * @example
285
260
  * import { useSelf } from "@liveblocks/react";
286
261
  *
287
262
  * const user = useSelf();
288
- * ```
289
263
  */
290
264
  function useSelf() {
291
265
  var room = useRoom();
@@ -303,60 +277,100 @@ function useSelf() {
303
277
  }, [room]);
304
278
  return room.getSelf();
305
279
  }
306
- function useStorage(initialStorage) {
280
+ function useStorage() {
307
281
  var room = useRoom();
308
- var storage = room.getStorage();
309
- var _a = React.useState(0), update = _a[1];
282
+ var _a = React.useState(null), root = _a[0], setState = _a[1];
310
283
  React.useEffect(function () {
311
- function onStorageChange() {
312
- update(function (x) { return x + 1; });
284
+ function fetchStorage() {
285
+ return __awaiter(this, void 0, void 0, function () {
286
+ var storage;
287
+ return __generator(this, function (_a) {
288
+ switch (_a.label) {
289
+ case 0: return [4 /*yield*/, room.getStorage()];
290
+ case 1:
291
+ storage = _a.sent();
292
+ setState(storage.root);
293
+ return [2 /*return*/];
294
+ }
295
+ });
296
+ });
313
297
  }
314
- room.fetchStorage(initialStorage);
315
- room.subscribe("storage", onStorageChange);
316
- return function () {
317
- room.unsubscribe("storage", onStorageChange);
318
- };
298
+ fetchStorage();
299
+ return function () { };
319
300
  }, [room]);
320
- var root = storage.state === LiveStorageState.Loaded
321
- ? storage.root
322
- : null;
323
- var actions = useStorageActions();
324
- return [root, actions];
301
+ return [root];
325
302
  }
326
- function useStorageActions() {
327
- var room = useRoom();
328
- return React.useMemo(function () {
329
- function createRecord(data) {
330
- return room.createRecord(data);
303
+ function useMap(key) {
304
+ var _a;
305
+ var root = useStorage()[0];
306
+ var _b = React.useState(0), setCount = _b[1];
307
+ React.useEffect(function () {
308
+ if (root == null) {
309
+ return;
310
+ }
311
+ var map = root.get(key);
312
+ if (map == null) {
313
+ map = new client.LiveMap();
314
+ root.set(key, map);
331
315
  }
332
- function updateRecord(record, overrides) {
333
- return room.updateRecord(record, overrides);
316
+ function onChange() {
317
+ setCount(function (x) { return x + 1; });
334
318
  }
335
- function createList() {
336
- return room.createList();
319
+ map.subscribe(onChange);
320
+ setCount(function (x) { return x + 1; });
321
+ return function () {
322
+ return map.unsubscribe(onChange);
323
+ };
324
+ }, [root]);
325
+ return (_a = root === null || root === void 0 ? void 0 : root.get(key)) !== null && _a !== void 0 ? _a : null;
326
+ }
327
+ function useList(key) {
328
+ var _a;
329
+ var root = useStorage()[0];
330
+ var _b = React.useState(0), setCount = _b[1];
331
+ React.useEffect(function () {
332
+ if (root == null) {
333
+ return;
334
+ }
335
+ var list = root.get(key);
336
+ if (list == null) {
337
+ list = new client.LiveList();
338
+ root.set(key, list);
337
339
  }
338
- function moveItem(list, index, targetIndex) {
339
- return room.moveItem(list, index, targetIndex);
340
+ function onChange() {
341
+ setCount(function (x) { return x + 1; });
340
342
  }
341
- function deleteItem(list, index) {
342
- return room.deleteItem(list, index);
343
+ list.subscribe(onChange);
344
+ setCount(function (x) { return x + 1; });
345
+ return function () {
346
+ return list.unsubscribe(onChange);
347
+ };
348
+ }, [root]);
349
+ return (_a = root === null || root === void 0 ? void 0 : root.get(key)) !== null && _a !== void 0 ? _a : null;
350
+ }
351
+ function useObject(key) {
352
+ var _a;
353
+ var root = useStorage()[0];
354
+ var _b = React.useState(0), setCount = _b[1];
355
+ React.useEffect(function () {
356
+ if (root == null) {
357
+ return;
343
358
  }
344
- function deleteItemById(list, itemId) {
345
- return room.deleteItemById(list, itemId);
359
+ var obj = root.get(key);
360
+ if (obj == null) {
361
+ obj = new client.LiveObject();
362
+ root.set(key, obj);
346
363
  }
347
- function pushItem(list, item) {
348
- return room.pushItem(list, item);
364
+ function onChange() {
365
+ setCount(function (x) { return x + 1; });
349
366
  }
350
- return {
351
- createRecord: createRecord,
352
- updateRecord: updateRecord,
353
- createList: createList,
354
- moveItem: moveItem,
355
- deleteItem: deleteItem,
356
- deleteItemById: deleteItemById,
357
- pushItem: pushItem,
367
+ obj.subscribe(onChange);
368
+ setCount(function (x) { return x + 1; });
369
+ return function () {
370
+ return obj.unsubscribe(onChange);
358
371
  };
359
- }, [room]);
372
+ }, [root]);
373
+ return (_a = root === null || root === void 0 ? void 0 : root.get(key)) !== null && _a !== void 0 ? _a : null;
360
374
  }
361
375
 
362
376
  exports.LiveblocksProvider = LiveblocksProvider;
@@ -364,10 +378,12 @@ exports.RoomProvider = RoomProvider;
364
378
  exports.useBroadcastEvent = useBroadcastEvent;
365
379
  exports.useErrorListener = useErrorListener;
366
380
  exports.useEventListener = useEventListener;
381
+ exports.useList = useList;
382
+ exports.useMap = useMap;
367
383
  exports.useMyPresence = useMyPresence;
384
+ exports.useObject = useObject;
368
385
  exports.useOthers = useOthers;
369
386
  exports.useSelf = useSelf;
370
387
  exports.useStorage = useStorage;
371
- exports.useStorageActions = useStorageActions;
372
388
  exports.useUpdateMyPresence = useUpdateMyPresence;
373
389
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../node_modules/@liveblocks/client/lib/esm/live.js","../node_modules/@liveblocks/client/lib/esm/types.js","../node_modules/@liveblocks/client/lib/esm/authentication.js","../node_modules/@liveblocks/client/lib/esm/room.js","../src/index.tsx"],"sourcesContent":["export var ServerMessageType;\n(function (ServerMessageType) {\n ServerMessageType[ServerMessageType[\"UpdatePresence\"] = 100] = \"UpdatePresence\";\n ServerMessageType[ServerMessageType[\"UserJoined\"] = 101] = \"UserJoined\";\n ServerMessageType[ServerMessageType[\"UserLeft\"] = 102] = \"UserLeft\";\n ServerMessageType[ServerMessageType[\"Event\"] = 103] = \"Event\";\n ServerMessageType[ServerMessageType[\"RoomState\"] = 104] = \"RoomState\";\n ServerMessageType[ServerMessageType[\"InitialStorageState\"] = 200] = \"InitialStorageState\";\n ServerMessageType[ServerMessageType[\"UpdateStorage\"] = 201] = \"UpdateStorage\";\n})(ServerMessageType || (ServerMessageType = {}));\nexport var ClientMessageType;\n(function (ClientMessageType) {\n ClientMessageType[ClientMessageType[\"UpdatePresence\"] = 100] = \"UpdatePresence\";\n ClientMessageType[ClientMessageType[\"ClientEvent\"] = 103] = \"ClientEvent\";\n ClientMessageType[ClientMessageType[\"FetchStorage\"] = 200] = \"FetchStorage\";\n ClientMessageType[ClientMessageType[\"UpdateStorage\"] = 201] = \"UpdateStorage\";\n})(ClientMessageType || (ClientMessageType = {}));\nexport var CrdtType;\n(function (CrdtType) {\n CrdtType[CrdtType[\"Record\"] = 0] = \"Record\";\n CrdtType[CrdtType[\"List\"] = 1] = \"List\";\n CrdtType[CrdtType[\"Register\"] = 2] = \"Register\";\n})(CrdtType || (CrdtType = {}));\nexport var OpType;\n(function (OpType) {\n OpType[OpType[\"Init\"] = 100] = \"Init\";\n OpType[OpType[\"ListInsert\"] = 200] = \"ListInsert\";\n OpType[OpType[\"ListMove\"] = 201] = \"ListMove\";\n OpType[OpType[\"ListRemove\"] = 202] = \"ListRemove\";\n OpType[OpType[\"RecordUpdate\"] = 300] = \"RecordUpdate\";\n})(OpType || (OpType = {}));\nexport var WebsocketCloseCodes;\n(function (WebsocketCloseCodes) {\n WebsocketCloseCodes[WebsocketCloseCodes[\"CLOSE_ABNORMAL\"] = 1006] = \"CLOSE_ABNORMAL\";\n WebsocketCloseCodes[WebsocketCloseCodes[\"INVALID_MESSAGE_FORMAT\"] = 4000] = \"INVALID_MESSAGE_FORMAT\";\n WebsocketCloseCodes[WebsocketCloseCodes[\"NOT_ALLOWED\"] = 4001] = \"NOT_ALLOWED\";\n WebsocketCloseCodes[WebsocketCloseCodes[\"MAX_NUMBER_OF_MESSAGES_PER_SECONDS\"] = 4002] = \"MAX_NUMBER_OF_MESSAGES_PER_SECONDS\";\n WebsocketCloseCodes[WebsocketCloseCodes[\"MAX_NUMBER_OF_CONCURRENT_CONNECTIONS\"] = 4003] = \"MAX_NUMBER_OF_CONCURRENT_CONNECTIONS\";\n WebsocketCloseCodes[WebsocketCloseCodes[\"MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP\"] = 4004] = \"MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP\";\n WebsocketCloseCodes[WebsocketCloseCodes[\"MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM\"] = 4005] = \"MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM\";\n})(WebsocketCloseCodes || (WebsocketCloseCodes = {}));\n","export var LiveStorageState;\n(function (LiveStorageState) {\n LiveStorageState[LiveStorageState[\"NotInitialized\"] = 0] = \"NotInitialized\";\n LiveStorageState[LiveStorageState[\"Loading\"] = 1] = \"Loading\";\n LiveStorageState[LiveStorageState[\"Loaded\"] = 2] = \"Loaded\";\n})(LiveStorageState || (LiveStorageState = {}));\n","var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nfunction fetchAuthorize(endpoint, room) {\n return __awaiter(this, void 0, void 0, function* () {\n const res = yield fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n room,\n }),\n });\n if (!res.ok) {\n throw new AuthenticationError(`Authentication error. Liveblocks could not parse the response of your authentication \"${endpoint}\"`);\n }\n let authResponse = null;\n try {\n authResponse = yield res.json();\n }\n catch (er) {\n throw new AuthenticationError(`Authentication error. Liveblocks could not parse the response of your authentication \"${endpoint}\"`);\n }\n if (typeof authResponse.token !== \"string\") {\n throw new AuthenticationError(`Authentication error. Liveblocks could not parse the response of your authentication \"${endpoint}\"`);\n }\n return authResponse.token;\n });\n}\nexport default function auth(endpoint, room) {\n return __awaiter(this, void 0, void 0, function* () {\n if (typeof endpoint === \"string\") {\n return fetchAuthorize(endpoint, room);\n }\n if (typeof endpoint === \"function\") {\n const { token } = yield endpoint(room);\n // TODO: Validation\n return token;\n }\n throw new Error(\"Authentication error. Liveblocks could not parse the response of your authentication endpoint\");\n });\n}\nclass AuthenticationError extends Error {\n constructor(message) {\n super(message);\n }\n}\nexport function parseToken(token) {\n const tokenParts = token.split(\".\");\n if (tokenParts.length !== 3) {\n throw new AuthenticationError(`Authentication error. Liveblocks could not parse the response of your authentication endpoint`);\n }\n const data = JSON.parse(atob(tokenParts[1]));\n if (typeof data.actor !== \"number\") {\n throw new AuthenticationError(`Authentication error. Liveblocks could not parse the response of your authentication endpoint`);\n }\n return data;\n}\n","var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { Doc } from \"./doc\";\nimport { LiveStorageState, } from \"./types\";\nimport { createRecord as innerCreateRecord, createList as innerCreateList, } from \"./doc\";\nimport { remove } from \"./utils\";\nimport auth, { parseToken } from \"./authentication\";\nimport { ClientMessageType, ServerMessageType, } from \"./live\";\nconst BACKOFF_RETRY_DELAYS = [250, 500, 1000, 2000, 4000, 8000, 10000];\nconst HEARTBEAT_INTERVAL = 30000;\n// const WAKE_UP_CHECK_INTERVAL = 2000;\nconst PONG_TIMEOUT = 2000;\nfunction isValidRoomEventType(value) {\n return (value === \"storage\" ||\n value === \"my-presence\" ||\n value === \"others\" ||\n value === \"event\" ||\n value === \"error\" ||\n value === \"connection\");\n}\nfunction makeIdFactory(connectionId) {\n let count = 0;\n return () => `${connectionId}:${count++}`;\n}\nfunction makeOthers(presenceMap) {\n const array = Object.values(presenceMap);\n return {\n get count() {\n return array.length;\n },\n map(callback) {\n return array.map(callback);\n },\n toArray() {\n return array;\n },\n };\n}\nfunction log(...params) {\n return;\n console.log(...params, new Date().toString());\n}\nexport function makeStateMachine(state, context, mockedEffects) {\n const effects = mockedEffects || {\n authenticate() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n const token = yield auth(context.authEndpoint, context.room);\n const parsedToken = parseToken(token);\n const socket = new WebSocket(`${context.liveblocksServer}/?token=${token}`);\n socket.addEventListener(\"message\", onMessage);\n socket.addEventListener(\"open\", onOpen);\n socket.addEventListener(\"close\", onClose);\n socket.addEventListener(\"error\", onError);\n authenticationSuccess(parsedToken, socket);\n }\n catch (er) {\n authenticationFailure(er);\n }\n });\n },\n send(messageOrMessages) {\n if (state.socket == null) {\n throw new Error(\"Can't send message if socket is null\");\n }\n state.socket.send(JSON.stringify(messageOrMessages));\n },\n delayFlush(delay) {\n return setTimeout(tryFlushing, delay);\n },\n startHeartbeatInterval() {\n return setInterval(heartbeat, HEARTBEAT_INTERVAL);\n },\n schedulePongTimeout() {\n return setTimeout(pongTimeout, PONG_TIMEOUT);\n },\n scheduleReconnect(delay) {\n return setTimeout(connect, delay);\n },\n };\n function subscribe(type, listener) {\n if (!isValidRoomEventType(type)) {\n throw new Error(`\"${type}\" is not a valid event name`);\n }\n state.listeners[type].push(listener);\n }\n function unsubscribe(event, callback) {\n if (!isValidRoomEventType(event)) {\n throw new Error(`\"${event}\" is not a valid event name`);\n }\n const callbacks = state.listeners[event];\n remove(callbacks, callback);\n }\n function getConnectionState() {\n return state.connection.state;\n }\n function getSelf() {\n return state.connection.state === \"open\" ||\n state.connection.state === \"connecting\"\n ? {\n connectionId: state.connection.id,\n id: state.connection.userId,\n info: state.connection.userInfo,\n presence: getPresence(),\n }\n : null;\n }\n function connect() {\n if (typeof window === \"undefined\") {\n return;\n }\n if (state.connection.state !== \"closed\" &&\n state.connection.state !== \"unavailable\") {\n return null;\n }\n updateConnection({ state: \"authenticating\" });\n effects.authenticate();\n }\n function updatePresence(overrides) {\n const newPresence = Object.assign(Object.assign({}, state.me), overrides);\n if (state.flushData.presence == null) {\n state.flushData.presence = overrides;\n }\n else {\n for (const key in overrides) {\n state.flushData.presence[key] = overrides[key];\n }\n }\n state.me = newPresence;\n tryFlushing();\n for (const listener of state.listeners[\"my-presence\"]) {\n listener(state.me);\n }\n }\n function authenticationSuccess(token, socket) {\n updateConnection({\n state: \"connecting\",\n id: token.actor,\n userInfo: token.info,\n userId: token.id,\n });\n state.idFactory = makeIdFactory(token.actor);\n state.socket = socket;\n }\n function authenticationFailure(error) {\n console.error(error);\n updateConnection({ state: \"unavailable\" });\n state.numberOfRetry++;\n state.timeoutHandles.reconnect = effects.scheduleReconnect(getRetryDelay());\n }\n function onVisibilityChange(visibilityState) {\n if (visibilityState === \"visible\" && state.connection.state === \"open\") {\n log(\"Heartbeat after visibility change\");\n heartbeat();\n }\n }\n function onUpdatePresenceMessage(message) {\n const user = state.users[message.actor];\n if (user == null) {\n state.users[message.actor] = {\n connectionId: message.actor,\n presence: message.data,\n };\n }\n else {\n state.users[message.actor] = {\n id: user.id,\n info: user.info,\n connectionId: message.actor,\n presence: Object.assign(Object.assign({}, user.presence), message.data),\n };\n }\n updateUsers({\n type: \"update\",\n updates: message.data,\n user: state.users[message.actor],\n });\n }\n function updateUsers(event) {\n state.others = makeOthers(state.users);\n for (const listener of state.listeners[\"others\"]) {\n listener(state.others, event);\n }\n }\n function onUserLeftMessage(message) {\n const userLeftMessage = message;\n const user = state.users[userLeftMessage.actor];\n if (user) {\n delete state.users[userLeftMessage.actor];\n updateUsers({ type: \"leave\", user });\n }\n }\n function onRoomStateMessage(message) {\n const newUsers = {};\n for (const key in message.users) {\n const connectionId = Number.parseInt(key);\n const user = message.users[key];\n newUsers[connectionId] = {\n connectionId,\n info: user.info,\n id: user.id,\n };\n }\n state.users = newUsers;\n updateUsers({ type: \"reset\" });\n }\n function onNavigatorOnline() {\n if (state.connection.state === \"unavailable\") {\n log(\"Try to reconnect after connectivity change\");\n reconnect();\n }\n }\n function onEvent(message) {\n for (const listener of state.listeners.event) {\n listener({ connectionId: message.actor, event: message.event });\n }\n }\n function onUserJoinedMessage(message) {\n state.users[message.actor] = {\n connectionId: message.actor,\n info: message.info,\n id: message.id,\n };\n updateUsers({ type: \"enter\", user: state.users[message.actor] });\n if (state.me) {\n // Send current presence to new user\n // TODO: Consider storing it on the backend\n state.flushData.messages.push({\n type: ClientMessageType.UpdatePresence,\n data: state.me,\n targetActor: message.actor,\n });\n tryFlushing();\n }\n }\n function onMessage(event) {\n if (event.data === \"pong\") {\n clearTimeout(state.timeoutHandles.pongTimeout);\n return;\n }\n const message = JSON.parse(event.data);\n switch (message.type) {\n case ServerMessageType.InitialStorageState: {\n onInitialStorageState(message);\n break;\n }\n case ServerMessageType.UpdateStorage: {\n onStorageUpdates(message);\n break;\n }\n case ServerMessageType.UserJoined: {\n onUserJoinedMessage(message);\n break;\n }\n case ServerMessageType.UpdatePresence: {\n onUpdatePresenceMessage(message);\n break;\n }\n case ServerMessageType.Event: {\n onEvent(message);\n break;\n }\n case ServerMessageType.UserLeft: {\n onUserLeftMessage(message);\n break;\n }\n case ServerMessageType.RoomState: {\n onRoomStateMessage(message);\n break;\n }\n }\n }\n // function onWakeUp() {\n // // Sometimes, the browser can put the webpage on pause (computer is on sleep mode for example)\n // // The client will not know that the server has probably close the connection even if the readyState is Open\n // // One way to detect this kind of pause is to ensure that a setInterval is not taking more than the delay it was configured with\n // if (state.connection.state === \"open\") {\n // log(\"Try to reconnect after laptop wake up\");\n // reconnect();\n // }\n // }\n function onClose(event) {\n state.socket = null;\n clearTimeout(state.timeoutHandles.pongTimeout);\n clearInterval(state.intervalHandles.heartbeat);\n if (state.timeoutHandles.flush) {\n clearTimeout(state.timeoutHandles.flush);\n }\n clearTimeout(state.timeoutHandles.reconnect);\n state.users = {};\n updateUsers({ type: \"reset\" });\n if (event.code >= 4000 && event.code <= 4100) {\n updateConnection({ state: \"failed\" });\n const error = new LiveblocksError(event.reason, event.code);\n for (const listener of state.listeners.error) {\n listener(error);\n }\n }\n else if (event.wasClean === false) {\n updateConnection({ state: \"unavailable\" });\n state.numberOfRetry++;\n state.timeoutHandles.reconnect = effects.scheduleReconnect(getRetryDelay());\n }\n else {\n updateConnection({ state: \"closed\" });\n }\n }\n function updateConnection(connection) {\n state.connection = connection;\n for (const listener of state.listeners.connection) {\n listener(connection.state);\n }\n }\n function getRetryDelay() {\n return BACKOFF_RETRY_DELAYS[state.numberOfRetry < BACKOFF_RETRY_DELAYS.length\n ? state.numberOfRetry\n : BACKOFF_RETRY_DELAYS.length - 1];\n }\n function onError() { }\n function onOpen() {\n clearInterval(state.intervalHandles.heartbeat);\n state.intervalHandles.heartbeat = effects.startHeartbeatInterval();\n if (state.connection.state === \"connecting\") {\n updateConnection(Object.assign(Object.assign({}, state.connection), { state: \"open\" }));\n state.numberOfRetry = 0;\n tryFlushing();\n }\n else {\n // TODO\n }\n }\n function heartbeat() {\n if (state.socket == null) {\n // Should never happen, because we clear the pong timeout when the connection is dropped explictly\n return;\n }\n clearTimeout(state.timeoutHandles.pongTimeout);\n state.timeoutHandles.pongTimeout = effects.schedulePongTimeout();\n if (state.socket.readyState === WebSocket.OPEN) {\n state.socket.send(\"ping\");\n }\n }\n function pongTimeout() {\n log(\"Pong timeout. Trying to reconnect.\");\n reconnect();\n }\n function reconnect() {\n if (state.socket) {\n state.socket.removeEventListener(\"open\", onOpen);\n state.socket.removeEventListener(\"message\", onMessage);\n state.socket.removeEventListener(\"close\", onClose);\n state.socket.removeEventListener(\"error\", onError);\n state.socket.close();\n state.socket = null;\n }\n updateConnection({ state: \"unavailable\" });\n clearTimeout(state.timeoutHandles.pongTimeout);\n if (state.timeoutHandles.flush) {\n clearTimeout(state.timeoutHandles.flush);\n }\n clearTimeout(state.timeoutHandles.reconnect);\n clearInterval(state.intervalHandles.heartbeat);\n connect();\n }\n function tryFlushing() {\n if (state.socket == null) {\n return;\n }\n if (state.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n const now = Date.now();\n const elapsedTime = now - state.lastFlushTime;\n if (elapsedTime > context.throttleDelay) {\n const messages = flushDataToMessages(state);\n if (messages.length === 0) {\n return;\n }\n effects.send(messages);\n state.flushData = {\n messages: [],\n storageOperations: [],\n presence: null,\n };\n state.lastFlushTime = now;\n }\n else {\n if (state.timeoutHandles.flush != null) {\n clearTimeout(state.timeoutHandles.flush);\n }\n state.timeoutHandles.flush = effects.delayFlush(context.throttleDelay - (now - state.lastFlushTime));\n }\n }\n function flushDataToMessages(state) {\n const messages = [];\n if (state.flushData.presence) {\n messages.push({\n type: ClientMessageType.UpdatePresence,\n data: state.flushData.presence,\n });\n }\n for (const event of state.flushData.messages) {\n messages.push(event);\n }\n if (state.flushData.storageOperations.length > 0) {\n messages.push({\n type: ClientMessageType.UpdateStorage,\n ops: state.flushData.storageOperations,\n });\n }\n return messages;\n }\n function disconnect() {\n if (state.socket) {\n state.socket.removeEventListener(\"open\", onOpen);\n state.socket.removeEventListener(\"message\", onMessage);\n state.socket.removeEventListener(\"close\", onClose);\n state.socket.removeEventListener(\"error\", onError);\n state.socket.close();\n state.socket = null;\n }\n updateConnection({ state: \"closed\" });\n if (state.timeoutHandles.flush) {\n clearTimeout(state.timeoutHandles.flush);\n }\n clearTimeout(state.timeoutHandles.reconnect);\n clearTimeout(state.timeoutHandles.pongTimeout);\n clearInterval(state.intervalHandles.heartbeat);\n state.users = {};\n updateUsers({ type: \"reset\" });\n clearListeners();\n }\n function clearListeners() {\n for (const key in state.listeners) {\n state.listeners[key] = [];\n }\n }\n function getPresence() {\n return state.me;\n }\n function getOthers() {\n return state.others;\n }\n function broadcastEvent(event) {\n if (state.socket == null) {\n return;\n }\n state.flushData.messages.push({\n type: ClientMessageType.ClientEvent,\n event,\n });\n tryFlushing();\n }\n /**\n * STORAGE\n */\n function onStorageUpdates(message) {\n if (state.doc == null) {\n // TODO: Cache updates in case they are coming while root is queried\n return;\n }\n updateDoc(message.ops.reduce((doc, op) => doc.dispatch(op), state.doc));\n }\n function updateDoc(doc) {\n state.doc = doc;\n if (doc) {\n for (const listener of state.listeners.storage) {\n listener(getStorage());\n }\n }\n }\n function getStorage() {\n if (state.storageState === LiveStorageState.Loaded) {\n return {\n state: state.storageState,\n root: state.doc.root,\n };\n }\n return {\n state: state.storageState,\n };\n }\n function onInitialStorageState(message) {\n state.storageState = LiveStorageState.Loaded;\n if (message.root == null) {\n const rootId = makeId();\n state.doc = Doc.empty(rootId, (op) => dispatch(op));\n updateDoc(state.doc.updateRecord(rootId, state.initialStorageFactory({\n createRecord: (data) => createRecord(data),\n createList: () => createList(),\n })));\n }\n else {\n updateDoc(Doc.load(message.root, (op) => dispatch(op)));\n }\n }\n function makeId() {\n if (state.idFactory == null) {\n throw new Error(\"Can't generate id. Id factory is missing.\");\n }\n return state.idFactory();\n }\n function dispatch(op) {\n state.flushData.storageOperations.push(op);\n tryFlushing();\n }\n function createRecord(data) {\n return innerCreateRecord(makeId(), data);\n }\n function createList() {\n return innerCreateList(makeId());\n }\n function fetchStorage(initialStorageFactory) {\n state.initialStorageFactory = initialStorageFactory;\n state.storageState = LiveStorageState.Loading;\n state.flushData.messages.push({ type: ClientMessageType.FetchStorage });\n tryFlushing();\n }\n function updateRecord(record, overrides) {\n updateDoc(state.doc.updateRecord(record.id, overrides));\n }\n function pushItem(list, item) {\n updateDoc(state.doc.pushItem(list.id, item));\n }\n function deleteItem(list, index) {\n updateDoc(state.doc.deleteItem(list.id, index));\n }\n function deleteItemById(list, itemId) {\n updateDoc(state.doc.deleteItemById(list.id, itemId));\n }\n function moveItem(list, index, targetIndex) {\n updateDoc(state.doc.moveItem(list.id, index, targetIndex));\n }\n return {\n // Internal\n onOpen,\n onClose,\n onMessage,\n authenticationSuccess,\n heartbeat,\n onNavigatorOnline,\n // onWakeUp,\n onVisibilityChange,\n // Core\n connect,\n disconnect,\n subscribe,\n unsubscribe,\n // Presence\n updatePresence,\n broadcastEvent,\n // Storage\n fetchStorage,\n createRecord,\n updateRecord,\n createList,\n pushItem,\n deleteItem,\n deleteItemById,\n moveItem,\n selectors: {\n // Core\n getConnectionState,\n getSelf,\n // Presence\n getPresence,\n getOthers,\n // Storage\n getStorage,\n },\n };\n}\nexport function defaultState(me) {\n return {\n connection: { state: \"closed\" },\n socket: null,\n listeners: {\n storage: [],\n event: [],\n others: [],\n \"my-presence\": [],\n error: [],\n connection: [],\n },\n numberOfRetry: 0,\n lastFlushTime: 0,\n timeoutHandles: {\n flush: null,\n reconnect: 0,\n pongTimeout: 0,\n },\n flushData: {\n presence: me == null ? {} : me,\n messages: [],\n storageOperations: [],\n },\n intervalHandles: {\n heartbeat: 0,\n },\n me: me == null ? {} : me,\n users: {},\n others: makeOthers({}),\n storageState: LiveStorageState.NotInitialized,\n initialStorageFactory: null,\n doc: null,\n idFactory: null,\n };\n}\nexport function createRoom(name, options) {\n const throttleDelay = options.throttle || 100;\n const liveblocksServer = options.liveblocksServer || \"wss://liveblocks.net\";\n const authEndpoint = options.authEndpoint;\n const state = defaultState(options.initialPresence);\n const machine = makeStateMachine(state, {\n throttleDelay,\n liveblocksServer,\n authEndpoint,\n room: name,\n });\n const room = {\n /////////////\n // Core //\n /////////////\n getConnectionState: machine.selectors.getConnectionState,\n getSelf: machine.selectors.getSelf,\n subscribe: machine.subscribe,\n unsubscribe: machine.unsubscribe,\n /////////////\n // Storage //\n /////////////\n getStorage: machine.selectors.getStorage,\n fetchStorage: machine.fetchStorage,\n createRecord: machine.createRecord,\n createList: machine.createList,\n updateRecord: machine.updateRecord,\n pushItem: machine.pushItem,\n deleteItem: machine.deleteItem,\n deleteItemById: machine.deleteItemById,\n moveItem: machine.moveItem,\n //////////////\n // Presence //\n //////////////\n getPresence: machine.selectors.getPresence,\n updatePresence: machine.updatePresence,\n getOthers: machine.selectors.getOthers,\n broadcastEvent: machine.broadcastEvent,\n };\n return {\n connect: machine.connect,\n disconnect: machine.disconnect,\n onNavigatorOnline: machine.onNavigatorOnline,\n onVisibilityChange: machine.onVisibilityChange,\n room,\n };\n}\nclass LiveblocksError extends Error {\n constructor(message, code) {\n super(message);\n this.code = code;\n }\n}\n","import {\n Client,\n RecordData,\n Others,\n Presence,\n Record,\n InitialStorageFactory,\n List,\n Room,\n LiveStorageState,\n User,\n} from \"@liveblocks/client\";\nimport * as React from \"react\";\n\ntype LiveblocksProviderProps = {\n children: React.ReactNode;\n client: Client;\n};\n\nconst ClientContext = React.createContext<Client | null>(null);\nconst RoomContext = React.createContext<Room | null>(null);\n\n/**\n * Makes the Liveblocks client available in the component hierarchy below.\n */\nexport function LiveblocksProvider(props: LiveblocksProviderProps) {\n return (\n <ClientContext.Provider value={props.client}>\n {props.children}\n </ClientContext.Provider>\n );\n}\n\n/**\n * Returns the client of the nearest LiveblocksProvider above in the react component tree\n */\nfunction useClient(): Client {\n const client = React.useContext(ClientContext);\n if (client == null) {\n throw new Error(\"LiveblocksProvider is missing from the react tree\");\n }\n\n return client;\n}\n\ntype RoomProviderProps = {\n /**\n * The id of the room you want to connect to\n */\n id: string;\n /**\n * A callback that let you initialize the default presence when entering the room.\n * If ommited, the default presence will be an empty object\n */\n defaultPresence?: () => Presence;\n\n children: React.ReactNode;\n};\n\n/**\n * Makes a Room available in the component hierarchy below.\n * When this component is unmounted, the current user leave the room.\n * That means that you can't have 2 RoomProvider with the same room id in your react tree.\n */\nexport function RoomProvider({\n id,\n children,\n defaultPresence,\n}: RoomProviderProps) {\n const client = useClient();\n\n React.useEffect(() => {\n return () => {\n client.leave(id);\n };\n }, [client, id]);\n\n const room =\n client.getRoom(id) ||\n client.enter(id, defaultPresence ? defaultPresence() : undefined);\n\n return <RoomContext.Provider value={room}>{children}</RoomContext.Provider>;\n}\n\n/**\n * Returns the room of the nearest RoomProvider above in the react component tree\n */\nfunction useRoom() {\n const room = React.useContext(RoomContext);\n\n if (room == null) {\n throw new Error(\"RoomProvider is missing from the react tree\");\n }\n\n return room;\n}\n\n/**\n * Returns the presence of the current user of the current room, and a function to update it.\n * It is different from the setState function returned by the useState hook from React.\n * You don't need to pass the full presence object to update it.\n *\n * ### Example\n * ``` typescript\n * import { useMyPresence } from \"@liveblocks/react\";\n *\n * const [myPresence, updateMyPresence] = useMyPresence();\n * updateMyPresence({ x: 0 });\n * updateMyPresence({ y: 0 });\n *\n * // At the next render, \"myPresence\" will be equal to \"{ x: 0, y: 0 }\"\n * ```\n */\nexport function useMyPresence<T extends Presence>(): [\n T,\n (overrides: Partial<T>) => void\n] {\n const room = useRoom();\n const presence = room.getPresence<T>();\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onMyPresenceChange() {\n update((x) => x + 1);\n }\n\n room.subscribe(\"my-presence\", onMyPresenceChange);\n\n return () => {\n room.unsubscribe(\"my-presence\", onMyPresenceChange);\n };\n }, [room]);\n\n const setPresence = React.useCallback(\n (overrides: Partial<T>) => room.updatePresence(overrides),\n [room]\n );\n\n return [presence, setPresence];\n}\n\n/**\n * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.\n * 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.\n *\n * ### Example\n * ``` typescript\n * import { useUpdateMyPresence } from \"@liveblocks/react\";\n *\n * const updateMyPresence = useUpdateMyPresence();\n * updateMyPresence({ x: 0 });\n * updateMyPresence({ y: 0 });\n *\n * // At the next render, the presence of the current user will be equal to \"{ x: 0, y: 0 }\"\n * ```\n */\nexport function useUpdateMyPresence<T extends Presence>(): (\n overrides: Partial<T>\n) => void {\n const room = useRoom();\n\n return React.useCallback(\n (overrides: Partial<T>) => {\n room.updatePresence(overrides);\n },\n [room]\n );\n}\n\n/**\n * Returns an object that lets you get information about all the the users currently connected in the room.\n *\n * ### Example\n * ``` typescript\n * import { useOthers } from \"@liveblocks/react\";\n *\n * const others = useOthers();\n *\n * // Example to map all cursors in jsx\n * {\n * others.map(({ connectionId, presence }) => {\n * if(presence == null || presence.cursor == null) {\n * return null;\n * }\n * return <Cursor key={connectionId} cursor={presence.cursor} />\n * })\n * }\n * ```\n */\nexport function useOthers<T extends Presence>(): Others<T> {\n const room = useRoom();\n\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onOthersChange() {\n update((x) => x + 1);\n }\n\n room.subscribe(\"others\", onOthersChange);\n\n return () => {\n room.subscribe(\"others\", onOthersChange);\n };\n }, [room]);\n\n return room.getOthers();\n}\n\n/**\n * Returns a callback that lets you broadcast custom events to other users in the room\n *\n * ### Example\n * ``` typescript\n * import { useBroadcastEvent } from \"@liveblocks/react\";\n *\n * const broadcast = useBroadcastEvent();\n *\n * broadcast({ type: \"CUSTOM_EVENT\", data: { x: 0, y: 0 } });\n * ```\n */\nexport function useBroadcastEvent() {\n const room = useRoom();\n\n return React.useCallback(\n (event: any) => {\n room.broadcastEvent(event);\n },\n [room]\n );\n}\n\n/**\n * useErrorListener is a react hook that lets you react to potential room connection errors.\n *\n * ### Example\n * ``` typescript\n * import { useErrorListener } from \"@liveblocks/react\";\n *\n * useErrorListener(er => {\n * console.error(er);\n * })\n * ```\n */\nexport function useErrorListener(callback: (er: Error) => void) {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (e: Error) => savedCallback.current(e);\n\n room.subscribe(\"error\", listener);\n\n return () => {\n room.unsubscribe(\"error\", listener);\n };\n }, [room]);\n}\n\n/**\n * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.\n *\n * ### Example\n * ``` typescript\n * import { useEventListener } from \"@liveblocks/react\";\n *\n * useEventListener(({ connectionId, event }) => {\n * if (event.type === \"CUSTOM_EVENT\") {\n * // Do something\n * }\n * });\n * ```\n */\nexport function useEventListener<TEvent>(\n callback: ({\n connectionId,\n event,\n }: {\n connectionId: number;\n event: TEvent;\n }) => void\n) {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (e: { connectionId: number; event: TEvent }) =>\n savedCallback.current(e);\n\n room.subscribe(\"event\", listener);\n\n return () => {\n room.unsubscribe(\"event\", listener);\n };\n }, [room]);\n}\n\n/**\n * Gets the current user once it is connected to the room.\n *\n * ### Example\n * ``` typescript\n * import { useSelf } from \"@liveblocks/react\";\n *\n * const user = useSelf();\n * ```\n */\nexport function useSelf<\n TPresence extends Presence = Presence\n>(): User<TPresence> | null {\n const room = useRoom();\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onChange() {\n update((x) => x + 1);\n }\n\n room.subscribe(\"my-presence\", onChange);\n room.subscribe(\"connection\", onChange);\n\n return () => {\n room.unsubscribe(\"my-presence\", onChange);\n room.unsubscribe(\"connection\", onChange);\n };\n }, [room]);\n\n return room.getSelf<TPresence>();\n}\n\ntype StorageActions = {\n createRecord: Room[\"createRecord\"];\n updateRecord: Room[\"updateRecord\"];\n\n createList: Room[\"createList\"];\n moveItem: Room[\"moveItem\"];\n deleteItem: Room[\"deleteItem\"];\n deleteItemById: Room[\"deleteItemById\"];\n pushItem: Room[\"pushItem\"];\n};\n\nexport function useStorage<TRoot extends RecordData>(\n initialStorage: InitialStorageFactory<TRoot>\n): [root: Record<TRoot> | null, actions: StorageActions] {\n const room = useRoom();\n const storage = room.getStorage();\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onStorageChange() {\n update((x) => x + 1);\n }\n\n room.fetchStorage(initialStorage);\n room.subscribe(\"storage\", onStorageChange);\n\n return () => {\n room.unsubscribe(\"storage\", onStorageChange);\n };\n }, [room]);\n\n const root =\n storage.state === LiveStorageState.Loaded\n ? (storage.root as Record<TRoot>)\n : null;\n\n const actions = useStorageActions();\n return [root, actions];\n}\n\nexport function useStorageActions(): StorageActions {\n const room = useRoom();\n return React.useMemo(() => {\n function createRecord<T extends RecordData>(data: T) {\n return room.createRecord<T>(data);\n }\n\n function updateRecord<T extends RecordData>(\n record: Record<T>,\n overrides: Partial<T>\n ) {\n return room.updateRecord<T>(record, overrides);\n }\n\n function createList<T extends RecordData>(): List<Record<T>> {\n return room.createList<T>();\n }\n\n function moveItem<T extends RecordData>(\n list: List<Record<T>>,\n index: number,\n targetIndex: number\n ) {\n return room.moveItem<T>(list, index, targetIndex);\n }\n\n function deleteItem<T extends RecordData>(\n list: List<Record<T>>,\n index: number\n ) {\n return room.deleteItem<T>(list, index);\n }\n\n function deleteItemById<T extends RecordData>(\n list: List<Record<T>>,\n itemId: string\n ) {\n return room.deleteItemById<T>(list, itemId);\n }\n\n function pushItem<T extends RecordData>(\n list: List<Record<T>>,\n item: Record<T>\n ) {\n return room.pushItem<T>(list, item);\n }\n\n return {\n createRecord,\n updateRecord,\n\n createList,\n moveItem,\n deleteItem,\n deleteItemById,\n pushItem,\n };\n }, [room]);\n}\n"],"names":["this","React.createContext","React.createElement","React.useContext","React.useEffect","React.useState","React.useCallback","React.useRef","React.useMemo"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import {\n Client,\n Others,\n Presence,\n LiveObject,\n LiveMap,\n Room,\n User,\n LiveList,\n} from \"@liveblocks/client\";\nimport * as React from \"react\";\n\ntype LiveblocksProviderProps = {\n children: React.ReactNode;\n client: Client;\n};\n\nconst ClientContext = React.createContext<Client | null>(null);\nconst RoomContext = React.createContext<Room | null>(null);\n\n/**\n * Makes the Liveblocks client available in the component hierarchy below.\n */\nexport function LiveblocksProvider(props: LiveblocksProviderProps) {\n return (\n <ClientContext.Provider value={props.client}>\n {props.children}\n </ClientContext.Provider>\n );\n}\n\n/**\n * Returns the client of the nearest LiveblocksProvider above in the react component tree\n */\nfunction useClient(): Client {\n const client = React.useContext(ClientContext);\n if (client == null) {\n throw new Error(\"LiveblocksProvider is missing from the react tree\");\n }\n\n return client;\n}\n\ntype RoomProviderProps<TStorageRoot> = {\n /**\n * The id of the room you want to connect to\n */\n id: string;\n /**\n * A callback that let you initialize the default presence when entering the room.\n * If ommited, the default presence will be an empty object\n */\n defaultPresence?: () => Presence;\n\n defaultStorageRoot?: TStorageRoot;\n\n children: React.ReactNode;\n};\n\n/**\n * Makes a Room available in the component hierarchy below.\n * When this component is unmounted, the current user leave the room.\n * That means that you can't have 2 RoomProvider with the same room id in your react tree.\n */\nexport function RoomProvider<TStorageRoot>({\n id,\n children,\n defaultPresence,\n defaultStorageRoot,\n}: RoomProviderProps<TStorageRoot>) {\n const client = useClient();\n\n React.useEffect(() => {\n return () => {\n client.leave(id);\n };\n }, [client, id]);\n\n const room =\n client.getRoom(id) ||\n client.enter(id, {\n defaultPresence: defaultPresence ? defaultPresence() : undefined,\n defaultStorageRoot,\n });\n\n return <RoomContext.Provider value={room}>{children}</RoomContext.Provider>;\n}\n\n/**\n * Returns the room of the nearest RoomProvider above in the react component tree\n */\nfunction useRoom() {\n const room = React.useContext(RoomContext);\n\n if (room == null) {\n throw new Error(\"RoomProvider is missing from the react tree\");\n }\n\n return room;\n}\n\n/**\n * Returns the presence of the current user of the current room, and a function to update it.\n * It is different from the setState function returned by the useState hook from React.\n * You don't need to pass the full presence object to update it.\n *\n * @example\n * import { useMyPresence } from \"@liveblocks/react\";\n *\n * const [myPresence, updateMyPresence] = useMyPresence();\n * updateMyPresence({ x: 0 });\n * updateMyPresence({ y: 0 });\n *\n * // At the next render, \"myPresence\" will be equal to \"{ x: 0, y: 0 }\"\n */\nexport function useMyPresence<T extends Presence>(): [\n T,\n (overrides: Partial<T>) => void\n] {\n const room = useRoom();\n const presence = room.getPresence<T>();\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onMyPresenceChange() {\n update((x) => x + 1);\n }\n\n room.subscribe(\"my-presence\", onMyPresenceChange);\n\n return () => {\n room.unsubscribe(\"my-presence\", onMyPresenceChange);\n };\n }, [room]);\n\n const setPresence = React.useCallback(\n (overrides: Partial<T>) => room.updatePresence(overrides),\n [room]\n );\n\n return [presence, setPresence];\n}\n\n/**\n * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.\n * 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.\n *\n * @example\n * import { useUpdateMyPresence } from \"@liveblocks/react\";\n *\n * const updateMyPresence = useUpdateMyPresence();\n * updateMyPresence({ x: 0 });\n * updateMyPresence({ y: 0 });\n *\n * // At the next render, the presence of the current user will be equal to \"{ x: 0, y: 0 }\"\n */\nexport function useUpdateMyPresence<T extends Presence>(): (\n overrides: Partial<T>\n) => void {\n const room = useRoom();\n\n return React.useCallback(\n (overrides: Partial<T>) => {\n room.updatePresence(overrides);\n },\n [room]\n );\n}\n\n/**\n * Returns an object that lets you get information about all the the users currently connected in the room.\n *\n * @example\n * import { useOthers } from \"@liveblocks/react\";\n *\n * const others = useOthers();\n *\n * // Example to map all cursors in jsx\n * {\n * others.map(({ connectionId, presence }) => {\n * if(presence == null || presence.cursor == null) {\n * return null;\n * }\n * return <Cursor key={connectionId} cursor={presence.cursor} />\n * })\n * }\n */\nexport function useOthers<T extends Presence>(): Others<T> {\n const room = useRoom();\n\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onOthersChange() {\n update((x) => x + 1);\n }\n\n room.subscribe(\"others\", onOthersChange);\n\n return () => {\n room.subscribe(\"others\", onOthersChange);\n };\n }, [room]);\n\n return room.getOthers();\n}\n\n/**\n * Returns a callback that lets you broadcast custom events to other users in the room\n *\n * @example\n * import { useBroadcastEvent } from \"@liveblocks/react\";\n *\n * const broadcast = useBroadcastEvent();\n *\n * broadcast({ type: \"CUSTOM_EVENT\", data: { x: 0, y: 0 } });\n */\nexport function useBroadcastEvent() {\n const room = useRoom();\n\n return React.useCallback(\n (event: any) => {\n room.broadcastEvent(event);\n },\n [room]\n );\n}\n\n/**\n * useErrorListener is a react hook that lets you react to potential room connection errors.\n *\n * @example\n * import { useErrorListener } from \"@liveblocks/react\";\n *\n * useErrorListener(er => {\n * console.error(er);\n * })\n */\nexport function useErrorListener(callback: (er: Error) => void) {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (e: Error) => savedCallback.current(e);\n\n room.subscribe(\"error\", listener);\n\n return () => {\n room.unsubscribe(\"error\", listener);\n };\n }, [room]);\n}\n\n/**\n * useEventListener is a react hook that lets you react to event broadcasted by other users in the room.\n *\n * @example\n * import { useEventListener } from \"@liveblocks/react\";\n *\n * useEventListener(({ connectionId, event }) => {\n * if (event.type === \"CUSTOM_EVENT\") {\n * // Do something\n * }\n * });\n */\nexport function useEventListener<TEvent>(\n callback: ({\n connectionId,\n event,\n }: {\n connectionId: number;\n event: TEvent;\n }) => void\n) {\n const room = useRoom();\n const savedCallback = React.useRef(callback);\n\n React.useEffect(() => {\n savedCallback.current = callback;\n });\n\n React.useEffect(() => {\n const listener = (e: { connectionId: number; event: TEvent }) =>\n savedCallback.current(e);\n\n room.subscribe(\"event\", listener);\n\n return () => {\n room.unsubscribe(\"event\", listener);\n };\n }, [room]);\n}\n\n/**\n * Gets the current user once it is connected to the room.\n *\n * @example\n * import { useSelf } from \"@liveblocks/react\";\n *\n * const user = useSelf();\n */\nexport function useSelf<\n TPresence extends Presence = Presence\n>(): User<TPresence> | null {\n const room = useRoom();\n const [, update] = React.useState(0);\n\n React.useEffect(() => {\n function onChange() {\n update((x) => x + 1);\n }\n\n room.subscribe(\"my-presence\", onChange);\n room.subscribe(\"connection\", onChange);\n\n return () => {\n room.unsubscribe(\"my-presence\", onChange);\n room.unsubscribe(\"connection\", onChange);\n };\n }, [room]);\n\n return room.getSelf<TPresence>();\n}\n\nexport function useStorage<TRoot extends Record<string, any>>(): [\n root: LiveObject<TRoot> | null\n] {\n const room = useRoom();\n const [root, setState] = React.useState<LiveObject<TRoot> | null>(null);\n\n React.useEffect(() => {\n async function fetchStorage() {\n const storage = await room.getStorage<TRoot>();\n setState(storage.root);\n }\n\n fetchStorage();\n\n return () => {};\n }, [room]);\n\n return [root];\n}\n\nexport function useMap<TKey extends string, TValue>(\n key: string\n): LiveMap<TKey, TValue> | null {\n const [root] = useStorage();\n const [, setCount] = React.useState(0);\n\n React.useEffect(() => {\n if (root == null) {\n return;\n }\n\n let map: LiveMap<TKey, TValue> = root.get(key);\n\n if (map == null) {\n map = new LiveMap();\n root.set(key, map);\n }\n\n function onChange() {\n setCount((x) => x + 1);\n }\n\n map.subscribe(onChange);\n\n setCount((x) => x + 1);\n\n return () => {\n return map.unsubscribe(onChange);\n };\n }, [root]);\n\n return root?.get(key) ?? null;\n}\n\nexport function useList<TValue>(\n key: string,\n): LiveList<TValue> | null {\n const [root] = useStorage();\n const [, setCount] = React.useState(0);\n\n React.useEffect(() => {\n if (root == null) {\n return;\n }\n\n let list: LiveList<TValue> = root.get(key);\n\n if (list == null) {\n list = new LiveList();\n root.set(key, list);\n }\n\n function onChange() {\n setCount((x) => x + 1);\n }\n\n list.subscribe(onChange);\n\n setCount((x) => x + 1);\n\n return () => {\n return list.unsubscribe(onChange);\n };\n }, [root]);\n\n return root?.get(key) ?? null;\n}\n\nexport function useObject<TData>(\n key: string\n): LiveObject<TData> | null {\n const [root] = useStorage();\n const [, setCount] = React.useState(0);\n\n React.useEffect(() => {\n if (root == null) {\n return;\n }\n\n let obj: LiveObject<TData> = root.get(key);\n\n if (obj == null) {\n obj = new LiveObject();\n root.set(key, obj);\n }\n\n function onChange() {\n setCount((x) => x + 1);\n }\n\n obj.subscribe(onChange);\n\n setCount((x) => x + 1);\n\n return () => {\n return obj.unsubscribe(onChange);\n };\n }, [root]);\n\n return root?.get(key) ?? null;\n}\n"],"names":["React.createContext","React.createElement","React.useContext","React.useEffect","React.useState","React.useCallback","React.useRef","LiveMap","LiveList","LiveObject"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/react",
3
- "version": "0.11.0",
3
+ "version": "0.12.0-beta.12",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "license": "Apache-2.0",
25
25
  "peerDependencies": {
26
- "@liveblocks/client": "0.11.0",
26
+ "@liveblocks/client": "0.12.0-beta.12",
27
27
  "react": "^16.14.0 || ^17"
28
28
  },
29
29
  "devDependencies": {