@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 +2 -12
- package/lib/index.d.ts +17 -35
- package/lib/index.js +149 -133
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
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
|
-
|
|
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,
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
(
|
|
55
|
-
|
|
56
|
-
|
|
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,
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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(
|
|
280
|
+
function useStorage() {
|
|
307
281
|
var room = useRoom();
|
|
308
|
-
var
|
|
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
|
|
312
|
-
|
|
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
|
-
|
|
315
|
-
|
|
316
|
-
return function () {
|
|
317
|
-
room.unsubscribe("storage", onStorageChange);
|
|
318
|
-
};
|
|
298
|
+
fetchStorage();
|
|
299
|
+
return function () { };
|
|
319
300
|
}, [room]);
|
|
320
|
-
|
|
321
|
-
? storage.root
|
|
322
|
-
: null;
|
|
323
|
-
var actions = useStorageActions();
|
|
324
|
-
return [root, actions];
|
|
301
|
+
return [root];
|
|
325
302
|
}
|
|
326
|
-
function
|
|
327
|
-
var
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
|
333
|
-
|
|
316
|
+
function onChange() {
|
|
317
|
+
setCount(function (x) { return x + 1; });
|
|
334
318
|
}
|
|
335
|
-
|
|
336
|
-
|
|
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
|
|
339
|
-
|
|
340
|
+
function onChange() {
|
|
341
|
+
setCount(function (x) { return x + 1; });
|
|
340
342
|
}
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
|
|
345
|
-
|
|
359
|
+
var obj = root.get(key);
|
|
360
|
+
if (obj == null) {
|
|
361
|
+
obj = new client.LiveObject();
|
|
362
|
+
root.set(key, obj);
|
|
346
363
|
}
|
|
347
|
-
function
|
|
348
|
-
|
|
364
|
+
function onChange() {
|
|
365
|
+
setCount(function (x) { return x + 1; });
|
|
349
366
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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
|
-
}, [
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,IAAM,aAAa,GAAGA,mBAAmB,CAAgB,IAAI,CAAC,CAAC;AAC/D,IAAM,WAAW,GAAGA,mBAAmB,CAAc,IAAI,CAAC,CAAC;AAE3D;;;SAGgB,kBAAkB,CAAC,KAA8B;IAC/D,QACEC,oBAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,CAAC,MAAM,IACxC,KAAK,CAAC,QAAQ,CACQ,EACzB;AACJ,CAAC;AAED;;;AAGA,SAAS,SAAS;IAChB,IAAM,MAAM,GAAGC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAC/C,IAAI,MAAM,IAAI,IAAI,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;KACtE;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAkBD;;;;;SAKgB,YAAY,CAAe,EAKT;QAJhC,EAAE,QAAA,EACF,QAAQ,cAAA,EACR,eAAe,qBAAA,EACf,kBAAkB,wBAAA;IAElB,IAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3BC,eAAe,CAAC;QACd,OAAO;YACL,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SAClB,CAAC;KACH,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IAEjB,IAAM,IAAI,GACR,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;YACf,eAAe,EAAE,eAAe,GAAG,eAAe,EAAE,GAAG,SAAS;YAChE,kBAAkB,oBAAA;SACnB,CAAC,CAAC;IAEL,OAAOF,oBAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,IAAG,QAAQ,CAAwB,CAAC;AAC9E,CAAC;AAED;;;AAGA,SAAS,OAAO;IACd,IAAM,IAAI,GAAGC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAE3C,IAAI,IAAI,IAAI,IAAI,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;KAChE;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;SAcgB,aAAa;IAI3B,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAK,CAAC;IACjC,IAAA,KAAaE,cAAc,CAAC,CAAC,CAAC,EAA3B,MAAM,QAAqB,CAAC;IAErCD,eAAe,CAAC;QACd,SAAS,kBAAkB;YACzB,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;SACtB;QAED,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;QAElD,OAAO;YACL,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;SACrD,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,IAAM,WAAW,GAAGE,iBAAiB,CACnC,UAAC,SAAqB,IAAK,OAAA,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAA,EACzD,CAAC,IAAI,CAAC,CACP,CAAC;IAEF,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;SAagB,mBAAmB;IAGjC,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,OAAOA,iBAAiB,CACtB,UAAC,SAAqB;QACpB,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;KAChC,EACD,CAAC,IAAI,CAAC,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;SAkBgB,SAAS;IACvB,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEjB,IAAA,KAAaD,cAAc,CAAC,CAAC,CAAC,EAA3B,MAAM,QAAqB,CAAC;IAErCD,eAAe,CAAC;QACd,SAAS,cAAc;YACrB,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;SACtB;QAED,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAEzC,OAAO;YACL,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;SAC1C,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;SAUgB,iBAAiB;IAC/B,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,OAAOE,iBAAiB,CACtB,UAAC,KAAU;QACT,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;KAC5B,EACD,CAAC,IAAI,CAAC,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;SAUgB,gBAAgB,CAAC,QAA6B;IAC5D,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAM,aAAa,GAAGC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE7CH,eAAe,CAAC;QACd,aAAa,CAAC,OAAO,GAAG,QAAQ,CAAC;KAClC,CAAC,CAAC;IAEHA,eAAe,CAAC;QACd,IAAM,QAAQ,GAAG,UAAC,CAAQ,IAAK,OAAA,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAA,CAAC;QAExD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAElC,OAAO;YACL,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;SACrC,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;SAYgB,gBAAgB,CAC9B,QAMU;IAEV,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAM,aAAa,GAAGG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE7CH,eAAe,CAAC;QACd,aAAa,CAAC,OAAO,GAAG,QAAQ,CAAC;KAClC,CAAC,CAAC;IAEHA,eAAe,CAAC;QACd,IAAM,QAAQ,GAAG,UAAC,CAA0C;YAC1D,OAAA,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;SAAA,CAAC;QAE3B,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAElC,OAAO;YACL,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;SACrC,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC;AAED;;;;;;;;SAQgB,OAAO;IAGrB,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACjB,IAAA,KAAaC,cAAc,CAAC,CAAC,CAAC,EAA3B,MAAM,QAAqB,CAAC;IAErCD,eAAe,CAAC;QACd,SAAS,QAAQ;YACf,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;SACtB;QAED,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAEvC,OAAO;YACL,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;SAC1C,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,IAAI,CAAC,OAAO,EAAa,CAAC;AACnC,CAAC;SAEe,UAAU;IAGxB,IAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACjB,IAAA,KAAmBC,cAAc,CAA2B,IAAI,CAAC,EAAhE,IAAI,QAAA,EAAE,QAAQ,QAAkD,CAAC;IAExED,eAAe,CAAC;QACd,SAAe,YAAY;;;;;gCACT,qBAAM,IAAI,CAAC,UAAU,EAAS,EAAA;;4BAAxC,OAAO,GAAG,SAA8B;4BAC9C,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;;;;;SACxB;QAED,YAAY,EAAE,CAAC;QAEf,OAAO,eAAQ,CAAC;KACjB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;SAEe,MAAM,CACpB,GAAW;;IAEJ,IAAA,IAAI,GAAI,UAAU,EAAE,GAAhB,CAAiB;IACtB,IAAA,KAAeC,cAAc,CAAC,CAAC,CAAC,EAA7B,QAAQ,QAAqB,CAAC;IAEvCD,eAAe,CAAC;QACd,IAAI,IAAI,IAAI,IAAI,EAAE;YAChB,OAAO;SACR;QAED,IAAI,GAAG,GAA0B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE/C,IAAI,GAAG,IAAI,IAAI,EAAE;YACf,GAAG,GAAG,IAAII,cAAO,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;SACpB;QAED,SAAS,QAAQ;YACf,QAAQ,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;SACxB;QAED,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAExB,QAAQ,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;QAEvB,OAAO;YACL,OAAO,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;SAClC,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,aAAO,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,CAAC,GAAG,oCAAK,IAAI,CAAC;AAChC,CAAC;SAEe,OAAO,CACrB,GAAW;;IAEJ,IAAA,IAAI,GAAI,UAAU,EAAE,GAAhB,CAAiB;IACtB,IAAA,KAAeH,cAAc,CAAC,CAAC,CAAC,EAA7B,QAAQ,QAAqB,CAAC;IAEvCD,eAAe,CAAC;QACd,IAAI,IAAI,IAAI,IAAI,EAAE;YAChB,OAAO;SACR;QAED,IAAI,IAAI,GAAqB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,IAAI,IAAI,IAAI,EAAE;YAChB,IAAI,GAAG,IAAIK,eAAQ,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;SACrB;QAED,SAAS,QAAQ;YACf,QAAQ,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;SACxB;QAED,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEzB,QAAQ,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;QAEvB,OAAO;YACL,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;SACnC,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,aAAO,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,CAAC,GAAG,oCAAK,IAAI,CAAC;AAChC,CAAC;SAEe,SAAS,CACvB,GAAW;;IAEJ,IAAA,IAAI,GAAI,UAAU,EAAE,GAAhB,CAAiB;IACtB,IAAA,KAAeJ,cAAc,CAAC,CAAC,CAAC,EAA7B,QAAQ,QAAqB,CAAC;IAEvCD,eAAe,CAAC;QACd,IAAI,IAAI,IAAI,IAAI,EAAE;YAChB,OAAO;SACR;QAED,IAAI,GAAG,GAAsB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,GAAG,IAAI,IAAI,EAAE;YACf,GAAG,GAAG,IAAIM,iBAAU,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;SACpB;QAED,SAAS,QAAQ;YACf,QAAQ,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;SACxB;QAED,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAExB,QAAQ,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,GAAA,CAAC,CAAC;QAEvB,OAAO;YACL,OAAO,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;SAClC,CAAC;KACH,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,aAAO,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,CAAC,GAAG,oCAAK,IAAI,CAAC;AAChC;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/react",
|
|
3
|
-
"version": "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.
|
|
26
|
+
"@liveblocks/client": "0.12.0-beta.12",
|
|
27
27
|
"react": "^16.14.0 || ^17"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|