@liveblocks/react 1.2.2-comments3 → 1.2.2-comments5
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/dist/index.d.mts +996 -403
- package/dist/index.d.ts +996 -403
- package/dist/index.js +616 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +618 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
2
4
|
var _core = require('@liveblocks/core');
|
|
3
5
|
|
|
4
6
|
// src/version.ts
|
|
5
7
|
var PKG_NAME = "@liveblocks/react";
|
|
6
|
-
var PKG_VERSION = "1.2.2-
|
|
8
|
+
var PKG_VERSION = "1.2.2-comments5";
|
|
7
9
|
var PKG_FORMAT = "cjs";
|
|
8
10
|
|
|
9
11
|
// src/ClientSideSuspense.tsx
|
|
@@ -24,8 +26,452 @@ var _client = require('@liveblocks/client');
|
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
|
|
29
|
+
|
|
30
|
+
|
|
27
31
|
var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
|
|
28
32
|
|
|
33
|
+
// src/comments/CommentsRoom.ts
|
|
34
|
+
|
|
35
|
+
var _nanoid = require('nanoid');
|
|
36
|
+
var _indexjs = require('use-sync-external-store/shim/index.js');
|
|
37
|
+
|
|
38
|
+
// src/comments/errors.ts
|
|
39
|
+
var CreateThreadError = class extends Error {
|
|
40
|
+
constructor(cause, context) {
|
|
41
|
+
super("Create thread failed.");
|
|
42
|
+
this.cause = cause;
|
|
43
|
+
this.context = context;
|
|
44
|
+
this.name = "CreateThreadError";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var EditThreadMetadataError = class extends Error {
|
|
48
|
+
constructor(cause, context) {
|
|
49
|
+
super("Edit thread metadata failed.");
|
|
50
|
+
this.cause = cause;
|
|
51
|
+
this.context = context;
|
|
52
|
+
this.name = "EditThreadMetadataError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var CreateCommentError = class extends Error {
|
|
56
|
+
constructor(cause, context) {
|
|
57
|
+
super("Create comment failed.");
|
|
58
|
+
this.cause = cause;
|
|
59
|
+
this.context = context;
|
|
60
|
+
this.name = "CreateCommentError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var EditCommentError = class extends Error {
|
|
64
|
+
constructor(cause, context) {
|
|
65
|
+
super("Edit comment failed.");
|
|
66
|
+
this.cause = cause;
|
|
67
|
+
this.context = context;
|
|
68
|
+
this.name = "EditCommentError";
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var DeleteCommentError = class extends Error {
|
|
72
|
+
constructor(cause, context) {
|
|
73
|
+
super("Delete comment failed.");
|
|
74
|
+
this.cause = cause;
|
|
75
|
+
this.context = context;
|
|
76
|
+
this.name = "DeleteCommentError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/comments/lib/store.ts
|
|
81
|
+
|
|
82
|
+
function createStore(initialState) {
|
|
83
|
+
let state = initialState;
|
|
84
|
+
const eventSource = _core.makeEventSource.call(void 0, );
|
|
85
|
+
return {
|
|
86
|
+
get() {
|
|
87
|
+
return state;
|
|
88
|
+
},
|
|
89
|
+
set(newState) {
|
|
90
|
+
state = newState;
|
|
91
|
+
eventSource.notify(state);
|
|
92
|
+
},
|
|
93
|
+
subscribe(callback) {
|
|
94
|
+
return eventSource.subscribe(callback);
|
|
95
|
+
},
|
|
96
|
+
subscribeOnce(callback) {
|
|
97
|
+
return eventSource.subscribeOnce(callback);
|
|
98
|
+
},
|
|
99
|
+
subscribersCount() {
|
|
100
|
+
return eventSource.count();
|
|
101
|
+
},
|
|
102
|
+
destroy() {
|
|
103
|
+
return eventSource.clear();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/comments/CommentsRoom.ts
|
|
109
|
+
var POLLING_INTERVAL_REALTIME = 3e4;
|
|
110
|
+
var POLLING_INTERVAL = 5e3;
|
|
111
|
+
var THREAD_ID_PREFIX = "th";
|
|
112
|
+
var COMMENT_ID_PREFIX = "cm";
|
|
113
|
+
function createOptimisticId(prefix) {
|
|
114
|
+
return `${prefix}_${_nanoid.nanoid.call(void 0, )}`;
|
|
115
|
+
}
|
|
116
|
+
function createCommentsRoom(room, errorEventSource) {
|
|
117
|
+
const store = createStore({
|
|
118
|
+
isLoading: true
|
|
119
|
+
});
|
|
120
|
+
let numberOfMutations = 0;
|
|
121
|
+
function endMutation() {
|
|
122
|
+
numberOfMutations--;
|
|
123
|
+
if (numberOfMutations === 0) {
|
|
124
|
+
revalidateThreads();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function startMutation() {
|
|
128
|
+
pollingHub.threads.stop();
|
|
129
|
+
numberOfMutations++;
|
|
130
|
+
}
|
|
131
|
+
const pollingHub = {
|
|
132
|
+
// TODO: If there's an error, it will currently infinitely retry at the current polling rate → add retry logic
|
|
133
|
+
threads: _core.makePoller.call(void 0, revalidateThreads)
|
|
134
|
+
};
|
|
135
|
+
let unsubscribeRealtimeEvents;
|
|
136
|
+
let unsubscribeRealtimeConnection;
|
|
137
|
+
let realtimeClientConnected = false;
|
|
138
|
+
function getPollingInterval() {
|
|
139
|
+
return realtimeClientConnected ? POLLING_INTERVAL_REALTIME : POLLING_INTERVAL;
|
|
140
|
+
}
|
|
141
|
+
function ensureThreadsAreLoadedForMutations() {
|
|
142
|
+
const state = store.get();
|
|
143
|
+
if (state.isLoading || state.error) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
"Cannot update threads or comments before they are loaded"
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return state.threads;
|
|
149
|
+
}
|
|
150
|
+
async function revalidateThreads() {
|
|
151
|
+
pollingHub.threads.pause();
|
|
152
|
+
if (numberOfMutations === 0) {
|
|
153
|
+
setThreads(await room.getThreads());
|
|
154
|
+
}
|
|
155
|
+
pollingHub.threads.resume();
|
|
156
|
+
}
|
|
157
|
+
function subscribe() {
|
|
158
|
+
if (!unsubscribeRealtimeEvents) {
|
|
159
|
+
unsubscribeRealtimeEvents = room.events.comments.subscribe(() => {
|
|
160
|
+
pollingHub.threads.restart(getPollingInterval());
|
|
161
|
+
revalidateThreads();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (!unsubscribeRealtimeConnection) {
|
|
165
|
+
unsubscribeRealtimeConnection = room.events.status.subscribe((status) => {
|
|
166
|
+
const nextRealtimeClientConnected = status === "connected";
|
|
167
|
+
if (nextRealtimeClientConnected !== realtimeClientConnected) {
|
|
168
|
+
realtimeClientConnected = nextRealtimeClientConnected;
|
|
169
|
+
pollingHub.threads.restart(getPollingInterval());
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
pollingHub.threads.start(getPollingInterval());
|
|
174
|
+
revalidateThreads();
|
|
175
|
+
return () => {
|
|
176
|
+
pollingHub.threads.stop();
|
|
177
|
+
_optionalChain([unsubscribeRealtimeEvents, 'optionalCall', _ => _()]);
|
|
178
|
+
unsubscribeRealtimeEvents = void 0;
|
|
179
|
+
_optionalChain([unsubscribeRealtimeConnection, 'optionalCall', _2 => _2()]);
|
|
180
|
+
unsubscribeRealtimeConnection = void 0;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function setThreads(newThreads) {
|
|
184
|
+
store.set({
|
|
185
|
+
threads: newThreads,
|
|
186
|
+
isLoading: false
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function getCurrentUserId() {
|
|
190
|
+
const self = room.getSelf();
|
|
191
|
+
if (self === null || self.id === void 0) {
|
|
192
|
+
return "anonymous";
|
|
193
|
+
} else {
|
|
194
|
+
return self.id;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function createThread(options) {
|
|
198
|
+
const body = options.body;
|
|
199
|
+
const metadata = "metadata" in options ? options.metadata : {};
|
|
200
|
+
const threads = ensureThreadsAreLoadedForMutations();
|
|
201
|
+
const threadId = createOptimisticId(THREAD_ID_PREFIX);
|
|
202
|
+
const commentId = createOptimisticId(COMMENT_ID_PREFIX);
|
|
203
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
204
|
+
const newThread = {
|
|
205
|
+
id: threadId,
|
|
206
|
+
type: "thread",
|
|
207
|
+
createdAt: now,
|
|
208
|
+
roomId: room.id,
|
|
209
|
+
metadata,
|
|
210
|
+
comments: [
|
|
211
|
+
{
|
|
212
|
+
id: commentId,
|
|
213
|
+
createdAt: now,
|
|
214
|
+
type: "comment",
|
|
215
|
+
userId: getCurrentUserId(),
|
|
216
|
+
body
|
|
217
|
+
}
|
|
218
|
+
]
|
|
219
|
+
};
|
|
220
|
+
setThreads([...threads, newThread]);
|
|
221
|
+
startMutation();
|
|
222
|
+
room.createThread({ threadId, commentId, body, metadata }).catch(
|
|
223
|
+
(er) => errorEventSource.notify(
|
|
224
|
+
new CreateThreadError(er, {
|
|
225
|
+
roomId: room.id,
|
|
226
|
+
threadId,
|
|
227
|
+
commentId,
|
|
228
|
+
body,
|
|
229
|
+
metadata
|
|
230
|
+
})
|
|
231
|
+
)
|
|
232
|
+
).finally(endMutation);
|
|
233
|
+
return newThread;
|
|
234
|
+
}
|
|
235
|
+
function editThreadMetadata(options) {
|
|
236
|
+
const threadId = options.threadId;
|
|
237
|
+
const metadata = "metadata" in options ? options.metadata : {};
|
|
238
|
+
const threads = ensureThreadsAreLoadedForMutations();
|
|
239
|
+
setThreads(
|
|
240
|
+
threads.map(
|
|
241
|
+
(thread) => thread.id === threadId ? {
|
|
242
|
+
...thread,
|
|
243
|
+
metadata: {
|
|
244
|
+
...thread.metadata,
|
|
245
|
+
...metadata
|
|
246
|
+
}
|
|
247
|
+
} : thread
|
|
248
|
+
)
|
|
249
|
+
);
|
|
250
|
+
startMutation();
|
|
251
|
+
room.editThreadMetadata({ metadata, threadId }).catch(
|
|
252
|
+
(er) => errorEventSource.notify(
|
|
253
|
+
new EditThreadMetadataError(er, {
|
|
254
|
+
roomId: room.id,
|
|
255
|
+
threadId,
|
|
256
|
+
metadata
|
|
257
|
+
})
|
|
258
|
+
)
|
|
259
|
+
).finally(endMutation);
|
|
260
|
+
}
|
|
261
|
+
function createComment({
|
|
262
|
+
threadId,
|
|
263
|
+
body
|
|
264
|
+
}) {
|
|
265
|
+
const threads = ensureThreadsAreLoadedForMutations();
|
|
266
|
+
const commentId = createOptimisticId(COMMENT_ID_PREFIX);
|
|
267
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
268
|
+
const comment = {
|
|
269
|
+
id: commentId,
|
|
270
|
+
threadId,
|
|
271
|
+
roomId: room.id,
|
|
272
|
+
type: "comment",
|
|
273
|
+
createdAt: now,
|
|
274
|
+
userId: getCurrentUserId(),
|
|
275
|
+
body
|
|
276
|
+
};
|
|
277
|
+
setThreads(
|
|
278
|
+
threads.map(
|
|
279
|
+
(thread) => thread.id === threadId ? {
|
|
280
|
+
...thread,
|
|
281
|
+
comments: [...thread.comments, comment]
|
|
282
|
+
} : thread
|
|
283
|
+
)
|
|
284
|
+
);
|
|
285
|
+
startMutation();
|
|
286
|
+
room.createComment({ threadId, commentId, body }).catch(
|
|
287
|
+
(er) => errorEventSource.notify(
|
|
288
|
+
new CreateCommentError(er, {
|
|
289
|
+
roomId: room.id,
|
|
290
|
+
threadId,
|
|
291
|
+
commentId,
|
|
292
|
+
body
|
|
293
|
+
})
|
|
294
|
+
)
|
|
295
|
+
).finally(endMutation);
|
|
296
|
+
return comment;
|
|
297
|
+
}
|
|
298
|
+
function editComment({ threadId, commentId, body }) {
|
|
299
|
+
const threads = ensureThreadsAreLoadedForMutations();
|
|
300
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
301
|
+
setThreads(
|
|
302
|
+
threads.map(
|
|
303
|
+
(thread) => thread.id === threadId ? {
|
|
304
|
+
...thread,
|
|
305
|
+
comments: thread.comments.map(
|
|
306
|
+
(comment) => comment.id === commentId ? {
|
|
307
|
+
...comment,
|
|
308
|
+
editedAt: now,
|
|
309
|
+
body
|
|
310
|
+
} : comment
|
|
311
|
+
)
|
|
312
|
+
} : thread
|
|
313
|
+
)
|
|
314
|
+
);
|
|
315
|
+
startMutation();
|
|
316
|
+
room.editComment({ threadId, commentId, body }).catch(
|
|
317
|
+
(er) => errorEventSource.notify(
|
|
318
|
+
new EditCommentError(er, {
|
|
319
|
+
roomId: room.id,
|
|
320
|
+
threadId,
|
|
321
|
+
commentId,
|
|
322
|
+
body
|
|
323
|
+
})
|
|
324
|
+
)
|
|
325
|
+
).finally(endMutation);
|
|
326
|
+
}
|
|
327
|
+
function deleteComment({ threadId, commentId }) {
|
|
328
|
+
const threads = ensureThreadsAreLoadedForMutations();
|
|
329
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
330
|
+
const newThreads = [];
|
|
331
|
+
for (const thread of threads) {
|
|
332
|
+
if (thread.id === threadId) {
|
|
333
|
+
const newThread = {
|
|
334
|
+
...thread,
|
|
335
|
+
comments: thread.comments.map(
|
|
336
|
+
(comment) => comment.id === commentId ? {
|
|
337
|
+
...comment,
|
|
338
|
+
deletedAt: now,
|
|
339
|
+
body: void 0
|
|
340
|
+
} : comment
|
|
341
|
+
)
|
|
342
|
+
};
|
|
343
|
+
if (newThread.comments.some((comment) => comment.deletedAt === void 0)) {
|
|
344
|
+
newThreads.push(newThread);
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
newThreads.push(thread);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
setThreads(newThreads);
|
|
351
|
+
startMutation();
|
|
352
|
+
room.deleteComment({ threadId, commentId }).catch(
|
|
353
|
+
(er) => errorEventSource.notify(
|
|
354
|
+
new DeleteCommentError(er, {
|
|
355
|
+
roomId: room.id,
|
|
356
|
+
threadId,
|
|
357
|
+
commentId
|
|
358
|
+
})
|
|
359
|
+
)
|
|
360
|
+
).finally(endMutation);
|
|
361
|
+
}
|
|
362
|
+
function useThreads() {
|
|
363
|
+
return _indexjs.useSyncExternalStore.call(void 0,
|
|
364
|
+
store.subscribe,
|
|
365
|
+
store.get,
|
|
366
|
+
store.get
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
function useThreadsSuspense() {
|
|
370
|
+
const result = useThreads();
|
|
371
|
+
if (result.isLoading) {
|
|
372
|
+
throw new Promise(store.subscribeOnce);
|
|
373
|
+
}
|
|
374
|
+
if (result.error) {
|
|
375
|
+
throw result.error;
|
|
376
|
+
}
|
|
377
|
+
return result.threads;
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
useThreads,
|
|
381
|
+
useThreadsSuspense,
|
|
382
|
+
createThread,
|
|
383
|
+
editThreadMetadata,
|
|
384
|
+
createComment,
|
|
385
|
+
editComment,
|
|
386
|
+
deleteComment,
|
|
387
|
+
subscribe
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/comments/lib/use-async-cache.ts
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
// src/comments/lib/use-initial.ts
|
|
396
|
+
|
|
397
|
+
function useInitial(value) {
|
|
398
|
+
return _react.useRef.call(void 0, value instanceof Function ? value() : value).current;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// src/comments/lib/use-async-cache.ts
|
|
402
|
+
var INITIAL_ASYNC_STATE = {
|
|
403
|
+
isLoading: false,
|
|
404
|
+
data: void 0,
|
|
405
|
+
error: void 0
|
|
406
|
+
};
|
|
407
|
+
var noop = () => {
|
|
408
|
+
};
|
|
409
|
+
function useAsyncCache(cache, key, options) {
|
|
410
|
+
const frozenOptions = useInitial(options);
|
|
411
|
+
const cacheItem = _react.useMemo.call(void 0, () => {
|
|
412
|
+
if (key === null || !cache) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const cacheItem2 = cache.create(key, _optionalChain([frozenOptions, 'optionalAccess', _3 => _3.overrideFunction]));
|
|
416
|
+
void cacheItem2.get();
|
|
417
|
+
return cacheItem2;
|
|
418
|
+
}, [cache, frozenOptions, key]);
|
|
419
|
+
const subscribe = _react.useCallback.call(void 0,
|
|
420
|
+
(callback) => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _4 => _4.subscribe, 'call', _5 => _5(callback)]), () => ( noop)),
|
|
421
|
+
[cacheItem]
|
|
422
|
+
);
|
|
423
|
+
const getState = _react.useCallback.call(void 0,
|
|
424
|
+
() => _nullishCoalesce(_optionalChain([cacheItem, 'optionalAccess', _6 => _6.getState, 'call', _7 => _7()]), () => ( INITIAL_ASYNC_STATE)),
|
|
425
|
+
[cacheItem]
|
|
426
|
+
);
|
|
427
|
+
const revalidate = _react.useCallback.call(void 0, () => _optionalChain([cacheItem, 'optionalAccess', _8 => _8.revalidate, 'call', _9 => _9()]), [cacheItem]);
|
|
428
|
+
const state = _indexjs.useSyncExternalStore.call(void 0, subscribe, getState, getState);
|
|
429
|
+
const previousData = _react.useRef.call(void 0, );
|
|
430
|
+
let data = state.data;
|
|
431
|
+
_react.useEffect.call(void 0, () => {
|
|
432
|
+
previousData.current = { key, data: state.data };
|
|
433
|
+
}, [key, state]);
|
|
434
|
+
if (_optionalChain([frozenOptions, 'optionalAccess', _10 => _10.suspense]) && state.isLoading && cacheItem) {
|
|
435
|
+
throw new Promise((resolve) => {
|
|
436
|
+
cacheItem.subscribeOnce(() => resolve());
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
if (state.isLoading && _optionalChain([frozenOptions, 'optionalAccess', _11 => _11.keepPreviousDataWhileLoading]) && typeof state.data === "undefined" && _optionalChain([previousData, 'access', _12 => _12.current, 'optionalAccess', _13 => _13.key]) !== key && typeof _optionalChain([previousData, 'access', _14 => _14.current, 'optionalAccess', _15 => _15.data]) !== "undefined") {
|
|
440
|
+
data = previousData.current.data;
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
isLoading: state.isLoading,
|
|
444
|
+
data,
|
|
445
|
+
error: state.error,
|
|
446
|
+
getState,
|
|
447
|
+
revalidate
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/comments/lib/use-debounce.ts
|
|
452
|
+
|
|
453
|
+
var DEFAULT_DELAY = 500;
|
|
454
|
+
function useDebounce(value, delay = DEFAULT_DELAY) {
|
|
455
|
+
const timeout = _react.useRef.call(void 0, );
|
|
456
|
+
const [debouncedValue, setDebouncedValue] = _react.useState.call(void 0, value);
|
|
457
|
+
_react.useEffect.call(void 0, () => {
|
|
458
|
+
if (delay === false) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (timeout.current === void 0) {
|
|
462
|
+
setDebouncedValue(value);
|
|
463
|
+
}
|
|
464
|
+
timeout.current = window.setTimeout(() => {
|
|
465
|
+
setDebouncedValue(value);
|
|
466
|
+
timeout.current = void 0;
|
|
467
|
+
}, delay);
|
|
468
|
+
return () => {
|
|
469
|
+
window.clearTimeout(timeout.current);
|
|
470
|
+
};
|
|
471
|
+
}, [value, delay]);
|
|
472
|
+
return debouncedValue;
|
|
473
|
+
}
|
|
474
|
+
|
|
29
475
|
// src/hooks.ts
|
|
30
476
|
|
|
31
477
|
function useRerender() {
|
|
@@ -38,12 +484,12 @@ function useRerender() {
|
|
|
38
484
|
);
|
|
39
485
|
return update;
|
|
40
486
|
}
|
|
41
|
-
function
|
|
487
|
+
function useInitial2(value) {
|
|
42
488
|
return _react.useRef.call(void 0, value).current;
|
|
43
489
|
}
|
|
44
490
|
|
|
45
491
|
// src/factory.tsx
|
|
46
|
-
var
|
|
492
|
+
var noop2 = () => {
|
|
47
493
|
};
|
|
48
494
|
var identity = (x) => x;
|
|
49
495
|
var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\u2019re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you\u2019re ready to upgrade to React 18:
|
|
@@ -58,7 +504,7 @@ var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\
|
|
|
58
504
|
|
|
59
505
|
Why? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;
|
|
60
506
|
var superfluous_unstable_batchedUpdates = "You don\u2019t need to pass unstable_batchedUpdates to RoomProvider anymore, since you\u2019re on React 18+ already.";
|
|
61
|
-
function
|
|
507
|
+
function useSyncExternalStore3(s, gs, gss) {
|
|
62
508
|
return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0, s, gs, gss, identity);
|
|
63
509
|
}
|
|
64
510
|
var EMPTY_OTHERS = (
|
|
@@ -95,7 +541,20 @@ function makeMutationContext(room) {
|
|
|
95
541
|
setMyPresence: room.updatePresence
|
|
96
542
|
};
|
|
97
543
|
}
|
|
98
|
-
|
|
544
|
+
var hasWarnedIfNoResolveUser = false;
|
|
545
|
+
function warnIfNoResolveUser(usersCache) {
|
|
546
|
+
if (!hasWarnedIfNoResolveUser && !usersCache && process.env.NODE_ENV !== "production") {
|
|
547
|
+
console.warn(
|
|
548
|
+
"Set the resolveUser option in createRoomContext to specify user info."
|
|
549
|
+
);
|
|
550
|
+
hasWarnedIfNoResolveUser = true;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
var ContextBundle = React2.createContext(null);
|
|
554
|
+
function useRoomContextBundle() {
|
|
555
|
+
return React2.useContext(ContextBundle);
|
|
556
|
+
}
|
|
557
|
+
function createRoomContext(client, options) {
|
|
99
558
|
const RoomContext = React2.createContext(null);
|
|
100
559
|
function RoomProvider(props) {
|
|
101
560
|
const {
|
|
@@ -125,7 +584,7 @@ function createRoomContext(client) {
|
|
|
125
584
|
superfluous_unstable_batchedUpdates
|
|
126
585
|
);
|
|
127
586
|
}
|
|
128
|
-
const frozen =
|
|
587
|
+
const frozen = useInitial2({
|
|
129
588
|
initialPresence,
|
|
130
589
|
initialStorage,
|
|
131
590
|
unstable_batchedUpdates,
|
|
@@ -140,19 +599,24 @@ function createRoomContext(client) {
|
|
|
140
599
|
})
|
|
141
600
|
);
|
|
142
601
|
React2.useEffect(() => {
|
|
143
|
-
|
|
144
|
-
|
|
602
|
+
const room2 = client.enter(
|
|
603
|
+
roomId,
|
|
604
|
+
{
|
|
145
605
|
initialPresence: frozen.initialPresence,
|
|
146
606
|
initialStorage: frozen.initialStorage,
|
|
147
607
|
shouldInitiallyConnect: frozen.shouldInitiallyConnect,
|
|
148
608
|
unstable_batchedUpdates: frozen.unstable_batchedUpdates
|
|
149
|
-
}
|
|
609
|
+
}
|
|
150
610
|
);
|
|
611
|
+
setRoom(room2);
|
|
612
|
+
const unsubscribe = getCommentsRoom(room2).subscribe();
|
|
151
613
|
return () => {
|
|
614
|
+
unsubscribe();
|
|
615
|
+
commentsRooms.delete(room2.id);
|
|
152
616
|
client.leave(roomId);
|
|
153
617
|
};
|
|
154
618
|
}, [roomId, frozen]);
|
|
155
|
-
return /* @__PURE__ */ React2.createElement(RoomContext.Provider, { value: room }, props.children);
|
|
619
|
+
return /* @__PURE__ */ React2.createElement(RoomContext.Provider, { value: room }, /* @__PURE__ */ React2.createElement(ContextBundle.Provider, { value: bundle }, props.children));
|
|
156
620
|
}
|
|
157
621
|
function connectionIdSelector(others) {
|
|
158
622
|
return others.map((user) => user.connectionId);
|
|
@@ -160,7 +624,7 @@ function createRoomContext(client) {
|
|
|
160
624
|
function useRoom() {
|
|
161
625
|
const room = React2.useContext(RoomContext);
|
|
162
626
|
if (room === null) {
|
|
163
|
-
throw new Error("RoomProvider is missing from the
|
|
627
|
+
throw new Error("RoomProvider is missing from the React tree.");
|
|
164
628
|
}
|
|
165
629
|
return room;
|
|
166
630
|
}
|
|
@@ -168,13 +632,13 @@ function createRoomContext(client) {
|
|
|
168
632
|
const room = useRoom();
|
|
169
633
|
const subscribe = room.events.status.subscribe;
|
|
170
634
|
const getSnapshot = room.getStatus;
|
|
171
|
-
return
|
|
635
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
|
|
172
636
|
}
|
|
173
637
|
function useMyPresence() {
|
|
174
638
|
const room = useRoom();
|
|
175
639
|
const subscribe = room.events.myPresence.subscribe;
|
|
176
640
|
const getSnapshot = room.getPresence;
|
|
177
|
-
const presence =
|
|
641
|
+
const presence = useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
|
|
178
642
|
const setPresence = room.updatePresence;
|
|
179
643
|
return [presence, setPresence];
|
|
180
644
|
}
|
|
@@ -248,8 +712,8 @@ function createRoomContext(client) {
|
|
|
248
712
|
function useBroadcastEvent() {
|
|
249
713
|
const room = useRoom();
|
|
250
714
|
return React2.useCallback(
|
|
251
|
-
(event,
|
|
252
|
-
room.broadcastEvent(event,
|
|
715
|
+
(event, options2 = { shouldQueueEventIfNotReady: false }) => {
|
|
716
|
+
room.broadcastEvent(event, options2);
|
|
253
717
|
},
|
|
254
718
|
[room]
|
|
255
719
|
);
|
|
@@ -314,7 +778,7 @@ function createRoomContext(client) {
|
|
|
314
778
|
const subscribe = room.events.storageDidLoad.subscribeOnce;
|
|
315
779
|
const getSnapshot = room.getStorageSnapshot;
|
|
316
780
|
const getServerSnapshot = React2.useCallback(() => null, []);
|
|
317
|
-
return
|
|
781
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot);
|
|
318
782
|
}
|
|
319
783
|
function useStorageRoot() {
|
|
320
784
|
return [useMutableStorageRoot()];
|
|
@@ -332,13 +796,13 @@ function createRoomContext(client) {
|
|
|
332
796
|
const room = useRoom();
|
|
333
797
|
const subscribe = room.events.history.subscribe;
|
|
334
798
|
const canUndo = room.history.canUndo;
|
|
335
|
-
return
|
|
799
|
+
return useSyncExternalStore3(subscribe, canUndo, canUndo);
|
|
336
800
|
}
|
|
337
801
|
function useCanRedo() {
|
|
338
802
|
const room = useRoom();
|
|
339
803
|
const subscribe = room.events.history.subscribe;
|
|
340
804
|
const canRedo = room.history.canRedo;
|
|
341
|
-
return
|
|
805
|
+
return useSyncExternalStore3(subscribe, canRedo, canRedo);
|
|
342
806
|
}
|
|
343
807
|
function useBatch() {
|
|
344
808
|
return useRoom().batch;
|
|
@@ -395,7 +859,7 @@ function createRoomContext(client) {
|
|
|
395
859
|
[selector]
|
|
396
860
|
);
|
|
397
861
|
const subscribe = React2.useCallback(
|
|
398
|
-
(onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) :
|
|
862
|
+
(onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop2,
|
|
399
863
|
[room, rootOrNull]
|
|
400
864
|
);
|
|
401
865
|
const getSnapshot = React2.useCallback(() => {
|
|
@@ -501,7 +965,119 @@ function createRoomContext(client) {
|
|
|
501
965
|
useSuspendUntilStorageLoaded();
|
|
502
966
|
return useLegacyKey(key);
|
|
503
967
|
}
|
|
504
|
-
|
|
968
|
+
const errorEventSource = _core.makeEventSource.call(void 0, );
|
|
969
|
+
const commentsRooms = /* @__PURE__ */ new Map();
|
|
970
|
+
function getCommentsRoom(room) {
|
|
971
|
+
let commentsRoom = commentsRooms.get(room.id);
|
|
972
|
+
if (commentsRoom === void 0) {
|
|
973
|
+
commentsRoom = createCommentsRoom(room, errorEventSource);
|
|
974
|
+
commentsRooms.set(room.id, commentsRoom);
|
|
975
|
+
}
|
|
976
|
+
return commentsRoom;
|
|
977
|
+
}
|
|
978
|
+
function useThreads() {
|
|
979
|
+
const room = useRoom();
|
|
980
|
+
return getCommentsRoom(room).useThreads();
|
|
981
|
+
}
|
|
982
|
+
function useThreadsSuspense() {
|
|
983
|
+
const room = useRoom();
|
|
984
|
+
return getCommentsRoom(room).useThreadsSuspense();
|
|
985
|
+
}
|
|
986
|
+
function useCreateThread() {
|
|
987
|
+
const room = useRoom();
|
|
988
|
+
return React2.useCallback(
|
|
989
|
+
(options2) => getCommentsRoom(room).createThread(options2),
|
|
990
|
+
[room]
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
function useEditThreadMetadata() {
|
|
994
|
+
const room = useRoom();
|
|
995
|
+
return React2.useCallback(
|
|
996
|
+
(options2) => getCommentsRoom(room).editThreadMetadata(options2),
|
|
997
|
+
[room]
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
function useCreateComment() {
|
|
1001
|
+
const room = useRoom();
|
|
1002
|
+
return React2.useCallback(
|
|
1003
|
+
(options2) => getCommentsRoom(room).createComment(options2),
|
|
1004
|
+
[room]
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
function useEditComment() {
|
|
1008
|
+
const room = useRoom();
|
|
1009
|
+
return React2.useCallback(
|
|
1010
|
+
(options2) => getCommentsRoom(room).editComment(options2),
|
|
1011
|
+
[room]
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
function useDeleteComment() {
|
|
1015
|
+
const room = useRoom();
|
|
1016
|
+
return React2.useCallback(
|
|
1017
|
+
(options2) => getCommentsRoom(room).deleteComment(options2),
|
|
1018
|
+
[room]
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
const { resolveUser, resolveMentionSuggestions } = _nullishCoalesce(options, () => ( {}));
|
|
1022
|
+
const usersCache = resolveUser ? _core.createAsyncCache.call(void 0, (stringifiedOptions) => {
|
|
1023
|
+
return resolveUser(
|
|
1024
|
+
JSON.parse(stringifiedOptions)
|
|
1025
|
+
);
|
|
1026
|
+
}) : void 0;
|
|
1027
|
+
function useUser(userId) {
|
|
1028
|
+
const resolverKey = React2.useMemo(
|
|
1029
|
+
() => JSON.stringify({ userId }),
|
|
1030
|
+
[userId]
|
|
1031
|
+
);
|
|
1032
|
+
const state = useAsyncCache(usersCache, resolverKey);
|
|
1033
|
+
React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
|
|
1034
|
+
if (state.isLoading) {
|
|
1035
|
+
return {
|
|
1036
|
+
isLoading: true
|
|
1037
|
+
};
|
|
1038
|
+
} else {
|
|
1039
|
+
return {
|
|
1040
|
+
user: state.data,
|
|
1041
|
+
error: state.error,
|
|
1042
|
+
isLoading: false
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
function useUserSuspense(userId) {
|
|
1047
|
+
const resolverKey = React2.useMemo(
|
|
1048
|
+
() => JSON.stringify({ userId }),
|
|
1049
|
+
[userId]
|
|
1050
|
+
);
|
|
1051
|
+
const state = useAsyncCache(usersCache, resolverKey, {
|
|
1052
|
+
suspense: true
|
|
1053
|
+
});
|
|
1054
|
+
React2.useEffect(() => warnIfNoResolveUser(usersCache), []);
|
|
1055
|
+
return {
|
|
1056
|
+
user: state.data,
|
|
1057
|
+
error: state.error,
|
|
1058
|
+
isLoading: false
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
const mentionSuggestionsCache = _core.createAsyncCache.call(void 0,
|
|
1062
|
+
resolveMentionSuggestions ? (stringifiedOptions) => {
|
|
1063
|
+
return resolveMentionSuggestions(
|
|
1064
|
+
JSON.parse(stringifiedOptions)
|
|
1065
|
+
);
|
|
1066
|
+
} : () => Promise.resolve([])
|
|
1067
|
+
);
|
|
1068
|
+
function useMentionSuggestions(search) {
|
|
1069
|
+
const room = useRoom();
|
|
1070
|
+
const debouncedSearch = useDebounce(search, 500);
|
|
1071
|
+
const resolverKey = React2.useMemo(
|
|
1072
|
+
() => debouncedSearch !== void 0 ? JSON.stringify({ text: debouncedSearch, roomId: room.id }) : null,
|
|
1073
|
+
[debouncedSearch, room.id]
|
|
1074
|
+
);
|
|
1075
|
+
const { data } = useAsyncCache(mentionSuggestionsCache, resolverKey, {
|
|
1076
|
+
keepPreviousDataWhileLoading: true
|
|
1077
|
+
});
|
|
1078
|
+
return data;
|
|
1079
|
+
}
|
|
1080
|
+
const bundle = {
|
|
505
1081
|
RoomContext,
|
|
506
1082
|
RoomProvider,
|
|
507
1083
|
useRoom,
|
|
@@ -530,6 +1106,14 @@ function createRoomContext(client) {
|
|
|
530
1106
|
useOthersConnectionIds,
|
|
531
1107
|
useOther,
|
|
532
1108
|
useMutation,
|
|
1109
|
+
useThreads,
|
|
1110
|
+
useUser,
|
|
1111
|
+
useCreateThread,
|
|
1112
|
+
useEditThreadMetadata,
|
|
1113
|
+
useCreateComment,
|
|
1114
|
+
useEditComment,
|
|
1115
|
+
useDeleteComment,
|
|
1116
|
+
useMentionSuggestions,
|
|
533
1117
|
suspense: {
|
|
534
1118
|
RoomContext,
|
|
535
1119
|
RoomProvider,
|
|
@@ -558,9 +1142,17 @@ function createRoomContext(client) {
|
|
|
558
1142
|
useOthersMapped: useOthersMappedSuspense,
|
|
559
1143
|
useOthersConnectionIds: useOthersConnectionIdsSuspense,
|
|
560
1144
|
useOther: useOtherSuspense,
|
|
561
|
-
useMutation
|
|
1145
|
+
useMutation,
|
|
1146
|
+
useThreads: useThreadsSuspense,
|
|
1147
|
+
useUser: useUserSuspense,
|
|
1148
|
+
useCreateThread,
|
|
1149
|
+
useEditThreadMetadata,
|
|
1150
|
+
useCreateComment,
|
|
1151
|
+
useEditComment,
|
|
1152
|
+
useDeleteComment
|
|
562
1153
|
}
|
|
563
1154
|
};
|
|
1155
|
+
return bundle;
|
|
564
1156
|
}
|
|
565
1157
|
|
|
566
1158
|
// src/index.ts
|
|
@@ -570,5 +1162,6 @@ _core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT);
|
|
|
570
1162
|
|
|
571
1163
|
|
|
572
1164
|
|
|
573
|
-
|
|
1165
|
+
|
|
1166
|
+
exports.ClientSideSuspense = ClientSideSuspense; exports.createRoomContext = createRoomContext; exports.shallow = _client.shallow; exports.useRoomContextBundle = useRoomContextBundle;
|
|
574
1167
|
//# sourceMappingURL=index.js.map
|