@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.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,7 +618,7 @@ 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,
@@ -458,7 +629,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
458
629
  " (",
459
630
  ellipsis(user.id.toString(), 8, "middle"),
460
631
  ")"
461
- )), !connectedUsers && /* @__PURE__ */ import_react3.default.createElement(
632
+ )), !connectedUsers && /* @__PURE__ */ import_react4.default.createElement(
462
633
  "div",
463
634
  {
464
635
  style: {
@@ -469,17 +640,17 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
469
640
  gap: "4px"
470
641
  }
471
642
  },
472
- /* @__PURE__ */ import_react3.default.createElement("span", null, "No connected users")
643
+ /* @__PURE__ */ import_react4.default.createElement("span", null, "No connected users")
473
644
  ))
474
645
  ),
475
- /* @__PURE__ */ import_react3.default.createElement(
646
+ /* @__PURE__ */ import_react4.default.createElement(
476
647
  DisclosureSection,
477
648
  {
478
649
  title: "Data",
479
650
  colorScheme,
480
651
  setOpen: setShowData,
481
652
  open: showData,
482
- right: /* @__PURE__ */ import_react3.default.createElement(
653
+ right: /* @__PURE__ */ import_react4.default.createElement(
483
654
  "span",
484
655
  {
485
656
  style: {
@@ -487,7 +658,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
487
658
  gap: "4px"
488
659
  }
489
660
  },
490
- /* @__PURE__ */ import_react3.default.createElement(
661
+ /* @__PURE__ */ import_react4.default.createElement(
491
662
  SmallButton,
492
663
  {
493
664
  theme,
@@ -499,14 +670,14 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
499
670
  )
500
671
  )
501
672
  },
502
- /* @__PURE__ */ import_react3.default.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ import_react3.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react3.default.createElement(
673
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
503
674
  import_react_inspector.ObjectInspector,
504
675
  {
505
676
  name: multiplayerStateManager.schema ? "state" : void 0,
506
677
  data: state,
507
678
  theme
508
679
  }
509
- )), multiplayerStateManager.schema && /* @__PURE__ */ import_react3.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react3.default.createElement(
680
+ )), multiplayerStateManager.schema && /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
510
681
  import_react_inspector.ObjectInspector,
511
682
  {
512
683
  name: "schema",
@@ -515,14 +686,14 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
515
686
  }
516
687
  )))
517
688
  ),
518
- /* @__PURE__ */ import_react3.default.createElement(
689
+ /* @__PURE__ */ import_react4.default.createElement(
519
690
  DisclosureSection,
520
691
  {
521
692
  open: showHistory,
522
693
  setOpen: setShowHistory,
523
694
  title: "History",
524
695
  colorScheme,
525
- right: /* @__PURE__ */ import_react3.default.createElement(
696
+ right: /* @__PURE__ */ import_react4.default.createElement(
526
697
  "span",
527
698
  {
528
699
  style: {
@@ -530,7 +701,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
530
701
  gap: "4px"
531
702
  }
532
703
  },
533
- /* @__PURE__ */ import_react3.default.createElement(
704
+ /* @__PURE__ */ import_react4.default.createElement(
534
705
  SmallButton,
535
706
  {
536
707
  disabled: !historySnapshot.canUndo,
@@ -539,7 +710,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
539
710
  multiplayerStateManager.undo();
540
711
  }
541
712
  },
542
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react3.default.createElement(
713
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react4.default.createElement(
543
714
  "svg",
544
715
  {
545
716
  xmlns: "http://www.w3.org/2000/svg",
@@ -547,7 +718,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
547
718
  height: "1em",
548
719
  viewBox: "0 0 20 20"
549
720
  },
550
- /* @__PURE__ */ import_react3.default.createElement(
721
+ /* @__PURE__ */ import_react4.default.createElement(
551
722
  "path",
552
723
  {
553
724
  fill: "currentColor",
@@ -556,7 +727,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
556
727
  )
557
728
  ))
558
729
  ),
559
- /* @__PURE__ */ import_react3.default.createElement(
730
+ /* @__PURE__ */ import_react4.default.createElement(
560
731
  SmallButton,
561
732
  {
562
733
  disabled: !historySnapshot.canRedo,
@@ -565,7 +736,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
565
736
  multiplayerStateManager.redo();
566
737
  }
567
738
  },
568
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react3.default.createElement(
739
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react4.default.createElement(
569
740
  "svg",
570
741
  {
571
742
  xmlns: "http://www.w3.org/2000/svg",
@@ -573,7 +744,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
573
744
  height: "1em",
574
745
  viewBox: "0 0 20 20"
575
746
  },
576
- /* @__PURE__ */ import_react3.default.createElement(
747
+ /* @__PURE__ */ import_react4.default.createElement(
577
748
  "path",
578
749
  {
579
750
  fill: "currentColor",
@@ -584,7 +755,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
584
755
  )
585
756
  )
586
757
  },
587
- /* @__PURE__ */ import_react3.default.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ import_react3.default.createElement(
758
+ /* @__PURE__ */ import_react4.default.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ import_react4.default.createElement(
588
759
  "div",
589
760
  {
590
761
  id: `${HISTORY_ELEMENT_PREFIX}0`,
@@ -598,7 +769,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
598
769
  background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
599
770
  }
600
771
  },
601
- /* @__PURE__ */ import_react3.default.createElement(
772
+ /* @__PURE__ */ import_react4.default.createElement(
602
773
  "span",
603
774
  {
604
775
  style: {
@@ -610,7 +781,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
610
781
  },
611
782
  "Initial state"
612
783
  )
613
- ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react3.default.createElement(
784
+ ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react4.default.createElement(
614
785
  "div",
615
786
  {
616
787
  id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
@@ -621,7 +792,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
621
792
  background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
622
793
  }
623
794
  },
624
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react3.default.createElement(
795
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react4.default.createElement(
625
796
  "pre",
626
797
  {
627
798
  key: j,
@@ -631,14 +802,14 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
631
802
  flexWrap: "wrap"
632
803
  }
633
804
  },
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)))
805
+ 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 })),
806
+ 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 })),
807
+ 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))),
808
+ 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
809
  ))
639
810
  )))
640
811
  ),
641
- /* @__PURE__ */ import_react3.default.createElement(
812
+ /* @__PURE__ */ import_react4.default.createElement(
642
813
  DisclosureSection,
643
814
  {
644
815
  title: "Tasks",
@@ -646,7 +817,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
646
817
  open: showTasks,
647
818
  setOpen: setShowTasks
648
819
  },
649
- /* @__PURE__ */ import_react3.default.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ import_react3.default.createElement(
820
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ import_react4.default.createElement(
650
821
  InspectorRow,
651
822
  {
652
823
  key: task.id,
@@ -655,7 +826,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
655
826
  backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
656
827
  }
657
828
  },
658
- /* @__PURE__ */ import_react3.default.createElement(
829
+ /* @__PURE__ */ import_react4.default.createElement(
659
830
  import_react_inspector.ObjectInspector,
660
831
  {
661
832
  name: task.name,
@@ -665,7 +836,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
665
836
  )
666
837
  )))
667
838
  ),
668
- /* @__PURE__ */ import_react3.default.createElement(
839
+ /* @__PURE__ */ import_react4.default.createElement(
669
840
  DisclosureSection,
670
841
  {
671
842
  open: showEphemeral,
@@ -673,9 +844,17 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
673
844
  title: "Ephemeral User Data",
674
845
  colorScheme
675
846
  },
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 }))))
847
+ /* @__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(
848
+ import_react_inspector.ObjectInspector,
849
+ {
850
+ name: key,
851
+ data: value,
852
+ theme,
853
+ expandLevel: 10
854
+ }
855
+ ))))
677
856
  ),
678
- /* @__PURE__ */ import_react3.default.createElement(
857
+ /* @__PURE__ */ import_react4.default.createElement(
679
858
  DisclosureSection,
680
859
  {
681
860
  open: showEvents,
@@ -683,8 +862,8 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
683
862
  title: "Events",
684
863
  colorScheme
685
864
  },
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(
865
+ /* @__PURE__ */ import_react4.default.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
866
+ (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
867
  InspectorRow,
689
868
  {
690
869
  key: index,
@@ -694,7 +873,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
694
873
  padding: "0px 12px 1px"
695
874
  }
696
875
  },
697
- /* @__PURE__ */ import_react3.default.createElement(
876
+ /* @__PURE__ */ import_react4.default.createElement(
698
877
  import_react_inspector.ObjectInspector,
699
878
  {
700
879
  data: event.message,
@@ -707,7 +886,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
707
886
  expanded
708
887
  }) => {
709
888
  const direction = event.type === "send" ? "up" : "down";
710
- return depth === 0 ? /* @__PURE__ */ import_react3.default.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ import_react3.default.createElement(
889
+ return depth === 0 ? /* @__PURE__ */ import_react4.default.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ import_react4.default.createElement(
711
890
  import_react_inspector.ObjectLabel,
712
891
  {
713
892
  direction,
@@ -720,7 +899,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
720
899
  }
721
900
  )
722
901
  )
723
- ), !connectionEvents && /* @__PURE__ */ import_react3.default.createElement(
902
+ ), !connectionEvents && /* @__PURE__ */ import_react4.default.createElement(
724
903
  "div",
725
904
  {
726
905
  style: {
@@ -731,18 +910,18 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
731
910
  gap: "4px"
732
911
  }
733
912
  },
734
- /* @__PURE__ */ import_react3.default.createElement("span", null, "No recorded events")
913
+ /* @__PURE__ */ import_react4.default.createElement("span", null, "No recorded events")
735
914
  ))
736
915
  )
737
916
  );
738
917
  });
739
918
  var ObjectRootLabel = ({ name, data, direction }) => {
740
919
  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 }));
920
+ 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
921
  }
743
922
  if (direction === "up" || direction === "down") {
744
923
  const arrow = direction === "up" ? "\u2191" : "\u2193";
745
- return /* @__PURE__ */ import_react3.default.createElement("span", null, /* @__PURE__ */ import_react3.default.createElement(
924
+ return /* @__PURE__ */ import_react4.default.createElement("span", null, /* @__PURE__ */ import_react4.default.createElement(
746
925
  "span",
747
926
  {
748
927
  style: {
@@ -759,9 +938,9 @@ var ObjectRootLabel = ({ name, data, direction }) => {
759
938
  }
760
939
  },
761
940
  arrow
762
- ), /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectPreview, { data }));
941
+ ), /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data }));
763
942
  } else {
764
- return /* @__PURE__ */ import_react3.default.createElement(import_react_inspector.ObjectPreview, { data });
943
+ return /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data });
765
944
  }
766
945
  };
767
946
  function Arrow({
@@ -769,7 +948,7 @@ function Arrow({
769
948
  onClick,
770
949
  style
771
950
  }) {
772
- return /* @__PURE__ */ import_react3.default.createElement(
951
+ return /* @__PURE__ */ import_react4.default.createElement(
773
952
  "span",
774
953
  {
775
954
  role: "button",
@@ -812,7 +991,7 @@ function SmallButton({
812
991
  theme,
813
992
  disabled
814
993
  }) {
815
- return /* @__PURE__ */ import_react3.default.createElement(
994
+ return /* @__PURE__ */ import_react4.default.createElement(
816
995
  "button",
817
996
  {
818
997
  type: "button",
@@ -861,8 +1040,8 @@ function useStateInspector({
861
1040
  ephemeralUserData,
862
1041
  forceInit
863
1042
  }) {
864
- const [root, setRoot] = import_react4.default.useState(null);
865
- (0, import_react4.useLayoutEffect)(() => {
1043
+ const [root, setRoot] = import_react5.default.useState(null);
1044
+ (0, import_react5.useLayoutEffect)(() => {
866
1045
  if (disabled)
867
1046
  return;
868
1047
  const portalElement = createPortalElement();
@@ -873,11 +1052,11 @@ function useStateInspector({
873
1052
  document.body.removeChild(portalElement);
874
1053
  };
875
1054
  }, [disabled]);
876
- (0, import_react4.useLayoutEffect)(() => {
1055
+ (0, import_react5.useLayoutEffect)(() => {
877
1056
  if (!root)
878
1057
  return;
879
1058
  root.render(
880
- /* @__PURE__ */ import_react4.default.createElement(
1059
+ /* @__PURE__ */ import_react5.default.createElement(
881
1060
  StateInspector,
882
1061
  {
883
1062
  state,
@@ -910,22 +1089,22 @@ function useStateInspector({
910
1089
 
911
1090
  // src/hooks.ts
912
1091
  function useSyncStateManager(stateManager, path) {
913
- const getSnapshot = (0, import_react5.useCallback)(
1092
+ const getSnapshot = (0, import_react6.useCallback)(
914
1093
  () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
915
1094
  [stateManager, path]
916
1095
  );
917
- return (0, import_react5.useSyncExternalStore)(
1096
+ return (0, import_react6.useSyncExternalStore)(
918
1097
  stateManager.addListener,
919
1098
  getSnapshot,
920
1099
  getSnapshot
921
1100
  );
922
1101
  }
923
1102
  function useManagedState(createInitialState, options) {
924
- const [stateManager] = (0, import_react5.useState)(
1103
+ const [stateManager] = (0, import_react6.useState)(
925
1104
  () => new import_state_manager.StateManager(createInitialState(), options)
926
1105
  );
927
1106
  const state = useSyncStateManager(stateManager);
928
- const setState = (0, import_react5.useCallback)(
1107
+ const setState = (0, import_react6.useCallback)(
929
1108
  (...args) => {
930
1109
  const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
931
1110
  if (metadata === void 0) {
@@ -961,21 +1140,21 @@ function useManagedState(createInitialState, options) {
961
1140
  return [state, setState, stateManager];
962
1141
  }
963
1142
  function useManagedHistory(stateManager) {
964
- return (0, import_react5.useSyncExternalStore)(
1143
+ return (0, import_react6.useSyncExternalStore)(
965
1144
  stateManager.historyEmittor.addListener,
966
1145
  stateManager.getHistorySnapshot,
967
1146
  stateManager.getHistorySnapshot
968
1147
  );
969
1148
  }
970
1149
  function useSyncMultiplayerStateManager(multiplayerStateManager) {
971
- return (0, import_react5.useSyncExternalStore)(
1150
+ return (0, import_react6.useSyncExternalStore)(
972
1151
  multiplayerStateManager.addListener,
973
1152
  multiplayerStateManager.getOptimisticState,
974
1153
  multiplayerStateManager.getOptimisticState
975
1154
  );
976
1155
  }
977
1156
  function useEphemeralUserData(ephemeralUserData) {
978
- return (0, import_react5.useSyncExternalStore)(
1157
+ return (0, import_react6.useSyncExternalStore)(
979
1158
  ephemeralUserData.addListener,
980
1159
  ephemeralUserData.getSnapshot,
981
1160
  ephemeralUserData.getSnapshot
@@ -984,20 +1163,21 @@ function useEphemeralUserData(ephemeralUserData) {
984
1163
  var defaultStubSync = (0, import_state_manager.stubSync)();
985
1164
  function useMultiplayerState(initialState, options) {
986
1165
  const { sync = defaultStubSync, ...rest } = options ?? {};
987
- const [multiplayerStateManager] = (0, import_react5.useState)(
1166
+ const [multiplayerStateManager] = (0, import_react6.useState)(
988
1167
  () => new import_state_manager.MultiplayerStateManager(initialState, rest)
989
1168
  );
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)(
1169
+ const syncRef = (0, import_react6.useRef)(sync);
1170
+ const [connectionEvents, setConnectionEvents] = (0, import_react6.useState)();
1171
+ const [connectedUsers, setConnectedUsers] = (0, import_react6.useState)([]);
1172
+ const [ephemeralUserData] = (0, import_react6.useState)(
994
1173
  () => new import_state_manager.EphemeralUserData()
995
1174
  );
996
- const [tasks, setTasks] = (0, import_react5.useState)([]);
997
- const [userId, setUserId] = (0, import_react5.useState)();
998
- const extras = (0, import_react5.useMemo)(() => {
1175
+ const [tasks, setTasks] = (0, import_react6.useState)([]);
1176
+ const [userId, setUserId] = (0, import_react6.useState)();
1177
+ const extras = (0, import_react6.useMemo)(() => {
999
1178
  return {
1000
1179
  tasks,
1180
+ userId,
1001
1181
  connectionEvents,
1002
1182
  connectedUsers,
1003
1183
  ephemeralUserData
@@ -1008,27 +1188,27 @@ function useMultiplayerState(initialState, options) {
1008
1188
  // }
1009
1189
  // },
1010
1190
  };
1011
- }, [tasks, connectionEvents, connectedUsers, ephemeralUserData]);
1191
+ }, [tasks, connectionEvents, connectedUsers, ephemeralUserData, userId]);
1012
1192
  const globalTrackEvents = useObservable(shouldTrackEvents$);
1013
1193
  const globalTrackTasks = useObservable(shouldTrackTasks$);
1014
1194
  const shouldTrackEvents = options?.trackConnectionEvents ?? globalTrackEvents;
1015
1195
  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)(() => {
1196
+ const trackEventsCallbackRef = (0, import_react6.useRef)();
1197
+ const trackConnectedUsersCallbackRef = (0, import_react6.useRef)();
1198
+ const trackTasksCallbackRef = (0, import_react6.useRef)();
1199
+ (0, import_react6.useEffect)(() => {
1020
1200
  trackEventsCallbackRef.current = shouldTrackEvents ? (e) => setConnectionEvents((events) => {
1021
1201
  const updated = events ? [...events, e] : [e];
1022
1202
  return updated.length > 50 ? updated.slice(-50) : updated;
1023
1203
  }) : void 0;
1024
1204
  }, [shouldTrackEvents]);
1025
- (0, import_react5.useEffect)(() => {
1205
+ (0, import_react6.useEffect)(() => {
1026
1206
  trackConnectedUsersCallbackRef.current = (users, userId2) => {
1027
1207
  setConnectedUsers(users);
1028
1208
  setUserId(userId2);
1029
1209
  };
1030
1210
  }, []);
1031
- (0, import_react5.useEffect)(() => {
1211
+ (0, import_react6.useEffect)(() => {
1032
1212
  trackTasksCallbackRef.current = shouldTrackTasks ? (tasks2) => {
1033
1213
  setTasks((old) => {
1034
1214
  const newIds = new Set(tasks2.map((t) => t.id));
@@ -1037,7 +1217,7 @@ function useMultiplayerState(initialState, options) {
1037
1217
  });
1038
1218
  } : void 0;
1039
1219
  }, [shouldTrackTasks]);
1040
- (0, import_react5.useEffect)(() => {
1220
+ (0, import_react6.useEffect)(() => {
1041
1221
  if (syncRef.current) {
1042
1222
  return syncRef.current({
1043
1223
  ms: multiplayerStateManager,
@@ -1049,7 +1229,7 @@ function useMultiplayerState(initialState, options) {
1049
1229
  }
1050
1230
  }, [ephemeralUserData, multiplayerStateManager]);
1051
1231
  const state = useSyncMultiplayerStateManager(multiplayerStateManager);
1052
- const forceInit = (0, import_react5.useCallback)(() => {
1232
+ const forceInit = (0, import_react6.useCallback)(() => {
1053
1233
  const state2 = typeof initialState === "function" ? initialState() : initialState;
1054
1234
  const schema = options?.schema;
1055
1235
  multiplayerStateManager.sm.clearHistory();
@@ -1077,6 +1257,13 @@ function useMultiplayerState(initialState, options) {
1077
1257
  // Annotate the CommonJS export names for ESM import in node:
1078
1258
  0 && (module.exports = {
1079
1259
  StateInspector,
1260
+ UserNameTag,
1261
+ UserPointer,
1262
+ UserPointerContainer,
1263
+ UserPointerIcon,
1264
+ UserPointersOverlay,
1265
+ getAvatarInitials,
1266
+ getAvatarStyle,
1080
1267
  useEphemeralUserData,
1081
1268
  useManagedHistory,
1082
1269
  useManagedState,