@noya-app/noya-multiplayer-react 0.1.22 → 0.1.24

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
@@ -42,13 +42,15 @@ __export(src_exports, {
42
42
  getAvatarInitials: () => getAvatarInitials,
43
43
  getAvatarStyle: () => getAvatarStyle,
44
44
  isEmbeddedApp: () => isEmbeddedApp,
45
+ useAppData: () => useAppData,
45
46
  useBroadcastConnectedUsers: () => useBroadcastConnectedUsers,
46
47
  useBroadcastMenuItems: () => useBroadcastMenuItems,
47
48
  useEphemeralUserData: () => useEphemeralUserData,
48
49
  useManagedHistory: () => useManagedHistory,
49
50
  useManagedState: () => useManagedState,
50
51
  useMultiplayerState: () => useMultiplayerState,
51
- useNoyaApp: () => useNoyaApp,
52
+ useNoyaAppState: () => useNoyaAppState,
53
+ useObservable: () => useObservable,
52
54
  useSyncMultiplayerStateManager: () => useSyncMultiplayerStateManager,
53
55
  useSyncStateManager: () => useSyncStateManager
54
56
  });
@@ -247,80 +249,9 @@ var UserPointerIcon = (0, import_react2.memo)(function CursorIcon({
247
249
  );
248
250
  });
249
251
 
250
- // src/embedded.ts
251
- var import_state_manager = require("@noya-app/state-manager");
252
- var import_react3 = require("react");
253
- function createDefaultAppData(initialState) {
254
- return {
255
- theme: "light",
256
- viewType: "editable",
257
- initialState,
258
- inspector: false
259
- };
260
- }
261
- function getAppData(initialState) {
262
- try {
263
- const urlHash = (window.location.hash || "").replace(/^#/, "");
264
- const params = new URLSearchParams(urlHash);
265
- const data = params.get("data");
266
- if (!data) {
267
- return initialState ? createDefaultAppData(initialState) : void 0;
268
- }
269
- const parsed = JSON.parse(data);
270
- if (!parsed.initialState) {
271
- parsed.initialState = initialState;
272
- }
273
- return parsed;
274
- } catch (e) {
275
- return initialState ? createDefaultAppData(initialState) : void 0;
276
- }
277
- }
278
- function useNoyaApp(initialState, { schema } = {}) {
279
- const appData = (0, import_react3.useMemo)(() => {
280
- return getAppData(
281
- schema ? (0, import_state_manager.createValue)(schema, initialState) : initialState
282
- );
283
- }, [initialState, schema]);
284
- return appData;
285
- }
286
- function useBroadcastConnectedUsers(connectedUsers) {
287
- (0, import_react3.useEffect)(() => {
288
- if (!isEmbeddedApp())
289
- return;
290
- const message = {
291
- type: "multiplayer.setUsers",
292
- payload: { users: connectedUsers }
293
- };
294
- parent?.postMessage(message, "*");
295
- }, [connectedUsers]);
296
- }
297
- function useBroadcastMenuItems(menuItems, handleSelectMenuItem) {
298
- (0, import_react3.useEffect)(() => {
299
- if (!isEmbeddedApp())
300
- return;
301
- const message = {
302
- type: "application.setMenuItems",
303
- payload: { menuItems }
304
- };
305
- parent?.postMessage(message, "*");
306
- const listener = (event) => {
307
- if (event.data.type === "application.selectMenuItem") {
308
- handleSelectMenuItem(event.data.payload.value);
309
- }
310
- };
311
- window.addEventListener("message", listener);
312
- return () => {
313
- window.removeEventListener("message", listener);
314
- };
315
- }, [handleSelectMenuItem, menuItems]);
316
- }
317
- function isEmbeddedApp() {
318
- return window.self !== window.top;
319
- }
320
-
321
252
  // src/hooks.ts
322
- var import_state_manager2 = require("@noya-app/state-manager");
323
- var import_react7 = require("react");
253
+ var import_state_manager = require("@noya-app/state-manager");
254
+ var import_react6 = require("react");
324
255
 
325
256
  // src/globals.ts
326
257
  var import_observable = require("@noya-app/observable");
@@ -328,18 +259,18 @@ var shouldTrackEvents$ = new import_observable.Observable(false);
328
259
  var shouldTrackTasks$ = new import_observable.Observable(false);
329
260
 
330
261
  // src/inspector/useStateInspector.tsx
331
- var import_react6 = __toESM(require("react"));
262
+ var import_react5 = __toESM(require("react"));
332
263
  var import_client = require("react-dom/client");
333
264
 
334
265
  // src/inspector/StateInspector.tsx
335
- var import_react5 = __toESM(require("react"));
266
+ var import_react4 = __toESM(require("react"));
336
267
  var import_react_inspector = require("react-inspector");
337
268
 
338
269
  // src/inspector/useLocalStorageState.tsx
339
- var import_react4 = __toESM(require("react"));
270
+ var import_react3 = __toESM(require("react"));
340
271
  var localStorage = typeof window !== "undefined" ? window.localStorage : null;
341
272
  function useLocalStorageState(key, defaultValue) {
342
- const [state, setState] = import_react4.default.useState(() => {
273
+ const [state, setState] = import_react3.default.useState(() => {
343
274
  const value = localStorage?.getItem(key);
344
275
  let result = defaultValue;
345
276
  if (value) {
@@ -384,7 +315,7 @@ function ToggleButton({
384
315
  theme,
385
316
  anchor
386
317
  }) {
387
- return /* @__PURE__ */ import_react5.default.createElement(
318
+ return /* @__PURE__ */ import_react4.default.createElement(
388
319
  "span",
389
320
  {
390
321
  role: "button",
@@ -405,7 +336,7 @@ function ToggleButton({
405
336
  setShowInspector(!showInspector);
406
337
  }
407
338
  },
408
- /* @__PURE__ */ import_react5.default.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ import_react5.default.createElement(
339
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ import_react4.default.createElement(
409
340
  "svg",
410
341
  {
411
342
  xmlns: "http://www.w3.org/2000/svg",
@@ -415,7 +346,7 @@ function ToggleButton({
415
346
  stroke: "currentColor",
416
347
  className: "size-6"
417
348
  },
418
- /* @__PURE__ */ import_react5.default.createElement(
349
+ /* @__PURE__ */ import_react4.default.createElement(
419
350
  "path",
420
351
  {
421
352
  strokeLinecap: "round",
@@ -423,7 +354,7 @@ function ToggleButton({
423
354
  d: "m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
424
355
  }
425
356
  )
426
- ) : /* @__PURE__ */ import_react5.default.createElement(
357
+ ) : /* @__PURE__ */ import_react4.default.createElement(
427
358
  "svg",
428
359
  {
429
360
  xmlns: "http://www.w3.org/2000/svg",
@@ -433,7 +364,7 @@ function ToggleButton({
433
364
  stroke: "currentColor",
434
365
  className: "size-6"
435
366
  },
436
- /* @__PURE__ */ import_react5.default.createElement(
367
+ /* @__PURE__ */ import_react4.default.createElement(
437
368
  "path",
438
369
  {
439
370
  strokeLinecap: "round",
@@ -456,7 +387,7 @@ function DisclosureSection({
456
387
  }) {
457
388
  const theme = colorScheme === "light" ? lightTheme : darkTheme;
458
389
  const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
459
- return /* @__PURE__ */ import_react5.default.createElement(
390
+ return /* @__PURE__ */ import_react4.default.createElement(
460
391
  "div",
461
392
  {
462
393
  style: {
@@ -466,7 +397,7 @@ function DisclosureSection({
466
397
  ...style
467
398
  }
468
399
  },
469
- /* @__PURE__ */ import_react5.default.createElement(
400
+ /* @__PURE__ */ import_react4.default.createElement(
470
401
  "div",
471
402
  {
472
403
  onClick: () => setOpen?.(!open),
@@ -480,7 +411,7 @@ function DisclosureSection({
480
411
  ...open && { borderBottom: `1px solid ${borderColor}` }
481
412
  }
482
413
  },
483
- setOpen && /* @__PURE__ */ import_react5.default.createElement(
414
+ setOpen && /* @__PURE__ */ import_react4.default.createElement(
484
415
  Arrow,
485
416
  {
486
417
  expanded: open,
@@ -491,7 +422,7 @@ function DisclosureSection({
491
422
  }
492
423
  }
493
424
  ),
494
- /* @__PURE__ */ import_react5.default.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
425
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
495
426
  right
496
427
  ),
497
428
  open && children
@@ -505,7 +436,7 @@ function InspectorRow({
505
436
  variant
506
437
  }) {
507
438
  const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
508
- return /* @__PURE__ */ import_react5.default.createElement(
439
+ return /* @__PURE__ */ import_react4.default.createElement(
509
440
  "div",
510
441
  {
511
442
  style: {
@@ -523,7 +454,7 @@ function InspectorRow({
523
454
  ...style
524
455
  }
525
456
  },
526
- /* @__PURE__ */ import_react5.default.createElement(
457
+ /* @__PURE__ */ import_react4.default.createElement(
527
458
  "span",
528
459
  {
529
460
  style: {
@@ -538,7 +469,7 @@ function InspectorRow({
538
469
  );
539
470
  }
540
471
  var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
541
- var StateInspector = (0, import_react5.memo)(function StateInspector2({
472
+ var StateInspector = (0, import_react4.memo)(function StateInspector2({
542
473
  state,
543
474
  connectionEvents,
544
475
  connectedUsers,
@@ -552,12 +483,12 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
552
483
  forceInit,
553
484
  ...props
554
485
  }) {
555
- const [didMount, setDidMount] = import_react5.default.useState(false);
556
- (0, import_react5.useLayoutEffect)(() => {
486
+ const [didMount, setDidMount] = import_react4.default.useState(false);
487
+ (0, import_react4.useLayoutEffect)(() => {
557
488
  setDidMount(true);
558
489
  }, []);
559
- const eventsContainerRef = import_react5.default.useRef(null);
560
- const historyContainerRef = import_react5.default.useRef(null);
490
+ const eventsContainerRef = import_react4.default.useRef(null);
491
+ const historyContainerRef = import_react4.default.useRef(null);
561
492
  const [showInspector, setShowInspector] = useLocalStorageState(
562
493
  "noya-multiplayer-react-show-inspector",
563
494
  true
@@ -586,25 +517,25 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
586
517
  "noya-multiplayer-react-show-ephemeral",
587
518
  false
588
519
  );
589
- (0, import_react5.useEffect)(() => {
520
+ (0, import_react4.useEffect)(() => {
590
521
  shouldTrackEvents$.set(showEvents);
591
522
  }, [showEvents]);
592
- (0, import_react5.useEffect)(() => {
523
+ (0, import_react4.useEffect)(() => {
593
524
  shouldTrackTasks$.set(showTasks);
594
525
  }, [showTasks]);
595
- (0, import_react5.useEffect)(() => {
526
+ (0, import_react4.useEffect)(() => {
596
527
  if (eventsContainerRef.current) {
597
528
  eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
598
529
  }
599
530
  }, [connectionEvents]);
600
531
  const ephemeral = useEphemeralUserData(ephemeralUserData);
601
532
  const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
602
- (0, import_react5.useEffect)(() => {
533
+ (0, import_react4.useEffect)(() => {
603
534
  if (historyContainerRef.current) {
604
535
  historyContainerRef.current.scrollTop = historyContainerRef.current.scrollHeight;
605
536
  }
606
537
  }, [historySnapshot]);
607
- (0, import_react5.useEffect)(() => {
538
+ (0, import_react4.useEffect)(() => {
608
539
  if (!historyContainerRef.current)
609
540
  return;
610
541
  const historyEntry = historyContainerRef.current.querySelector(
@@ -641,7 +572,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
641
572
  if (!didMount)
642
573
  return null;
643
574
  if (!showInspector) {
644
- return /* @__PURE__ */ import_react5.default.createElement(
575
+ return /* @__PURE__ */ import_react4.default.createElement(
645
576
  "div",
646
577
  {
647
578
  ...props,
@@ -653,7 +584,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
653
584
  },
654
585
  onClick: () => setShowInspector(true)
655
586
  },
656
- /* @__PURE__ */ import_react5.default.createElement(
587
+ /* @__PURE__ */ import_react4.default.createElement(
657
588
  ToggleButton,
658
589
  {
659
590
  showInspector,
@@ -664,7 +595,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
664
595
  )
665
596
  );
666
597
  }
667
- return /* @__PURE__ */ import_react5.default.createElement(
598
+ return /* @__PURE__ */ import_react4.default.createElement(
668
599
  "div",
669
600
  {
670
601
  ...props,
@@ -673,7 +604,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
673
604
  ...props.style
674
605
  }
675
606
  },
676
- /* @__PURE__ */ import_react5.default.createElement(
607
+ /* @__PURE__ */ import_react4.default.createElement(
677
608
  DisclosureSection,
678
609
  {
679
610
  isFirst: true,
@@ -685,7 +616,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
685
616
  flex: "0 0 auto",
686
617
  maxHeight: "200px"
687
618
  },
688
- right: /* @__PURE__ */ import_react5.default.createElement(
619
+ right: /* @__PURE__ */ import_react4.default.createElement(
689
620
  ToggleButton,
690
621
  {
691
622
  showInspector,
@@ -695,14 +626,14 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
695
626
  }
696
627
  )
697
628
  },
698
- /* @__PURE__ */ import_react5.default.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ import_react5.default.createElement(
629
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ import_react4.default.createElement(
699
630
  InspectorRow,
700
631
  {
701
632
  key: user.id,
702
633
  colorScheme,
703
634
  variant: user.id === userId ? "up" : void 0
704
635
  },
705
- user.image && /* @__PURE__ */ import_react5.default.createElement(
636
+ user.image && /* @__PURE__ */ import_react4.default.createElement(
706
637
  "img",
707
638
  {
708
639
  src: user.image,
@@ -723,7 +654,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
723
654
  " (",
724
655
  ellipsis(user.id.toString(), 8, "middle"),
725
656
  ")"
726
- )), !connectedUsers && /* @__PURE__ */ import_react5.default.createElement(
657
+ )), !connectedUsers && /* @__PURE__ */ import_react4.default.createElement(
727
658
  "div",
728
659
  {
729
660
  style: {
@@ -734,17 +665,17 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
734
665
  gap: "4px"
735
666
  }
736
667
  },
737
- /* @__PURE__ */ import_react5.default.createElement("span", null, "No connected users")
668
+ /* @__PURE__ */ import_react4.default.createElement("span", null, "No connected users")
738
669
  ))
739
670
  ),
740
- /* @__PURE__ */ import_react5.default.createElement(
671
+ /* @__PURE__ */ import_react4.default.createElement(
741
672
  DisclosureSection,
742
673
  {
743
674
  title: "Data",
744
675
  colorScheme,
745
676
  setOpen: setShowData,
746
677
  open: showData,
747
- right: /* @__PURE__ */ import_react5.default.createElement(
678
+ right: /* @__PURE__ */ import_react4.default.createElement(
748
679
  "span",
749
680
  {
750
681
  style: {
@@ -752,7 +683,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
752
683
  gap: "4px"
753
684
  }
754
685
  },
755
- /* @__PURE__ */ import_react5.default.createElement(
686
+ /* @__PURE__ */ import_react4.default.createElement(
756
687
  SmallButton,
757
688
  {
758
689
  theme,
@@ -764,14 +695,14 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
764
695
  )
765
696
  )
766
697
  },
767
- /* @__PURE__ */ import_react5.default.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ import_react5.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react5.default.createElement(
698
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
768
699
  import_react_inspector.ObjectInspector,
769
700
  {
770
701
  name: multiplayerStateManager.schema ? "state" : void 0,
771
702
  data: state,
772
703
  theme
773
704
  }
774
- )), multiplayerStateManager.schema && /* @__PURE__ */ import_react5.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react5.default.createElement(
705
+ )), multiplayerStateManager.schema && /* @__PURE__ */ import_react4.default.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ import_react4.default.createElement(
775
706
  import_react_inspector.ObjectInspector,
776
707
  {
777
708
  name: "schema",
@@ -780,14 +711,14 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
780
711
  }
781
712
  )))
782
713
  ),
783
- /* @__PURE__ */ import_react5.default.createElement(
714
+ /* @__PURE__ */ import_react4.default.createElement(
784
715
  DisclosureSection,
785
716
  {
786
717
  open: showHistory,
787
718
  setOpen: setShowHistory,
788
719
  title: "History",
789
720
  colorScheme,
790
- right: /* @__PURE__ */ import_react5.default.createElement(
721
+ right: /* @__PURE__ */ import_react4.default.createElement(
791
722
  "span",
792
723
  {
793
724
  style: {
@@ -795,7 +726,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
795
726
  gap: "4px"
796
727
  }
797
728
  },
798
- /* @__PURE__ */ import_react5.default.createElement(
729
+ /* @__PURE__ */ import_react4.default.createElement(
799
730
  SmallButton,
800
731
  {
801
732
  disabled: !historySnapshot.canUndo,
@@ -804,7 +735,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
804
735
  multiplayerStateManager.undo();
805
736
  }
806
737
  },
807
- /* @__PURE__ */ import_react5.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react5.default.createElement(
738
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react4.default.createElement(
808
739
  "svg",
809
740
  {
810
741
  xmlns: "http://www.w3.org/2000/svg",
@@ -812,7 +743,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
812
743
  height: "1em",
813
744
  viewBox: "0 0 20 20"
814
745
  },
815
- /* @__PURE__ */ import_react5.default.createElement(
746
+ /* @__PURE__ */ import_react4.default.createElement(
816
747
  "path",
817
748
  {
818
749
  fill: "currentColor",
@@ -821,7 +752,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
821
752
  )
822
753
  ))
823
754
  ),
824
- /* @__PURE__ */ import_react5.default.createElement(
755
+ /* @__PURE__ */ import_react4.default.createElement(
825
756
  SmallButton,
826
757
  {
827
758
  disabled: !historySnapshot.canRedo,
@@ -830,7 +761,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
830
761
  multiplayerStateManager.redo();
831
762
  }
832
763
  },
833
- /* @__PURE__ */ import_react5.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react5.default.createElement(
764
+ /* @__PURE__ */ import_react4.default.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ import_react4.default.createElement(
834
765
  "svg",
835
766
  {
836
767
  xmlns: "http://www.w3.org/2000/svg",
@@ -838,7 +769,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
838
769
  height: "1em",
839
770
  viewBox: "0 0 20 20"
840
771
  },
841
- /* @__PURE__ */ import_react5.default.createElement(
772
+ /* @__PURE__ */ import_react4.default.createElement(
842
773
  "path",
843
774
  {
844
775
  fill: "currentColor",
@@ -849,7 +780,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
849
780
  )
850
781
  )
851
782
  },
852
- /* @__PURE__ */ import_react5.default.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ import_react5.default.createElement(
783
+ /* @__PURE__ */ import_react4.default.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ import_react4.default.createElement(
853
784
  "div",
854
785
  {
855
786
  id: `${HISTORY_ELEMENT_PREFIX}0`,
@@ -863,7 +794,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
863
794
  background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
864
795
  }
865
796
  },
866
- /* @__PURE__ */ import_react5.default.createElement(
797
+ /* @__PURE__ */ import_react4.default.createElement(
867
798
  "span",
868
799
  {
869
800
  style: {
@@ -875,7 +806,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
875
806
  },
876
807
  "Initial state"
877
808
  )
878
- ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react5.default.createElement(
809
+ ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react4.default.createElement(
879
810
  "div",
880
811
  {
881
812
  id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
@@ -886,7 +817,18 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
886
817
  background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
887
818
  }
888
819
  },
889
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react5.default.createElement(
820
+ "name" in entry.metadata && typeof entry.metadata.name === "string" && /* @__PURE__ */ import_react4.default.createElement(
821
+ "pre",
822
+ {
823
+ style: {
824
+ fontSize: "11px",
825
+ display: "flex",
826
+ flexWrap: "wrap"
827
+ }
828
+ },
829
+ entry.metadata.name
830
+ ),
831
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react4.default.createElement(
890
832
  "pre",
891
833
  {
892
834
  key: j,
@@ -896,14 +838,14 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
896
838
  flexWrap: "wrap"
897
839
  }
898
840
  },
899
- patch.op === "add" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ import_react5.default.createElement(import_react_inspector.ObjectInspector, { data: patch.value, theme })),
900
- patch.op === "replace" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ import_react5.default.createElement(import_react_inspector.ObjectInspector, { data: patch.value, theme })),
901
- patch.op === "remove" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ import_react5.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
902
- patch.op === "move" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ import_react5.default.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
841
+ 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 })),
842
+ 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 })),
843
+ 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))),
844
+ 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)))
903
845
  ))
904
846
  )))
905
847
  ),
906
- /* @__PURE__ */ import_react5.default.createElement(
848
+ /* @__PURE__ */ import_react4.default.createElement(
907
849
  DisclosureSection,
908
850
  {
909
851
  title: "Tasks",
@@ -911,7 +853,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
911
853
  open: showTasks,
912
854
  setOpen: setShowTasks
913
855
  },
914
- /* @__PURE__ */ import_react5.default.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ import_react5.default.createElement(
856
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ import_react4.default.createElement(
915
857
  InspectorRow,
916
858
  {
917
859
  key: task.id,
@@ -920,7 +862,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
920
862
  backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
921
863
  }
922
864
  },
923
- /* @__PURE__ */ import_react5.default.createElement(
865
+ /* @__PURE__ */ import_react4.default.createElement(
924
866
  import_react_inspector.ObjectInspector,
925
867
  {
926
868
  name: task.name,
@@ -930,7 +872,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
930
872
  )
931
873
  )))
932
874
  ),
933
- /* @__PURE__ */ import_react5.default.createElement(
875
+ /* @__PURE__ */ import_react4.default.createElement(
934
876
  DisclosureSection,
935
877
  {
936
878
  open: showEphemeral,
@@ -938,7 +880,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
938
880
  title: "Ephemeral User Data",
939
881
  colorScheme
940
882
  },
941
- /* @__PURE__ */ import_react5.default.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ import_react5.default.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ import_react5.default.createElement(
883
+ /* @__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(
942
884
  import_react_inspector.ObjectInspector,
943
885
  {
944
886
  name: key,
@@ -948,7 +890,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
948
890
  }
949
891
  ))))
950
892
  ),
951
- /* @__PURE__ */ import_react5.default.createElement(
893
+ /* @__PURE__ */ import_react4.default.createElement(
952
894
  DisclosureSection,
953
895
  {
954
896
  open: showEvents,
@@ -956,8 +898,8 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
956
898
  title: "Events",
957
899
  colorScheme
958
900
  },
959
- /* @__PURE__ */ import_react5.default.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
960
- (event, index) => event.type === "stateChange" ? /* @__PURE__ */ import_react5.default.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ import_react5.default.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ import_react5.default.createElement(
901
+ /* @__PURE__ */ import_react4.default.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
902
+ (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(
961
903
  InspectorRow,
962
904
  {
963
905
  key: index,
@@ -967,7 +909,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
967
909
  padding: "0px 12px 1px"
968
910
  }
969
911
  },
970
- /* @__PURE__ */ import_react5.default.createElement(
912
+ /* @__PURE__ */ import_react4.default.createElement(
971
913
  import_react_inspector.ObjectInspector,
972
914
  {
973
915
  data: event.message,
@@ -980,7 +922,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
980
922
  expanded
981
923
  }) => {
982
924
  const direction = event.type === "send" ? "up" : "down";
983
- return depth === 0 ? /* @__PURE__ */ import_react5.default.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ import_react5.default.createElement(
925
+ return depth === 0 ? /* @__PURE__ */ import_react4.default.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ import_react4.default.createElement(
984
926
  import_react_inspector.ObjectLabel,
985
927
  {
986
928
  direction,
@@ -993,7 +935,7 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
993
935
  }
994
936
  )
995
937
  )
996
- ), !connectionEvents && /* @__PURE__ */ import_react5.default.createElement(
938
+ ), !connectionEvents && /* @__PURE__ */ import_react4.default.createElement(
997
939
  "div",
998
940
  {
999
941
  style: {
@@ -1004,18 +946,18 @@ var StateInspector = (0, import_react5.memo)(function StateInspector2({
1004
946
  gap: "4px"
1005
947
  }
1006
948
  },
1007
- /* @__PURE__ */ import_react5.default.createElement("span", null, "No recorded events")
949
+ /* @__PURE__ */ import_react4.default.createElement("span", null, "No recorded events")
1008
950
  ))
1009
951
  )
1010
952
  );
1011
953
  });
1012
954
  var ObjectRootLabel = ({ name, data, direction }) => {
1013
955
  if (typeof name === "string") {
1014
- return /* @__PURE__ */ import_react5.default.createElement("span", null, /* @__PURE__ */ import_react5.default.createElement(import_react_inspector.ObjectName, { name }), /* @__PURE__ */ import_react5.default.createElement("span", null, ": "), /* @__PURE__ */ import_react5.default.createElement(import_react_inspector.ObjectPreview, { data }));
956
+ 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 }));
1015
957
  }
1016
958
  if (direction === "up" || direction === "down") {
1017
959
  const arrow = direction === "up" ? "\u2191" : "\u2193";
1018
- return /* @__PURE__ */ import_react5.default.createElement("span", null, /* @__PURE__ */ import_react5.default.createElement(
960
+ return /* @__PURE__ */ import_react4.default.createElement("span", null, /* @__PURE__ */ import_react4.default.createElement(
1019
961
  "span",
1020
962
  {
1021
963
  style: {
@@ -1032,9 +974,9 @@ var ObjectRootLabel = ({ name, data, direction }) => {
1032
974
  }
1033
975
  },
1034
976
  arrow
1035
- ), /* @__PURE__ */ import_react5.default.createElement(import_react_inspector.ObjectPreview, { data }));
977
+ ), /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data }));
1036
978
  } else {
1037
- return /* @__PURE__ */ import_react5.default.createElement(import_react_inspector.ObjectPreview, { data });
979
+ return /* @__PURE__ */ import_react4.default.createElement(import_react_inspector.ObjectPreview, { data });
1038
980
  }
1039
981
  };
1040
982
  function Arrow({
@@ -1042,7 +984,7 @@ function Arrow({
1042
984
  onClick,
1043
985
  style
1044
986
  }) {
1045
- return /* @__PURE__ */ import_react5.default.createElement(
987
+ return /* @__PURE__ */ import_react4.default.createElement(
1046
988
  "span",
1047
989
  {
1048
990
  role: "button",
@@ -1085,7 +1027,7 @@ function SmallButton({
1085
1027
  theme,
1086
1028
  disabled
1087
1029
  }) {
1088
- return /* @__PURE__ */ import_react5.default.createElement(
1030
+ return /* @__PURE__ */ import_react4.default.createElement(
1089
1031
  "button",
1090
1032
  {
1091
1033
  type: "button",
@@ -1134,8 +1076,8 @@ function useStateInspector({
1134
1076
  ephemeralUserData,
1135
1077
  forceInit
1136
1078
  }) {
1137
- const [root, setRoot] = import_react6.default.useState(null);
1138
- (0, import_react6.useLayoutEffect)(() => {
1079
+ const [root, setRoot] = import_react5.default.useState(null);
1080
+ (0, import_react5.useLayoutEffect)(() => {
1139
1081
  if (disabled)
1140
1082
  return;
1141
1083
  const portalElement = createPortalElement();
@@ -1146,11 +1088,11 @@ function useStateInspector({
1146
1088
  document.body.removeChild(portalElement);
1147
1089
  };
1148
1090
  }, [disabled]);
1149
- (0, import_react6.useLayoutEffect)(() => {
1091
+ (0, import_react5.useLayoutEffect)(() => {
1150
1092
  if (!root)
1151
1093
  return;
1152
1094
  root.render(
1153
- /* @__PURE__ */ import_react6.default.createElement(
1095
+ /* @__PURE__ */ import_react5.default.createElement(
1154
1096
  StateInspector,
1155
1097
  {
1156
1098
  state,
@@ -1183,22 +1125,22 @@ function useStateInspector({
1183
1125
 
1184
1126
  // src/hooks.ts
1185
1127
  function useSyncStateManager(stateManager, path) {
1186
- const getSnapshot = (0, import_react7.useCallback)(
1128
+ const getSnapshot = (0, import_react6.useCallback)(
1187
1129
  () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
1188
1130
  [stateManager, path]
1189
1131
  );
1190
- return (0, import_react7.useSyncExternalStore)(
1132
+ return (0, import_react6.useSyncExternalStore)(
1191
1133
  stateManager.addListener,
1192
1134
  getSnapshot,
1193
1135
  getSnapshot
1194
1136
  );
1195
1137
  }
1196
1138
  function useManagedState(createInitialState, options) {
1197
- const [stateManager] = (0, import_react7.useState)(
1198
- () => new import_state_manager2.StateManager(createInitialState(), options)
1139
+ const [stateManager] = (0, import_react6.useState)(
1140
+ () => new import_state_manager.StateManager(createInitialState(), options)
1199
1141
  );
1200
1142
  const state = useSyncStateManager(stateManager);
1201
- const setState = (0, import_react7.useCallback)(
1143
+ const setState = (0, import_react6.useCallback)(
1202
1144
  (...args) => {
1203
1145
  const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
1204
1146
  if (metadata === void 0) {
@@ -1234,47 +1176,80 @@ function useManagedState(createInitialState, options) {
1234
1176
  return [state, setState, stateManager];
1235
1177
  }
1236
1178
  function useManagedHistory(stateManager) {
1237
- return (0, import_react7.useSyncExternalStore)(
1179
+ return (0, import_react6.useSyncExternalStore)(
1238
1180
  stateManager.historyEmittor.addListener,
1239
1181
  stateManager.getHistorySnapshot,
1240
1182
  stateManager.getHistorySnapshot
1241
1183
  );
1242
1184
  }
1243
1185
  function useSyncMultiplayerStateManager(multiplayerStateManager) {
1244
- return (0, import_react7.useSyncExternalStore)(
1186
+ return (0, import_react6.useSyncExternalStore)(
1245
1187
  multiplayerStateManager.addListener,
1246
1188
  multiplayerStateManager.getOptimisticState,
1247
1189
  multiplayerStateManager.getOptimisticState
1248
1190
  );
1249
1191
  }
1250
- function useEphemeralUserData(ephemeralUserData) {
1251
- return (0, import_react7.useSyncExternalStore)(
1252
- ephemeralUserData.addListener,
1192
+ function throttle(fn, ms) {
1193
+ let lastCall = 0;
1194
+ let timeoutId = null;
1195
+ return (...args) => {
1196
+ const now = Date.now();
1197
+ if (now - lastCall < ms) {
1198
+ if (timeoutId)
1199
+ clearTimeout(timeoutId);
1200
+ timeoutId = setTimeout(
1201
+ () => {
1202
+ lastCall = now;
1203
+ fn(...args);
1204
+ },
1205
+ ms - (now - lastCall)
1206
+ );
1207
+ return;
1208
+ }
1209
+ lastCall = now;
1210
+ return fn(...args);
1211
+ };
1212
+ }
1213
+ function useEphemeralUserData(ephemeralUserData, options) {
1214
+ const throttledAddListener = (0, import_react6.useMemo)(() => {
1215
+ const throttleMs = options?.throttle ?? 0;
1216
+ if (throttleMs > 0) {
1217
+ const addListener = (fn) => {
1218
+ const throttledFn = throttle(fn, throttleMs);
1219
+ return ephemeralUserData.addListener(throttledFn);
1220
+ };
1221
+ return addListener;
1222
+ }
1223
+ return ephemeralUserData.addListener;
1224
+ }, [ephemeralUserData, options?.throttle]);
1225
+ return (0, import_react6.useSyncExternalStore)(
1226
+ throttledAddListener,
1253
1227
  ephemeralUserData.getSnapshot,
1254
1228
  ephemeralUserData.getSnapshot
1255
1229
  );
1256
1230
  }
1257
- var defaultStubSync = (0, import_state_manager2.stubSync)();
1231
+ var defaultStubSync = (0, import_state_manager.stubSync)();
1258
1232
  function useMultiplayerState(initialState, options) {
1259
1233
  const { sync = defaultStubSync, ...rest } = options ?? {};
1260
- const [multiplayerStateManager] = (0, import_react7.useState)(
1261
- () => new import_state_manager2.MultiplayerStateManager(initialState, rest)
1234
+ const [multiplayerStateManager] = (0, import_react6.useState)(
1235
+ () => new import_state_manager.MultiplayerStateManager(initialState, rest)
1262
1236
  );
1263
- const syncRef = (0, import_react7.useRef)(sync);
1264
- const [connectionEvents, setConnectionEvents] = (0, import_react7.useState)();
1265
- const [connectedUsers, setConnectedUsers] = (0, import_react7.useState)([]);
1266
- const [ephemeralUserData] = (0, import_react7.useState)(
1267
- () => new import_state_manager2.EphemeralUserData()
1237
+ const syncRef = (0, import_react6.useRef)(sync);
1238
+ const [connectionEvents, setConnectionEvents] = (0, import_react6.useState)();
1239
+ const [connectedUsers, setConnectedUsers] = (0, import_react6.useState)([]);
1240
+ const [ephemeralUserData] = (0, import_react6.useState)(
1241
+ () => new import_state_manager.EphemeralUserData()
1268
1242
  );
1269
- const [tasks, setTasks] = (0, import_react7.useState)([]);
1270
- const [userId, setUserId] = (0, import_react7.useState)();
1271
- const extras = (0, import_react7.useMemo)(() => {
1243
+ const [tasks, setTasks] = (0, import_react6.useState)([]);
1244
+ const [userId, setUserId] = (0, import_react6.useState)();
1245
+ const extras = (0, import_react6.useMemo)(() => {
1272
1246
  return {
1273
1247
  tasks,
1274
1248
  userId,
1275
1249
  connectionEvents,
1276
1250
  connectedUsers,
1277
- ephemeralUserData
1251
+ ephemeralUserData,
1252
+ multiplayerStateManager
1278
1253
  // evaluate: async (code: string) => {
1279
1254
  // const payload = await rpcManager.request({ type: "eval", code });
1280
1255
  // if (payload.type !== "eval") {
@@ -1282,27 +1257,34 @@ function useMultiplayerState(initialState, options) {
1282
1257
  // }
1283
1258
  // },
1284
1259
  };
1285
- }, [tasks, connectionEvents, connectedUsers, ephemeralUserData, userId]);
1260
+ }, [
1261
+ tasks,
1262
+ userId,
1263
+ connectionEvents,
1264
+ connectedUsers,
1265
+ ephemeralUserData,
1266
+ multiplayerStateManager
1267
+ ]);
1286
1268
  const globalTrackEvents = useObservable(shouldTrackEvents$);
1287
1269
  const globalTrackTasks = useObservable(shouldTrackTasks$);
1288
1270
  const shouldTrackEvents = options?.trackConnectionEvents ?? globalTrackEvents;
1289
1271
  const shouldTrackTasks = options?.trackTasks ?? globalTrackTasks;
1290
- const trackEventsCallbackRef = (0, import_react7.useRef)();
1291
- const trackConnectedUsersCallbackRef = (0, import_react7.useRef)();
1292
- const trackTasksCallbackRef = (0, import_react7.useRef)();
1293
- (0, import_react7.useEffect)(() => {
1272
+ const trackEventsCallbackRef = (0, import_react6.useRef)();
1273
+ const trackConnectedUsersCallbackRef = (0, import_react6.useRef)();
1274
+ const trackTasksCallbackRef = (0, import_react6.useRef)();
1275
+ (0, import_react6.useEffect)(() => {
1294
1276
  trackEventsCallbackRef.current = shouldTrackEvents ? (e) => setConnectionEvents((events) => {
1295
1277
  const updated = events ? [...events, e] : [e];
1296
1278
  return updated.length > 50 ? updated.slice(-50) : updated;
1297
1279
  }) : void 0;
1298
1280
  }, [shouldTrackEvents]);
1299
- (0, import_react7.useEffect)(() => {
1281
+ (0, import_react6.useEffect)(() => {
1300
1282
  trackConnectedUsersCallbackRef.current = (users, userId2) => {
1301
1283
  setConnectedUsers(users);
1302
1284
  setUserId(userId2);
1303
1285
  };
1304
1286
  }, []);
1305
- (0, import_react7.useEffect)(() => {
1287
+ (0, import_react6.useEffect)(() => {
1306
1288
  trackTasksCallbackRef.current = shouldTrackTasks ? (tasks2) => {
1307
1289
  setTasks((old) => {
1308
1290
  const newIds = new Set(tasks2.map((t) => t.id));
@@ -1311,7 +1293,7 @@ function useMultiplayerState(initialState, options) {
1311
1293
  });
1312
1294
  } : void 0;
1313
1295
  }, [shouldTrackTasks]);
1314
- (0, import_react7.useEffect)(() => {
1296
+ (0, import_react6.useEffect)(() => {
1315
1297
  if (syncRef.current) {
1316
1298
  return syncRef.current({
1317
1299
  ms: multiplayerStateManager,
@@ -1323,7 +1305,7 @@ function useMultiplayerState(initialState, options) {
1323
1305
  }
1324
1306
  }, [ephemeralUserData, multiplayerStateManager]);
1325
1307
  const state = useSyncMultiplayerStateManager(multiplayerStateManager);
1326
- const forceInit = (0, import_react7.useCallback)(() => {
1308
+ const forceInit = (0, import_react6.useCallback)(() => {
1327
1309
  const state2 = typeof initialState === "function" ? initialState() : initialState;
1328
1310
  const schema = options?.schema;
1329
1311
  multiplayerStateManager.sm.clearHistory();
@@ -1341,13 +1323,104 @@ function useMultiplayerState(initialState, options) {
1341
1323
  disabled: !options?.inspector,
1342
1324
  ...typeof options?.inspector === "object" && options.inspector
1343
1325
  });
1344
- useBroadcastConnectedUsers(connectedUsers);
1345
- return [
1346
- state,
1347
- multiplayerStateManager.setState,
1348
- multiplayerStateManager,
1349
- extras
1350
- ];
1326
+ return [state, multiplayerStateManager.setState, extras];
1327
+ }
1328
+
1329
+ // src/noyaApp.ts
1330
+ var import_state_manager2 = require("@noya-app/state-manager");
1331
+ var import_react7 = require("react");
1332
+ function createDefaultAppData(initialState) {
1333
+ return {
1334
+ theme: "light",
1335
+ viewType: "editable",
1336
+ initialState,
1337
+ inspector: false
1338
+ };
1339
+ }
1340
+ function getAppData(initialState) {
1341
+ try {
1342
+ const urlHash = (window.location.hash || "").replace(/^#/, "");
1343
+ const params = new URLSearchParams(urlHash);
1344
+ const data = params.get("data");
1345
+ if (!data) {
1346
+ return initialState ? createDefaultAppData(initialState) : void 0;
1347
+ }
1348
+ const parsed = JSON.parse(data);
1349
+ if (!parsed.initialState) {
1350
+ parsed.initialState = initialState;
1351
+ }
1352
+ return parsed;
1353
+ } catch (e) {
1354
+ return initialState ? createDefaultAppData(initialState) : void 0;
1355
+ }
1356
+ }
1357
+ function useAppData(initialState, { schema } = {}) {
1358
+ const appData = (0, import_react7.useMemo)(() => {
1359
+ return getAppData(
1360
+ schema ? (0, import_state_manager2.createValue)(schema, initialState) : initialState
1361
+ );
1362
+ }, [initialState, schema]);
1363
+ return appData;
1364
+ }
1365
+ function useBroadcastConnectedUsers(connectedUsers) {
1366
+ (0, import_react7.useEffect)(() => {
1367
+ if (!isEmbeddedApp())
1368
+ return;
1369
+ const message = {
1370
+ type: "multiplayer.setUsers",
1371
+ payload: { users: connectedUsers }
1372
+ };
1373
+ parent?.postMessage(message, "*");
1374
+ }, [connectedUsers]);
1375
+ }
1376
+ function useBroadcastMenuItems(menuItems, handleSelectMenuItem) {
1377
+ (0, import_react7.useEffect)(() => {
1378
+ if (!isEmbeddedApp())
1379
+ return;
1380
+ const message = {
1381
+ type: "application.setMenuItems",
1382
+ payload: { menuItems }
1383
+ };
1384
+ parent?.postMessage(message, "*");
1385
+ const listener = (event) => {
1386
+ if (event.data.type === "application.selectMenuItem") {
1387
+ handleSelectMenuItem(event.data.payload.value);
1388
+ }
1389
+ };
1390
+ window.addEventListener("message", listener);
1391
+ return () => {
1392
+ window.removeEventListener("message", listener);
1393
+ };
1394
+ }, [handleSelectMenuItem, menuItems]);
1395
+ }
1396
+ function isEmbeddedApp() {
1397
+ return window.self !== window.top;
1398
+ }
1399
+ function useNoyaAppState(initialState, options) {
1400
+ const [state] = (0, import_react7.useState)(initialState);
1401
+ const {
1402
+ multiplayerUrl,
1403
+ inspector,
1404
+ initialState: noyaAppInitialState,
1405
+ theme,
1406
+ viewType
1407
+ } = useAppData(state, {
1408
+ schema: options.schema
1409
+ });
1410
+ const sync = (0, import_react7.useMemo)(() => {
1411
+ return multiplayerUrl ? (0, import_state_manager2.webSocketSync)(multiplayerUrl) : (0, import_state_manager2.localStorageSync)({ key: options.localStorageKey || "noya-app" });
1412
+ }, [multiplayerUrl, options.localStorageKey]);
1413
+ const result = useMultiplayerState(noyaAppInitialState, {
1414
+ ...options,
1415
+ inspector: options.inspector ?? inspector,
1416
+ sync
1417
+ });
1418
+ const [, , extras] = result;
1419
+ useBroadcastConnectedUsers(extras.connectedUsers);
1420
+ const mergedExtras = (0, import_react7.useMemo)(() => {
1421
+ return { ...extras, theme, viewType };
1422
+ }, [extras, theme, viewType]);
1423
+ return [result[0], result[1], mergedExtras];
1351
1424
  }
1352
1425
  // Annotate the CommonJS export names for ESM import in node:
1353
1426
  0 && (module.exports = {
@@ -1362,13 +1435,15 @@ function useMultiplayerState(initialState, options) {
1362
1435
  getAvatarInitials,
1363
1436
  getAvatarStyle,
1364
1437
  isEmbeddedApp,
1438
+ useAppData,
1365
1439
  useBroadcastConnectedUsers,
1366
1440
  useBroadcastMenuItems,
1367
1441
  useEphemeralUserData,
1368
1442
  useManagedHistory,
1369
1443
  useManagedState,
1370
1444
  useMultiplayerState,
1371
- useNoyaApp,
1445
+ useNoyaAppState,
1446
+ useObservable,
1372
1447
  useSyncMultiplayerStateManager,
1373
1448
  useSyncStateManager,
1374
1449
  ...require("@noya-app/state-manager")