@liveblocks/react
Advanced tools
Comparing version 0.6.0-beta.5 to 0.7.0
@@ -7,9 +7,122 @@ import { Client, RecordData, Others, Presence, Record, InitialStorageFactory, Room } from "@liveblocks/client"; | ||
}; | ||
export declare function LiveblocksProvider({ client, children, }: LiveblocksProviderProps): JSX.Element; | ||
export declare function useClient(): Client; | ||
export declare function useMyPresence<T extends Presence>(room: string, initPresence: () => T): [T, (overrides: Partial<T>) => void]; | ||
export declare function useUpdateMyPresence<T extends Presence>(room: string, initPresence: () => T): (overrides: Partial<T>) => void; | ||
export declare function useOthersPresence<T extends Presence>(room: string): Others<T>; | ||
export declare function useBroadcastEvent(room: string): (event: any) => void; | ||
export declare function useEventListener<TEvent>(room: string, callback: ({ connectionId, event, }: { | ||
/** | ||
* Makes the Liveblocks client available in the component hierarchy below. | ||
*/ | ||
export declare function LiveblocksProvider(props: LiveblocksProviderProps): JSX.Element; | ||
declare type RoomProviderProps = { | ||
/** | ||
* The id of the room you want to connect to | ||
*/ | ||
id: string; | ||
/** | ||
* A callback that let you initialize the default presence when entering the room. | ||
* If ommited, the default presence will be an empty object | ||
*/ | ||
defaultPresence?: () => Presence; | ||
children: React.ReactNode; | ||
}; | ||
/** | ||
* Makes a Room available in the component hierarchy below. | ||
* When this component is unmounted, the current user leave the room. | ||
* That means that you can't have 2 RoomProvider with the same room id in your react tree. | ||
*/ | ||
export declare function RoomProvider({ id, children, defaultPresence, }: RoomProviderProps): JSX.Element; | ||
/** | ||
* Returns the presence of the current user of the current room, and a function to update it. | ||
* It is different from the setState function returned by the useState hook from React. | ||
* You don't need to pass the full presence object to update it. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useMyPresence } from "@liveblocks/react"; | ||
* | ||
* const [myPresence, updateMyPresence] = useMyPresence(); | ||
* updateMyPresence({ x: 0 }); | ||
* updateMyPresence({ y: 0 }); | ||
* | ||
* // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }" | ||
* ``` | ||
*/ | ||
export declare function useMyPresence<T extends Presence>(): [ | ||
T, | ||
(overrides: Partial<T>) => void | ||
]; | ||
/** | ||
* useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence. | ||
* 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. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useUpdateMyPresence } from "@liveblocks/react"; | ||
* | ||
* const updateMyPresence = useUpdateMyPresence(); | ||
* updateMyPresence({ x: 0 }); | ||
* updateMyPresence({ y: 0 }); | ||
* | ||
* // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }" | ||
* ``` | ||
*/ | ||
export declare function useUpdateMyPresence<T extends Presence>(): (overrides: Partial<T>) => void; | ||
/** | ||
* Returns an object that lets you get information about all the the users currently connected in the room. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useOthers } from "@liveblocks/react"; | ||
* | ||
* const others = useOthers(); | ||
* | ||
* // Example to map all cursors in jsx | ||
* { | ||
* others.map(({ connectionId, presence }) => { | ||
* if(presence == null || presence.cursor == null) { | ||
* return null; | ||
* } | ||
* return <Cursor key={connectionId} cursor={presence.cursor} /> | ||
* }) | ||
* } | ||
* ``` | ||
*/ | ||
export declare function useOthers<T extends Presence>(): Others<T>; | ||
/** | ||
* Returns a callback that lets you broadcast custom events to other users in the room | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useBroadcastEvent } from "@liveblocks/react"; | ||
* | ||
* const broadcast = useBroadcastEvent(); | ||
* | ||
* broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } }); | ||
* ``` | ||
*/ | ||
export declare function useBroadcastEvent(): (event: any) => void; | ||
/** | ||
* useErrorListener is a react hook that lets you react to potential room connection errors. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useErrorListener } from "@liveblocks/react"; | ||
* | ||
* useErrorListener(er => { | ||
* console.error(er); | ||
* }) | ||
* ``` | ||
*/ | ||
export declare function useErrorListener(callback: (er: Error) => void): void; | ||
/** | ||
* useEventListener is a react hook that lets you react to event broadcasted by other users in the room. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useEventListener } from "@liveblocks/react"; | ||
* | ||
* useEventListener(({ connectionId, event }) => { | ||
* if (event.type === "CUSTOM_EVENT") { | ||
* // Do something | ||
* } | ||
* }); | ||
* ``` | ||
*/ | ||
export declare function useEventListener<TEvent>(callback: ({ connectionId, event, }: { | ||
connectionId: number; | ||
@@ -26,5 +139,5 @@ event: TEvent; | ||
}; | ||
export declare function useStorage<TRoot extends RecordData>(room: string, initialStorage: InitialStorageFactory<TRoot>): [root: Record<TRoot> | null, actions: StorageActions]; | ||
export declare function useStorageActions(room: string): StorageActions; | ||
export declare function useStorage<TRoot extends RecordData>(initialStorage: InitialStorageFactory<TRoot>): [root: Record<TRoot> | null, actions: StorageActions]; | ||
export declare function useStorageActions(): StorageActions; | ||
export { createClient } from "@liveblocks/client"; | ||
export type { Record, Client, List } from "@liveblocks/client"; |
450
lib/index.js
@@ -44,2 +44,3 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
WebsocketCloseCodes[WebsocketCloseCodes["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"; | ||
WebsocketCloseCodes[WebsocketCloseCodes["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"; | ||
})(WebsocketCloseCodes || (WebsocketCloseCodes = {})); | ||
@@ -641,13 +642,2 @@ | ||
}; | ||
var __rest = (undefined && undefined.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
const BACKOFF_RETRY_DELAYS = [250, 500, 1000, 2000, 4000, 8000, 10000]; | ||
@@ -660,4 +650,5 @@ const HEARTBEAT_INTERVAL = 30000; | ||
value === "my-presence" || | ||
value === "others-presence" || | ||
value === "event"); | ||
value === "others" || | ||
value === "event" || | ||
value === "error"); | ||
} | ||
@@ -720,3 +711,3 @@ function makeIdFactory(connectionId) { | ||
}; | ||
function addEventListener(type, listener) { | ||
function subscribe(type, listener) { | ||
if (!isValidRoomEventType(type)) { | ||
@@ -727,3 +718,3 @@ throw new Error(`"${type}" is not a valid event name`); | ||
} | ||
function removeEventListener(event, callback) { | ||
function unsubscribe(event, callback) { | ||
if (!isValidRoomEventType(event)) { | ||
@@ -738,9 +729,6 @@ throw new Error(`"${event}" is not a valid event name`); | ||
} | ||
function getListenersCount() { | ||
return (state.listeners["my-presence"].length + | ||
state.listeners["others-presence"].length + | ||
state.listeners.storage.length + | ||
state.listeners.event.length); | ||
} | ||
function connect() { | ||
if (typeof window === "undefined") { | ||
return; | ||
} | ||
if (state.connection.state !== "closed" && | ||
@@ -787,4 +775,10 @@ state.connection.state !== "unavailable") { | ||
const user = state.users[message.actor]; | ||
const newUser = user | ||
? { | ||
if (user == null) { | ||
state.users[message.actor] = { | ||
connectionId: message.actor, | ||
presence: message.data, | ||
}; | ||
} | ||
else { | ||
state.users[message.actor] = { | ||
id: user.id, | ||
@@ -794,13 +788,9 @@ info: user.info, | ||
presence: Object.assign(Object.assign({}, user.presence), message.data), | ||
} | ||
: { | ||
connectionId: message.actor, | ||
presence: message.data, | ||
}; | ||
updateUsers(Object.assign(Object.assign({}, state.users), { [message.actor]: newUser })); | ||
} | ||
updateUsers(); | ||
} | ||
function updateUsers(newUsers) { | ||
state.users = newUsers; | ||
state.others = makeOthers(newUsers); | ||
for (const listener of state.listeners["others-presence"]) { | ||
function updateUsers() { | ||
state.others = makeOthers(state.users); | ||
for (const listener of state.listeners["others"]) { | ||
listener(state.others); | ||
@@ -811,4 +801,4 @@ } | ||
const userLeftMessage = message; | ||
const _a = state.users, _b = userLeftMessage.actor; _a[_b]; const rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]); | ||
updateUsers(rest); | ||
delete state.users[userLeftMessage.actor]; | ||
updateUsers(); | ||
} | ||
@@ -826,3 +816,4 @@ function onRoomStateMessage(message) { | ||
} | ||
updateUsers(newUsers); | ||
state.users = newUsers; | ||
updateUsers(); | ||
} | ||
@@ -840,7 +831,8 @@ function onNavigatorOnline() { | ||
function onUserJoinedMessage(message) { | ||
updateUsers(Object.assign(Object.assign({}, state.users), { [message.actor]: { | ||
connectionId: message.actor, | ||
info: message.info, | ||
id: message.id, | ||
} })); | ||
state.users[message.actor] = { | ||
connectionId: message.actor, | ||
info: message.info, | ||
id: message.id, | ||
}; | ||
updateUsers(); | ||
if (state.me) { | ||
@@ -911,6 +903,10 @@ // Send current presence to new user | ||
clearTimeout(state.timeoutHandles.reconnect); | ||
updateUsers({}); | ||
state.users = {}; | ||
updateUsers(); | ||
if (event.code >= 4000 && event.code <= 4100) { | ||
updateConnection({ state: "failed" }); | ||
context.onError(new Error(event.reason)); | ||
const error = new LiveblocksError(event.reason, event.code); | ||
for (const listener of state.listeners.error) { | ||
listener(error); | ||
} | ||
} | ||
@@ -1032,3 +1028,2 @@ else if (event.wasClean === false) { | ||
updateConnection({ state: "closed" }); | ||
state.me = null; | ||
if (state.timeoutHandles.flush) { | ||
@@ -1040,8 +1035,11 @@ clearTimeout(state.timeoutHandles.flush); | ||
clearInterval(state.intervalHandles.heartbeat); | ||
updateUsers({}); | ||
state.listeners["my-presence"] = []; | ||
state.listeners["others-presence"] = []; | ||
state.listeners.event = []; | ||
state.listeners.storage = []; | ||
state.users = {}; | ||
updateUsers(); | ||
clearListeners(); | ||
} | ||
function clearListeners() { | ||
for (const key in state.listeners) { | ||
state.listeners[key] = []; | ||
} | ||
} | ||
function getPresence() { | ||
@@ -1153,4 +1151,4 @@ return state.me; | ||
disconnect, | ||
addEventListener, | ||
removeEventListener, | ||
subscribe, | ||
unsubscribe, | ||
// Presence | ||
@@ -1169,3 +1167,2 @@ updatePresence, | ||
// Core | ||
getListenersCount, | ||
getConnectionState, | ||
@@ -1180,3 +1177,3 @@ // Presence | ||
} | ||
function defaultState() { | ||
function defaultState(me) { | ||
return { | ||
@@ -1188,4 +1185,5 @@ connection: { state: "closed" }, | ||
event: [], | ||
"others-presence": [], | ||
others: [], | ||
"my-presence": [], | ||
error: [], | ||
}, | ||
@@ -1207,3 +1205,3 @@ numberOfRetry: 0, | ||
}, | ||
me: null, | ||
me: me == null ? {} : me, | ||
users: {}, | ||
@@ -1221,3 +1219,3 @@ others: makeOthers({}), | ||
const authEndpoint = options.authEndpoint; | ||
const state = defaultState(); | ||
const state = defaultState(options.initialPresence); | ||
const machine = makeStateMachine(state, { | ||
@@ -1227,3 +1225,2 @@ throttleDelay, | ||
authEndpoint, | ||
onError: options.onError, | ||
room: name, | ||
@@ -1238,5 +1235,4 @@ }); | ||
getConnectionState: machine.selectors.getConnectionState, | ||
getListenersCount: machine.selectors.getListenersCount, | ||
addEventListener: machine.addEventListener, | ||
removeEventListener: machine.removeEventListener, | ||
subscribe: machine.subscribe, | ||
unsubscribe: machine.unsubscribe, | ||
///////////// | ||
@@ -1265,2 +1261,8 @@ // Storage // | ||
} | ||
class LiveblocksError extends Error { | ||
constructor(message, code) { | ||
super(message); | ||
this.code = code; | ||
} | ||
} | ||
@@ -1274,33 +1276,22 @@ function createClient(options) { | ||
const rooms = new Map(); | ||
const _listeners = { | ||
error: [], | ||
}; | ||
function onError(error) { | ||
for (const listener of _listeners.error) { | ||
listener(error); | ||
} | ||
function getRoom(roomId) { | ||
return rooms.get(roomId) || null; | ||
} | ||
function getRoomOrInit(name) { | ||
let room = rooms.get(name); | ||
if (room == null) { | ||
room = createRoom(name, Object.assign(Object.assign({}, options), { onError })); | ||
rooms.set(name, room); | ||
function enter(roomId, initialPresence) { | ||
let room = rooms.get(roomId); | ||
if (room) { | ||
return room; | ||
} | ||
room = createRoom(roomId, Object.assign(Object.assign({}, options), { initialPresence })); | ||
rooms.set(roomId, room); | ||
room.connect(); | ||
return room; | ||
} | ||
function getRoom(room) { | ||
return getRoomOrInit(room); | ||
} | ||
function addEventListener(type, listener) { | ||
if (type !== "error") { | ||
throw new Error(`"${type}" is not a valid event name`); | ||
function leave(roomId) { | ||
let room = rooms.get(roomId); | ||
if (room) { | ||
room.disconnect(); | ||
rooms.delete(roomId); | ||
} | ||
_listeners.error.push(listener); | ||
} | ||
function removeEventListener(type, listener) { | ||
if (type !== "error") { | ||
throw new Error(`"${type}" is not a valid event name`); | ||
} | ||
remove(_listeners.error, listener); | ||
} | ||
if (typeof window !== "undefined") { | ||
@@ -1322,5 +1313,5 @@ // TODO: Expose a way to clear these | ||
return { | ||
addEventListener, | ||
removeEventListener, | ||
getRoom, | ||
enter, | ||
leave, | ||
}; | ||
@@ -1330,30 +1321,65 @@ } | ||
var ClientContext = React.createContext(null); | ||
function LiveblocksProvider(_a) { | ||
var client = _a.client, children = _a.children; | ||
var _b = React.useState(null), error = _b[0], setError = _b[1]; | ||
if (error) { | ||
throw error; | ||
} | ||
React.useEffect(function () { | ||
function onError(error) { | ||
setError(error); | ||
} | ||
client.addEventListener("error", onError); | ||
return function () { | ||
client.removeEventListener("error", onError); | ||
}; | ||
}, [client]); | ||
return (React.createElement(ClientContext.Provider, { value: client }, children)); | ||
var RoomContext = React.createContext(null); | ||
/** | ||
* Makes the Liveblocks client available in the component hierarchy below. | ||
*/ | ||
function LiveblocksProvider(props) { | ||
return (React.createElement(ClientContext.Provider, { value: props.client }, props.children)); | ||
} | ||
/** | ||
* Returns the client of the nearest LiveblocksProvider above in the react component tree | ||
*/ | ||
function useClient() { | ||
var client = React.useContext(ClientContext); | ||
if (client == null) { | ||
throw new Error("Missing context"); | ||
throw new Error("LiveblocksProvider is missing from the react tree"); | ||
} | ||
return client; | ||
} | ||
function useMyPresence(room, initPresence) { | ||
/** | ||
* Makes a Room available in the component hierarchy below. | ||
* When this component is unmounted, the current user leave the room. | ||
* That means that you can't have 2 RoomProvider with the same room id in your react tree. | ||
*/ | ||
function RoomProvider(_a) { | ||
var id = _a.id, children = _a.children, defaultPresence = _a.defaultPresence; | ||
var client = useClient(); | ||
var _room = client.getRoom(room); | ||
var presence = _room.getPresence() || initPresence(); | ||
React.useEffect(function () { | ||
return function () { | ||
client.leave(id); | ||
}; | ||
}, [client, id]); | ||
var room = client.getRoom(id) || | ||
client.enter(id, defaultPresence ? defaultPresence() : undefined); | ||
return React.createElement(RoomContext.Provider, { value: room }, children); | ||
} | ||
/** | ||
* Returns the room of the nearest RoomProvider above in the react component tree | ||
*/ | ||
function useRoom() { | ||
var room = React.useContext(RoomContext); | ||
if (room == null) { | ||
throw new Error("RoomProvider is missing from the react tree"); | ||
} | ||
return room; | ||
} | ||
/** | ||
* Returns the presence of the current user of the current room, and a function to update it. | ||
* It is different from the setState function returned by the useState hook from React. | ||
* You don't need to pass the full presence object to update it. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useMyPresence } from "@liveblocks/react"; | ||
* | ||
* const [myPresence, updateMyPresence] = useMyPresence(); | ||
* updateMyPresence({ x: 0 }); | ||
* updateMyPresence({ y: 0 }); | ||
* | ||
* // At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }" | ||
* ``` | ||
*/ | ||
function useMyPresence() { | ||
var room = useRoom(); | ||
var presence = room.getPresence(); | ||
var _a = React.useState(0), update = _a[1]; | ||
@@ -1364,37 +1390,53 @@ React.useEffect(function () { | ||
} | ||
var _room = client.getRoom(room); | ||
_room.connect(); | ||
var existingPresence = _room.getPresence(); | ||
if (existingPresence == null) { | ||
_room.updatePresence(initPresence()); | ||
} | ||
_room.addEventListener("my-presence", onMyPresenceChange); | ||
room.subscribe("my-presence", onMyPresenceChange); | ||
return function () { | ||
_room.removeEventListener("my-presence", onMyPresenceChange); | ||
if (_room.getListenersCount() === 0) { | ||
_room.disconnect(); | ||
} | ||
room.unsubscribe("my-presence", onMyPresenceChange); | ||
}; | ||
}, [client, room]); | ||
var setPresence = React.useCallback(function (overrides) { return client.getRoom(room).updatePresence(overrides); }, [room, client]); | ||
}, [room]); | ||
var setPresence = React.useCallback(function (overrides) { return room.updatePresence(overrides); }, [room]); | ||
return [presence, setPresence]; | ||
} | ||
function useUpdateMyPresence(room, initPresence) { | ||
var client = useClient(); | ||
React.useEffect(function () { | ||
var _room = client.getRoom(room); | ||
_room.connect(); | ||
var existingPresence = _room.getPresence(); | ||
if (existingPresence == null) { | ||
_room.updatePresence(initPresence()); | ||
} | ||
}, [client, room]); | ||
/** | ||
* useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence. | ||
* 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. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useUpdateMyPresence } from "@liveblocks/react"; | ||
* | ||
* const updateMyPresence = useUpdateMyPresence(); | ||
* updateMyPresence({ x: 0 }); | ||
* updateMyPresence({ y: 0 }); | ||
* | ||
* // At the next render, the presence of the current user will be equal to "{ x: 0, y: 0 }" | ||
* ``` | ||
*/ | ||
function useUpdateMyPresence() { | ||
var room = useRoom(); | ||
return React.useCallback(function (overrides) { | ||
var _room = client.getRoom(room); | ||
_room.updatePresence(overrides); | ||
}, [room, client]); | ||
room.updatePresence(overrides); | ||
}, [room]); | ||
} | ||
function useOthersPresence(room) { | ||
var client = useClient(); | ||
var _room = client.getRoom(room); | ||
/** | ||
* Returns an object that lets you get information about all the the users currently connected in the room. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useOthers } from "@liveblocks/react"; | ||
* | ||
* const others = useOthers(); | ||
* | ||
* // Example to map all cursors in jsx | ||
* { | ||
* others.map(({ connectionId, presence }) => { | ||
* if(presence == null || presence.cursor == null) { | ||
* return null; | ||
* } | ||
* return <Cursor key={connectionId} cursor={presence.cursor} /> | ||
* }) | ||
* } | ||
* ``` | ||
*/ | ||
function useOthers() { | ||
var room = useRoom(); | ||
var _a = React.useState(0), update = _a[1]; | ||
@@ -1405,32 +1447,69 @@ React.useEffect(function () { | ||
} | ||
var _room = client.getRoom(room); | ||
_room.connect(); | ||
_room.addEventListener("others-presence", onOthersChange); | ||
room.subscribe("others", onOthersChange); | ||
return function () { | ||
_room.removeEventListener("others-presence", onOthersChange); | ||
if (_room.getListenersCount() === 0) { | ||
_room.disconnect(); | ||
} | ||
room.subscribe("others", onOthersChange); | ||
}; | ||
}, [client, room]); | ||
return _room.getOthers(); | ||
}, [room]); | ||
return room.getOthers(); | ||
} | ||
function useBroadcastEvent(room) { | ||
var client = useClient(); | ||
/** | ||
* Returns a callback that lets you broadcast custom events to other users in the room | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useBroadcastEvent } from "@liveblocks/react"; | ||
* | ||
* const broadcast = useBroadcastEvent(); | ||
* | ||
* broadcast({ type: "CUSTOM_EVENT", data: { x: 0, y: 0 } }); | ||
* ``` | ||
*/ | ||
function useBroadcastEvent() { | ||
var room = useRoom(); | ||
return React.useCallback(function (event) { | ||
room.broadcastEvent(event); | ||
}, [room]); | ||
} | ||
/** | ||
* useErrorListener is a react hook that lets you react to potential room connection errors. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useErrorListener } from "@liveblocks/react"; | ||
* | ||
* useErrorListener(er => { | ||
* console.error(er); | ||
* }) | ||
* ``` | ||
*/ | ||
function useErrorListener(callback) { | ||
var room = useRoom(); | ||
var savedCallback = React.useRef(callback); | ||
React.useEffect(function () { | ||
var _room = client.getRoom(room); | ||
_room.connect(); | ||
savedCallback.current = callback; | ||
}); | ||
React.useEffect(function () { | ||
var listener = function (e) { return savedCallback.current(e); }; | ||
room.subscribe("error", listener); | ||
return function () { | ||
if (_room.getListenersCount() === 0) { | ||
_room.disconnect(); | ||
} | ||
room.unsubscribe("error", listener); | ||
}; | ||
}, [client, room]); | ||
return React.useCallback(function (event) { | ||
var _room = client.getRoom(room); | ||
_room.broadcastEvent(event); | ||
}, [room, client]); | ||
}, [room]); | ||
} | ||
function useEventListener(room, callback) { | ||
var client = useClient(); | ||
/** | ||
* useEventListener is a react hook that lets you react to event broadcasted by other users in the room. | ||
* | ||
* ### Example | ||
* ``` typescript | ||
* import { useEventListener } from "@liveblocks/react"; | ||
* | ||
* useEventListener(({ connectionId, event }) => { | ||
* if (event.type === "CUSTOM_EVENT") { | ||
* // Do something | ||
* } | ||
* }); | ||
* ``` | ||
*/ | ||
function useEventListener(callback) { | ||
var room = useRoom(); | ||
var savedCallback = React.useRef(callback); | ||
@@ -1441,20 +1520,14 @@ React.useEffect(function () { | ||
React.useEffect(function () { | ||
var _room = client.getRoom(room); | ||
_room.connect(); | ||
var listener = function (e) { | ||
return savedCallback.current(e); | ||
}; | ||
_room.addEventListener("event", listener); | ||
room.subscribe("event", listener); | ||
return function () { | ||
_room.removeEventListener("event", listener); | ||
if (_room.getListenersCount() === 0) { | ||
_room.disconnect(); | ||
} | ||
room.unsubscribe("event", listener); | ||
}; | ||
}, [room, client]); | ||
}, [room]); | ||
} | ||
function useStorage(room, initialStorage) { | ||
var client = useClient(); | ||
var _room = client.getRoom(room); | ||
var storage = _room.getStorage(); | ||
function useStorage(initialStorage) { | ||
var room = useRoom(); | ||
var storage = room.getStorage(); | ||
var _a = React.useState(0), update = _a[1]; | ||
@@ -1465,11 +1538,6 @@ React.useEffect(function () { | ||
} | ||
var _room = client.getRoom(room); | ||
_room.connect(); | ||
_room.fetchStorage(initialStorage); | ||
_room.addEventListener("storage", onStorageChange); | ||
room.fetchStorage(initialStorage); | ||
room.subscribe("storage", onStorageChange); | ||
return function () { | ||
_room.removeEventListener("storage", onStorageChange); | ||
if (_room.getListenersCount() === 0) { | ||
_room.disconnect(); | ||
} | ||
room.unsubscribe("storage", onStorageChange); | ||
}; | ||
@@ -1480,26 +1548,25 @@ }, [room]); | ||
: null; | ||
var actions = useStorageActions(room); | ||
var actions = useStorageActions(); | ||
return [root, actions]; | ||
} | ||
function useStorageActions(room) { | ||
var client = useClient(); | ||
function useStorageActions() { | ||
var room = useRoom(); | ||
return React.useMemo(function () { | ||
var _room = client.getRoom(room); | ||
function createRecord(data) { | ||
return _room.createRecord(data); | ||
return room.createRecord(data); | ||
} | ||
function updateRecord(record, overrides) { | ||
return _room.updateRecord(record, overrides); | ||
return room.updateRecord(record, overrides); | ||
} | ||
function createList() { | ||
return _room.createList(); | ||
return room.createList(); | ||
} | ||
function moveItem(list, index, targetIndex) { | ||
return _room.moveItem(list, index, targetIndex); | ||
return room.moveItem(list, index, targetIndex); | ||
} | ||
function deleteItem(list, index) { | ||
return _room.deleteItem(list, index); | ||
return room.deleteItem(list, index); | ||
} | ||
function pushItem(list, item) { | ||
return _room.pushItem(list, item); | ||
return room.pushItem(list, item); | ||
} | ||
@@ -1514,12 +1581,13 @@ return { | ||
}; | ||
}, [client, room]); | ||
}, [room]); | ||
} | ||
exports.LiveblocksProvider = LiveblocksProvider; | ||
exports.RoomProvider = RoomProvider; | ||
exports.createClient = createClient; | ||
exports.useBroadcastEvent = useBroadcastEvent; | ||
exports.useClient = useClient; | ||
exports.useErrorListener = useErrorListener; | ||
exports.useEventListener = useEventListener; | ||
exports.useMyPresence = useMyPresence; | ||
exports.useOthersPresence = useOthersPresence; | ||
exports.useOthers = useOthers; | ||
exports.useStorage = useStorage; | ||
@@ -1526,0 +1594,0 @@ exports.useStorageActions = useStorageActions; |
{ | ||
"name": "@liveblocks/react", | ||
"version": "0.6.0-beta.5", | ||
"version": "0.7.0", | ||
"description": "", | ||
@@ -16,3 +16,3 @@ "main": "./lib/index.js", | ||
"dependencies": { | ||
"@liveblocks/client": "0.6.0-beta.4" | ||
"@liveblocks/client": "0.7.0" | ||
}, | ||
@@ -19,0 +19,0 @@ "peerDependencies": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
168323
1695
+ Added@liveblocks/client@0.7.0(transitive)
- Removed@liveblocks/client@0.6.0-beta.4(transitive)
Updated@liveblocks/client@0.7.0