@pluv/react 0.18.0 → 0.20.0
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/.turbo/turbo-build.log +15 -15
- package/CHANGELOG.md +94 -0
- package/README.md +0 -138
- package/dist/index.d.mts +12 -12
- package/dist/index.d.ts +12 -12
- package/dist/index.js +99 -59
- package/dist/index.mjs +81 -41
- package/package.json +10 -11
- package/src/createBundle.tsx +3 -6
- package/src/createRoomBundle.tsx +48 -45
- package/src/index.ts +1 -1
- package/src/internal/hooks/index.ts +1 -1
- package/src/internal/hooks/useNoSsr.ts +18 -0
- package/src/internal/hooks/useSyncExternalStoreWithSelector.ts +56 -1
- package/src/internal/utils/index.ts +1 -0
- package/src/internal/utils/shallowEqual.ts +1 -0
- package/tsconfig.json +4 -1
- package/src/internal/hooks/useSyncExternalStore.ts +0 -10
package/dist/index.js
CHANGED
|
@@ -38,25 +38,39 @@ module.exports = __toCommonJS(src_exports);
|
|
|
38
38
|
var import_client2 = require("@pluv/client");
|
|
39
39
|
|
|
40
40
|
// src/createBundle.tsx
|
|
41
|
-
var
|
|
41
|
+
var import_react5 = require("react");
|
|
42
42
|
|
|
43
43
|
// src/createRoomBundle.tsx
|
|
44
44
|
var import_client = require("@pluv/client");
|
|
45
45
|
var import_crdt = require("@pluv/crdt");
|
|
46
46
|
var import_fast_deep_equal = __toESM(require("fast-deep-equal"));
|
|
47
|
-
var
|
|
47
|
+
var import_react4 = require("react");
|
|
48
48
|
|
|
49
|
-
// src/internal/hooks/
|
|
49
|
+
// src/internal/hooks/useNoSsr.ts
|
|
50
50
|
var import_react = require("react");
|
|
51
|
+
var useNoSsr = () => {
|
|
52
|
+
const [didMount, setDidMount] = (0, import_react.useState)(false);
|
|
53
|
+
(0, import_react.useEffect)(() => setDidMount(typeof window !== "undefined"), []);
|
|
54
|
+
const noSsr = (0, import_react.useCallback)(
|
|
55
|
+
(value, fallback = null) => {
|
|
56
|
+
return didMount ? typeof value !== "function" ? value : value() : fallback;
|
|
57
|
+
},
|
|
58
|
+
[didMount]
|
|
59
|
+
);
|
|
60
|
+
return noSsr;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// src/internal/hooks/useRerender.ts
|
|
64
|
+
var import_react2 = require("react");
|
|
51
65
|
var useRerender = () => {
|
|
52
|
-
const [, setCount] = (0,
|
|
53
|
-
return (0,
|
|
66
|
+
const [, setCount] = (0, import_react2.useState)(0);
|
|
67
|
+
return (0, import_react2.useCallback)(() => {
|
|
54
68
|
setCount((oldCount) => (oldCount + 1) % Number.MAX_SAFE_INTEGER);
|
|
55
69
|
}, []);
|
|
56
70
|
};
|
|
57
71
|
|
|
58
72
|
// src/internal/hooks/useSyncExternalStoreWithSelector.ts
|
|
59
|
-
var
|
|
73
|
+
var import_react3 = require("react");
|
|
60
74
|
|
|
61
75
|
// src/internal/utils/identity.ts
|
|
62
76
|
var identity = (x) => x;
|
|
@@ -66,16 +80,45 @@ var shallowArrayEqual = (a, b) => {
|
|
|
66
80
|
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
67
81
|
};
|
|
68
82
|
|
|
83
|
+
// src/internal/utils/shallowEqual.ts
|
|
84
|
+
var shallowEqual = (a, b) => a === b;
|
|
85
|
+
|
|
86
|
+
// src/internal/hooks/useSyncExternalStoreWithSelector.ts
|
|
87
|
+
var useSyncExternalStoreWithSelector = (subscribe, getClientSnapshot, getServerSnapshot, selector, isEqual) => {
|
|
88
|
+
const noSsr = useNoSsr();
|
|
89
|
+
const cacheRef = (0, import_react3.useRef)(null);
|
|
90
|
+
const _getServerSnapshot = getServerSnapshot ? () => {
|
|
91
|
+
const data = getServerSnapshot();
|
|
92
|
+
const snapshot = selector(data);
|
|
93
|
+
const compare = isEqual != null ? isEqual : shallowEqual;
|
|
94
|
+
const cached = cacheRef.current;
|
|
95
|
+
const isUnchanged = cached === null ? snapshot === null : compare(cached, snapshot);
|
|
96
|
+
cacheRef.current = isUnchanged ? cached != null ? cached : snapshot : snapshot;
|
|
97
|
+
return cacheRef.current;
|
|
98
|
+
} : void 0;
|
|
99
|
+
const _getClientSnapshot = () => {
|
|
100
|
+
const data = getClientSnapshot();
|
|
101
|
+
const snapshot = selector(data);
|
|
102
|
+
const compare = isEqual != null ? isEqual : shallowEqual;
|
|
103
|
+
const cached = cacheRef.current;
|
|
104
|
+
const isUnchanged = cached === null ? snapshot === null : compare(cached, snapshot);
|
|
105
|
+
cacheRef.current = isUnchanged ? cached != null ? cached : snapshot : snapshot;
|
|
106
|
+
return cacheRef.current;
|
|
107
|
+
};
|
|
108
|
+
const result = (0, import_react3.useSyncExternalStore)(subscribe, _getClientSnapshot, _getServerSnapshot);
|
|
109
|
+
return typeof window !== "undefined" ? noSsr(result, _getServerSnapshot == null ? void 0 : _getServerSnapshot()) : result;
|
|
110
|
+
};
|
|
111
|
+
|
|
69
112
|
// src/createRoomBundle.tsx
|
|
70
113
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
71
114
|
var createRoomBundle = (client, options) => {
|
|
72
115
|
var _a;
|
|
73
116
|
const _initialStorage = (_a = options.initialStorage) != null ? _a : import_crdt.noop.doc();
|
|
74
|
-
const PluvRoomContext = (0,
|
|
75
|
-
const MockedRoomContext = (0,
|
|
76
|
-
const MockedRoomProvider = (0,
|
|
117
|
+
const PluvRoomContext = (0, import_react4.createContext)(null);
|
|
118
|
+
const MockedRoomContext = (0, import_react4.createContext)({ room: null });
|
|
119
|
+
const MockedRoomProvider = (0, import_react4.memo)((props) => {
|
|
77
120
|
const { children, events, initialPresence, initialStorage, room: _room } = props;
|
|
78
|
-
const [room] = (0,
|
|
121
|
+
const [room] = (0, import_react4.useState)(() => {
|
|
79
122
|
return new import_client.MockedRoom(_room, {
|
|
80
123
|
events,
|
|
81
124
|
initialPresence,
|
|
@@ -86,11 +129,11 @@ var createRoomBundle = (client, options) => {
|
|
|
86
129
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MockedRoomContext.Provider, { value: { room }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluvRoomContext.Provider, { value: room, children }) });
|
|
87
130
|
});
|
|
88
131
|
MockedRoomProvider.displayName = "MockedRoomProvider";
|
|
89
|
-
const PluvRoomProvider = (0,
|
|
132
|
+
const PluvRoomProvider = (0, import_react4.memo)((props) => {
|
|
90
133
|
const { children, debug, initialPresence, initialStorage, onAuthorizationFail, room: _room } = props;
|
|
91
134
|
const rerender = useRerender();
|
|
92
|
-
const { room: mockedRoom } = (0,
|
|
93
|
-
const [room] = (0,
|
|
135
|
+
const { room: mockedRoom } = (0, import_react4.useContext)(MockedRoomContext);
|
|
136
|
+
const [room] = (0, import_react4.useState)(() => {
|
|
94
137
|
return client.createRoom(_room, {
|
|
95
138
|
addons: options.addons,
|
|
96
139
|
debug,
|
|
@@ -100,7 +143,7 @@ var createRoomBundle = (client, options) => {
|
|
|
100
143
|
onAuthorizationFail
|
|
101
144
|
});
|
|
102
145
|
});
|
|
103
|
-
(0,
|
|
146
|
+
(0, import_react4.useEffect)(() => {
|
|
104
147
|
const unsubscribe = room.subscribe("connection", () => {
|
|
105
148
|
rerender();
|
|
106
149
|
});
|
|
@@ -108,7 +151,7 @@ var createRoomBundle = (client, options) => {
|
|
|
108
151
|
unsubscribe();
|
|
109
152
|
};
|
|
110
153
|
}, [rerender, room]);
|
|
111
|
-
(0,
|
|
154
|
+
(0, import_react4.useEffect)(() => {
|
|
112
155
|
client.enter(room);
|
|
113
156
|
return () => {
|
|
114
157
|
client.leave(room);
|
|
@@ -117,16 +160,16 @@ var createRoomBundle = (client, options) => {
|
|
|
117
160
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluvRoomContext.Provider, { value: mockedRoom != null ? mockedRoom : room, children });
|
|
118
161
|
});
|
|
119
162
|
PluvRoomProvider.displayName = "PluvRoomProvider";
|
|
120
|
-
const useRoom = () => (0,
|
|
163
|
+
const useRoom = () => (0, import_react4.useContext)(PluvRoomContext);
|
|
121
164
|
const useBroadcast = () => {
|
|
122
165
|
const room = useRoom();
|
|
123
|
-
const broadcast = (0,
|
|
166
|
+
const broadcast = (0, import_react4.useCallback)(
|
|
124
167
|
(event2, data) => {
|
|
125
168
|
room.broadcast(event2, data);
|
|
126
169
|
},
|
|
127
170
|
[room]
|
|
128
171
|
);
|
|
129
|
-
return (0,
|
|
172
|
+
return (0, import_react4.useMemo)(() => {
|
|
130
173
|
return new Proxy(broadcast, {
|
|
131
174
|
get(fn, prop) {
|
|
132
175
|
return (data) => {
|
|
@@ -138,30 +181,30 @@ var createRoomBundle = (client, options) => {
|
|
|
138
181
|
};
|
|
139
182
|
const useCanRedo = () => {
|
|
140
183
|
const room = useRoom();
|
|
141
|
-
const subscribe = (0,
|
|
142
|
-
const getSnapshot = (0,
|
|
143
|
-
const canRedo =
|
|
184
|
+
const subscribe = (0, import_react4.useCallback)((onStoreChange) => room.storageRoot(onStoreChange), [room]);
|
|
185
|
+
const getSnapshot = (0, import_react4.useCallback)(() => room.canRedo(), [room]);
|
|
186
|
+
const canRedo = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity);
|
|
144
187
|
return canRedo;
|
|
145
188
|
};
|
|
146
189
|
const useCanUndo = () => {
|
|
147
190
|
const room = useRoom();
|
|
148
|
-
const subscribe = (0,
|
|
149
|
-
const getSnapshot = (0,
|
|
150
|
-
const
|
|
151
|
-
return
|
|
191
|
+
const subscribe = (0, import_react4.useCallback)((onStoreChange) => room.storageRoot(onStoreChange), [room]);
|
|
192
|
+
const getSnapshot = (0, import_react4.useCallback)(() => room.canUndo(), [room]);
|
|
193
|
+
const canUndo = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity);
|
|
194
|
+
return canUndo;
|
|
152
195
|
};
|
|
153
196
|
const useConnection = (selector = identity, options2) => {
|
|
154
197
|
var _a2;
|
|
155
198
|
const room = useRoom();
|
|
156
|
-
const subscribe = (0,
|
|
199
|
+
const subscribe = (0, import_react4.useCallback)(
|
|
157
200
|
(onStoreChange) => {
|
|
158
201
|
return room.subscribe("connection", onStoreChange);
|
|
159
202
|
},
|
|
160
203
|
[room]
|
|
161
204
|
);
|
|
162
205
|
const getSnapshot = room.getConnection;
|
|
163
|
-
const _selector = (0,
|
|
164
|
-
return
|
|
206
|
+
const _selector = (0, import_react4.useCallback)((snapshot) => selector(snapshot), [selector]);
|
|
207
|
+
return useSyncExternalStoreWithSelector(
|
|
165
208
|
subscribe,
|
|
166
209
|
getSnapshot,
|
|
167
210
|
getSnapshot,
|
|
@@ -175,7 +218,7 @@ var createRoomBundle = (client, options) => {
|
|
|
175
218
|
};
|
|
176
219
|
const useEvent = (type, callback) => {
|
|
177
220
|
const room = useRoom();
|
|
178
|
-
(0,
|
|
221
|
+
(0, import_react4.useEffect)(() => {
|
|
179
222
|
const unsubscribe = room.event(type, callback);
|
|
180
223
|
return () => {
|
|
181
224
|
unsubscribe();
|
|
@@ -196,47 +239,40 @@ var createRoomBundle = (client, options) => {
|
|
|
196
239
|
const useMyPresence = (selector = identity, options2) => {
|
|
197
240
|
var _a2;
|
|
198
241
|
const room = useRoom();
|
|
199
|
-
const subscribe = (0,
|
|
242
|
+
const subscribe = (0, import_react4.useCallback)(
|
|
200
243
|
(onStoreChange) => {
|
|
201
244
|
return room.subscribe("my-presence", onStoreChange);
|
|
202
245
|
},
|
|
203
246
|
[room]
|
|
204
247
|
);
|
|
205
248
|
const getSnapshot = room.getMyPresence;
|
|
206
|
-
const _selector = (0,
|
|
207
|
-
const myPresence =
|
|
249
|
+
const _selector = (0, import_react4.useCallback)((snapshot) => selector(snapshot), [selector]);
|
|
250
|
+
const myPresence = useSyncExternalStoreWithSelector(
|
|
208
251
|
subscribe,
|
|
209
252
|
getSnapshot,
|
|
210
253
|
getSnapshot,
|
|
211
254
|
_selector,
|
|
212
255
|
(_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
|
|
213
256
|
);
|
|
214
|
-
|
|
215
|
-
(value) => {
|
|
216
|
-
const presence = typeof value === "function" ? value(room.getMyPresence()) : value;
|
|
217
|
-
room.updateMyPresence(presence);
|
|
218
|
-
},
|
|
219
|
-
[room]
|
|
220
|
-
);
|
|
221
|
-
return [myPresence, updateMyPresence];
|
|
257
|
+
return [myPresence, room.updateMyPresence];
|
|
222
258
|
};
|
|
223
259
|
const useMyself = (selector = identity, options2) => {
|
|
224
260
|
var _a2;
|
|
225
261
|
const room = useRoom();
|
|
226
|
-
const subscribe = (0,
|
|
262
|
+
const subscribe = (0, import_react4.useCallback)(
|
|
227
263
|
(onStoreChange) => {
|
|
228
264
|
return room.subscribe("myself", onStoreChange);
|
|
229
265
|
},
|
|
230
266
|
[room]
|
|
231
267
|
);
|
|
232
268
|
const getSnapshot = room.getMyself;
|
|
233
|
-
const _selector = (0,
|
|
269
|
+
const _selector = (0, import_react4.useCallback)(
|
|
234
270
|
(snapshot) => {
|
|
235
271
|
return !snapshot ? null : selector(snapshot);
|
|
236
272
|
},
|
|
237
273
|
[selector]
|
|
238
274
|
);
|
|
239
|
-
return
|
|
275
|
+
return useSyncExternalStoreWithSelector(
|
|
240
276
|
subscribe,
|
|
241
277
|
getSnapshot,
|
|
242
278
|
getSnapshot,
|
|
@@ -247,20 +283,20 @@ var createRoomBundle = (client, options) => {
|
|
|
247
283
|
const useOther = (connectionId, selector = identity, options2) => {
|
|
248
284
|
var _a2;
|
|
249
285
|
const room = useRoom();
|
|
250
|
-
const subscribe = (0,
|
|
286
|
+
const subscribe = (0, import_react4.useCallback)(
|
|
251
287
|
(onStoreChange) => {
|
|
252
288
|
return room.other(connectionId, onStoreChange);
|
|
253
289
|
},
|
|
254
290
|
[room, connectionId]
|
|
255
291
|
);
|
|
256
|
-
const getSnapshot = (0,
|
|
257
|
-
const _selector = (0,
|
|
292
|
+
const getSnapshot = (0, import_react4.useCallback)(() => room.getOther(connectionId), [room, connectionId]);
|
|
293
|
+
const _selector = (0, import_react4.useCallback)(
|
|
258
294
|
(snapshot) => {
|
|
259
295
|
return !snapshot ? null : selector(snapshot);
|
|
260
296
|
},
|
|
261
297
|
[selector]
|
|
262
298
|
);
|
|
263
|
-
return
|
|
299
|
+
return useSyncExternalStoreWithSelector(
|
|
264
300
|
subscribe,
|
|
265
301
|
getSnapshot,
|
|
266
302
|
getSnapshot,
|
|
@@ -271,19 +307,24 @@ var createRoomBundle = (client, options) => {
|
|
|
271
307
|
const useOthers = (selector = identity, options2) => {
|
|
272
308
|
var _a2;
|
|
273
309
|
const room = useRoom();
|
|
274
|
-
const subscribe = (0,
|
|
310
|
+
const subscribe = (0, import_react4.useCallback)(
|
|
275
311
|
(onStoreChange) => {
|
|
276
312
|
return room.subscribe("others", onStoreChange);
|
|
277
313
|
},
|
|
278
314
|
[room]
|
|
279
315
|
);
|
|
280
316
|
const getSnapshot = room.getOthers;
|
|
281
|
-
return
|
|
317
|
+
return useSyncExternalStoreWithSelector(
|
|
282
318
|
subscribe,
|
|
283
319
|
getSnapshot,
|
|
284
320
|
getSnapshot,
|
|
285
321
|
selector,
|
|
286
|
-
(_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 :
|
|
322
|
+
(_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : (a, b) => {
|
|
323
|
+
if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
|
|
324
|
+
return shallowArrayEqual(a, b);
|
|
325
|
+
}
|
|
326
|
+
return (0, import_fast_deep_equal.default)(a, b);
|
|
327
|
+
}
|
|
287
328
|
);
|
|
288
329
|
};
|
|
289
330
|
const useRedo = () => {
|
|
@@ -297,18 +338,17 @@ var createRoomBundle = (client, options) => {
|
|
|
297
338
|
room.subscribe("storage-loaded", () => {
|
|
298
339
|
rerender();
|
|
299
340
|
});
|
|
300
|
-
const subscribe = (0,
|
|
301
|
-
const getSnapshot = (0,
|
|
302
|
-
|
|
303
|
-
return (_a3 = room.getStorage(key)) == null ? void 0 : _a3.toJson();
|
|
341
|
+
const subscribe = (0, import_react4.useCallback)((onStoreChange) => room.storage(key, onStoreChange), [key, room]);
|
|
342
|
+
const getSnapshot = (0, import_react4.useCallback)(() => {
|
|
343
|
+
return room.getStorageJson(key);
|
|
304
344
|
}, [key, room]);
|
|
305
|
-
const _selector = (0,
|
|
345
|
+
const _selector = (0, import_react4.useCallback)(
|
|
306
346
|
(snapshot) => {
|
|
307
347
|
return snapshot === null ? null : selector(snapshot);
|
|
308
348
|
},
|
|
309
349
|
[selector]
|
|
310
350
|
);
|
|
311
|
-
const data =
|
|
351
|
+
const data = useSyncExternalStoreWithSelector(
|
|
312
352
|
subscribe,
|
|
313
353
|
getSnapshot,
|
|
314
354
|
getSnapshot,
|
|
@@ -354,13 +394,13 @@ var createRoomBundle = (client, options) => {
|
|
|
354
394
|
// src/createBundle.tsx
|
|
355
395
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
356
396
|
var createBundle = (client) => {
|
|
357
|
-
const PluvContext = (0,
|
|
358
|
-
const PluvProvider = (0,
|
|
397
|
+
const PluvContext = (0, import_react5.createContext)(null);
|
|
398
|
+
const PluvProvider = (0, import_react5.memo)((props) => {
|
|
359
399
|
const { children } = props;
|
|
360
400
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PluvContext.Provider, { value: client, children });
|
|
361
401
|
});
|
|
362
402
|
PluvProvider.displayName = "PluvProvider";
|
|
363
|
-
const useClient = () => (0,
|
|
403
|
+
const useClient = () => (0, import_react5.useContext)(PluvContext);
|
|
364
404
|
const createRoomBundle2 = (options) => createRoomBundle(client, options);
|
|
365
405
|
return {
|
|
366
406
|
createRoomBundle: createRoomBundle2,
|
package/dist/index.mjs
CHANGED
|
@@ -8,19 +8,33 @@ import { createContext as createContext2, memo as memo2, useContext as useContex
|
|
|
8
8
|
import { MockedRoom } from "@pluv/client";
|
|
9
9
|
import { noop } from "@pluv/crdt";
|
|
10
10
|
import fastDeepEqual from "fast-deep-equal";
|
|
11
|
-
import { createContext, memo, useCallback as
|
|
11
|
+
import { createContext, memo, useCallback as useCallback3, useContext, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
|
|
12
|
+
|
|
13
|
+
// src/internal/hooks/useNoSsr.ts
|
|
14
|
+
import { useCallback, useEffect, useState } from "react";
|
|
15
|
+
var useNoSsr = () => {
|
|
16
|
+
const [didMount, setDidMount] = useState(false);
|
|
17
|
+
useEffect(() => setDidMount(typeof window !== "undefined"), []);
|
|
18
|
+
const noSsr = useCallback(
|
|
19
|
+
(value, fallback = null) => {
|
|
20
|
+
return didMount ? typeof value !== "function" ? value : value() : fallback;
|
|
21
|
+
},
|
|
22
|
+
[didMount]
|
|
23
|
+
);
|
|
24
|
+
return noSsr;
|
|
25
|
+
};
|
|
12
26
|
|
|
13
27
|
// src/internal/hooks/useRerender.ts
|
|
14
|
-
import { useCallback, useState } from "react";
|
|
28
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
15
29
|
var useRerender = () => {
|
|
16
|
-
const [, setCount] =
|
|
17
|
-
return
|
|
30
|
+
const [, setCount] = useState2(0);
|
|
31
|
+
return useCallback2(() => {
|
|
18
32
|
setCount((oldCount) => (oldCount + 1) % Number.MAX_SAFE_INTEGER);
|
|
19
33
|
}, []);
|
|
20
34
|
};
|
|
21
35
|
|
|
22
36
|
// src/internal/hooks/useSyncExternalStoreWithSelector.ts
|
|
23
|
-
import {
|
|
37
|
+
import { useRef, useSyncExternalStore } from "react";
|
|
24
38
|
|
|
25
39
|
// src/internal/utils/identity.ts
|
|
26
40
|
var identity = (x) => x;
|
|
@@ -30,6 +44,35 @@ var shallowArrayEqual = (a, b) => {
|
|
|
30
44
|
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
31
45
|
};
|
|
32
46
|
|
|
47
|
+
// src/internal/utils/shallowEqual.ts
|
|
48
|
+
var shallowEqual = (a, b) => a === b;
|
|
49
|
+
|
|
50
|
+
// src/internal/hooks/useSyncExternalStoreWithSelector.ts
|
|
51
|
+
var useSyncExternalStoreWithSelector = (subscribe, getClientSnapshot, getServerSnapshot, selector, isEqual) => {
|
|
52
|
+
const noSsr = useNoSsr();
|
|
53
|
+
const cacheRef = useRef(null);
|
|
54
|
+
const _getServerSnapshot = getServerSnapshot ? () => {
|
|
55
|
+
const data = getServerSnapshot();
|
|
56
|
+
const snapshot = selector(data);
|
|
57
|
+
const compare = isEqual != null ? isEqual : shallowEqual;
|
|
58
|
+
const cached = cacheRef.current;
|
|
59
|
+
const isUnchanged = cached === null ? snapshot === null : compare(cached, snapshot);
|
|
60
|
+
cacheRef.current = isUnchanged ? cached != null ? cached : snapshot : snapshot;
|
|
61
|
+
return cacheRef.current;
|
|
62
|
+
} : void 0;
|
|
63
|
+
const _getClientSnapshot = () => {
|
|
64
|
+
const data = getClientSnapshot();
|
|
65
|
+
const snapshot = selector(data);
|
|
66
|
+
const compare = isEqual != null ? isEqual : shallowEqual;
|
|
67
|
+
const cached = cacheRef.current;
|
|
68
|
+
const isUnchanged = cached === null ? snapshot === null : compare(cached, snapshot);
|
|
69
|
+
cacheRef.current = isUnchanged ? cached != null ? cached : snapshot : snapshot;
|
|
70
|
+
return cacheRef.current;
|
|
71
|
+
};
|
|
72
|
+
const result = useSyncExternalStore(subscribe, _getClientSnapshot, _getServerSnapshot);
|
|
73
|
+
return typeof window !== "undefined" ? noSsr(result, _getServerSnapshot == null ? void 0 : _getServerSnapshot()) : result;
|
|
74
|
+
};
|
|
75
|
+
|
|
33
76
|
// src/createRoomBundle.tsx
|
|
34
77
|
import { jsx } from "react/jsx-runtime";
|
|
35
78
|
var createRoomBundle = (client, options) => {
|
|
@@ -39,7 +82,7 @@ var createRoomBundle = (client, options) => {
|
|
|
39
82
|
const MockedRoomContext = createContext({ room: null });
|
|
40
83
|
const MockedRoomProvider = memo((props) => {
|
|
41
84
|
const { children, events, initialPresence, initialStorage, room: _room } = props;
|
|
42
|
-
const [room] =
|
|
85
|
+
const [room] = useState3(() => {
|
|
43
86
|
return new MockedRoom(_room, {
|
|
44
87
|
events,
|
|
45
88
|
initialPresence,
|
|
@@ -54,7 +97,7 @@ var createRoomBundle = (client, options) => {
|
|
|
54
97
|
const { children, debug, initialPresence, initialStorage, onAuthorizationFail, room: _room } = props;
|
|
55
98
|
const rerender = useRerender();
|
|
56
99
|
const { room: mockedRoom } = useContext(MockedRoomContext);
|
|
57
|
-
const [room] =
|
|
100
|
+
const [room] = useState3(() => {
|
|
58
101
|
return client.createRoom(_room, {
|
|
59
102
|
addons: options.addons,
|
|
60
103
|
debug,
|
|
@@ -64,7 +107,7 @@ var createRoomBundle = (client, options) => {
|
|
|
64
107
|
onAuthorizationFail
|
|
65
108
|
});
|
|
66
109
|
});
|
|
67
|
-
|
|
110
|
+
useEffect2(() => {
|
|
68
111
|
const unsubscribe = room.subscribe("connection", () => {
|
|
69
112
|
rerender();
|
|
70
113
|
});
|
|
@@ -72,7 +115,7 @@ var createRoomBundle = (client, options) => {
|
|
|
72
115
|
unsubscribe();
|
|
73
116
|
};
|
|
74
117
|
}, [rerender, room]);
|
|
75
|
-
|
|
118
|
+
useEffect2(() => {
|
|
76
119
|
client.enter(room);
|
|
77
120
|
return () => {
|
|
78
121
|
client.leave(room);
|
|
@@ -84,7 +127,7 @@ var createRoomBundle = (client, options) => {
|
|
|
84
127
|
const useRoom = () => useContext(PluvRoomContext);
|
|
85
128
|
const useBroadcast = () => {
|
|
86
129
|
const room = useRoom();
|
|
87
|
-
const broadcast =
|
|
130
|
+
const broadcast = useCallback3(
|
|
88
131
|
(event2, data) => {
|
|
89
132
|
room.broadcast(event2, data);
|
|
90
133
|
},
|
|
@@ -102,29 +145,29 @@ var createRoomBundle = (client, options) => {
|
|
|
102
145
|
};
|
|
103
146
|
const useCanRedo = () => {
|
|
104
147
|
const room = useRoom();
|
|
105
|
-
const subscribe =
|
|
106
|
-
const getSnapshot =
|
|
148
|
+
const subscribe = useCallback3((onStoreChange) => room.storageRoot(onStoreChange), [room]);
|
|
149
|
+
const getSnapshot = useCallback3(() => room.canRedo(), [room]);
|
|
107
150
|
const canRedo = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity);
|
|
108
151
|
return canRedo;
|
|
109
152
|
};
|
|
110
153
|
const useCanUndo = () => {
|
|
111
154
|
const room = useRoom();
|
|
112
|
-
const subscribe =
|
|
113
|
-
const getSnapshot =
|
|
114
|
-
const
|
|
115
|
-
return
|
|
155
|
+
const subscribe = useCallback3((onStoreChange) => room.storageRoot(onStoreChange), [room]);
|
|
156
|
+
const getSnapshot = useCallback3(() => room.canUndo(), [room]);
|
|
157
|
+
const canUndo = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity);
|
|
158
|
+
return canUndo;
|
|
116
159
|
};
|
|
117
160
|
const useConnection = (selector = identity, options2) => {
|
|
118
161
|
var _a2;
|
|
119
162
|
const room = useRoom();
|
|
120
|
-
const subscribe =
|
|
163
|
+
const subscribe = useCallback3(
|
|
121
164
|
(onStoreChange) => {
|
|
122
165
|
return room.subscribe("connection", onStoreChange);
|
|
123
166
|
},
|
|
124
167
|
[room]
|
|
125
168
|
);
|
|
126
169
|
const getSnapshot = room.getConnection;
|
|
127
|
-
const _selector =
|
|
170
|
+
const _selector = useCallback3((snapshot) => selector(snapshot), [selector]);
|
|
128
171
|
return useSyncExternalStoreWithSelector(
|
|
129
172
|
subscribe,
|
|
130
173
|
getSnapshot,
|
|
@@ -139,7 +182,7 @@ var createRoomBundle = (client, options) => {
|
|
|
139
182
|
};
|
|
140
183
|
const useEvent = (type, callback) => {
|
|
141
184
|
const room = useRoom();
|
|
142
|
-
|
|
185
|
+
useEffect2(() => {
|
|
143
186
|
const unsubscribe = room.event(type, callback);
|
|
144
187
|
return () => {
|
|
145
188
|
unsubscribe();
|
|
@@ -160,14 +203,14 @@ var createRoomBundle = (client, options) => {
|
|
|
160
203
|
const useMyPresence = (selector = identity, options2) => {
|
|
161
204
|
var _a2;
|
|
162
205
|
const room = useRoom();
|
|
163
|
-
const subscribe =
|
|
206
|
+
const subscribe = useCallback3(
|
|
164
207
|
(onStoreChange) => {
|
|
165
208
|
return room.subscribe("my-presence", onStoreChange);
|
|
166
209
|
},
|
|
167
210
|
[room]
|
|
168
211
|
);
|
|
169
212
|
const getSnapshot = room.getMyPresence;
|
|
170
|
-
const _selector =
|
|
213
|
+
const _selector = useCallback3((snapshot) => selector(snapshot), [selector]);
|
|
171
214
|
const myPresence = useSyncExternalStoreWithSelector(
|
|
172
215
|
subscribe,
|
|
173
216
|
getSnapshot,
|
|
@@ -175,26 +218,19 @@ var createRoomBundle = (client, options) => {
|
|
|
175
218
|
_selector,
|
|
176
219
|
(_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : fastDeepEqual
|
|
177
220
|
);
|
|
178
|
-
|
|
179
|
-
(value) => {
|
|
180
|
-
const presence = typeof value === "function" ? value(room.getMyPresence()) : value;
|
|
181
|
-
room.updateMyPresence(presence);
|
|
182
|
-
},
|
|
183
|
-
[room]
|
|
184
|
-
);
|
|
185
|
-
return [myPresence, updateMyPresence];
|
|
221
|
+
return [myPresence, room.updateMyPresence];
|
|
186
222
|
};
|
|
187
223
|
const useMyself = (selector = identity, options2) => {
|
|
188
224
|
var _a2;
|
|
189
225
|
const room = useRoom();
|
|
190
|
-
const subscribe =
|
|
226
|
+
const subscribe = useCallback3(
|
|
191
227
|
(onStoreChange) => {
|
|
192
228
|
return room.subscribe("myself", onStoreChange);
|
|
193
229
|
},
|
|
194
230
|
[room]
|
|
195
231
|
);
|
|
196
232
|
const getSnapshot = room.getMyself;
|
|
197
|
-
const _selector =
|
|
233
|
+
const _selector = useCallback3(
|
|
198
234
|
(snapshot) => {
|
|
199
235
|
return !snapshot ? null : selector(snapshot);
|
|
200
236
|
},
|
|
@@ -211,14 +247,14 @@ var createRoomBundle = (client, options) => {
|
|
|
211
247
|
const useOther = (connectionId, selector = identity, options2) => {
|
|
212
248
|
var _a2;
|
|
213
249
|
const room = useRoom();
|
|
214
|
-
const subscribe =
|
|
250
|
+
const subscribe = useCallback3(
|
|
215
251
|
(onStoreChange) => {
|
|
216
252
|
return room.other(connectionId, onStoreChange);
|
|
217
253
|
},
|
|
218
254
|
[room, connectionId]
|
|
219
255
|
);
|
|
220
|
-
const getSnapshot =
|
|
221
|
-
const _selector =
|
|
256
|
+
const getSnapshot = useCallback3(() => room.getOther(connectionId), [room, connectionId]);
|
|
257
|
+
const _selector = useCallback3(
|
|
222
258
|
(snapshot) => {
|
|
223
259
|
return !snapshot ? null : selector(snapshot);
|
|
224
260
|
},
|
|
@@ -235,7 +271,7 @@ var createRoomBundle = (client, options) => {
|
|
|
235
271
|
const useOthers = (selector = identity, options2) => {
|
|
236
272
|
var _a2;
|
|
237
273
|
const room = useRoom();
|
|
238
|
-
const subscribe =
|
|
274
|
+
const subscribe = useCallback3(
|
|
239
275
|
(onStoreChange) => {
|
|
240
276
|
return room.subscribe("others", onStoreChange);
|
|
241
277
|
},
|
|
@@ -247,7 +283,12 @@ var createRoomBundle = (client, options) => {
|
|
|
247
283
|
getSnapshot,
|
|
248
284
|
getSnapshot,
|
|
249
285
|
selector,
|
|
250
|
-
(_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 :
|
|
286
|
+
(_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : (a, b) => {
|
|
287
|
+
if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
|
|
288
|
+
return shallowArrayEqual(a, b);
|
|
289
|
+
}
|
|
290
|
+
return fastDeepEqual(a, b);
|
|
291
|
+
}
|
|
251
292
|
);
|
|
252
293
|
};
|
|
253
294
|
const useRedo = () => {
|
|
@@ -261,12 +302,11 @@ var createRoomBundle = (client, options) => {
|
|
|
261
302
|
room.subscribe("storage-loaded", () => {
|
|
262
303
|
rerender();
|
|
263
304
|
});
|
|
264
|
-
const subscribe =
|
|
265
|
-
const getSnapshot =
|
|
266
|
-
|
|
267
|
-
return (_a3 = room.getStorage(key)) == null ? void 0 : _a3.toJson();
|
|
305
|
+
const subscribe = useCallback3((onStoreChange) => room.storage(key, onStoreChange), [key, room]);
|
|
306
|
+
const getSnapshot = useCallback3(() => {
|
|
307
|
+
return room.getStorageJson(key);
|
|
268
308
|
}, [key, room]);
|
|
269
|
-
const _selector =
|
|
309
|
+
const _selector = useCallback3(
|
|
270
310
|
(snapshot) => {
|
|
271
311
|
return snapshot === null ? null : selector(snapshot);
|
|
272
312
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "@pluv/client React.js bindings",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,24 +17,23 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@types/react": "^18.3.3",
|
|
21
|
-
"@types/use-sync-external-store": "^0.0.6",
|
|
22
20
|
"fast-deep-equal": "^3.1.3",
|
|
23
|
-
"
|
|
24
|
-
"@pluv/
|
|
25
|
-
"@pluv/
|
|
26
|
-
"@pluv/types": "^0.18.0"
|
|
21
|
+
"@pluv/client": "^0.20.0",
|
|
22
|
+
"@pluv/crdt": "^0.20.0",
|
|
23
|
+
"@pluv/types": "^0.20.0"
|
|
27
24
|
},
|
|
28
25
|
"peerDependencies": {
|
|
29
|
-
"react": "^
|
|
26
|
+
"@types/react": "^18.0.0",
|
|
27
|
+
"react": "^18.0.0"
|
|
30
28
|
},
|
|
31
29
|
"devDependencies": {
|
|
30
|
+
"@types/react": "^18.3.3",
|
|
32
31
|
"eslint": "^8.57.0",
|
|
33
32
|
"react": "^18.3.1",
|
|
34
|
-
"tsup": "^8.0
|
|
33
|
+
"tsup": "^8.1.0",
|
|
35
34
|
"typescript": "^5.4.5",
|
|
36
|
-
"@pluv/tsconfig": "^0.
|
|
37
|
-
"eslint-config-pluv": "^0.
|
|
35
|
+
"@pluv/tsconfig": "^0.20.0",
|
|
36
|
+
"eslint-config-pluv": "^0.20.0"
|
|
38
37
|
},
|
|
39
38
|
"scripts": {
|
|
40
39
|
"build": "tsup src/index.ts --format esm,cjs --dts --external react",
|