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

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
@@ -32,6 +32,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  var src_exports = {};
33
33
  __export(src_exports, {
34
34
  StateInspector: () => StateInspector,
35
+ UserNameTag: () => UserNameTag,
36
+ UserPointer: () => UserPointer2,
37
+ UserPointerContainer: () => UserPointerContainer,
38
+ UserPointerIcon: () => UserPointerIcon,
39
+ UserPointersOverlay: () => UserPointersOverlay,
40
+ getAvatarInitials: () => getAvatarInitials,
41
+ getAvatarStyle: () => getAvatarStyle,
35
42
  useEphemeralUserData: () => useEphemeralUserData,
36
43
  useManagedHistory: () => useManagedHistory,
37
44
  useManagedState: () => useManagedState,
@@ -42,56 +49,220 @@ __export(src_exports, {
42
49
  module.exports = __toCommonJS(src_exports);
43
50
  __reExport(src_exports, require("@noya-app/state-manager"), module.exports);
44
51
 
45
- // src/hooks.ts
46
- var import_state_manager = require("@noya-app/state-manager");
47
- var import_react5 = require("react");
52
+ // src/avatarStyle.ts
53
+ function hashCode(string) {
54
+ let hash = 0;
55
+ for (const char of string) {
56
+ hash = char.charCodeAt(0) + ((hash << 5) - hash);
57
+ }
58
+ return hash;
59
+ }
60
+ function elementFromHash(array, hash) {
61
+ return array[Math.abs(hash) % array.length];
62
+ }
63
+ function getAvatarInitials(name) {
64
+ return name.split(" ").filter((c) => c.length > 0).map((c) => c[0]).join("").toLocaleUpperCase();
65
+ }
66
+ function getAvatarStyle(name) {
67
+ const hash = hashCode(name);
68
+ const color = elementFromHash(Object.values(colors500), hash);
69
+ return {
70
+ color: "white",
71
+ backgroundColor: color
72
+ // primaryColors: {
73
+ // "500": color,
74
+ // "800": darkerColor,
75
+ // },
76
+ };
77
+ }
78
+ var colors500 = {
79
+ red500: "#ef4444",
80
+ orange500: "#f97316",
81
+ amber500: "#f59e0b",
82
+ yellow500: "#eab308",
83
+ lime500: "#84cc16",
84
+ green500: "#22c55e",
85
+ emerald500: "#10b981",
86
+ teal500: "#14b8a6",
87
+ cyan500: "#06b6d4",
88
+ sky500: "#0ea5e9",
89
+ blue500: "#3b82f6",
90
+ indigo500: "#6366f1",
91
+ violet500: "#8b5cf6",
92
+ purple500: "#a855f7",
93
+ fuchsia500: "#d946ef",
94
+ pink500: "#ec4899",
95
+ rose500: "#f43f5e"
96
+ };
48
97
 
49
- // src/globals.ts
50
- var import_emitter = require("@noya-app/emitter");
98
+ // src/components/UserPointersOverlay.tsx
99
+ var import_react2 = __toESM(require("react"));
100
+
101
+ // src/useObservable.ts
51
102
  var import_react = require("react");
52
- var Observable = class {
53
- value;
54
- emitter = new import_emitter.Emitter();
55
- constructor(value) {
56
- this.value = value;
57
- }
58
- get() {
59
- return this.value;
60
- }
61
- set(value) {
62
- if (this.value === value)
103
+ function useObservable(observable, path) {
104
+ const { get, listen } = (0, import_react.useMemo)(() => {
105
+ const listen2 = path ? (callback) => observable.listen(path, callback) : observable.listen;
106
+ const get2 = path ? () => observable.get(path) : observable.get;
107
+ return { get: get2, listen: listen2 };
108
+ }, [observable, path]);
109
+ return (0, import_react.useSyncExternalStore)(listen, get, get);
110
+ }
111
+
112
+ // src/components/UserPointersOverlay.tsx
113
+ function shouldShow(hideAfter, updatedAt) {
114
+ return !!updatedAt && Date.now() - updatedAt < hideAfter;
115
+ }
116
+ var UserPointer_ = function UserPointer({
117
+ user,
118
+ ephemeralUserData,
119
+ hideAfter = 5e3
120
+ }) {
121
+ const metadata = useObservable(ephemeralUserData.metadata$, [
122
+ user.id
123
+ ]);
124
+ const data = useObservable(ephemeralUserData.data$, [user.id]);
125
+ const avatarStyle = (0, import_react2.useMemo)(() => getAvatarStyle(user.id), [user.id]);
126
+ const [, setForceUpdate] = (0, import_react2.useState)(0);
127
+ const updatedAt = metadata?.updatedAt ?? 0;
128
+ (0, import_react2.useEffect)(() => {
129
+ if (!shouldShow(hideAfter, updatedAt))
63
130
  return;
64
- this.value = value;
65
- this.emitter.emit(value);
66
- }
67
- listen(callback) {
68
- callback(this.value);
69
- return this.emitter.addListener(callback);
70
- }
131
+ const timeoutId = setTimeout(() => {
132
+ setForceUpdate((prev) => prev + 1);
133
+ }, hideAfter);
134
+ return () => clearTimeout(timeoutId);
135
+ }, [hideAfter, updatedAt]);
136
+ const show = shouldShow(hideAfter, updatedAt);
137
+ if (!data || !data.pointer)
138
+ return null;
139
+ return /* @__PURE__ */ import_react2.default.createElement(UserPointerContainer, { key: user.id, point: data.pointer, show }, /* @__PURE__ */ import_react2.default.createElement(UserPointerIcon, { color: avatarStyle.backgroundColor }), /* @__PURE__ */ import_react2.default.createElement(UserNameTag, { background: avatarStyle.backgroundColor }, user.name));
71
140
  };
72
- function useObservable(observable) {
73
- const [value, setValue] = (0, import_react.useState)(observable.get());
74
- (0, import_react.useEffect)(() => {
75
- return observable.listen(setValue);
76
- }, [observable]);
77
- return value;
78
- }
79
- var shouldTrackEvents$ = new Observable(false);
80
- var shouldTrackTasks$ = new Observable(false);
141
+ var UserPointer2 = (0, import_react2.memo)(UserPointer_);
142
+ var UserPointerContainer = (0, import_react2.memo)(function UserPointerContainer2({
143
+ point,
144
+ children,
145
+ show = true
146
+ }) {
147
+ return /* @__PURE__ */ import_react2.default.createElement(
148
+ "div",
149
+ {
150
+ style: {
151
+ position: "absolute",
152
+ top: 0,
153
+ left: 0,
154
+ transform: `translate(${Math.round(point.x)}px, ${Math.round(
155
+ point.y
156
+ )}px)`,
157
+ opacity: show ? 1 : 0,
158
+ transition: "transform 0.1s, opacity 0.2s"
159
+ }
160
+ },
161
+ children
162
+ );
163
+ });
164
+ var UserNameTag = (0, import_react2.memo)(function UserNameTag2({
165
+ background,
166
+ children
167
+ }) {
168
+ return /* @__PURE__ */ import_react2.default.createElement(
169
+ "span",
170
+ {
171
+ style: {
172
+ position: "relative",
173
+ top: "8px",
174
+ left: "15px",
175
+ fontSize: 11,
176
+ lineHeight: "1",
177
+ fontWeight: 500,
178
+ boxShadow: "0 1px 1px rgba(0,0,0,0.1)",
179
+ padding: "2px 4px 3px",
180
+ pointerEvents: "none",
181
+ letterSpacing: "-0.3px",
182
+ outline: `1px solid rgba(255,255,255,0.3)`,
183
+ outlineOffset: "-1px",
184
+ background,
185
+ color: "white"
186
+ }
187
+ },
188
+ children
189
+ );
190
+ });
191
+ var UserPointersOverlay = (0, import_react2.memo)(function UserPointers({ connectedUsers, ephemeralUserData }) {
192
+ const currentUserId = useObservable(ephemeralUserData.currentUserId$);
193
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, connectedUsers.map((user) => {
194
+ if (user.id === currentUserId)
195
+ return null;
196
+ return /* @__PURE__ */ import_react2.default.createElement(
197
+ UserPointer2,
198
+ {
199
+ key: user.id,
200
+ user,
201
+ ephemeralUserData
202
+ }
203
+ );
204
+ }));
205
+ });
206
+ var UserPointerIcon = (0, import_react2.memo)(function CursorIcon({
207
+ color = "black"
208
+ }) {
209
+ return /* @__PURE__ */ import_react2.default.createElement(
210
+ "svg",
211
+ {
212
+ width: "15",
213
+ height: "15",
214
+ viewBox: "0 0 15 15",
215
+ fill: "none",
216
+ xmlns: "http://www.w3.org/2000/svg",
217
+ style: {
218
+ position: "absolute",
219
+ filter: "drop-shadow(0 1px 1px rgba(0,0,0,0.1))"
220
+ // filter: "drop-shadow(0 1px 1px rgba(0,0,0,0.6))",
221
+ }
222
+ },
223
+ /* @__PURE__ */ import_react2.default.createElement(
224
+ "path",
225
+ {
226
+ fillRule: "evenodd",
227
+ clipRule: "evenodd",
228
+ 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",
229
+ fill: color
230
+ }
231
+ ),
232
+ /* @__PURE__ */ import_react2.default.createElement(
233
+ "path",
234
+ {
235
+ fillRule: "evenodd",
236
+ clipRule: "evenodd",
237
+ 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",
238
+ fill: "rgba(255,255,255,0.5)"
239
+ }
240
+ )
241
+ );
242
+ });
243
+
244
+ // src/hooks.ts
245
+ var import_state_manager = require("@noya-app/state-manager");
246
+ var import_react6 = require("react");
247
+
248
+ // src/globals.ts
249
+ var import_observable = require("@noya-app/observable");
250
+ var shouldTrackEvents$ = new import_observable.Observable(false);
251
+ var shouldTrackTasks$ = new import_observable.Observable(false);
81
252
 
82
253
  // src/inspector/useStateInspector.tsx
83
- var import_react4 = __toESM(require("react"));
254
+ var import_react5 = __toESM(require("react"));
84
255
  var import_client = require("react-dom/client");
85
256
 
86
257
  // src/inspector/StateInspector.tsx
87
- var import_react3 = __toESM(require("react"));
258
+ var import_react4 = __toESM(require("react"));
88
259
  var import_react_inspector = require("react-inspector");
89
260
 
90
261
  // src/inspector/useLocalStorageState.tsx
91
- var import_react2 = __toESM(require("react"));
262
+ var import_react3 = __toESM(require("react"));
92
263
  var localStorage = typeof window !== "undefined" ? window.localStorage : null;
93
264
  function useLocalStorageState(key, defaultValue) {
94
- const [state, setState] = import_react2.default.useState(() => {
265
+ const [state, setState] = import_react3.default.useState(() => {
95
266
  const value = localStorage?.getItem(key);
96
267
  let result = defaultValue;
97
268
  if (value) {
@@ -136,7 +307,7 @@ function ToggleButton({
136
307
  theme,
137
308
  anchor
138
309
  }) {
139
- return /* @__PURE__ */ import_react3.default.createElement(
310
+ return /* @__PURE__ */ import_react4.default.createElement(
140
311
  "span",
141
312
  {
142
313
  role: "button",
@@ -157,7 +328,7 @@ function ToggleButton({
157
328
  setShowInspector(!showInspector);
158
329
  }
159
330
  },
160
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ import_react3.default.createElement(
331
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ import_react4.default.createElement(
161
332
  "svg",
162
333
  {
163
334
  xmlns: "http://www.w3.org/2000/svg",
@@ -167,7 +338,7 @@ function ToggleButton({
167
338
  stroke: "currentColor",
168
339
  className: "size-6"
169
340
  },
170
- /* @__PURE__ */ import_react3.default.createElement(
341
+ /* @__PURE__ */ import_react4.default.createElement(
171
342
  "path",
172
343
  {
173
344
  strokeLinecap: "round",
@@ -175,7 +346,7 @@ function ToggleButton({
175
346
  d: "m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
176
347
  }
177
348
  )
178
- ) : /* @__PURE__ */ import_react3.default.createElement(
349
+ ) : /* @__PURE__ */ import_react4.default.createElement(
179
350
  "svg",
180
351
  {
181
352
  xmlns: "http://www.w3.org/2000/svg",
@@ -185,7 +356,7 @@ function ToggleButton({
185
356
  stroke: "currentColor",
186
357
  className: "size-6"
187
358
  },
188
- /* @__PURE__ */ import_react3.default.createElement(
359
+ /* @__PURE__ */ import_react4.default.createElement(
189
360
  "path",
190
361
  {
191
362
  strokeLinecap: "round",
@@ -208,7 +379,7 @@ function DisclosureSection({
208
379
  }) {
209
380
  const theme = colorScheme === "light" ? lightTheme : darkTheme;
210
381
  const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
211
- return /* @__PURE__ */ import_react3.default.createElement(
382
+ return /* @__PURE__ */ import_react4.default.createElement(
212
383
  "div",
213
384
  {
214
385
  style: {
@@ -218,7 +389,7 @@ function DisclosureSection({
218
389
  ...style
219
390
  }
220
391
  },
221
- /* @__PURE__ */ import_react3.default.createElement(
392
+ /* @__PURE__ */ import_react4.default.createElement(
222
393
  "div",
223
394
  {
224
395
  onClick: () => setOpen?.(!open),
@@ -232,7 +403,7 @@ function DisclosureSection({
232
403
  ...open && { borderBottom: `1px solid ${borderColor}` }
233
404
  }
234
405
  },
235
- setOpen && /* @__PURE__ */ import_react3.default.createElement(
406
+ setOpen && /* @__PURE__ */ import_react4.default.createElement(
236
407
  Arrow,
237
408
  {
238
409
  expanded: open,
@@ -243,7 +414,7 @@ function DisclosureSection({
243
414
  }
244
415
  }
245
416
  ),
246
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
417
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
247
418
  right
248
419
  ),
249
420
  open && children
@@ -257,7 +428,7 @@ function InspectorRow({
257
428
  variant
258
429
  }) {
259
430
  const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
260
- return /* @__PURE__ */ import_react3.default.createElement(
431
+ return /* @__PURE__ */ import_react4.default.createElement(
261
432
  "div",
262
433
  {
263
434
  style: {
@@ -275,7 +446,7 @@ function InspectorRow({
275
446
  ...style
276
447
  }
277
448
  },
278
- /* @__PURE__ */ import_react3.default.createElement(
449
+ /* @__PURE__ */ import_react4.default.createElement(
279
450
  "span",
280
451
  {
281
452
  style: {
@@ -290,7 +461,7 @@ function InspectorRow({
290
461
  );
291
462
  }
292
463
  var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
293
- var StateInspector = (0, import_react3.memo)(function StateInspector2({
464
+ var StateInspector = (0, import_react4.memo)(function StateInspector2({
294
465
  state,
295
466
  connectionEvents,
296
467
  connectedUsers,
@@ -304,12 +475,12 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
304
475
  forceInit,
305
476
  ...props
306
477
  }) {
307
- const [didMount, setDidMount] = import_react3.default.useState(false);
308
- (0, import_react3.useLayoutEffect)(() => {
478
+ const [didMount, setDidMount] = import_react4.default.useState(false);
479
+ (0, import_react4.useLayoutEffect)(() => {
309
480
  setDidMount(true);
310
481
  }, []);
311
- const eventsContainerRef = import_react3.default.useRef(null);
312
- const historyContainerRef = import_react3.default.useRef(null);
482
+ const eventsContainerRef = import_react4.default.useRef(null);
483
+ const historyContainerRef = import_react4.default.useRef(null);
313
484
  const [showInspector, setShowInspector] = useLocalStorageState(
314
485
  "noya-multiplayer-react-show-inspector",
315
486
  true
@@ -338,25 +509,25 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
338
509
  "noya-multiplayer-react-show-ephemeral",
339
510
  false
340
511
  );
341
- (0, import_react3.useEffect)(() => {
512
+ (0, import_react4.useEffect)(() => {
342
513
  shouldTrackEvents$.set(showEvents);
343
514
  }, [showEvents]);
344
- (0, import_react3.useEffect)(() => {
515
+ (0, import_react4.useEffect)(() => {
345
516
  shouldTrackTasks$.set(showTasks);
346
517
  }, [showTasks]);
347
- (0, import_react3.useEffect)(() => {
518
+ (0, import_react4.useEffect)(() => {
348
519
  if (eventsContainerRef.current) {
349
520
  eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
350
521
  }
351
522
  }, [connectionEvents]);
352
523
  const ephemeral = useEphemeralUserData(ephemeralUserData);
353
524
  const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
354
- (0, import_react3.useEffect)(() => {
525
+ (0, import_react4.useEffect)(() => {
355
526
  if (historyContainerRef.current) {
356
527
  historyContainerRef.current.scrollTop = historyContainerRef.current.scrollHeight;
357
528
  }
358
529
  }, [historySnapshot]);
359
- (0, import_react3.useEffect)(() => {
530
+ (0, import_react4.useEffect)(() => {
360
531
  if (!historyContainerRef.current)
361
532
  return;
362
533
  const historyEntry = historyContainerRef.current.querySelector(
@@ -393,7 +564,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
393
564
  if (!didMount)
394
565
  return null;
395
566
  if (!showInspector) {
396
- return /* @__PURE__ */ import_react3.default.createElement(
567
+ return /* @__PURE__ */ import_react4.default.createElement(
397
568
  "div",
398
569
  {
399
570
  ...props,
@@ -405,7 +576,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
405
576
  },
406
577
  onClick: () => setShowInspector(true)
407
578
  },
408
- /* @__PURE__ */ import_react3.default.createElement(
579
+ /* @__PURE__ */ import_react4.default.createElement(
409
580
  ToggleButton,
410
581
  {
411
582
  showInspector,
@@ -416,7 +587,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
416
587
  )
417
588
  );
418
589
  }
419
- return /* @__PURE__ */ import_react3.default.createElement(
590
+ return /* @__PURE__ */ import_react4.default.createElement(
420
591
  "div",
421
592
  {
422
593
  ...props,
@@ -425,7 +596,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
425
596
  ...props.style
426
597
  }
427
598
  },
428
- /* @__PURE__ */ import_react3.default.createElement(
599
+ /* @__PURE__ */ import_react4.default.createElement(
429
600
  DisclosureSection,
430
601
  {
431
602
  isFirst: true,
@@ -437,7 +608,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
437
608
  flex: "0 0 auto",
438
609
  maxHeight: "200px"
439
610
  },
440
- right: /* @__PURE__ */ import_react3.default.createElement(
611
+ right: /* @__PURE__ */ import_react4.default.createElement(
441
612
  ToggleButton,
442
613
  {
443
614
  showInspector,
@@ -447,18 +618,35 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
447
618
  }
448
619
  )
449
620
  },
450
- /* @__PURE__ */ import_react3.default.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ import_react3.default.createElement(
621
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ import_react4.default.createElement(
451
622
  InspectorRow,
452
623
  {
453
624
  key: user.id,
454
625
  colorScheme,
455
626
  variant: user.id === userId ? "up" : void 0
456
627
  },
628
+ user.image && /* @__PURE__ */ import_react4.default.createElement(
629
+ "img",
630
+ {
631
+ src: user.image,
632
+ alt: user.name,
633
+ style: {
634
+ width: "12px",
635
+ height: "12px",
636
+ borderRadius: "50%",
637
+ marginRight: "4px",
638
+ display: "inline-block",
639
+ position: "relative",
640
+ top: "-1px",
641
+ background: solidBorderColor
642
+ }
643
+ }
644
+ ),
457
645
  user.name,
458
646
  " (",
459
647
  ellipsis(user.id.toString(), 8, "middle"),
460
648
  ")"
461
- )), !connectedUsers && /* @__PURE__ */ import_react3.default.createElement(
649
+ )), !connectedUsers && /* @__PURE__ */ import_react4.default.createElement(
462
650
  "div",
463
651
  {
464
652
  style: {
@@ -469,17 +657,17 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
469
657
  gap: "4px"
470
658
  }
471
659
  },
472
- /* @__PURE__ */ import_react3.default.createElement("span", null, "No connected users")
660
+ /* @__PURE__ */ import_react4.default.createElement("span", null, "No connected users")
473
661
  ))
474
662
  ),
475
- /* @__PURE__ */ import_react3.default.createElement(
663
+ /* @__PURE__ */ import_react4.default.createElement(
476
664
  DisclosureSection,
477
665
  {
478
666
  title: "Data",
479
667
  colorScheme,
480
668
  setOpen: setShowData,
481
669
  open: showData,
482
- right: /* @__PURE__ */ import_react3.default.createElement(
670
+ right: /* @__PURE__ */ import_react4.default.createElement(
483
671
  "span",
484
672
  {
485
673
  style: {
@@ -487,7 +675,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
487
675
  gap: "4px"
488
676
  }
489
677
  },
490
- /* @__PURE__ */ import_react3.default.createElement(
678
+ /* @__PURE__ */ import_react4.default.createElement(
491
679
  SmallButton,
492
680
  {
493
681
  theme,
@@ -499,14 +687,14 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
499
687
  )
500
688
  )
501
689
  },
502
- /* @__PURE__ */ import_react3.default.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ import_react3.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react3.default.createElement(
690
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
503
691
  import_react_inspector.ObjectInspector,
504
692
  {
505
693
  name: multiplayerStateManager.schema ? "state" : void 0,
506
694
  data: state,
507
695
  theme
508
696
  }
509
- )), multiplayerStateManager.schema && /* @__PURE__ */ import_react3.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react3.default.createElement(
697
+ )), multiplayerStateManager.schema && /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
510
698
  import_react_inspector.ObjectInspector,
511
699
  {
512
700
  name: "schema",
@@ -515,14 +703,14 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
515
703
  }
516
704
  )))
517
705
  ),
518
- /* @__PURE__ */ import_react3.default.createElement(
706
+ /* @__PURE__ */ import_react4.default.createElement(
519
707
  DisclosureSection,
520
708
  {
521
709
  open: showHistory,
522
710
  setOpen: setShowHistory,
523
711
  title: "History",
524
712
  colorScheme,
525
- right: /* @__PURE__ */ import_react3.default.createElement(
713
+ right: /* @__PURE__ */ import_react4.default.createElement(
526
714
  "span",
527
715
  {
528
716
  style: {
@@ -530,7 +718,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
530
718
  gap: "4px"
531
719
  }
532
720
  },
533
- /* @__PURE__ */ import_react3.default.createElement(
721
+ /* @__PURE__ */ import_react4.default.createElement(
534
722
  SmallButton,
535
723
  {
536
724
  disabled: !historySnapshot.canUndo,
@@ -539,7 +727,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
539
727
  multiplayerStateManager.undo();
540
728
  }
541
729
  },
542
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react3.default.createElement(
730
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react4.default.createElement(
543
731
  "svg",
544
732
  {
545
733
  xmlns: "http://www.w3.org/2000/svg",
@@ -547,7 +735,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
547
735
  height: "1em",
548
736
  viewBox: "0 0 20 20"
549
737
  },
550
- /* @__PURE__ */ import_react3.default.createElement(
738
+ /* @__PURE__ */ import_react4.default.createElement(
551
739
  "path",
552
740
  {
553
741
  fill: "currentColor",
@@ -556,7 +744,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
556
744
  )
557
745
  ))
558
746
  ),
559
- /* @__PURE__ */ import_react3.default.createElement(
747
+ /* @__PURE__ */ import_react4.default.createElement(
560
748
  SmallButton,
561
749
  {
562
750
  disabled: !historySnapshot.canRedo,
@@ -565,7 +753,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
565
753
  multiplayerStateManager.redo();
566
754
  }
567
755
  },
568
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react3.default.createElement(
756
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react4.default.createElement(
569
757
  "svg",
570
758
  {
571
759
  xmlns: "http://www.w3.org/2000/svg",
@@ -573,7 +761,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
573
761
  height: "1em",
574
762
  viewBox: "0 0 20 20"
575
763
  },
576
- /* @__PURE__ */ import_react3.default.createElement(
764
+ /* @__PURE__ */ import_react4.default.createElement(
577
765
  "path",
578
766
  {
579
767
  fill: "currentColor",
@@ -584,7 +772,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
584
772
  )
585
773
  )
586
774
  },
587
- /* @__PURE__ */ import_react3.default.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ import_react3.default.createElement(
775
+ /* @__PURE__ */ import_react4.default.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ import_react4.default.createElement(
588
776
  "div",
589
777
  {
590
778
  id: `${HISTORY_ELEMENT_PREFIX}0`,
@@ -598,7 +786,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
598
786
  background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
599
787
  }
600
788
  },
601
- /* @__PURE__ */ import_react3.default.createElement(
789
+ /* @__PURE__ */ import_react4.default.createElement(
602
790
  "span",
603
791
  {
604
792
  style: {
@@ -610,7 +798,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
610
798
  },
611
799
  "Initial state"
612
800
  )
613
- ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react3.default.createElement(
801
+ ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react4.default.createElement(
614
802
  "div",
615
803
  {
616
804
  id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
@@ -621,7 +809,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
621
809
  background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
622
810
  }
623
811
  },
624
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react3.default.createElement(
812
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react4.default.createElement(
625
813
  "pre",
626
814
  {
627
815
  key: j,
@@ -631,14 +819,14 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
631
819
  flexWrap: "wrap"
632
820
  }
633
821
  },
634
- patch.op === "add" && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectInspector, { data: patch.value, theme })),
635
- patch.op === "replace" && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectInspector, { data: patch.value, theme })),
636
- patch.op === "remove" && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
637
- patch.op === "move" && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
822
+ patch.op === "add" && /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectInspector, { data: patch.value, theme })),
823
+ patch.op === "replace" && /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectInspector, { data: patch.value, theme })),
824
+ patch.op === "remove" && /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ import_react4.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
825
+ patch.op === "move" && /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ import_react4.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
638
826
  ))
639
827
  )))
640
828
  ),
641
- /* @__PURE__ */ import_react3.default.createElement(
829
+ /* @__PURE__ */ import_react4.default.createElement(
642
830
  DisclosureSection,
643
831
  {
644
832
  title: "Tasks",
@@ -646,7 +834,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
646
834
  open: showTasks,
647
835
  setOpen: setShowTasks
648
836
  },
649
- /* @__PURE__ */ import_react3.default.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ import_react3.default.createElement(
837
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ import_react4.default.createElement(
650
838
  InspectorRow,
651
839
  {
652
840
  key: task.id,
@@ -655,7 +843,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
655
843
  backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
656
844
  }
657
845
  },
658
- /* @__PURE__ */ import_react3.default.createElement(
846
+ /* @__PURE__ */ import_react4.default.createElement(
659
847
  import_react_inspector.ObjectInspector,
660
848
  {
661
849
  name: task.name,
@@ -665,7 +853,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
665
853
  )
666
854
  )))
667
855
  ),
668
- /* @__PURE__ */ import_react3.default.createElement(
856
+ /* @__PURE__ */ import_react4.default.createElement(
669
857
  DisclosureSection,
670
858
  {
671
859
  open: showEphemeral,
@@ -673,9 +861,17 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
673
861
  title: "Ephemeral User Data",
674
862
  colorScheme
675
863
  },
676
- /* @__PURE__ */ import_react3.default.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ import_react3.default.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectInspector, { name: key, data: value, theme }))))
864
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
865
+ import_react_inspector.ObjectInspector,
866
+ {
867
+ name: key,
868
+ data: value,
869
+ theme,
870
+ expandLevel: 10
871
+ }
872
+ ))))
677
873
  ),
678
- /* @__PURE__ */ import_react3.default.createElement(
874
+ /* @__PURE__ */ import_react4.default.createElement(
679
875
  DisclosureSection,
680
876
  {
681
877
  open: showEvents,
@@ -683,8 +879,8 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
683
879
  title: "Events",
684
880
  colorScheme
685
881
  },
686
- /* @__PURE__ */ import_react3.default.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
687
- (event, index) => event.type === "stateChange" ? /* @__PURE__ */ import_react3.default.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ import_react3.default.createElement(
882
+ /* @__PURE__ */ import_react4.default.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
883
+ (event, index) => event.type === "stateChange" ? /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ import_react4.default.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ import_react4.default.createElement(
688
884
  InspectorRow,
689
885
  {
690
886
  key: index,
@@ -694,7 +890,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
694
890
  padding: "0px 12px 1px"
695
891
  }
696
892
  },
697
- /* @__PURE__ */ import_react3.default.createElement(
893
+ /* @__PURE__ */ import_react4.default.createElement(
698
894
  import_react_inspector.ObjectInspector,
699
895
  {
700
896
  data: event.message,
@@ -707,7 +903,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
707
903
  expanded
708
904
  }) => {
709
905
  const direction = event.type === "send" ? "up" : "down";
710
- return depth === 0 ? /* @__PURE__ */ import_react3.default.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ import_react3.default.createElement(
906
+ return depth === 0 ? /* @__PURE__ */ import_react4.default.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ import_react4.default.createElement(
711
907
  import_react_inspector.ObjectLabel,
712
908
  {
713
909
  direction,
@@ -720,7 +916,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
720
916
  }
721
917
  )
722
918
  )
723
- ), !connectionEvents && /* @__PURE__ */ import_react3.default.createElement(
919
+ ), !connectionEvents && /* @__PURE__ */ import_react4.default.createElement(
724
920
  "div",
725
921
  {
726
922
  style: {
@@ -731,18 +927,18 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
731
927
  gap: "4px"
732
928
  }
733
929
  },
734
- /* @__PURE__ */ import_react3.default.createElement("span", null, "No recorded events")
930
+ /* @__PURE__ */ import_react4.default.createElement("span", null, "No recorded events")
735
931
  ))
736
932
  )
737
933
  );
738
934
  });
739
935
  var ObjectRootLabel = ({ name, data, direction }) => {
740
936
  if (typeof name === "string") {
741
- return /* @__PURE__ */ import_react3.default.createElement("span", null, /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectName, { name }), /* @__PURE__ */ import_react3.default.createElement("span", null, ": "), /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectPreview, { data }));
937
+ return /* @__PURE__ */ import_react4.default.createElement("span", null, /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectName, { name }), /* @__PURE__ */ import_react4.default.createElement("span", null, ": "), /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data }));
742
938
  }
743
939
  if (direction === "up" || direction === "down") {
744
940
  const arrow = direction === "up" ? "\u2191" : "\u2193";
745
- return /* @__PURE__ */ import_react3.default.createElement("span", null, /* @__PURE__ */ import_react3.default.createElement(
941
+ return /* @__PURE__ */ import_react4.default.createElement("span", null, /* @__PURE__ */ import_react4.default.createElement(
746
942
  "span",
747
943
  {
748
944
  style: {
@@ -759,9 +955,9 @@ var ObjectRootLabel = ({ name, data, direction }) => {
759
955
  }
760
956
  },
761
957
  arrow
762
- ), /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectPreview, { data }));
958
+ ), /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data }));
763
959
  } else {
764
- return /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectPreview, { data });
960
+ return /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data });
765
961
  }
766
962
  };
767
963
  function Arrow({
@@ -769,7 +965,7 @@ function Arrow({
769
965
  onClick,
770
966
  style
771
967
  }) {
772
- return /* @__PURE__ */ import_react3.default.createElement(
968
+ return /* @__PURE__ */ import_react4.default.createElement(
773
969
  "span",
774
970
  {
775
971
  role: "button",
@@ -812,7 +1008,7 @@ function SmallButton({
812
1008
  theme,
813
1009
  disabled
814
1010
  }) {
815
- return /* @__PURE__ */ import_react3.default.createElement(
1011
+ return /* @__PURE__ */ import_react4.default.createElement(
816
1012
  "button",
817
1013
  {
818
1014
  type: "button",
@@ -861,8 +1057,8 @@ function useStateInspector({
861
1057
  ephemeralUserData,
862
1058
  forceInit
863
1059
  }) {
864
- const [root, setRoot] = import_react4.default.useState(null);
865
- (0, import_react4.useLayoutEffect)(() => {
1060
+ const [root, setRoot] = import_react5.default.useState(null);
1061
+ (0, import_react5.useLayoutEffect)(() => {
866
1062
  if (disabled)
867
1063
  return;
868
1064
  const portalElement = createPortalElement();
@@ -873,11 +1069,11 @@ function useStateInspector({
873
1069
  document.body.removeChild(portalElement);
874
1070
  };
875
1071
  }, [disabled]);
876
- (0, import_react4.useLayoutEffect)(() => {
1072
+ (0, import_react5.useLayoutEffect)(() => {
877
1073
  if (!root)
878
1074
  return;
879
1075
  root.render(
880
- /* @__PURE__ */ import_react4.default.createElement(
1076
+ /* @__PURE__ */ import_react5.default.createElement(
881
1077
  StateInspector,
882
1078
  {
883
1079
  state,
@@ -910,22 +1106,22 @@ function useStateInspector({
910
1106
 
911
1107
  // src/hooks.ts
912
1108
  function useSyncStateManager(stateManager, path) {
913
- const getSnapshot = (0, import_react5.useCallback)(
1109
+ const getSnapshot = (0, import_react6.useCallback)(
914
1110
  () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
915
1111
  [stateManager, path]
916
1112
  );
917
- return (0, import_react5.useSyncExternalStore)(
1113
+ return (0, import_react6.useSyncExternalStore)(
918
1114
  stateManager.addListener,
919
1115
  getSnapshot,
920
1116
  getSnapshot
921
1117
  );
922
1118
  }
923
1119
  function useManagedState(createInitialState, options) {
924
- const [stateManager] = (0, import_react5.useState)(
1120
+ const [stateManager] = (0, import_react6.useState)(
925
1121
  () => new import_state_manager.StateManager(createInitialState(), options)
926
1122
  );
927
1123
  const state = useSyncStateManager(stateManager);
928
- const setState = (0, import_react5.useCallback)(
1124
+ const setState = (0, import_react6.useCallback)(
929
1125
  (...args) => {
930
1126
  const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
931
1127
  if (metadata === void 0) {
@@ -961,21 +1157,21 @@ function useManagedState(createInitialState, options) {
961
1157
  return [state, setState, stateManager];
962
1158
  }
963
1159
  function useManagedHistory(stateManager) {
964
- return (0, import_react5.useSyncExternalStore)(
1160
+ return (0, import_react6.useSyncExternalStore)(
965
1161
  stateManager.historyEmittor.addListener,
966
1162
  stateManager.getHistorySnapshot,
967
1163
  stateManager.getHistorySnapshot
968
1164
  );
969
1165
  }
970
1166
  function useSyncMultiplayerStateManager(multiplayerStateManager) {
971
- return (0, import_react5.useSyncExternalStore)(
1167
+ return (0, import_react6.useSyncExternalStore)(
972
1168
  multiplayerStateManager.addListener,
973
1169
  multiplayerStateManager.getOptimisticState,
974
1170
  multiplayerStateManager.getOptimisticState
975
1171
  );
976
1172
  }
977
1173
  function useEphemeralUserData(ephemeralUserData) {
978
- return (0, import_react5.useSyncExternalStore)(
1174
+ return (0, import_react6.useSyncExternalStore)(
979
1175
  ephemeralUserData.addListener,
980
1176
  ephemeralUserData.getSnapshot,
981
1177
  ephemeralUserData.getSnapshot
@@ -984,20 +1180,21 @@ function useEphemeralUserData(ephemeralUserData) {
984
1180
  var defaultStubSync = (0, import_state_manager.stubSync)();
985
1181
  function useMultiplayerState(initialState, options) {
986
1182
  const { sync = defaultStubSync, ...rest } = options ?? {};
987
- const [multiplayerStateManager] = (0, import_react5.useState)(
1183
+ const [multiplayerStateManager] = (0, import_react6.useState)(
988
1184
  () => new import_state_manager.MultiplayerStateManager(initialState, rest)
989
1185
  );
990
- const syncRef = (0, import_react5.useRef)(sync);
991
- const [connectionEvents, setConnectionEvents] = (0, import_react5.useState)();
992
- const [connectedUsers, setConnectedUsers] = (0, import_react5.useState)([]);
993
- const [ephemeralUserData] = (0, import_react5.useState)(
1186
+ const syncRef = (0, import_react6.useRef)(sync);
1187
+ const [connectionEvents, setConnectionEvents] = (0, import_react6.useState)();
1188
+ const [connectedUsers, setConnectedUsers] = (0, import_react6.useState)([]);
1189
+ const [ephemeralUserData] = (0, import_react6.useState)(
994
1190
  () => new import_state_manager.EphemeralUserData()
995
1191
  );
996
- const [tasks, setTasks] = (0, import_react5.useState)([]);
997
- const [userId, setUserId] = (0, import_react5.useState)();
998
- const extras = (0, import_react5.useMemo)(() => {
1192
+ const [tasks, setTasks] = (0, import_react6.useState)([]);
1193
+ const [userId, setUserId] = (0, import_react6.useState)();
1194
+ const extras = (0, import_react6.useMemo)(() => {
999
1195
  return {
1000
1196
  tasks,
1197
+ userId,
1001
1198
  connectionEvents,
1002
1199
  connectedUsers,
1003
1200
  ephemeralUserData
@@ -1008,27 +1205,27 @@ function useMultiplayerState(initialState, options) {
1008
1205
  // }
1009
1206
  // },
1010
1207
  };
1011
- }, [tasks, connectionEvents, connectedUsers, ephemeralUserData]);
1208
+ }, [tasks, connectionEvents, connectedUsers, ephemeralUserData, userId]);
1012
1209
  const globalTrackEvents = useObservable(shouldTrackEvents$);
1013
1210
  const globalTrackTasks = useObservable(shouldTrackTasks$);
1014
1211
  const shouldTrackEvents = options?.trackConnectionEvents ?? globalTrackEvents;
1015
1212
  const shouldTrackTasks = options?.trackTasks ?? globalTrackTasks;
1016
- const trackEventsCallbackRef = (0, import_react5.useRef)();
1017
- const trackConnectedUsersCallbackRef = (0, import_react5.useRef)();
1018
- const trackTasksCallbackRef = (0, import_react5.useRef)();
1019
- (0, import_react5.useEffect)(() => {
1213
+ const trackEventsCallbackRef = (0, import_react6.useRef)();
1214
+ const trackConnectedUsersCallbackRef = (0, import_react6.useRef)();
1215
+ const trackTasksCallbackRef = (0, import_react6.useRef)();
1216
+ (0, import_react6.useEffect)(() => {
1020
1217
  trackEventsCallbackRef.current = shouldTrackEvents ? (e) => setConnectionEvents((events) => {
1021
1218
  const updated = events ? [...events, e] : [e];
1022
1219
  return updated.length > 50 ? updated.slice(-50) : updated;
1023
1220
  }) : void 0;
1024
1221
  }, [shouldTrackEvents]);
1025
- (0, import_react5.useEffect)(() => {
1222
+ (0, import_react6.useEffect)(() => {
1026
1223
  trackConnectedUsersCallbackRef.current = (users, userId2) => {
1027
1224
  setConnectedUsers(users);
1028
1225
  setUserId(userId2);
1029
1226
  };
1030
1227
  }, []);
1031
- (0, import_react5.useEffect)(() => {
1228
+ (0, import_react6.useEffect)(() => {
1032
1229
  trackTasksCallbackRef.current = shouldTrackTasks ? (tasks2) => {
1033
1230
  setTasks((old) => {
1034
1231
  const newIds = new Set(tasks2.map((t) => t.id));
@@ -1037,7 +1234,7 @@ function useMultiplayerState(initialState, options) {
1037
1234
  });
1038
1235
  } : void 0;
1039
1236
  }, [shouldTrackTasks]);
1040
- (0, import_react5.useEffect)(() => {
1237
+ (0, import_react6.useEffect)(() => {
1041
1238
  if (syncRef.current) {
1042
1239
  return syncRef.current({
1043
1240
  ms: multiplayerStateManager,
@@ -1049,7 +1246,7 @@ function useMultiplayerState(initialState, options) {
1049
1246
  }
1050
1247
  }, [ephemeralUserData, multiplayerStateManager]);
1051
1248
  const state = useSyncMultiplayerStateManager(multiplayerStateManager);
1052
- const forceInit = (0, import_react5.useCallback)(() => {
1249
+ const forceInit = (0, import_react6.useCallback)(() => {
1053
1250
  const state2 = typeof initialState === "function" ? initialState() : initialState;
1054
1251
  const schema = options?.schema;
1055
1252
  multiplayerStateManager.sm.clearHistory();
@@ -1077,6 +1274,13 @@ function useMultiplayerState(initialState, options) {
1077
1274
  // Annotate the CommonJS export names for ESM import in node:
1078
1275
  0 && (module.exports = {
1079
1276
  StateInspector,
1277
+ UserNameTag,
1278
+ UserPointer,
1279
+ UserPointerContainer,
1280
+ UserPointerIcon,
1281
+ UserPointersOverlay,
1282
+ getAvatarInitials,
1283
+ getAvatarStyle,
1080
1284
  useEphemeralUserData,
1081
1285
  useManagedHistory,
1082
1286
  useManagedState,