@noya-app/noya-multiplayer-react 0.1.18 → 0.1.19

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.mjs CHANGED
@@ -1,6 +1,198 @@
1
1
  // src/index.ts
2
2
  export * from "@noya-app/state-manager";
3
3
 
4
+ // src/avatarStyle.ts
5
+ function hashCode(string) {
6
+ let hash = 0;
7
+ for (const char of string) {
8
+ hash = char.charCodeAt(0) + ((hash << 5) - hash);
9
+ }
10
+ return hash;
11
+ }
12
+ function elementFromHash(array, hash) {
13
+ return array[Math.abs(hash) % array.length];
14
+ }
15
+ function getAvatarInitials(name) {
16
+ return name.split(" ").filter((c) => c.length > 0).map((c) => c[0]).join("").toLocaleUpperCase();
17
+ }
18
+ function getAvatarStyle(name) {
19
+ const hash = hashCode(name);
20
+ const color = elementFromHash(Object.values(colors500), hash);
21
+ return {
22
+ color: "white",
23
+ backgroundColor: color
24
+ // primaryColors: {
25
+ // "500": color,
26
+ // "800": darkerColor,
27
+ // },
28
+ };
29
+ }
30
+ var colors500 = {
31
+ red500: "#ef4444",
32
+ orange500: "#f97316",
33
+ amber500: "#f59e0b",
34
+ yellow500: "#eab308",
35
+ lime500: "#84cc16",
36
+ green500: "#22c55e",
37
+ emerald500: "#10b981",
38
+ teal500: "#14b8a6",
39
+ cyan500: "#06b6d4",
40
+ sky500: "#0ea5e9",
41
+ blue500: "#3b82f6",
42
+ indigo500: "#6366f1",
43
+ violet500: "#8b5cf6",
44
+ purple500: "#a855f7",
45
+ fuchsia500: "#d946ef",
46
+ pink500: "#ec4899",
47
+ rose500: "#f43f5e"
48
+ };
49
+
50
+ // src/components/UserPointersOverlay.tsx
51
+ import React, { memo, useEffect, useMemo as useMemo2, useState } from "react";
52
+
53
+ // src/useObservable.ts
54
+ import { useMemo, useSyncExternalStore } from "react";
55
+ function useObservable(observable, path) {
56
+ const { get, listen } = useMemo(() => {
57
+ const listen2 = path ? (callback) => observable.listen(path, callback) : observable.listen;
58
+ const get2 = path ? () => observable.get(path) : observable.get;
59
+ return { get: get2, listen: listen2 };
60
+ }, [observable, path]);
61
+ return useSyncExternalStore(listen, get, get);
62
+ }
63
+
64
+ // src/components/UserPointersOverlay.tsx
65
+ function shouldShow(hideAfter, updatedAt) {
66
+ return !!updatedAt && Date.now() - updatedAt < hideAfter;
67
+ }
68
+ var UserPointer_ = function UserPointer({
69
+ user,
70
+ ephemeralUserData,
71
+ hideAfter = 5e3
72
+ }) {
73
+ const metadata = useObservable(ephemeralUserData.metadata$, [
74
+ user.id
75
+ ]);
76
+ const data = useObservable(ephemeralUserData.data$, [user.id]);
77
+ const avatarStyle = useMemo2(() => getAvatarStyle(user.id), [user.id]);
78
+ const [, setForceUpdate] = useState(0);
79
+ const updatedAt = metadata?.updatedAt ?? 0;
80
+ useEffect(() => {
81
+ if (!shouldShow(hideAfter, updatedAt))
82
+ return;
83
+ const timeoutId = setTimeout(() => {
84
+ setForceUpdate((prev) => prev + 1);
85
+ }, hideAfter);
86
+ return () => clearTimeout(timeoutId);
87
+ }, [hideAfter, updatedAt]);
88
+ const show = shouldShow(hideAfter, updatedAt);
89
+ if (!data || !data.pointer)
90
+ return null;
91
+ return /* @__PURE__ */ React.createElement(UserPointerContainer, { key: user.id, point: data.pointer, show }, /* @__PURE__ */ React.createElement(UserPointerIcon, { color: avatarStyle.backgroundColor }), /* @__PURE__ */ React.createElement(UserNameTag, { background: avatarStyle.backgroundColor }, user.name));
92
+ };
93
+ var UserPointer2 = memo(UserPointer_);
94
+ var UserPointerContainer = memo(function UserPointerContainer2({
95
+ point,
96
+ children,
97
+ show = true
98
+ }) {
99
+ return /* @__PURE__ */ React.createElement(
100
+ "div",
101
+ {
102
+ style: {
103
+ position: "absolute",
104
+ top: 0,
105
+ left: 0,
106
+ transform: `translate(${Math.round(point.x)}px, ${Math.round(
107
+ point.y
108
+ )}px)`,
109
+ opacity: show ? 1 : 0,
110
+ transition: "transform 0.1s, opacity 0.2s"
111
+ }
112
+ },
113
+ children
114
+ );
115
+ });
116
+ var UserNameTag = memo(function UserNameTag2({
117
+ background,
118
+ children
119
+ }) {
120
+ return /* @__PURE__ */ React.createElement(
121
+ "span",
122
+ {
123
+ style: {
124
+ position: "relative",
125
+ top: "8px",
126
+ left: "15px",
127
+ fontSize: 11,
128
+ lineHeight: "1",
129
+ fontWeight: 500,
130
+ boxShadow: "0 1px 1px rgba(0,0,0,0.1)",
131
+ padding: "2px 4px 3px",
132
+ pointerEvents: "none",
133
+ letterSpacing: "-0.3px",
134
+ outline: `1px solid rgba(255,255,255,0.3)`,
135
+ outlineOffset: "-1px",
136
+ background,
137
+ color: "white"
138
+ }
139
+ },
140
+ children
141
+ );
142
+ });
143
+ var UserPointersOverlay = memo(function UserPointers({ connectedUsers, ephemeralUserData }) {
144
+ const currentUserId = useObservable(ephemeralUserData.currentUserId$);
145
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, connectedUsers.map((user) => {
146
+ if (user.id === currentUserId)
147
+ return null;
148
+ return /* @__PURE__ */ React.createElement(
149
+ UserPointer2,
150
+ {
151
+ key: user.id,
152
+ user,
153
+ ephemeralUserData
154
+ }
155
+ );
156
+ }));
157
+ });
158
+ var UserPointerIcon = memo(function CursorIcon({
159
+ color = "black"
160
+ }) {
161
+ return /* @__PURE__ */ React.createElement(
162
+ "svg",
163
+ {
164
+ width: "15",
165
+ height: "15",
166
+ viewBox: "0 0 15 15",
167
+ fill: "none",
168
+ xmlns: "http://www.w3.org/2000/svg",
169
+ style: {
170
+ position: "absolute",
171
+ filter: "drop-shadow(0 1px 1px rgba(0,0,0,0.1))"
172
+ // filter: "drop-shadow(0 1px 1px rgba(0,0,0,0.6))",
173
+ }
174
+ },
175
+ /* @__PURE__ */ React.createElement(
176
+ "path",
177
+ {
178
+ fillRule: "evenodd",
179
+ clipRule: "evenodd",
180
+ d: "M3.29227 0.0451998C3.47033 -0.0361222 3.67946 -0.00606629 3.8274 0.122107L12.8587 7.94648C13.0134 8.08054 13.0708 8.29538 13.0035 8.48873C12.9362 8.68208 12.7578 8.81488 12.5533 8.8239L9.21887 8.97096L11.1504 13.2149C11.2648 13.4662 11.1538 13.7626 10.9026 13.877L8.75024 14.8575C8.499 14.972 8.20255 14.8611 8.08802 14.6099L6.15339 10.3665L3.86279 12.7817C3.72196 12.9302 3.50487 12.9779 3.31479 12.9021C3.1247 12.8263 3 12.6423 3 12.4376V0.500008C3 0.304264 3.11422 0.126522 3.29227 0.0451998Z",
181
+ fill: color
182
+ }
183
+ ),
184
+ /* @__PURE__ */ React.createElement(
185
+ "path",
186
+ {
187
+ fillRule: "evenodd",
188
+ clipRule: "evenodd",
189
+ d: "M3.29227 0.048984C3.47033 -0.032338 3.67946 -0.00228211 3.8274 0.125891L12.8587 7.95026C13.0134 8.08432 13.0708 8.29916 13.0035 8.49251C12.9362 8.68586 12.7578 8.81866 12.5533 8.82768L9.21887 8.97474L11.1504 13.2187C11.2648 13.47 11.1538 13.7664 10.9026 13.8808L8.75024 14.8613C8.499 14.9758 8.20255 14.8649 8.08802 14.6137L6.15339 10.3703L3.86279 12.7855C3.72196 12.934 3.50487 12.9817 3.31479 12.9059C3.1247 12.8301 3 12.6461 3 12.4414V0.503792C3 0.308048 3.11422 0.130306 3.29227 0.048984ZM4 1.59852V11.1877L5.93799 9.14425C6.05238 9.02363 6.21924 8.96776 6.38319 8.99516C6.54715 9.02256 6.68677 9.12965 6.75573 9.2809L8.79056 13.7441L10.0332 13.178L8.00195 8.71497C7.93313 8.56376 7.94391 8.38824 8.03072 8.24659C8.11753 8.10494 8.26903 8.01566 8.435 8.00834L11.2549 7.88397L4 1.59852Z",
190
+ fill: "rgba(255,255,255,0.5)"
191
+ }
192
+ )
193
+ );
194
+ });
195
+
4
196
  // src/hooks.ts
5
197
  import {
6
198
  EphemeralUserData,
@@ -11,52 +203,24 @@ import {
11
203
  import {
12
204
  useCallback,
13
205
  useEffect as useEffect3,
14
- useMemo,
206
+ useMemo as useMemo3,
15
207
  useRef,
16
208
  useState as useState2,
17
- useSyncExternalStore
209
+ useSyncExternalStore as useSyncExternalStore2
18
210
  } from "react";
19
211
 
20
212
  // src/globals.ts
21
- import { Emitter } from "@noya-app/emitter";
22
- import { useEffect, useState } from "react";
23
- var Observable = class {
24
- value;
25
- emitter = new Emitter();
26
- constructor(value) {
27
- this.value = value;
28
- }
29
- get() {
30
- return this.value;
31
- }
32
- set(value) {
33
- if (this.value === value)
34
- return;
35
- this.value = value;
36
- this.emitter.emit(value);
37
- }
38
- listen(callback) {
39
- callback(this.value);
40
- return this.emitter.addListener(callback);
41
- }
42
- };
43
- function useObservable(observable) {
44
- const [value, setValue] = useState(observable.get());
45
- useEffect(() => {
46
- return observable.listen(setValue);
47
- }, [observable]);
48
- return value;
49
- }
213
+ import { Observable } from "@noya-app/observable";
50
214
  var shouldTrackEvents$ = new Observable(false);
51
215
  var shouldTrackTasks$ = new Observable(false);
52
216
 
53
217
  // src/inspector/useStateInspector.tsx
54
- import React3, { useLayoutEffect as useLayoutEffect2 } from "react";
218
+ import React4, { useLayoutEffect as useLayoutEffect2 } from "react";
55
219
  import { createRoot } from "react-dom/client";
56
220
 
57
221
  // src/inspector/StateInspector.tsx
58
- import React2, {
59
- memo,
222
+ import React3, {
223
+ memo as memo2,
60
224
  useEffect as useEffect2,
61
225
  useLayoutEffect
62
226
  } from "react";
@@ -70,10 +234,10 @@ import {
70
234
  } from "react-inspector";
71
235
 
72
236
  // src/inspector/useLocalStorageState.tsx
73
- import React from "react";
237
+ import React2 from "react";
74
238
  var localStorage = typeof window !== "undefined" ? window.localStorage : null;
75
239
  function useLocalStorageState(key, defaultValue) {
76
- const [state, setState] = React.useState(() => {
240
+ const [state, setState] = React2.useState(() => {
77
241
  const value = localStorage?.getItem(key);
78
242
  let result = defaultValue;
79
243
  if (value) {
@@ -118,7 +282,7 @@ function ToggleButton({
118
282
  theme,
119
283
  anchor
120
284
  }) {
121
- return /* @__PURE__ */ React2.createElement(
285
+ return /* @__PURE__ */ React3.createElement(
122
286
  "span",
123
287
  {
124
288
  role: "button",
@@ -139,7 +303,7 @@ function ToggleButton({
139
303
  setShowInspector(!showInspector);
140
304
  }
141
305
  },
142
- /* @__PURE__ */ React2.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ React2.createElement(
306
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ React3.createElement(
143
307
  "svg",
144
308
  {
145
309
  xmlns: "http://www.w3.org/2000/svg",
@@ -149,7 +313,7 @@ function ToggleButton({
149
313
  stroke: "currentColor",
150
314
  className: "size-6"
151
315
  },
152
- /* @__PURE__ */ React2.createElement(
316
+ /* @__PURE__ */ React3.createElement(
153
317
  "path",
154
318
  {
155
319
  strokeLinecap: "round",
@@ -157,7 +321,7 @@ function ToggleButton({
157
321
  d: "m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
158
322
  }
159
323
  )
160
- ) : /* @__PURE__ */ React2.createElement(
324
+ ) : /* @__PURE__ */ React3.createElement(
161
325
  "svg",
162
326
  {
163
327
  xmlns: "http://www.w3.org/2000/svg",
@@ -167,7 +331,7 @@ function ToggleButton({
167
331
  stroke: "currentColor",
168
332
  className: "size-6"
169
333
  },
170
- /* @__PURE__ */ React2.createElement(
334
+ /* @__PURE__ */ React3.createElement(
171
335
  "path",
172
336
  {
173
337
  strokeLinecap: "round",
@@ -190,7 +354,7 @@ function DisclosureSection({
190
354
  }) {
191
355
  const theme = colorScheme === "light" ? lightTheme : darkTheme;
192
356
  const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
193
- return /* @__PURE__ */ React2.createElement(
357
+ return /* @__PURE__ */ React3.createElement(
194
358
  "div",
195
359
  {
196
360
  style: {
@@ -200,7 +364,7 @@ function DisclosureSection({
200
364
  ...style
201
365
  }
202
366
  },
203
- /* @__PURE__ */ React2.createElement(
367
+ /* @__PURE__ */ React3.createElement(
204
368
  "div",
205
369
  {
206
370
  onClick: () => setOpen?.(!open),
@@ -214,7 +378,7 @@ function DisclosureSection({
214
378
  ...open && { borderBottom: `1px solid ${borderColor}` }
215
379
  }
216
380
  },
217
- setOpen && /* @__PURE__ */ React2.createElement(
381
+ setOpen && /* @__PURE__ */ React3.createElement(
218
382
  Arrow,
219
383
  {
220
384
  expanded: open,
@@ -225,7 +389,7 @@ function DisclosureSection({
225
389
  }
226
390
  }
227
391
  ),
228
- /* @__PURE__ */ React2.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
392
+ /* @__PURE__ */ React3.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
229
393
  right
230
394
  ),
231
395
  open && children
@@ -239,7 +403,7 @@ function InspectorRow({
239
403
  variant
240
404
  }) {
241
405
  const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
242
- return /* @__PURE__ */ React2.createElement(
406
+ return /* @__PURE__ */ React3.createElement(
243
407
  "div",
244
408
  {
245
409
  style: {
@@ -257,7 +421,7 @@ function InspectorRow({
257
421
  ...style
258
422
  }
259
423
  },
260
- /* @__PURE__ */ React2.createElement(
424
+ /* @__PURE__ */ React3.createElement(
261
425
  "span",
262
426
  {
263
427
  style: {
@@ -272,7 +436,7 @@ function InspectorRow({
272
436
  );
273
437
  }
274
438
  var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
275
- var StateInspector = memo(function StateInspector2({
439
+ var StateInspector = memo2(function StateInspector2({
276
440
  state,
277
441
  connectionEvents,
278
442
  connectedUsers,
@@ -286,12 +450,12 @@ var StateInspector = memo(function StateInspector2({
286
450
  forceInit,
287
451
  ...props
288
452
  }) {
289
- const [didMount, setDidMount] = React2.useState(false);
453
+ const [didMount, setDidMount] = React3.useState(false);
290
454
  useLayoutEffect(() => {
291
455
  setDidMount(true);
292
456
  }, []);
293
- const eventsContainerRef = React2.useRef(null);
294
- const historyContainerRef = React2.useRef(null);
457
+ const eventsContainerRef = React3.useRef(null);
458
+ const historyContainerRef = React3.useRef(null);
295
459
  const [showInspector, setShowInspector] = useLocalStorageState(
296
460
  "noya-multiplayer-react-show-inspector",
297
461
  true
@@ -375,7 +539,7 @@ var StateInspector = memo(function StateInspector2({
375
539
  if (!didMount)
376
540
  return null;
377
541
  if (!showInspector) {
378
- return /* @__PURE__ */ React2.createElement(
542
+ return /* @__PURE__ */ React3.createElement(
379
543
  "div",
380
544
  {
381
545
  ...props,
@@ -387,7 +551,7 @@ var StateInspector = memo(function StateInspector2({
387
551
  },
388
552
  onClick: () => setShowInspector(true)
389
553
  },
390
- /* @__PURE__ */ React2.createElement(
554
+ /* @__PURE__ */ React3.createElement(
391
555
  ToggleButton,
392
556
  {
393
557
  showInspector,
@@ -398,7 +562,7 @@ var StateInspector = memo(function StateInspector2({
398
562
  )
399
563
  );
400
564
  }
401
- return /* @__PURE__ */ React2.createElement(
565
+ return /* @__PURE__ */ React3.createElement(
402
566
  "div",
403
567
  {
404
568
  ...props,
@@ -407,7 +571,7 @@ var StateInspector = memo(function StateInspector2({
407
571
  ...props.style
408
572
  }
409
573
  },
410
- /* @__PURE__ */ React2.createElement(
574
+ /* @__PURE__ */ React3.createElement(
411
575
  DisclosureSection,
412
576
  {
413
577
  isFirst: true,
@@ -419,7 +583,7 @@ var StateInspector = memo(function StateInspector2({
419
583
  flex: "0 0 auto",
420
584
  maxHeight: "200px"
421
585
  },
422
- right: /* @__PURE__ */ React2.createElement(
586
+ right: /* @__PURE__ */ React3.createElement(
423
587
  ToggleButton,
424
588
  {
425
589
  showInspector,
@@ -429,7 +593,7 @@ var StateInspector = memo(function StateInspector2({
429
593
  }
430
594
  )
431
595
  },
432
- /* @__PURE__ */ React2.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React2.createElement(
596
+ /* @__PURE__ */ React3.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React3.createElement(
433
597
  InspectorRow,
434
598
  {
435
599
  key: user.id,
@@ -440,7 +604,7 @@ var StateInspector = memo(function StateInspector2({
440
604
  " (",
441
605
  ellipsis(user.id.toString(), 8, "middle"),
442
606
  ")"
443
- )), !connectedUsers && /* @__PURE__ */ React2.createElement(
607
+ )), !connectedUsers && /* @__PURE__ */ React3.createElement(
444
608
  "div",
445
609
  {
446
610
  style: {
@@ -451,17 +615,17 @@ var StateInspector = memo(function StateInspector2({
451
615
  gap: "4px"
452
616
  }
453
617
  },
454
- /* @__PURE__ */ React2.createElement("span", null, "No connected users")
618
+ /* @__PURE__ */ React3.createElement("span", null, "No connected users")
455
619
  ))
456
620
  ),
457
- /* @__PURE__ */ React2.createElement(
621
+ /* @__PURE__ */ React3.createElement(
458
622
  DisclosureSection,
459
623
  {
460
624
  title: "Data",
461
625
  colorScheme,
462
626
  setOpen: setShowData,
463
627
  open: showData,
464
- right: /* @__PURE__ */ React2.createElement(
628
+ right: /* @__PURE__ */ React3.createElement(
465
629
  "span",
466
630
  {
467
631
  style: {
@@ -469,7 +633,7 @@ var StateInspector = memo(function StateInspector2({
469
633
  gap: "4px"
470
634
  }
471
635
  },
472
- /* @__PURE__ */ React2.createElement(
636
+ /* @__PURE__ */ React3.createElement(
473
637
  SmallButton,
474
638
  {
475
639
  theme,
@@ -481,14 +645,14 @@ var StateInspector = memo(function StateInspector2({
481
645
  )
482
646
  )
483
647
  },
484
- /* @__PURE__ */ React2.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ React2.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React2.createElement(
648
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
485
649
  ObjectInspector,
486
650
  {
487
651
  name: multiplayerStateManager.schema ? "state" : void 0,
488
652
  data: state,
489
653
  theme
490
654
  }
491
- )), multiplayerStateManager.schema && /* @__PURE__ */ React2.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React2.createElement(
655
+ )), multiplayerStateManager.schema && /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
492
656
  ObjectInspector,
493
657
  {
494
658
  name: "schema",
@@ -497,14 +661,14 @@ var StateInspector = memo(function StateInspector2({
497
661
  }
498
662
  )))
499
663
  ),
500
- /* @__PURE__ */ React2.createElement(
664
+ /* @__PURE__ */ React3.createElement(
501
665
  DisclosureSection,
502
666
  {
503
667
  open: showHistory,
504
668
  setOpen: setShowHistory,
505
669
  title: "History",
506
670
  colorScheme,
507
- right: /* @__PURE__ */ React2.createElement(
671
+ right: /* @__PURE__ */ React3.createElement(
508
672
  "span",
509
673
  {
510
674
  style: {
@@ -512,7 +676,7 @@ var StateInspector = memo(function StateInspector2({
512
676
  gap: "4px"
513
677
  }
514
678
  },
515
- /* @__PURE__ */ React2.createElement(
679
+ /* @__PURE__ */ React3.createElement(
516
680
  SmallButton,
517
681
  {
518
682
  disabled: !historySnapshot.canUndo,
@@ -521,7 +685,7 @@ var StateInspector = memo(function StateInspector2({
521
685
  multiplayerStateManager.undo();
522
686
  }
523
687
  },
524
- /* @__PURE__ */ React2.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React2.createElement(
688
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
525
689
  "svg",
526
690
  {
527
691
  xmlns: "http://www.w3.org/2000/svg",
@@ -529,7 +693,7 @@ var StateInspector = memo(function StateInspector2({
529
693
  height: "1em",
530
694
  viewBox: "0 0 20 20"
531
695
  },
532
- /* @__PURE__ */ React2.createElement(
696
+ /* @__PURE__ */ React3.createElement(
533
697
  "path",
534
698
  {
535
699
  fill: "currentColor",
@@ -538,7 +702,7 @@ var StateInspector = memo(function StateInspector2({
538
702
  )
539
703
  ))
540
704
  ),
541
- /* @__PURE__ */ React2.createElement(
705
+ /* @__PURE__ */ React3.createElement(
542
706
  SmallButton,
543
707
  {
544
708
  disabled: !historySnapshot.canRedo,
@@ -547,7 +711,7 @@ var StateInspector = memo(function StateInspector2({
547
711
  multiplayerStateManager.redo();
548
712
  }
549
713
  },
550
- /* @__PURE__ */ React2.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React2.createElement(
714
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
551
715
  "svg",
552
716
  {
553
717
  xmlns: "http://www.w3.org/2000/svg",
@@ -555,7 +719,7 @@ var StateInspector = memo(function StateInspector2({
555
719
  height: "1em",
556
720
  viewBox: "0 0 20 20"
557
721
  },
558
- /* @__PURE__ */ React2.createElement(
722
+ /* @__PURE__ */ React3.createElement(
559
723
  "path",
560
724
  {
561
725
  fill: "currentColor",
@@ -566,7 +730,7 @@ var StateInspector = memo(function StateInspector2({
566
730
  )
567
731
  )
568
732
  },
569
- /* @__PURE__ */ React2.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ React2.createElement(
733
+ /* @__PURE__ */ React3.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(
570
734
  "div",
571
735
  {
572
736
  id: `${HISTORY_ELEMENT_PREFIX}0`,
@@ -580,7 +744,7 @@ var StateInspector = memo(function StateInspector2({
580
744
  background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
581
745
  }
582
746
  },
583
- /* @__PURE__ */ React2.createElement(
747
+ /* @__PURE__ */ React3.createElement(
584
748
  "span",
585
749
  {
586
750
  style: {
@@ -592,7 +756,7 @@ var StateInspector = memo(function StateInspector2({
592
756
  },
593
757
  "Initial state"
594
758
  )
595
- ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ React2.createElement(
759
+ ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ React3.createElement(
596
760
  "div",
597
761
  {
598
762
  id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
@@ -603,7 +767,7 @@ var StateInspector = memo(function StateInspector2({
603
767
  background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
604
768
  }
605
769
  },
606
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React2.createElement(
770
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React3.createElement(
607
771
  "pre",
608
772
  {
609
773
  key: j,
@@ -613,14 +777,14 @@ var StateInspector = memo(function StateInspector2({
613
777
  flexWrap: "wrap"
614
778
  }
615
779
  },
616
- patch.op === "add" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React2.createElement(ObjectInspector, { data: patch.value, theme })),
617
- patch.op === "replace" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React2.createElement(ObjectInspector, { data: patch.value, theme })),
618
- patch.op === "remove" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React2.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
619
- patch.op === "move" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React2.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
780
+ patch.op === "add" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React3.createElement(ObjectInspector, { data: patch.value, theme })),
781
+ patch.op === "replace" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React3.createElement(ObjectInspector, { data: patch.value, theme })),
782
+ patch.op === "remove" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
783
+ patch.op === "move" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
620
784
  ))
621
785
  )))
622
786
  ),
623
- /* @__PURE__ */ React2.createElement(
787
+ /* @__PURE__ */ React3.createElement(
624
788
  DisclosureSection,
625
789
  {
626
790
  title: "Tasks",
@@ -628,7 +792,7 @@ var StateInspector = memo(function StateInspector2({
628
792
  open: showTasks,
629
793
  setOpen: setShowTasks
630
794
  },
631
- /* @__PURE__ */ React2.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ React2.createElement(
795
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ React3.createElement(
632
796
  InspectorRow,
633
797
  {
634
798
  key: task.id,
@@ -637,7 +801,7 @@ var StateInspector = memo(function StateInspector2({
637
801
  backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
638
802
  }
639
803
  },
640
- /* @__PURE__ */ React2.createElement(
804
+ /* @__PURE__ */ React3.createElement(
641
805
  ObjectInspector,
642
806
  {
643
807
  name: task.name,
@@ -647,7 +811,7 @@ var StateInspector = memo(function StateInspector2({
647
811
  )
648
812
  )))
649
813
  ),
650
- /* @__PURE__ */ React2.createElement(
814
+ /* @__PURE__ */ React3.createElement(
651
815
  DisclosureSection,
652
816
  {
653
817
  open: showEphemeral,
@@ -655,9 +819,17 @@ var StateInspector = memo(function StateInspector2({
655
819
  title: "Ephemeral User Data",
656
820
  colorScheme
657
821
  },
658
- /* @__PURE__ */ React2.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React2.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ React2.createElement(ObjectInspector, { name: key, data: value, theme }))))
822
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React3.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ React3.createElement(
823
+ ObjectInspector,
824
+ {
825
+ name: key,
826
+ data: value,
827
+ theme,
828
+ expandLevel: 10
829
+ }
830
+ ))))
659
831
  ),
660
- /* @__PURE__ */ React2.createElement(
832
+ /* @__PURE__ */ React3.createElement(
661
833
  DisclosureSection,
662
834
  {
663
835
  open: showEvents,
@@ -665,8 +837,8 @@ var StateInspector = memo(function StateInspector2({
665
837
  title: "Events",
666
838
  colorScheme
667
839
  },
668
- /* @__PURE__ */ React2.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
669
- (event, index) => event.type === "stateChange" ? /* @__PURE__ */ React2.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ React2.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ React2.createElement(
840
+ /* @__PURE__ */ React3.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
841
+ (event, index) => event.type === "stateChange" ? /* @__PURE__ */ React3.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ React3.createElement(
670
842
  InspectorRow,
671
843
  {
672
844
  key: index,
@@ -676,7 +848,7 @@ var StateInspector = memo(function StateInspector2({
676
848
  padding: "0px 12px 1px"
677
849
  }
678
850
  },
679
- /* @__PURE__ */ React2.createElement(
851
+ /* @__PURE__ */ React3.createElement(
680
852
  ObjectInspector,
681
853
  {
682
854
  data: event.message,
@@ -689,7 +861,7 @@ var StateInspector = memo(function StateInspector2({
689
861
  expanded
690
862
  }) => {
691
863
  const direction = event.type === "send" ? "up" : "down";
692
- return depth === 0 ? /* @__PURE__ */ React2.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React2.createElement(
864
+ return depth === 0 ? /* @__PURE__ */ React3.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React3.createElement(
693
865
  ObjectLabel,
694
866
  {
695
867
  direction,
@@ -702,7 +874,7 @@ var StateInspector = memo(function StateInspector2({
702
874
  }
703
875
  )
704
876
  )
705
- ), !connectionEvents && /* @__PURE__ */ React2.createElement(
877
+ ), !connectionEvents && /* @__PURE__ */ React3.createElement(
706
878
  "div",
707
879
  {
708
880
  style: {
@@ -713,18 +885,18 @@ var StateInspector = memo(function StateInspector2({
713
885
  gap: "4px"
714
886
  }
715
887
  },
716
- /* @__PURE__ */ React2.createElement("span", null, "No recorded events")
888
+ /* @__PURE__ */ React3.createElement("span", null, "No recorded events")
717
889
  ))
718
890
  )
719
891
  );
720
892
  });
721
893
  var ObjectRootLabel = ({ name, data, direction }) => {
722
894
  if (typeof name === "string") {
723
- return /* @__PURE__ */ React2.createElement("span", null, /* @__PURE__ */ React2.createElement(ObjectName, { name }), /* @__PURE__ */ React2.createElement("span", null, ": "), /* @__PURE__ */ React2.createElement(ObjectPreview, { data }));
895
+ return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(ObjectName, { name }), /* @__PURE__ */ React3.createElement("span", null, ": "), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
724
896
  }
725
897
  if (direction === "up" || direction === "down") {
726
898
  const arrow = direction === "up" ? "\u2191" : "\u2193";
727
- return /* @__PURE__ */ React2.createElement("span", null, /* @__PURE__ */ React2.createElement(
899
+ return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(
728
900
  "span",
729
901
  {
730
902
  style: {
@@ -741,9 +913,9 @@ var ObjectRootLabel = ({ name, data, direction }) => {
741
913
  }
742
914
  },
743
915
  arrow
744
- ), /* @__PURE__ */ React2.createElement(ObjectPreview, { data }));
916
+ ), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
745
917
  } else {
746
- return /* @__PURE__ */ React2.createElement(ObjectPreview, { data });
918
+ return /* @__PURE__ */ React3.createElement(ObjectPreview, { data });
747
919
  }
748
920
  };
749
921
  function Arrow({
@@ -751,7 +923,7 @@ function Arrow({
751
923
  onClick,
752
924
  style
753
925
  }) {
754
- return /* @__PURE__ */ React2.createElement(
926
+ return /* @__PURE__ */ React3.createElement(
755
927
  "span",
756
928
  {
757
929
  role: "button",
@@ -794,7 +966,7 @@ function SmallButton({
794
966
  theme,
795
967
  disabled
796
968
  }) {
797
- return /* @__PURE__ */ React2.createElement(
969
+ return /* @__PURE__ */ React3.createElement(
798
970
  "button",
799
971
  {
800
972
  type: "button",
@@ -843,7 +1015,7 @@ function useStateInspector({
843
1015
  ephemeralUserData,
844
1016
  forceInit
845
1017
  }) {
846
- const [root, setRoot] = React3.useState(null);
1018
+ const [root, setRoot] = React4.useState(null);
847
1019
  useLayoutEffect2(() => {
848
1020
  if (disabled)
849
1021
  return;
@@ -859,7 +1031,7 @@ function useStateInspector({
859
1031
  if (!root)
860
1032
  return;
861
1033
  root.render(
862
- /* @__PURE__ */ React3.createElement(
1034
+ /* @__PURE__ */ React4.createElement(
863
1035
  StateInspector,
864
1036
  {
865
1037
  state,
@@ -896,7 +1068,7 @@ function useSyncStateManager(stateManager, path) {
896
1068
  () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
897
1069
  [stateManager, path]
898
1070
  );
899
- return useSyncExternalStore(
1071
+ return useSyncExternalStore2(
900
1072
  stateManager.addListener,
901
1073
  getSnapshot,
902
1074
  getSnapshot
@@ -943,21 +1115,21 @@ function useManagedState(createInitialState, options) {
943
1115
  return [state, setState, stateManager];
944
1116
  }
945
1117
  function useManagedHistory(stateManager) {
946
- return useSyncExternalStore(
1118
+ return useSyncExternalStore2(
947
1119
  stateManager.historyEmittor.addListener,
948
1120
  stateManager.getHistorySnapshot,
949
1121
  stateManager.getHistorySnapshot
950
1122
  );
951
1123
  }
952
1124
  function useSyncMultiplayerStateManager(multiplayerStateManager) {
953
- return useSyncExternalStore(
1125
+ return useSyncExternalStore2(
954
1126
  multiplayerStateManager.addListener,
955
1127
  multiplayerStateManager.getOptimisticState,
956
1128
  multiplayerStateManager.getOptimisticState
957
1129
  );
958
1130
  }
959
1131
  function useEphemeralUserData(ephemeralUserData) {
960
- return useSyncExternalStore(
1132
+ return useSyncExternalStore2(
961
1133
  ephemeralUserData.addListener,
962
1134
  ephemeralUserData.getSnapshot,
963
1135
  ephemeralUserData.getSnapshot
@@ -977,9 +1149,10 @@ function useMultiplayerState(initialState, options) {
977
1149
  );
978
1150
  const [tasks, setTasks] = useState2([]);
979
1151
  const [userId, setUserId] = useState2();
980
- const extras = useMemo(() => {
1152
+ const extras = useMemo3(() => {
981
1153
  return {
982
1154
  tasks,
1155
+ userId,
983
1156
  connectionEvents,
984
1157
  connectedUsers,
985
1158
  ephemeralUserData
@@ -990,7 +1163,7 @@ function useMultiplayerState(initialState, options) {
990
1163
  // }
991
1164
  // },
992
1165
  };
993
- }, [tasks, connectionEvents, connectedUsers, ephemeralUserData]);
1166
+ }, [tasks, connectionEvents, connectedUsers, ephemeralUserData, userId]);
994
1167
  const globalTrackEvents = useObservable(shouldTrackEvents$);
995
1168
  const globalTrackTasks = useObservable(shouldTrackTasks$);
996
1169
  const shouldTrackEvents = options?.trackConnectionEvents ?? globalTrackEvents;
@@ -1058,6 +1231,13 @@ function useMultiplayerState(initialState, options) {
1058
1231
  }
1059
1232
  export {
1060
1233
  StateInspector,
1234
+ UserNameTag,
1235
+ UserPointer2 as UserPointer,
1236
+ UserPointerContainer,
1237
+ UserPointerIcon,
1238
+ UserPointersOverlay,
1239
+ getAvatarInitials,
1240
+ getAvatarStyle,
1061
1241
  useEphemeralUserData,
1062
1242
  useManagedHistory,
1063
1243
  useManagedState,