@pluv/react 0.17.3 → 0.19.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/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 import_react3 = require("react");
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 import_react2 = require("react");
47
+ var import_react4 = require("react");
48
48
 
49
- // src/internal/hooks/useRerender.ts
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, import_react.useState)(0);
53
- return (0, import_react.useCallback)(() => {
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 import_with_selector = require("use-sync-external-store/with-selector.js");
73
+ var import_react3 = require("react");
60
74
 
61
75
  // src/internal/utils/identity.ts
62
76
  var identity = (x) => x;
@@ -66,22 +80,40 @@ 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
+ return selector(data);
93
+ } : void 0;
94
+ const _getClientSnapshot = () => {
95
+ const data = getClientSnapshot();
96
+ const snapshot = selector(data);
97
+ const compare = isEqual != null ? isEqual : shallowEqual;
98
+ const cached = cacheRef.current;
99
+ const isUnchanged = cached === null ? snapshot === null : compare(cached, snapshot);
100
+ cacheRef.current = isUnchanged ? cached != null ? cached : snapshot : snapshot;
101
+ return cacheRef.current;
102
+ };
103
+ const result = (0, import_react3.useSyncExternalStore)(subscribe, _getClientSnapshot, _getServerSnapshot);
104
+ return typeof window !== "undefined" ? noSsr(result, _getServerSnapshot == null ? void 0 : _getServerSnapshot()) : result;
105
+ };
106
+
69
107
  // src/createRoomBundle.tsx
70
108
  var import_jsx_runtime = require("react/jsx-runtime");
71
109
  var createRoomBundle = (client, options) => {
72
110
  var _a;
73
111
  const _initialStorage = (_a = options.initialStorage) != null ? _a : import_crdt.noop.doc();
74
- const PluvRoomContext = (0, import_react2.createContext)(null);
75
- const MockedRoomContext = (0, import_react2.createContext)({ room: null });
76
- const MockedRoomProvider = (0, import_react2.memo)((props) => {
77
- const {
78
- children,
79
- events,
80
- initialPresence,
81
- initialStorage,
82
- room: _room
83
- } = props;
84
- const [room] = (0, import_react2.useState)(() => {
112
+ const PluvRoomContext = (0, import_react4.createContext)(null);
113
+ const MockedRoomContext = (0, import_react4.createContext)({ room: null });
114
+ const MockedRoomProvider = (0, import_react4.memo)((props) => {
115
+ const { children, events, initialPresence, initialStorage, room: _room } = props;
116
+ const [room] = (0, import_react4.useState)(() => {
85
117
  return new import_client.MockedRoom(_room, {
86
118
  events,
87
119
  initialPresence,
@@ -92,18 +124,11 @@ var createRoomBundle = (client, options) => {
92
124
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MockedRoomContext.Provider, { value: { room }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluvRoomContext.Provider, { value: room, children }) });
93
125
  });
94
126
  MockedRoomProvider.displayName = "MockedRoomProvider";
95
- const PluvRoomProvider = (0, import_react2.memo)((props) => {
96
- const {
97
- children,
98
- debug,
99
- initialPresence,
100
- initialStorage,
101
- onAuthorizationFail,
102
- room: _room
103
- } = props;
127
+ const PluvRoomProvider = (0, import_react4.memo)((props) => {
128
+ const { children, debug, initialPresence, initialStorage, onAuthorizationFail, room: _room } = props;
104
129
  const rerender = useRerender();
105
- const { room: mockedRoom } = (0, import_react2.useContext)(MockedRoomContext);
106
- const [room] = (0, import_react2.useState)(() => {
130
+ const { room: mockedRoom } = (0, import_react4.useContext)(MockedRoomContext);
131
+ const [room] = (0, import_react4.useState)(() => {
107
132
  return client.createRoom(_room, {
108
133
  addons: options.addons,
109
134
  debug,
@@ -113,7 +138,7 @@ var createRoomBundle = (client, options) => {
113
138
  onAuthorizationFail
114
139
  });
115
140
  });
116
- (0, import_react2.useEffect)(() => {
141
+ (0, import_react4.useEffect)(() => {
117
142
  const unsubscribe = room.subscribe("connection", () => {
118
143
  rerender();
119
144
  });
@@ -121,7 +146,7 @@ var createRoomBundle = (client, options) => {
121
146
  unsubscribe();
122
147
  };
123
148
  }, [rerender, room]);
124
- (0, import_react2.useEffect)(() => {
149
+ (0, import_react4.useEffect)(() => {
125
150
  client.enter(room);
126
151
  return () => {
127
152
  client.leave(room);
@@ -130,61 +155,51 @@ var createRoomBundle = (client, options) => {
130
155
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluvRoomContext.Provider, { value: mockedRoom != null ? mockedRoom : room, children });
131
156
  });
132
157
  PluvRoomProvider.displayName = "PluvRoomProvider";
133
- const useRoom = () => (0, import_react2.useContext)(PluvRoomContext);
158
+ const useRoom = () => (0, import_react4.useContext)(PluvRoomContext);
134
159
  const useBroadcast = () => {
135
160
  const room = useRoom();
136
- return (0, import_react2.useCallback)(
137
- (event, data) => {
138
- room.broadcast(event, data);
161
+ const broadcast = (0, import_react4.useCallback)(
162
+ (event2, data) => {
163
+ room.broadcast(event2, data);
139
164
  },
140
165
  [room]
141
166
  );
167
+ return (0, import_react4.useMemo)(() => {
168
+ return new Proxy(broadcast, {
169
+ get(fn, prop) {
170
+ return (data) => {
171
+ return fn(prop, data);
172
+ };
173
+ }
174
+ });
175
+ }, [broadcast]);
142
176
  };
143
177
  const useCanRedo = () => {
144
178
  const room = useRoom();
145
- const subscribe = (0, import_react2.useCallback)(
146
- (onStoreChange) => room.storageRoot(onStoreChange),
147
- [room]
148
- );
149
- const getSnapshot = (0, import_react2.useCallback)(() => room.canRedo(), [room]);
150
- const canRedo = (0, import_with_selector.useSyncExternalStoreWithSelector)(
151
- subscribe,
152
- getSnapshot,
153
- getSnapshot,
154
- identity
155
- );
179
+ const subscribe = (0, import_react4.useCallback)((onStoreChange) => room.storageRoot(onStoreChange), [room]);
180
+ const getSnapshot = (0, import_react4.useCallback)(() => room.canRedo(), [room]);
181
+ const canRedo = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity);
156
182
  return canRedo;
157
183
  };
158
184
  const useCanUndo = () => {
159
185
  const room = useRoom();
160
- const subscribe = (0, import_react2.useCallback)(
161
- (onStoreChange) => room.storageRoot(onStoreChange),
162
- [room]
163
- );
164
- const getSnapshot = (0, import_react2.useCallback)(() => room.canUndo(), [room]);
165
- const canRedo = (0, import_with_selector.useSyncExternalStoreWithSelector)(
166
- subscribe,
167
- getSnapshot,
168
- getSnapshot,
169
- identity
170
- );
171
- return canRedo;
186
+ const subscribe = (0, import_react4.useCallback)((onStoreChange) => room.storageRoot(onStoreChange), [room]);
187
+ const getSnapshot = (0, import_react4.useCallback)(() => room.canUndo(), [room]);
188
+ const canUndo = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, identity);
189
+ return canUndo;
172
190
  };
173
191
  const useConnection = (selector = identity, options2) => {
174
192
  var _a2;
175
193
  const room = useRoom();
176
- const subscribe = (0, import_react2.useCallback)(
194
+ const subscribe = (0, import_react4.useCallback)(
177
195
  (onStoreChange) => {
178
196
  return room.subscribe("connection", onStoreChange);
179
197
  },
180
198
  [room]
181
199
  );
182
200
  const getSnapshot = room.getConnection;
183
- const _selector = (0, import_react2.useCallback)(
184
- (snapshot) => selector(snapshot),
185
- [selector]
186
- );
187
- return (0, import_with_selector.useSyncExternalStoreWithSelector)(
201
+ const _selector = (0, import_react4.useCallback)((snapshot) => selector(snapshot), [selector]);
202
+ return useSyncExternalStoreWithSelector(
188
203
  subscribe,
189
204
  getSnapshot,
190
205
  getSnapshot,
@@ -198,60 +213,61 @@ var createRoomBundle = (client, options) => {
198
213
  };
199
214
  const useEvent = (type, callback) => {
200
215
  const room = useRoom();
201
- (0, import_react2.useEffect)(() => {
216
+ (0, import_react4.useEffect)(() => {
202
217
  const unsubscribe = room.event(type, callback);
203
218
  return () => {
204
219
  unsubscribe();
205
220
  };
206
221
  }, [callback, room, type]);
207
222
  };
223
+ const event = new Proxy(
224
+ {},
225
+ {
226
+ get(_, prop) {
227
+ const useProxyEvent = (callback) => {
228
+ return useEvent(prop, callback);
229
+ };
230
+ return { useEvent: useProxyEvent };
231
+ }
232
+ }
233
+ );
208
234
  const useMyPresence = (selector = identity, options2) => {
209
235
  var _a2;
210
236
  const room = useRoom();
211
- const subscribe = (0, import_react2.useCallback)(
237
+ const subscribe = (0, import_react4.useCallback)(
212
238
  (onStoreChange) => {
213
239
  return room.subscribe("my-presence", onStoreChange);
214
240
  },
215
241
  [room]
216
242
  );
217
243
  const getSnapshot = room.getMyPresence;
218
- const _selector = (0, import_react2.useCallback)(
219
- (snapshot) => selector(snapshot),
220
- [selector]
221
- );
222
- const myPresence = (0, import_with_selector.useSyncExternalStoreWithSelector)(
244
+ const _selector = (0, import_react4.useCallback)((snapshot) => selector(snapshot), [selector]);
245
+ const myPresence = useSyncExternalStoreWithSelector(
223
246
  subscribe,
224
247
  getSnapshot,
225
248
  getSnapshot,
226
249
  _selector,
227
250
  (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
228
251
  );
229
- const updateMyPresence = (0, import_react2.useCallback)(
230
- (value) => {
231
- const presence = typeof value === "function" ? value(room.getMyPresence()) : value;
232
- room.updateMyPresence(presence);
233
- },
234
- [room]
235
- );
236
- return [myPresence, updateMyPresence];
252
+ return [myPresence, room.updateMyPresence];
237
253
  };
238
254
  const useMyself = (selector = identity, options2) => {
239
255
  var _a2;
240
256
  const room = useRoom();
241
- const subscribe = (0, import_react2.useCallback)(
257
+ const subscribe = (0, import_react4.useCallback)(
242
258
  (onStoreChange) => {
243
259
  return room.subscribe("myself", onStoreChange);
244
260
  },
245
261
  [room]
246
262
  );
247
263
  const getSnapshot = room.getMyself;
248
- const _selector = (0, import_react2.useCallback)(
264
+ const _selector = (0, import_react4.useCallback)(
249
265
  (snapshot) => {
250
266
  return !snapshot ? null : selector(snapshot);
251
267
  },
252
268
  [selector]
253
269
  );
254
- return (0, import_with_selector.useSyncExternalStoreWithSelector)(
270
+ return useSyncExternalStoreWithSelector(
255
271
  subscribe,
256
272
  getSnapshot,
257
273
  getSnapshot,
@@ -262,23 +278,20 @@ var createRoomBundle = (client, options) => {
262
278
  const useOther = (connectionId, selector = identity, options2) => {
263
279
  var _a2;
264
280
  const room = useRoom();
265
- const subscribe = (0, import_react2.useCallback)(
281
+ const subscribe = (0, import_react4.useCallback)(
266
282
  (onStoreChange) => {
267
283
  return room.other(connectionId, onStoreChange);
268
284
  },
269
285
  [room, connectionId]
270
286
  );
271
- const getSnapshot = (0, import_react2.useCallback)(
272
- () => room.getOther(connectionId),
273
- [room, connectionId]
274
- );
275
- const _selector = (0, import_react2.useCallback)(
287
+ const getSnapshot = (0, import_react4.useCallback)(() => room.getOther(connectionId), [room, connectionId]);
288
+ const _selector = (0, import_react4.useCallback)(
276
289
  (snapshot) => {
277
290
  return !snapshot ? null : selector(snapshot);
278
291
  },
279
292
  [selector]
280
293
  );
281
- return (0, import_with_selector.useSyncExternalStoreWithSelector)(
294
+ return useSyncExternalStoreWithSelector(
282
295
  subscribe,
283
296
  getSnapshot,
284
297
  getSnapshot,
@@ -289,19 +302,24 @@ var createRoomBundle = (client, options) => {
289
302
  const useOthers = (selector = identity, options2) => {
290
303
  var _a2;
291
304
  const room = useRoom();
292
- const subscribe = (0, import_react2.useCallback)(
305
+ const subscribe = (0, import_react4.useCallback)(
293
306
  (onStoreChange) => {
294
307
  return room.subscribe("others", onStoreChange);
295
308
  },
296
309
  [room]
297
310
  );
298
311
  const getSnapshot = room.getOthers;
299
- return (0, import_with_selector.useSyncExternalStoreWithSelector)(
312
+ return useSyncExternalStoreWithSelector(
300
313
  subscribe,
301
314
  getSnapshot,
302
315
  getSnapshot,
303
316
  selector,
304
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : shallowArrayEqual
317
+ (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : (a, b) => {
318
+ if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
319
+ return shallowArrayEqual(a, b);
320
+ }
321
+ return (0, import_fast_deep_equal.default)(a, b);
322
+ }
305
323
  );
306
324
  };
307
325
  const useRedo = () => {
@@ -315,21 +333,18 @@ var createRoomBundle = (client, options) => {
315
333
  room.subscribe("storage-loaded", () => {
316
334
  rerender();
317
335
  });
318
- const subscribe = (0, import_react2.useCallback)(
319
- (onStoreChange) => room.storage(key, onStoreChange),
320
- [key, room]
321
- );
322
- const getSnapshot = (0, import_react2.useCallback)(() => {
336
+ const subscribe = (0, import_react4.useCallback)((onStoreChange) => room.storage(key, onStoreChange), [key, room]);
337
+ const getSnapshot = (0, import_react4.useCallback)(() => {
323
338
  var _a3;
324
339
  return (_a3 = room.getStorage(key)) == null ? void 0 : _a3.toJson();
325
340
  }, [key, room]);
326
- const _selector = (0, import_react2.useCallback)(
341
+ const _selector = (0, import_react4.useCallback)(
327
342
  (snapshot) => {
328
343
  return snapshot === null ? null : selector(snapshot);
329
344
  },
330
345
  [selector]
331
346
  );
332
- const data = (0, import_with_selector.useSyncExternalStoreWithSelector)(
347
+ const data = useSyncExternalStoreWithSelector(
333
348
  subscribe,
334
349
  getSnapshot,
335
350
  getSnapshot,
@@ -351,6 +366,8 @@ var createRoomBundle = (client, options) => {
351
366
  // components
352
367
  MockedRoomProvider,
353
368
  PluvRoomProvider,
369
+ // proxies
370
+ event,
354
371
  // hooks
355
372
  useBroadcast,
356
373
  useCanRedo,
@@ -373,13 +390,13 @@ var createRoomBundle = (client, options) => {
373
390
  // src/createBundle.tsx
374
391
  var import_jsx_runtime2 = require("react/jsx-runtime");
375
392
  var createBundle = (client) => {
376
- const PluvContext = (0, import_react3.createContext)(null);
377
- const PluvProvider = (0, import_react3.memo)((props) => {
393
+ const PluvContext = (0, import_react5.createContext)(null);
394
+ const PluvProvider = (0, import_react5.memo)((props) => {
378
395
  const { children } = props;
379
396
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PluvContext.Provider, { value: client, children });
380
397
  });
381
398
  PluvProvider.displayName = "PluvProvider";
382
- const useClient = () => (0, import_react3.useContext)(PluvContext);
399
+ const useClient = () => (0, import_react5.useContext)(PluvContext);
383
400
  const createRoomBundle2 = (options) => createRoomBundle(client, options);
384
401
  return {
385
402
  createRoomBundle: createRoomBundle2,