@noya-app/noya-multiplayer-react 0.1.13 → 0.1.15

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.
@@ -252,6 +252,7 @@ export const StateInspector = memo(function StateInspector<
252
252
  colorScheme = "light",
253
253
  multiplayerStateManager,
254
254
  anchor = "right",
255
+ forceInit,
255
256
  ...props
256
257
  }: {
257
258
  state: S;
@@ -263,6 +264,7 @@ export const StateInspector = memo(function StateInspector<
263
264
  colorScheme?: "light" | "dark";
264
265
  multiplayerStateManager: MultiplayerStateManager<S, M>;
265
266
  anchor?: Anchor;
267
+ forceInit: () => void;
266
268
  } & ComponentPropsWithoutRef<"div">) {
267
269
  const [didMount, setDidMount] = React.useState(false);
268
270
 
@@ -448,20 +450,38 @@ export const StateInspector = memo(function StateInspector<
448
450
  colorScheme={colorScheme}
449
451
  setOpen={setShowData}
450
452
  open={showData}
453
+ right={
454
+ <span
455
+ style={{
456
+ display: "flex",
457
+ gap: "4px",
458
+ }}
459
+ >
460
+ <SmallButton
461
+ // disabled={!historySnapshot.canUndo}
462
+ theme={theme}
463
+ onClick={() => {
464
+ forceInit();
465
+ }}
466
+ >
467
+ Reset
468
+ </SmallButton>
469
+ </span>
470
+ }
451
471
  >
452
472
  <div style={styles.sectionInner}>
453
473
  <InspectorRow colorScheme={colorScheme}>
454
474
  <ObjectInspector
455
- name={multiplayerStateManager.sm.schema ? "state" : undefined}
475
+ name={multiplayerStateManager.schema ? "state" : undefined}
456
476
  data={state}
457
477
  theme={theme}
458
478
  />
459
479
  </InspectorRow>
460
- {multiplayerStateManager.sm.schema && (
480
+ {multiplayerStateManager.schema && (
461
481
  <InspectorRow colorScheme={colorScheme}>
462
482
  <ObjectInspector
463
483
  name="schema"
464
- data={multiplayerStateManager.sm.schema}
484
+ data={multiplayerStateManager.schema}
465
485
  theme={theme}
466
486
  />
467
487
  </InspectorRow>
@@ -473,6 +493,57 @@ export const StateInspector = memo(function StateInspector<
473
493
  setOpen={setShowHistory}
474
494
  title="History"
475
495
  colorScheme={colorScheme}
496
+ right={
497
+ <span
498
+ style={{
499
+ display: "flex",
500
+ gap: "4px",
501
+ }}
502
+ >
503
+ <SmallButton
504
+ disabled={!historySnapshot.canUndo}
505
+ theme={theme}
506
+ onClick={() => {
507
+ multiplayerStateManager.undo();
508
+ }}
509
+ >
510
+ <span style={{ width: "12px", height: "12px" }}>
511
+ <svg
512
+ xmlns="http://www.w3.org/2000/svg"
513
+ width="1em"
514
+ height="1em"
515
+ viewBox="0 0 20 20"
516
+ >
517
+ <path
518
+ fill="currentColor"
519
+ d="M12 5H7V2L1 6l6 4V7h5c2.2 0 4 1.8 4 4s-1.8 4-4 4H7v2h5c3.3 0 6-2.7 6-6s-2.7-6-6-6"
520
+ />
521
+ </svg>
522
+ </span>
523
+ </SmallButton>
524
+ <SmallButton
525
+ disabled={!historySnapshot.canRedo}
526
+ theme={theme}
527
+ onClick={() => {
528
+ multiplayerStateManager.redo();
529
+ }}
530
+ >
531
+ <span style={{ width: "12px", height: "12px" }}>
532
+ <svg
533
+ xmlns="http://www.w3.org/2000/svg"
534
+ width="1em"
535
+ height="1em"
536
+ viewBox="0 0 20 20"
537
+ >
538
+ <path
539
+ fill="currentColor"
540
+ d="M8 5h5V2l6 4l-6 4V7H8c-2.2 0-4 1.8-4 4s1.8 4 4 4h5v2H8c-3.3 0-6-2.7-6-6s2.7-6 6-6"
541
+ />
542
+ </svg>
543
+ </span>
544
+ </SmallButton>
545
+ </span>
546
+ }
476
547
  >
477
548
  <div ref={historyContainerRef} style={styles.sectionInner}>
478
549
  <div
@@ -551,6 +622,17 @@ export const StateInspector = memo(function StateInspector<
551
622
  </span>
552
623
  </>
553
624
  )}
625
+ {patch.op === "move" && (
626
+ <>
627
+ <span style={{ fontStyle: "italic" }}>
628
+ {pathToString(patch.from!)}
629
+ </span>
630
+ {" -> "}
631
+ <span style={{ fontStyle: "italic" }}>
632
+ {pathToString(patch.path)}
633
+ </span>
634
+ </>
635
+ )}
554
636
  </pre>
555
637
  ))}
556
638
  </div>
@@ -763,3 +845,46 @@ function ellipsis(
763
845
  return `${str.slice(0, maxLength)}…`;
764
846
  }
765
847
  }
848
+
849
+ function SmallButton({
850
+ children,
851
+ onClick,
852
+ style,
853
+ theme,
854
+ disabled,
855
+ }: {
856
+ children: React.ReactNode;
857
+ onClick: () => void;
858
+ style?: CSSProperties;
859
+ theme: typeof chromeLight;
860
+ disabled?: boolean;
861
+ }) {
862
+ return (
863
+ <button
864
+ type="button"
865
+ disabled={disabled}
866
+ onClick={(event) => {
867
+ event.stopPropagation();
868
+ onClick();
869
+ }}
870
+ style={{
871
+ flex: "0",
872
+ appearance: "none",
873
+ background: "none",
874
+ color: theme.BASE_COLOR,
875
+ opacity: disabled ? 0.25 : 1,
876
+ border: "none",
877
+ fontSize: "12px",
878
+ whiteSpace: "nowrap",
879
+ display: "inline-flex",
880
+ alignItems: "center",
881
+ justifyContent: "center",
882
+ padding: "2px 0",
883
+ cursor: "pointer",
884
+ ...style,
885
+ }}
886
+ >
887
+ {children}
888
+ </button>
889
+ );
890
+ }
@@ -28,6 +28,7 @@ export function useStateInspector<S extends object, M>({
28
28
  colorScheme,
29
29
  anchor,
30
30
  multiplayerStateManager,
31
+ forceInit,
31
32
  }: {
32
33
  state: S;
33
34
  connectionEvents?: ConnectionEvent<S>[];
@@ -36,6 +37,7 @@ export function useStateInspector<S extends object, M>({
36
37
  userId?: string;
37
38
  disabled: boolean;
38
39
  multiplayerStateManager: MultiplayerStateManager<S, M>;
40
+ forceInit: () => void;
39
41
  } & Pick<ComponentProps<typeof StateInspector>, "colorScheme" | "anchor">) {
40
42
  const [root, setRoot] = React.useState<Root | null>(null);
41
43
 
@@ -67,6 +69,7 @@ export function useStateInspector<S extends object, M>({
67
69
  userId={userId}
68
70
  colorScheme={colorScheme}
69
71
  anchor={anchor}
72
+ forceInit={forceInit}
70
73
  multiplayerStateManager={
71
74
  multiplayerStateManager as MultiplayerStateManager<any, any>
72
75
  }
@@ -82,5 +85,6 @@ export function useStateInspector<S extends object, M>({
82
85
  multiplayerStateManager,
83
86
  userId,
84
87
  tasks,
88
+ forceInit,
85
89
  ]);
86
90
  }