@noya-app/noya-multiplayer-react 0.1.9 → 0.1.11
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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +16 -0
- package/dist/index.d.mts +17 -17
- package/dist/index.d.ts +17 -17
- package/dist/index.js +33 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/hooks.ts +14 -13
- package/src/inspector/StateInspector.tsx +49 -42
- package/src/inspector/useStateInspector.tsx +4 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
[34mCLI[39m Target: esnext
|
|
6
6
|
[34mCJS[39m Build start
|
|
7
7
|
[34mESM[39m Build start
|
|
8
|
-
[
|
|
9
|
-
[
|
|
10
|
-
[
|
|
11
|
-
[
|
|
12
|
-
[
|
|
13
|
-
[
|
|
8
|
+
[32mCJS[39m [1mdist/index.js [22m[32m25.32 KB[39m
|
|
9
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m40.59 KB[39m
|
|
10
|
+
[32mCJS[39m ⚡️ Build success in 18ms
|
|
11
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m21.85 KB[39m
|
|
12
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m40.79 KB[39m
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 18ms
|
|
14
14
|
[34mDTS[39m Build start
|
|
15
15
|
"ComponentPropsWithoutRef" is imported from external module "react" but never used in "src/inspector/StateInspector.tsx" and "src/hooks.ts".
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
17
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m2.
|
|
18
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m2.
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 1599ms
|
|
17
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m2.32 KB[39m
|
|
18
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m2.32 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @noya-app/state-manager
|
|
2
2
|
|
|
3
|
+
## 0.1.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 843913b: Improve metadata and reconnection
|
|
8
|
+
- Updated dependencies [843913b]
|
|
9
|
+
- @noya-app/state-manager@0.1.11
|
|
10
|
+
|
|
11
|
+
## 0.1.10
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 6c8aff6: Update inspector UI
|
|
16
|
+
- Updated dependencies [6c8aff6]
|
|
17
|
+
- @noya-app/state-manager@0.1.10
|
|
18
|
+
|
|
3
19
|
## 0.1.9
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import * as _noya_app_state_manager from '@noya-app/state-manager';
|
|
2
|
-
import { StateManager, Get, StateManagerOptions, MultiplayerStateManager,
|
|
2
|
+
import { ConnectionEvent, StateManager, Get, StateManagerOptions, MultiplayerStateManager, MultiplayerStateManagerOptions } from '@noya-app/state-manager';
|
|
3
3
|
export * from '@noya-app/state-manager';
|
|
4
|
-
import React, { SetStateAction } from 'react';
|
|
4
|
+
import React, { SetStateAction, ComponentProps } from 'react';
|
|
5
|
+
|
|
6
|
+
type Anchor = "left" | "right";
|
|
7
|
+
declare const StateInspector: React.MemoExoticComponent<(<S extends object, M>({ state, connectionEvents, unstyled, colorScheme, stateManager, anchor, ...props }: {
|
|
8
|
+
state: S;
|
|
9
|
+
connectionEvents?: ConnectionEvent<S>[] | undefined;
|
|
10
|
+
unstyled?: boolean | undefined;
|
|
11
|
+
colorScheme?: "light" | "dark" | undefined;
|
|
12
|
+
stateManager: StateManager<S, M>;
|
|
13
|
+
anchor?: Anchor | undefined;
|
|
14
|
+
} & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">) => React.JSX.Element | null)>;
|
|
5
15
|
|
|
6
16
|
declare function useSyncStateManager<S extends object, M>(stateManager: StateManager<S, M>): S;
|
|
7
17
|
declare function useSyncStateManager<S extends object, M, P extends string>(stateManager: StateManager<S, M>, path: P): Get<S, P, unknown>;
|
|
8
18
|
declare function useManagedState<S extends object, M = void>(createInitialState: () => S, options?: StateManagerOptions<S, M>): readonly [S, (...args: M extends {} ? [metadata: M, action: SetStateAction<S>] : [action: SetStateAction<S>]) => void, StateManager<S, M>];
|
|
9
19
|
declare function useManagedHistory<S extends object, M = void>(stateManager: StateManager<S, M>): _noya_app_state_manager.HistorySnapshot<S, M>;
|
|
10
|
-
declare function useSyncMultiplayerStateManager<S extends object>(multiplayerStateManager: MultiplayerStateManager<S>): S;
|
|
11
|
-
declare function useMultiplayerState<S extends object>(initialState: S | (() => S), options:
|
|
12
|
-
sync?: (self: MultiplayerStateManager<S>) => void;
|
|
20
|
+
declare function useSyncMultiplayerStateManager<S extends object, M = void>(multiplayerStateManager: MultiplayerStateManager<S, M>): S;
|
|
21
|
+
declare function useMultiplayerState<S extends object, M = void>(initialState: S | (() => S), options: MultiplayerStateManagerOptions<S, M> & {
|
|
22
|
+
sync?: (self: MultiplayerStateManager<S, M>) => void;
|
|
13
23
|
trackConnectionEvents?: boolean;
|
|
14
|
-
inspector?: boolean |
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
}): readonly [S, (metadata: MultiplayerPatchMetadata, action: S | ((prevState: S) => S)) => void, MultiplayerStateManager<S>, {
|
|
24
|
+
inspector?: boolean | Pick<ComponentProps<typeof StateInspector>, "colorScheme" | "anchor">;
|
|
25
|
+
}): readonly [S, (...args: M extends {} ? [metadata: M, action: S | ((prevState: S) => S)] : [action: S | ((prevState: S) => S)]) => void, MultiplayerStateManager<S, M>, {
|
|
18
26
|
connectionEvents: ConnectionEvent<S>[] | undefined;
|
|
19
27
|
}];
|
|
20
28
|
|
|
21
|
-
declare const StateInspector: React.MemoExoticComponent<(<S extends object, M>({ state, connectionEvents, unstyled, colorScheme, stateManager, ...props }: {
|
|
22
|
-
state: S;
|
|
23
|
-
connectionEvents?: ConnectionEvent<S>[] | undefined;
|
|
24
|
-
unstyled?: boolean | undefined;
|
|
25
|
-
colorScheme?: "light" | "dark" | undefined;
|
|
26
|
-
stateManager: StateManager<S, M>;
|
|
27
|
-
} & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">) => React.JSX.Element | null)>;
|
|
28
|
-
|
|
29
29
|
export { StateInspector, useManagedHistory, useManagedState, useMultiplayerState, useSyncMultiplayerStateManager, useSyncStateManager };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import * as _noya_app_state_manager from '@noya-app/state-manager';
|
|
2
|
-
import { StateManager, Get, StateManagerOptions, MultiplayerStateManager,
|
|
2
|
+
import { ConnectionEvent, StateManager, Get, StateManagerOptions, MultiplayerStateManager, MultiplayerStateManagerOptions } from '@noya-app/state-manager';
|
|
3
3
|
export * from '@noya-app/state-manager';
|
|
4
|
-
import React, { SetStateAction } from 'react';
|
|
4
|
+
import React, { SetStateAction, ComponentProps } from 'react';
|
|
5
|
+
|
|
6
|
+
type Anchor = "left" | "right";
|
|
7
|
+
declare const StateInspector: React.MemoExoticComponent<(<S extends object, M>({ state, connectionEvents, unstyled, colorScheme, stateManager, anchor, ...props }: {
|
|
8
|
+
state: S;
|
|
9
|
+
connectionEvents?: ConnectionEvent<S>[] | undefined;
|
|
10
|
+
unstyled?: boolean | undefined;
|
|
11
|
+
colorScheme?: "light" | "dark" | undefined;
|
|
12
|
+
stateManager: StateManager<S, M>;
|
|
13
|
+
anchor?: Anchor | undefined;
|
|
14
|
+
} & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">) => React.JSX.Element | null)>;
|
|
5
15
|
|
|
6
16
|
declare function useSyncStateManager<S extends object, M>(stateManager: StateManager<S, M>): S;
|
|
7
17
|
declare function useSyncStateManager<S extends object, M, P extends string>(stateManager: StateManager<S, M>, path: P): Get<S, P, unknown>;
|
|
8
18
|
declare function useManagedState<S extends object, M = void>(createInitialState: () => S, options?: StateManagerOptions<S, M>): readonly [S, (...args: M extends {} ? [metadata: M, action: SetStateAction<S>] : [action: SetStateAction<S>]) => void, StateManager<S, M>];
|
|
9
19
|
declare function useManagedHistory<S extends object, M = void>(stateManager: StateManager<S, M>): _noya_app_state_manager.HistorySnapshot<S, M>;
|
|
10
|
-
declare function useSyncMultiplayerStateManager<S extends object>(multiplayerStateManager: MultiplayerStateManager<S>): S;
|
|
11
|
-
declare function useMultiplayerState<S extends object>(initialState: S | (() => S), options:
|
|
12
|
-
sync?: (self: MultiplayerStateManager<S>) => void;
|
|
20
|
+
declare function useSyncMultiplayerStateManager<S extends object, M = void>(multiplayerStateManager: MultiplayerStateManager<S, M>): S;
|
|
21
|
+
declare function useMultiplayerState<S extends object, M = void>(initialState: S | (() => S), options: MultiplayerStateManagerOptions<S, M> & {
|
|
22
|
+
sync?: (self: MultiplayerStateManager<S, M>) => void;
|
|
13
23
|
trackConnectionEvents?: boolean;
|
|
14
|
-
inspector?: boolean |
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
}): readonly [S, (metadata: MultiplayerPatchMetadata, action: S | ((prevState: S) => S)) => void, MultiplayerStateManager<S>, {
|
|
24
|
+
inspector?: boolean | Pick<ComponentProps<typeof StateInspector>, "colorScheme" | "anchor">;
|
|
25
|
+
}): readonly [S, (...args: M extends {} ? [metadata: M, action: S | ((prevState: S) => S)] : [action: S | ((prevState: S) => S)]) => void, MultiplayerStateManager<S, M>, {
|
|
18
26
|
connectionEvents: ConnectionEvent<S>[] | undefined;
|
|
19
27
|
}];
|
|
20
28
|
|
|
21
|
-
declare const StateInspector: React.MemoExoticComponent<(<S extends object, M>({ state, connectionEvents, unstyled, colorScheme, stateManager, ...props }: {
|
|
22
|
-
state: S;
|
|
23
|
-
connectionEvents?: ConnectionEvent<S>[] | undefined;
|
|
24
|
-
unstyled?: boolean | undefined;
|
|
25
|
-
colorScheme?: "light" | "dark" | undefined;
|
|
26
|
-
stateManager: StateManager<S, M>;
|
|
27
|
-
} & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">) => React.JSX.Element | null)>;
|
|
28
|
-
|
|
29
29
|
export { StateInspector, useManagedHistory, useManagedState, useMultiplayerState, useSyncMultiplayerStateManager, useSyncStateManager };
|
package/dist/index.js
CHANGED
|
@@ -122,7 +122,8 @@ var darkTheme = {
|
|
|
122
122
|
function ToggleButton({
|
|
123
123
|
showInspector,
|
|
124
124
|
setShowInspector,
|
|
125
|
-
theme
|
|
125
|
+
theme,
|
|
126
|
+
anchor
|
|
126
127
|
}) {
|
|
127
128
|
return /* @__PURE__ */ import_react3.default.createElement(
|
|
128
129
|
"span",
|
|
@@ -132,7 +133,6 @@ function ToggleButton({
|
|
|
132
133
|
flex: "0",
|
|
133
134
|
appearance: "none",
|
|
134
135
|
color: theme.BASE_COLOR,
|
|
135
|
-
background: "rgba(0,0,0,0.1)",
|
|
136
136
|
border: "none",
|
|
137
137
|
fontSize: "12px",
|
|
138
138
|
whiteSpace: "nowrap",
|
|
@@ -143,7 +143,7 @@ function ToggleButton({
|
|
|
143
143
|
},
|
|
144
144
|
onClick: () => setShowInspector(!showInspector)
|
|
145
145
|
},
|
|
146
|
-
/* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector ? /* @__PURE__ */ import_react3.default.createElement(
|
|
146
|
+
/* @__PURE__ */ import_react3.default.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ import_react3.default.createElement(
|
|
147
147
|
"svg",
|
|
148
148
|
{
|
|
149
149
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -211,6 +211,7 @@ function DisclosureSection({
|
|
|
211
211
|
fontSize: "12px",
|
|
212
212
|
padding: "4px 10px",
|
|
213
213
|
display: "flex",
|
|
214
|
+
alignItems: "center",
|
|
214
215
|
...!isFirst && { borderTop: `1px solid ${borderColor}` },
|
|
215
216
|
...open && { borderBottom: `1px solid ${borderColor}` }
|
|
216
217
|
}
|
|
@@ -220,9 +221,8 @@ function DisclosureSection({
|
|
|
220
221
|
{
|
|
221
222
|
expanded: open,
|
|
222
223
|
style: {
|
|
223
|
-
fontSize:
|
|
224
|
-
|
|
225
|
-
marginRight: theme.ARROW_MARGIN_RIGHT,
|
|
224
|
+
fontSize: theme.ARROW_FONT_SIZE,
|
|
225
|
+
marginRight: theme.ARROW_MARGIN_RIGHT + 1,
|
|
226
226
|
color: theme.ARROW_COLOR
|
|
227
227
|
}
|
|
228
228
|
}
|
|
@@ -233,12 +233,14 @@ function DisclosureSection({
|
|
|
233
233
|
open && children
|
|
234
234
|
);
|
|
235
235
|
}
|
|
236
|
+
var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
|
|
236
237
|
var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
237
238
|
state,
|
|
238
239
|
connectionEvents,
|
|
239
240
|
unstyled,
|
|
240
241
|
colorScheme = "light",
|
|
241
242
|
stateManager,
|
|
243
|
+
anchor = "right",
|
|
242
244
|
...props
|
|
243
245
|
}) {
|
|
244
246
|
const [didMount, setDidMount] = import_react3.default.useState(false);
|
|
@@ -277,7 +279,7 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
277
279
|
if (!historyContainerRef.current)
|
|
278
280
|
return;
|
|
279
281
|
const historyEntry = historyContainerRef.current.querySelector(
|
|
280
|
-
|
|
282
|
+
`#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
|
|
281
283
|
);
|
|
282
284
|
if (historyEntry) {
|
|
283
285
|
historyEntry.scrollIntoView({
|
|
@@ -288,15 +290,16 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
288
290
|
}, [historySnapshot.historyIndex]);
|
|
289
291
|
const theme = colorScheme === "light" ? lightTheme : darkTheme;
|
|
290
292
|
const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
|
|
293
|
+
const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
|
|
291
294
|
const baseStyle = {
|
|
292
295
|
position: "fixed",
|
|
293
296
|
top: 12,
|
|
294
|
-
right: 12,
|
|
297
|
+
...anchor === "right" ? { right: 12 } : { left: 12 },
|
|
295
298
|
bottom: 12,
|
|
296
299
|
width: 400,
|
|
297
300
|
background: colorScheme === "light" ? "rgba(255,255,255,0.95)" : "rgba(0,0,0,0.95)",
|
|
298
301
|
backdropFilter: "blur(48px)",
|
|
299
|
-
border: `1px solid ${
|
|
302
|
+
border: `1px solid ${solidBorderColor}`,
|
|
300
303
|
// outlineOffset: -1,
|
|
301
304
|
borderRadius: 4,
|
|
302
305
|
display: "flex",
|
|
@@ -304,7 +307,8 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
304
307
|
// gap: 12,
|
|
305
308
|
color: theme.BASE_COLOR,
|
|
306
309
|
overflow: "hidden",
|
|
307
|
-
zIndex: 9999
|
|
310
|
+
zIndex: 9999,
|
|
311
|
+
lineHeight: "13px"
|
|
308
312
|
};
|
|
309
313
|
if (!didMount)
|
|
310
314
|
return null;
|
|
@@ -316,17 +320,18 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
316
320
|
style: {
|
|
317
321
|
...baseStyle,
|
|
318
322
|
padding: "4px 10px",
|
|
319
|
-
borderRadius: 8,
|
|
320
323
|
bottom: void 0,
|
|
321
324
|
width: void 0
|
|
322
|
-
}
|
|
325
|
+
},
|
|
326
|
+
onClick: () => setShowInspector(true)
|
|
323
327
|
},
|
|
324
328
|
/* @__PURE__ */ import_react3.default.createElement(
|
|
325
329
|
ToggleButton,
|
|
326
330
|
{
|
|
327
331
|
showInspector,
|
|
328
332
|
setShowInspector,
|
|
329
|
-
theme
|
|
333
|
+
theme,
|
|
334
|
+
anchor
|
|
330
335
|
}
|
|
331
336
|
)
|
|
332
337
|
);
|
|
@@ -352,7 +357,8 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
352
357
|
{
|
|
353
358
|
showInspector,
|
|
354
359
|
setShowInspector,
|
|
355
|
-
theme
|
|
360
|
+
theme,
|
|
361
|
+
anchor
|
|
356
362
|
}
|
|
357
363
|
)
|
|
358
364
|
},
|
|
@@ -391,18 +397,18 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
391
397
|
flexDirection: "column"
|
|
392
398
|
}
|
|
393
399
|
},
|
|
394
|
-
|
|
400
|
+
/* @__PURE__ */ import_react3.default.createElement(
|
|
395
401
|
"div",
|
|
396
402
|
{
|
|
397
|
-
id:
|
|
403
|
+
id: `${HISTORY_ELEMENT_PREFIX}0`,
|
|
398
404
|
style: {
|
|
399
|
-
borderBottom: `1px solid ${
|
|
405
|
+
borderBottom: `1px solid ${solidBorderColor}`,
|
|
400
406
|
fontSize: "12px",
|
|
401
407
|
fontFamily: "Menlo, monospace",
|
|
402
408
|
padding: "2px 12px 1px",
|
|
403
409
|
display: "flex",
|
|
404
410
|
alignItems: "center",
|
|
405
|
-
background: historySnapshot.historyIndex === 0 ?
|
|
411
|
+
background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
|
|
406
412
|
}
|
|
407
413
|
},
|
|
408
414
|
/* @__PURE__ */ import_react3.default.createElement(
|
|
@@ -418,15 +424,15 @@ var StateInspector = (0, import_react3.memo)(function StateInspector2({
|
|
|
418
424
|
"Initial state"
|
|
419
425
|
)
|
|
420
426
|
),
|
|
421
|
-
historySnapshot.history.
|
|
427
|
+
historySnapshot.history.map((entry, index) => /* @__PURE__ */ import_react3.default.createElement(
|
|
422
428
|
"div",
|
|
423
429
|
{
|
|
424
|
-
id:
|
|
430
|
+
id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
|
|
425
431
|
key: index,
|
|
426
432
|
style: {
|
|
427
433
|
padding: "0px 12px 1px",
|
|
428
|
-
borderBottom: `1px solid ${
|
|
429
|
-
background: index === historySnapshot.historyIndex
|
|
434
|
+
borderBottom: `1px solid ${solidBorderColor}`,
|
|
435
|
+
background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
|
|
430
436
|
}
|
|
431
437
|
},
|
|
432
438
|
entry.redoPatches?.map((patch, j) => /* @__PURE__ */ import_react3.default.createElement(
|
|
@@ -591,6 +597,7 @@ function Arrow({
|
|
|
591
597
|
display: "inline-block",
|
|
592
598
|
textAlign: "center",
|
|
593
599
|
transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
|
|
600
|
+
fontFamily: "Menlo, monospace",
|
|
594
601
|
...style
|
|
595
602
|
}
|
|
596
603
|
},
|
|
@@ -629,6 +636,7 @@ function useStateInspector({
|
|
|
629
636
|
connectionEvents,
|
|
630
637
|
disabled = false,
|
|
631
638
|
colorScheme,
|
|
639
|
+
anchor,
|
|
632
640
|
stateManager
|
|
633
641
|
}) {
|
|
634
642
|
const [root, setRoot] = import_react4.default.useState(null);
|
|
@@ -653,11 +661,12 @@ function useStateInspector({
|
|
|
653
661
|
state,
|
|
654
662
|
connectionEvents,
|
|
655
663
|
colorScheme,
|
|
664
|
+
anchor,
|
|
656
665
|
stateManager
|
|
657
666
|
}
|
|
658
667
|
)
|
|
659
668
|
);
|
|
660
|
-
}, [colorScheme, connectionEvents, root, state, stateManager]);
|
|
669
|
+
}, [anchor, colorScheme, connectionEvents, root, state, stateManager]);
|
|
661
670
|
}
|
|
662
671
|
|
|
663
672
|
// src/hooks.ts
|
|
@@ -762,7 +771,7 @@ function useMultiplayerState(initialState, options) {
|
|
|
762
771
|
state,
|
|
763
772
|
connectionEvents,
|
|
764
773
|
disabled: !options.inspector,
|
|
765
|
-
|
|
774
|
+
...typeof options.inspector === "object" && options.inspector
|
|
766
775
|
});
|
|
767
776
|
return [
|
|
768
777
|
state,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/hooks.ts","../src/globals.ts","../src/inspector/useStateInspector.tsx","../src/inspector/StateInspector.tsx","../src/inspector/useLocalStorageState.tsx"],"sourcesContent":["export * from \"@noya-app/state-manager\";\nexport * from \"./hooks\";\nexport * from \"./inspector/StateInspector\";\n","import {\n ActionHandler,\n ConnectionEvent,\n Get,\n MultiplayerPatchMetadata,\n MultiplayerStateManager,\n StateManager,\n StateManagerOptions,\n SyncAdapter,\n stubSync,\n} from \"@noya-app/state-manager\";\nimport {\n SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { trackEvents, useObservable } from \"./globals\";\nimport { useStateInspector } from \"./inspector/useStateInspector\";\n\nexport function useSyncStateManager<S extends object, M>(\n stateManager: StateManager<S, M>\n): S;\nexport function useSyncStateManager<S extends object, M, P extends string>(\n stateManager: StateManager<S, M>,\n path: P\n): Get<S, P, unknown>;\nexport function useSyncStateManager<S extends object, M>(\n stateManager: StateManager<S, M>,\n path?: string\n) {\n const getSnapshot = useCallback(\n () =>\n typeof path === \"string\"\n ? stateManager.getState(path)\n : stateManager.getState(),\n [stateManager, path]\n );\n\n return useSyncExternalStore(\n stateManager.addListener,\n getSnapshot,\n getSnapshot\n );\n}\n\nexport function useManagedState<S extends object, M = void>(\n createInitialState: () => S,\n options?: StateManagerOptions<S, M>\n) {\n const [stateManager] = useState(\n () => new StateManager<S, M>(createInitialState(), options)\n );\n\n const state = useSyncStateManager(stateManager);\n\n const setState = useCallback(\n (\n ...args: M extends {}\n ? [metadata: M, action: SetStateAction<S>]\n : [action: SetStateAction<S>]\n ) => {\n const [metadata, action] =\n args.length === 1 ? [undefined, args[0]] : args;\n\n if (metadata === undefined) {\n const performActionNoMetadata = stateManager.performAction as (\n handler: ActionHandler<S>\n ) => void;\n\n if (typeof action === \"function\") {\n performActionNoMetadata({\n run: action,\n undo: () => state,\n });\n } else {\n performActionNoMetadata({\n run: () => action,\n undo: () => state,\n });\n }\n } else {\n const performActionWithMetadata = stateManager.performAction as (\n metadata: M,\n handler: ActionHandler<S>\n ) => void;\n\n if (typeof action === \"function\") {\n performActionWithMetadata(metadata, {\n run: action,\n undo: () => state,\n });\n } else {\n performActionWithMetadata(metadata, {\n run: () => action,\n undo: () => state,\n });\n }\n }\n },\n [state, stateManager]\n );\n\n return [state, setState, stateManager] as const;\n}\n\nexport function useManagedHistory<S extends object, M = void>(\n stateManager: StateManager<S, M>\n) {\n return useSyncExternalStore(\n stateManager.historyEmittor.addListener,\n stateManager.getHistorySnapshot,\n stateManager.getHistorySnapshot\n );\n}\n\nexport function useSyncMultiplayerStateManager<S extends object>(\n multiplayerStateManager: MultiplayerStateManager<S>\n) {\n return useSyncExternalStore(\n multiplayerStateManager.addListener,\n multiplayerStateManager.getOptimisticState,\n multiplayerStateManager.getOptimisticState\n );\n}\n\nconst defaultStubSync = stubSync();\n\nexport function useMultiplayerState<S extends object>(\n initialState: S | (() => S),\n options: StateManagerOptions<S, MultiplayerPatchMetadata> & {\n sync?: (self: MultiplayerStateManager<S>) => void;\n trackConnectionEvents?: boolean;\n inspector?: boolean | { colorScheme?: \"dark\" | \"light\" };\n }\n) {\n const { sync = defaultStubSync as unknown as SyncAdapter<S>, ...rest } =\n options;\n\n const [multiplayerStateManager] = useState(\n () => new MultiplayerStateManager<S>(initialState, rest)\n );\n\n const syncRef = useRef(sync);\n\n const [connectionEvents, setConnectionEvents] = useState<\n ConnectionEvent<S>[] | undefined\n >();\n\n const extras = useMemo(() => {\n return {\n connectionEvents,\n };\n }, [connectionEvents]);\n\n const globalTrackEvents = useObservable(trackEvents);\n const trackConnectionEvents =\n options.trackConnectionEvents ?? globalTrackEvents;\n\n const trackEventsCallbackRef = useRef<\n ((e: ConnectionEvent<S>) => void) | undefined\n >();\n\n useEffect(() => {\n trackEventsCallbackRef.current = trackConnectionEvents\n ? (e) =>\n setConnectionEvents((events) => {\n const updated = events ? [...events, e] : [e];\n return updated.length > 50 ? updated.slice(-50) : updated;\n })\n : undefined;\n }, [trackConnectionEvents]);\n\n useEffect(() => {\n if (syncRef.current) {\n return syncRef.current(multiplayerStateManager, (e) =>\n trackEventsCallbackRef.current?.(e)\n );\n }\n }, [multiplayerStateManager]);\n\n const state = useSyncMultiplayerStateManager(multiplayerStateManager);\n\n useStateInspector({\n stateManager: multiplayerStateManager.sm,\n state,\n connectionEvents,\n disabled: !options.inspector,\n colorScheme:\n typeof options.inspector === \"object\"\n ? options.inspector.colorScheme\n : undefined,\n });\n\n return [\n state,\n multiplayerStateManager.setOptimisticState,\n multiplayerStateManager,\n extras,\n ] as const;\n}\n","import { Emitter } from \"@noya-app/emitter\";\nimport { useEffect, useState } from \"react\";\n\nclass Observable<T> {\n private value: T;\n private emitter = new Emitter<[T]>();\n\n constructor(value: T) {\n this.value = value;\n }\n\n get() {\n return this.value;\n }\n\n set(value: T) {\n if (this.value === value) return;\n\n this.value = value;\n\n this.emitter.emit(value);\n }\n\n listen(callback: (value: T) => void) {\n callback(this.value);\n\n return this.emitter.addListener(callback);\n }\n}\n\nexport function useObservable<T>(observable: Observable<T>) {\n const [value, setValue] = useState(observable.get());\n\n useEffect(() => {\n return observable.listen(setValue);\n }, [observable]);\n\n return value;\n}\n\nexport const trackEvents = new Observable(false);\n","import { ConnectionEvent, StateManager } from \"@noya-app/state-manager\";\nimport React, { ComponentProps, useLayoutEffect } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nimport { Root } from \"react-dom/client\";\nimport { StateInspector } from \"./StateInspector\";\n\nfunction createPortalElement() {\n const el = document.createElement(\"div\");\n el.id = \"noya-multiplayer-react-inspector-portal\";\n return el;\n}\n\nexport function useStateInspector<S extends object, M>({\n state,\n connectionEvents,\n disabled = false,\n colorScheme,\n stateManager,\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n disabled: boolean;\n colorScheme: ComponentProps<typeof StateInspector>[\"colorScheme\"];\n stateManager: StateManager<S, M>;\n}) {\n const [root, setRoot] = React.useState<Root | null>(null);\n\n useLayoutEffect(() => {\n if (disabled) return;\n\n const portalElement = createPortalElement();\n\n const root = createRoot(portalElement);\n\n document.body.appendChild(portalElement);\n\n setRoot(root);\n\n return () => {\n document.body.removeChild(portalElement);\n };\n }, [disabled]);\n\n useLayoutEffect(() => {\n if (!root) return;\n\n root.render(\n <StateInspector\n state={state}\n connectionEvents={connectionEvents}\n colorScheme={colorScheme}\n stateManager={stateManager as StateManager<any, any>}\n />\n );\n }, [colorScheme, connectionEvents, root, state, stateManager]);\n}\n","import {\n ConnectionEvent,\n ExtendedPathKey,\n StateManager,\n} from \"@noya-app/state-manager\";\nimport React, {\n CSSProperties,\n ComponentPropsWithoutRef,\n FC,\n memo,\n useEffect,\n useLayoutEffect,\n} from \"react\";\nimport {\n ObjectInspector,\n ObjectLabel,\n ObjectName,\n ObjectPreview,\n chromeDark,\n chromeLight,\n} from \"react-inspector\";\nimport { trackEvents } from \"../globals\";\nimport { useManagedHistory } from \"../hooks\";\nimport { useLocalStorageState } from \"./useLocalStorageState\";\n\nconst lightTheme = {\n ...chromeLight,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(0,0,0,0.7)\",\n} as any;\n\nconst darkTheme = {\n ...chromeDark,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(255,255,255,0.7)\",\n} as any;\n\nfunction ToggleButton({\n showInspector,\n setShowInspector,\n theme,\n}: {\n showInspector: boolean;\n setShowInspector: (value: boolean) => void;\n theme: typeof chromeLight;\n}) {\n return (\n <span\n role=\"button\"\n style={{\n flex: \"0\",\n appearance: \"none\",\n color: theme.BASE_COLOR,\n background: \"rgba(0,0,0,0.1)\",\n border: \"none\",\n fontSize: \"12px\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2px 0\",\n }}\n onClick={() => setShowInspector(!showInspector)}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n {showInspector ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\"\n />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\"\n />\n </svg>\n )}\n </span>\n </span>\n );\n}\n\nfunction DisclosureSection({\n open,\n setOpen,\n title,\n right,\n children,\n colorScheme,\n isFirst,\n}: {\n open: boolean;\n setOpen?: (value: boolean) => void;\n title: string;\n right?: React.ReactNode;\n children: React.ReactNode;\n colorScheme: \"light\" | \"dark\";\n isFirst?: boolean;\n}) {\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n\n const borderColor =\n colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n\n return (\n <div\n style={{\n flex: open ? \"1 1 0\" : \"0\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div\n onClick={() => setOpen?.(!open)}\n style={{\n cursor: \"default\",\n fontSize: \"12px\",\n padding: \"4px 10px\",\n display: \"flex\",\n ...(!isFirst && { borderTop: `1px solid ${borderColor}` }),\n ...(open && { borderBottom: `1px solid ${borderColor}` }),\n }}\n >\n {setOpen && (\n <Arrow\n expanded={open}\n style={{\n fontSize: \"11px\",\n // fontSize: theme.ARROW_FONT_SIZE,\n marginRight: theme.ARROW_MARGIN_RIGHT,\n color: theme.ARROW_COLOR,\n }}\n />\n )}\n <span style={{ flex: \"1 1 0\" }}>{title}</span>\n {right}\n </div>\n {open && children}\n </div>\n );\n}\n\nexport const StateInspector = memo(function StateInspector<\n S extends object,\n M,\n>({\n state,\n connectionEvents,\n unstyled,\n colorScheme = \"light\",\n stateManager,\n ...props\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n unstyled?: boolean;\n colorScheme?: \"light\" | \"dark\";\n stateManager: StateManager<S, M>;\n} & ComponentPropsWithoutRef<\"div\">) {\n const [didMount, setDidMount] = React.useState(false);\n\n useLayoutEffect(() => {\n setDidMount(true);\n }, []);\n\n const eventsContainerRef = React.useRef<HTMLDivElement>(null);\n const historyContainerRef = React.useRef<HTMLDivElement>(null);\n\n const [showInspector, setShowInspector] = useLocalStorageState(\n \"noya-multiplayer-react-show-inspector\",\n true\n );\n const [showEvents, setShowEvents] = useLocalStorageState(\n \"noya-multiplayer-react-show-events\",\n false\n );\n const [showHistory, setShowHistory] = useLocalStorageState(\n \"noya-multiplayer-react-show-history\",\n false\n );\n\n useEffect(() => {\n trackEvents.set(showEvents);\n }, [showEvents]);\n\n useEffect(() => {\n if (eventsContainerRef.current) {\n eventsContainerRef.current.scrollTop =\n eventsContainerRef.current.scrollHeight;\n }\n }, [connectionEvents]);\n\n const historySnapshot = useManagedHistory(stateManager);\n\n useEffect(() => {\n if (historyContainerRef.current) {\n historyContainerRef.current.scrollTop =\n historyContainerRef.current.scrollHeight;\n }\n }, [historySnapshot]);\n\n // If history index changes, scroll to the new history entry into view\n useEffect(() => {\n if (!historyContainerRef.current) return;\n\n const historyEntry = historyContainerRef.current.querySelector(\n `#history-${historySnapshot.historyIndex - 1}`\n );\n\n if (historyEntry) {\n historyEntry.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n }\n }, [historySnapshot.historyIndex]);\n\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n const borderColor =\n colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n\n const baseStyle: CSSProperties = {\n position: \"fixed\",\n top: 12,\n right: 12,\n bottom: 12,\n width: 400,\n background:\n colorScheme === \"light\" ? \"rgba(255,255,255,0.95)\" : \"rgba(0,0,0,0.95)\",\n backdropFilter: \"blur(48px)\",\n border: `1px solid ${borderColor}`,\n // outlineOffset: -1,\n borderRadius: 4,\n display: \"flex\",\n flexDirection: \"column\",\n // gap: 12,\n color: theme.BASE_COLOR,\n overflow: \"hidden\",\n zIndex: 9999,\n };\n\n if (!didMount) return null;\n\n if (!showInspector) {\n return (\n <div\n {...props}\n style={{\n ...baseStyle,\n padding: \"4px 10px\",\n borderRadius: 8,\n bottom: undefined,\n width: undefined,\n }}\n >\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n />\n </div>\n );\n }\n\n return (\n <div\n {...props}\n style={{\n ...(!unstyled && baseStyle),\n ...props.style,\n }}\n >\n {/* <div style={{ flex: \"0\", fontSize: \"12px\" }}>User ID: {userId}</div> */}\n <DisclosureSection\n open\n title=\"Data\"\n colorScheme={colorScheme}\n isFirst\n right={\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n />\n }\n >\n <div\n style={{\n flex: \"1 1 0\",\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"1px\",\n padding: \"1px 12px\",\n }}\n >\n <ObjectInspector data={state} theme={theme} />\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showHistory}\n setOpen={setShowHistory}\n title=\"History\"\n colorScheme={colorScheme}\n >\n <div\n ref={historyContainerRef}\n style={{\n flex: \"1 1 0\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {historySnapshot.history.length < 50 && (\n <div\n id={`history-${0}`}\n style={{\n borderBottom: `1px solid ${borderColor}`,\n fontSize: \"12px\",\n fontFamily: \"Menlo, monospace\",\n padding: \"2px 12px 1px\",\n display: \"flex\",\n alignItems: \"center\",\n background:\n historySnapshot.historyIndex === 0\n ? colorScheme === \"light\"\n ? \"rgba(0,0,0,0.2)\"\n : \"rgb(59 130 246 / 38%)\"\n : undefined,\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n Initial state\n </span>\n </div>\n )}\n {historySnapshot.history.slice(-50).map((entry, index) => (\n <div\n id={`history-${index}`}\n key={index}\n style={{\n padding: \"0px 12px 1px\",\n borderBottom: `1px solid ${borderColor}`,\n background:\n index === historySnapshot.historyIndex - 1\n ? colorScheme === \"light\"\n ? \"rgba(0,0,0,0.2)\"\n : \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n {entry.redoPatches?.map((patch, j) => (\n <pre\n key={j}\n style={{\n fontSize: \"11px\",\n display: \"flex\",\n flexWrap: \"wrap\",\n }}\n >\n {patch.op === \"add\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"replace\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"remove\" && (\n <>\n <span style={{ color: theme.OBJECT_VALUE_STRING_COLOR }}>\n delete{\" \"}\n </span>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n </>\n )}\n </pre>\n ))}\n </div>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showEvents}\n setOpen={setShowEvents}\n title=\"Events\"\n colorScheme={colorScheme}\n >\n <div\n ref={eventsContainerRef}\n style={{\n flex: \"1 1 0\",\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {connectionEvents?.map((event, index) => (\n <div\n key={index}\n style={{\n borderBottom: `1px solid ${borderColor}`,\n }}\n >\n {event.type === \"stateChange\" ? (\n <div\n style={{\n padding: \"2px 12px\",\n background:\n colorScheme === \"light\"\n ? \"rgba(0,0,0,0.05)\"\n : \"rgba(255,255,255,0.05)\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n connection:{\" \"}\n <span style={{ fontStyle: \"italic\" }}>\n {event.state.toLowerCase()}\n </span>\n </span>\n </div>\n ) : (\n <div\n style={{\n padding: \"0px 12px 1px\",\n background:\n event.type === \"send\"\n ? \"rgba(0,255,0,0.1)\"\n : \"rgba(255,0,0,0.1)\",\n }}\n >\n <ObjectInspector\n data={event.message}\n theme={theme}\n nodeRenderer={({\n depth,\n name,\n data,\n isNonenumerable,\n expanded,\n }: any) => {\n const direction = event.type === \"send\" ? \"up\" : \"down\";\n\n return depth === 0 ? (\n <ObjectRootLabel direction={direction} data={data} />\n ) : (\n <ObjectLabel\n direction={direction}\n name={name}\n data={data}\n isNonenumerable={isNonenumerable}\n />\n );\n }}\n />\n </div>\n )}\n </div>\n ))}\n {!connectionEvents && (\n <div\n style={{\n padding: \"12px\",\n fontSize: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n }}\n >\n <span>No recorded events</span>\n </div>\n )}\n </div>\n </DisclosureSection>\n </div>\n );\n});\n\ntype MessageDirection = \"up\" | \"down\";\n\nconst ObjectRootLabel: FC<{\n name?: string;\n data: any;\n direction?: MessageDirection;\n}> = ({ name, data, direction }) => {\n if (typeof name === \"string\") {\n return (\n <span>\n <ObjectName name={name} />\n <span>: </span>\n <ObjectPreview data={data} />\n </span>\n );\n }\n if (direction === \"up\" || direction === \"down\") {\n const arrow = direction === \"up\" ? \"↑\" : \"↓\";\n\n return (\n <span>\n <span\n style={{\n background:\n direction === \"up\" ? \"rgba(0,255,0,0.2)\" : \"rgba(255,0,0,0.2)\",\n // color: \"white\",\n width: 12,\n height: 12,\n borderRadius: 2,\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n marginRight: 4,\n lineHeight: \"12px\",\n }}\n >\n {arrow}\n </span>\n <ObjectPreview data={data} />\n </span>\n );\n } else {\n return <ObjectPreview data={data} />;\n }\n};\n\n// Rotates ▶️ or ▼ based on expanded state\nfunction Arrow({\n expanded,\n onClick,\n style,\n}: {\n expanded: boolean;\n onClick?: () => void;\n style?: CSSProperties;\n}) {\n return (\n <span\n role=\"button\"\n onClick={onClick}\n style={{\n display: \"inline-block\",\n textAlign: \"center\",\n transform: expanded ? \"rotate(0deg)\" : \"rotate(-90deg)\",\n ...style,\n }}\n >\n {\"▼\"}\n </span>\n );\n}\n\n// <div className=\"flex py-px flex-col-reverse\">\n// <button\n// type=\"button\"\n// className={cx(\n// \"px-4 py-2 cursor-pointer text-left\",\n// 0 === historySnapshot.historyIndex && \"bg-orange-500/25\"\n// )}\n// onClick={() => {\n// // stateManager.goToHistoryIndex(0);\n// }}\n// >\n// <div className=\"flex justify-between gap-2\">\n// <span>Initial State</span>\n// </div>\n// </button>\n// {historySnapshot.history.map((entry, index) => (\n// <button\n// key={index}\n// type=\"button\"\n// className={cx(\n// \"px-4 py-2 cursor-pointer text-left\",\n// index === historySnapshot.historyIndex - 1 &&\n// \"bg-orange-500/25\"\n// )}\n// onClick={() => {\n// // stateManager.goToHistoryIndex(index + 1);\n// }}\n// >\n// <div className=\"flex justify-between gap-2\">\n// <span>\n// {index + 1}. {entry.metadata.name}\n// </span>\n// <span>\n// {new Date(\n// entry.metadata.timestamp\n// ).toLocaleTimeString()}\n// </span>\n// </div>\n// <div className=\"font-mono text-xs\">\n// {entry.redoPatches?.map((patch, index) => (\n// <pre key={index} className=\"max-w-full\">\n// {patch.op === \"remove\"\n// ? `Delete ${pathToString(patch.path)}`\n// : `${pathToString(patch.path)} = ${JSON.stringify(\n// patch.value,\n// null,\n// 2\n// )}`}\n// </pre>\n// ))}\n// </div>\n// </button>\n// ))}\n// </div>\n\nfunction pathToString(extendedPath: ExtendedPathKey[]) {\n return extendedPath\n .map((key) =>\n typeof key === \"object\"\n ? `:${ellipsis(key.id.toString(), 8, \"middle\")}`\n : key\n )\n .map((key, index) =>\n index === 0 || (typeof key === \"string\" && key.startsWith(\":\"))\n ? key\n : `.${key}`\n )\n .join(\"\");\n}\n\ntype EllipsisPosition = \"start\" | \"middle\" | \"end\";\n\nfunction ellipsis(\n str: string,\n maxLength: number,\n position: EllipsisPosition = \"end\"\n) {\n if (str.length <= maxLength) return str;\n\n switch (position) {\n case \"start\":\n return `…${str.slice(str.length - maxLength)}`;\n case \"middle\":\n const halfLength = Math.floor(maxLength / 2);\n return `${str.slice(0, halfLength)}…${str.slice(str.length - halfLength)}`;\n case \"end\":\n return `${str.slice(0, maxLength)}…`;\n }\n}\n","import React from \"react\";\n\nconst localStorage = typeof window !== \"undefined\" ? window.localStorage : null;\n\nexport function useLocalStorageState<S>(\n key: string,\n defaultValue: S\n): [S, (value: S) => void] {\n const [state, setState] = React.useState<S>(() => {\n const value = localStorage?.getItem(key);\n let result = defaultValue;\n if (value) {\n try {\n result = JSON.parse(value);\n } catch (error) {\n console.error(\"Error parsing localStorage value\", error);\n }\n }\n return result;\n });\n\n const setLocalStorageState = (value: S) => {\n localStorage?.setItem(key, JSON.stringify(value));\n setState(value);\n };\n\n return [state, setLocalStorageState];\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","React","React","StateInspector","React","root"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/hooks.ts","../src/globals.ts","../src/inspector/useStateInspector.tsx","../src/inspector/StateInspector.tsx","../src/inspector/useLocalStorageState.tsx"],"sourcesContent":["export * from \"@noya-app/state-manager\";\nexport * from \"./hooks\";\nexport * from \"./inspector/StateInspector\";\n","import {\n ActionHandler,\n ConnectionEvent,\n Get,\n MultiplayerStateManager,\n MultiplayerStateManagerOptions,\n StateManager,\n StateManagerOptions,\n SyncAdapter,\n stubSync,\n} from \"@noya-app/state-manager\";\nimport {\n ComponentProps,\n SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { trackEvents, useObservable } from \"./globals\";\nimport { StateInspector } from \"./inspector/StateInspector\";\nimport { useStateInspector } from \"./inspector/useStateInspector\";\n\nexport function useSyncStateManager<S extends object, M>(\n stateManager: StateManager<S, M>\n): S;\nexport function useSyncStateManager<S extends object, M, P extends string>(\n stateManager: StateManager<S, M>,\n path: P\n): Get<S, P, unknown>;\nexport function useSyncStateManager<S extends object, M>(\n stateManager: StateManager<S, M>,\n path?: string\n) {\n const getSnapshot = useCallback(\n () =>\n typeof path === \"string\"\n ? stateManager.getState(path)\n : stateManager.getState(),\n [stateManager, path]\n );\n\n return useSyncExternalStore(\n stateManager.addListener,\n getSnapshot,\n getSnapshot\n );\n}\n\nexport function useManagedState<S extends object, M = void>(\n createInitialState: () => S,\n options?: StateManagerOptions<S, M>\n) {\n const [stateManager] = useState(\n () => new StateManager<S, M>(createInitialState(), options)\n );\n\n const state = useSyncStateManager(stateManager);\n\n const setState = useCallback(\n (\n ...args: M extends {}\n ? [metadata: M, action: SetStateAction<S>]\n : [action: SetStateAction<S>]\n ) => {\n const [metadata, action] =\n args.length === 1 ? [undefined, args[0]] : args;\n\n if (metadata === undefined) {\n const performActionNoMetadata = stateManager.performAction as (\n handler: ActionHandler<S>\n ) => void;\n\n if (typeof action === \"function\") {\n performActionNoMetadata({\n run: action,\n undo: () => state,\n });\n } else {\n performActionNoMetadata({\n run: () => action,\n undo: () => state,\n });\n }\n } else {\n const performActionWithMetadata = stateManager.performAction as (\n metadata: M,\n handler: ActionHandler<S>\n ) => void;\n\n if (typeof action === \"function\") {\n performActionWithMetadata(metadata, {\n run: action,\n undo: () => state,\n });\n } else {\n performActionWithMetadata(metadata, {\n run: () => action,\n undo: () => state,\n });\n }\n }\n },\n [state, stateManager]\n );\n\n return [state, setState, stateManager] as const;\n}\n\nexport function useManagedHistory<S extends object, M = void>(\n stateManager: StateManager<S, M>\n) {\n return useSyncExternalStore(\n stateManager.historyEmittor.addListener,\n stateManager.getHistorySnapshot,\n stateManager.getHistorySnapshot\n );\n}\n\nexport function useSyncMultiplayerStateManager<S extends object, M = void>(\n multiplayerStateManager: MultiplayerStateManager<S, M>\n) {\n return useSyncExternalStore(\n multiplayerStateManager.addListener,\n multiplayerStateManager.getOptimisticState,\n multiplayerStateManager.getOptimisticState\n );\n}\n\nconst defaultStubSync = stubSync();\n\nexport function useMultiplayerState<S extends object, M = void>(\n initialState: S | (() => S),\n options: MultiplayerStateManagerOptions<S, M> & {\n sync?: (self: MultiplayerStateManager<S, M>) => void;\n trackConnectionEvents?: boolean;\n inspector?:\n | boolean\n | Pick<ComponentProps<typeof StateInspector>, \"colorScheme\" | \"anchor\">;\n }\n) {\n const { sync = defaultStubSync as unknown as SyncAdapter<S, M>, ...rest } =\n options;\n\n const [multiplayerStateManager] = useState(\n () => new MultiplayerStateManager<S, M>(initialState, rest)\n );\n\n const syncRef = useRef(sync);\n\n const [connectionEvents, setConnectionEvents] = useState<\n ConnectionEvent<S>[] | undefined\n >();\n\n const extras = useMemo(() => {\n return {\n connectionEvents,\n };\n }, [connectionEvents]);\n\n const globalTrackEvents = useObservable(trackEvents);\n const trackConnectionEvents =\n options.trackConnectionEvents ?? globalTrackEvents;\n\n const trackEventsCallbackRef = useRef<\n ((e: ConnectionEvent<S>) => void) | undefined\n >();\n\n useEffect(() => {\n trackEventsCallbackRef.current = trackConnectionEvents\n ? (e) =>\n setConnectionEvents((events) => {\n const updated = events ? [...events, e] : [e];\n return updated.length > 50 ? updated.slice(-50) : updated;\n })\n : undefined;\n }, [trackConnectionEvents]);\n\n useEffect(() => {\n if (syncRef.current) {\n return syncRef.current(multiplayerStateManager, (e) =>\n trackEventsCallbackRef.current?.(e)\n );\n }\n }, [multiplayerStateManager]);\n\n const state = useSyncMultiplayerStateManager(multiplayerStateManager);\n\n useStateInspector({\n stateManager: multiplayerStateManager.sm,\n state,\n connectionEvents,\n disabled: !options.inspector,\n ...(typeof options.inspector === \"object\" && options.inspector),\n });\n\n return [\n state,\n multiplayerStateManager.setOptimisticState,\n multiplayerStateManager,\n extras,\n ] as const;\n}\n","import { Emitter } from \"@noya-app/emitter\";\nimport { useEffect, useState } from \"react\";\n\nclass Observable<T> {\n private value: T;\n private emitter = new Emitter<[T]>();\n\n constructor(value: T) {\n this.value = value;\n }\n\n get() {\n return this.value;\n }\n\n set(value: T) {\n if (this.value === value) return;\n\n this.value = value;\n\n this.emitter.emit(value);\n }\n\n listen(callback: (value: T) => void) {\n callback(this.value);\n\n return this.emitter.addListener(callback);\n }\n}\n\nexport function useObservable<T>(observable: Observable<T>) {\n const [value, setValue] = useState(observable.get());\n\n useEffect(() => {\n return observable.listen(setValue);\n }, [observable]);\n\n return value;\n}\n\nexport const trackEvents = new Observable(false);\n","import { ConnectionEvent, StateManager } from \"@noya-app/state-manager\";\nimport React, { ComponentProps, useLayoutEffect } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nimport { Root } from \"react-dom/client\";\nimport { StateInspector } from \"./StateInspector\";\n\nfunction createPortalElement() {\n const el = document.createElement(\"div\");\n el.id = \"noya-multiplayer-react-inspector-portal\";\n return el;\n}\n\nexport function useStateInspector<S extends object, M>({\n state,\n connectionEvents,\n disabled = false,\n colorScheme,\n anchor,\n stateManager,\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n disabled: boolean;\n stateManager: StateManager<S, M>;\n} & Pick<ComponentProps<typeof StateInspector>, \"colorScheme\" | \"anchor\">) {\n const [root, setRoot] = React.useState<Root | null>(null);\n\n useLayoutEffect(() => {\n if (disabled) return;\n\n const portalElement = createPortalElement();\n\n const root = createRoot(portalElement);\n\n document.body.appendChild(portalElement);\n\n setRoot(root);\n\n return () => {\n document.body.removeChild(portalElement);\n };\n }, [disabled]);\n\n useLayoutEffect(() => {\n if (!root) return;\n\n root.render(\n <StateInspector\n state={state}\n connectionEvents={connectionEvents}\n colorScheme={colorScheme}\n anchor={anchor}\n stateManager={stateManager as StateManager<any, any>}\n />\n );\n }, [anchor, colorScheme, connectionEvents, root, state, stateManager]);\n}\n","import {\n ConnectionEvent,\n ExtendedPathKey,\n StateManager,\n} from \"@noya-app/state-manager\";\nimport React, {\n CSSProperties,\n ComponentPropsWithoutRef,\n FC,\n memo,\n useEffect,\n useLayoutEffect,\n} from \"react\";\nimport {\n ObjectInspector,\n ObjectLabel,\n ObjectName,\n ObjectPreview,\n chromeDark,\n chromeLight,\n} from \"react-inspector\";\nimport { trackEvents } from \"../globals\";\nimport { useManagedHistory } from \"../hooks\";\nimport { useLocalStorageState } from \"./useLocalStorageState\";\n\nconst lightTheme = {\n ...chromeLight,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(0,0,0,0.7)\",\n} as any;\n\nconst darkTheme = {\n ...chromeDark,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(255,255,255,0.7)\",\n} as any;\n\nfunction ToggleButton({\n showInspector,\n setShowInspector,\n theme,\n anchor,\n}: {\n showInspector: boolean;\n setShowInspector: (value: boolean) => void;\n theme: typeof chromeLight;\n anchor: Anchor;\n}) {\n return (\n <span\n role=\"button\"\n style={{\n flex: \"0\",\n appearance: \"none\",\n color: theme.BASE_COLOR,\n border: \"none\",\n fontSize: \"12px\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2px 0\",\n }}\n onClick={() => setShowInspector(!showInspector)}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n {showInspector === (anchor === \"right\") ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\"\n />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\"\n />\n </svg>\n )}\n </span>\n </span>\n );\n}\n\nfunction DisclosureSection({\n open,\n setOpen,\n title,\n right,\n children,\n colorScheme,\n isFirst,\n}: {\n open: boolean;\n setOpen?: (value: boolean) => void;\n title: string;\n right?: React.ReactNode;\n children: React.ReactNode;\n colorScheme: \"light\" | \"dark\";\n isFirst?: boolean;\n}) {\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n\n const borderColor =\n colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n\n return (\n <div\n style={{\n flex: open ? \"1 1 0\" : \"0\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div\n onClick={() => setOpen?.(!open)}\n style={{\n cursor: \"default\",\n fontSize: \"12px\",\n padding: \"4px 10px\",\n display: \"flex\",\n alignItems: \"center\",\n ...(!isFirst && { borderTop: `1px solid ${borderColor}` }),\n ...(open && { borderBottom: `1px solid ${borderColor}` }),\n }}\n >\n {setOpen && (\n <Arrow\n expanded={open}\n style={{\n fontSize: theme.ARROW_FONT_SIZE,\n marginRight: theme.ARROW_MARGIN_RIGHT + 1,\n color: theme.ARROW_COLOR,\n }}\n />\n )}\n <span style={{ flex: \"1 1 0\" }}>{title}</span>\n {right}\n </div>\n {open && children}\n </div>\n );\n}\n\nconst HISTORY_ELEMENT_PREFIX = \"noya-multiplayer-history-\";\n\ntype Anchor = \"left\" | \"right\";\n\nexport const StateInspector = memo(function StateInspector<\n S extends object,\n M,\n>({\n state,\n connectionEvents,\n unstyled,\n colorScheme = \"light\",\n stateManager,\n anchor = \"right\",\n ...props\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n unstyled?: boolean;\n colorScheme?: \"light\" | \"dark\";\n stateManager: StateManager<S, M>;\n anchor?: Anchor;\n} & ComponentPropsWithoutRef<\"div\">) {\n const [didMount, setDidMount] = React.useState(false);\n\n useLayoutEffect(() => {\n setDidMount(true);\n }, []);\n\n const eventsContainerRef = React.useRef<HTMLDivElement>(null);\n const historyContainerRef = React.useRef<HTMLDivElement>(null);\n\n const [showInspector, setShowInspector] = useLocalStorageState(\n \"noya-multiplayer-react-show-inspector\",\n true\n );\n const [showEvents, setShowEvents] = useLocalStorageState(\n \"noya-multiplayer-react-show-events\",\n false\n );\n const [showHistory, setShowHistory] = useLocalStorageState(\n \"noya-multiplayer-react-show-history\",\n false\n );\n\n useEffect(() => {\n trackEvents.set(showEvents);\n }, [showEvents]);\n\n useEffect(() => {\n if (eventsContainerRef.current) {\n eventsContainerRef.current.scrollTop =\n eventsContainerRef.current.scrollHeight;\n }\n }, [connectionEvents]);\n\n const historySnapshot = useManagedHistory(stateManager);\n\n useEffect(() => {\n if (historyContainerRef.current) {\n historyContainerRef.current.scrollTop =\n historyContainerRef.current.scrollHeight;\n }\n }, [historySnapshot]);\n\n // If history index changes, scroll to the new history entry into view\n useEffect(() => {\n if (!historyContainerRef.current) return;\n\n const historyEntry = historyContainerRef.current.querySelector(\n `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`\n );\n\n if (historyEntry) {\n historyEntry.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n }\n }, [historySnapshot.historyIndex]);\n\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n const borderColor =\n colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n const solidBorderColor =\n colorScheme === \"light\" ? \"rgb(223 223 223)\" : \"rgb(29 29 29)\";\n\n const baseStyle: CSSProperties = {\n position: \"fixed\",\n top: 12,\n ...(anchor === \"right\" ? { right: 12 } : { left: 12 }),\n bottom: 12,\n width: 400,\n background:\n colorScheme === \"light\" ? \"rgba(255,255,255,0.95)\" : \"rgba(0,0,0,0.95)\",\n backdropFilter: \"blur(48px)\",\n border: `1px solid ${solidBorderColor}`,\n // outlineOffset: -1,\n borderRadius: 4,\n display: \"flex\",\n flexDirection: \"column\",\n // gap: 12,\n color: theme.BASE_COLOR,\n overflow: \"hidden\",\n zIndex: 9999,\n lineHeight: \"13px\",\n };\n\n if (!didMount) return null;\n\n if (!showInspector) {\n return (\n <div\n {...props}\n style={{\n ...baseStyle,\n padding: \"4px 10px\",\n bottom: undefined,\n width: undefined,\n }}\n onClick={() => setShowInspector(true)}\n >\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n anchor={anchor}\n />\n </div>\n );\n }\n\n return (\n <div\n {...props}\n style={{\n ...(!unstyled && baseStyle),\n ...props.style,\n }}\n >\n {/* <div style={{ flex: \"0\", fontSize: \"12px\" }}>User ID: {userId}</div> */}\n <DisclosureSection\n open\n title=\"Data\"\n colorScheme={colorScheme}\n isFirst\n right={\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n anchor={anchor}\n />\n }\n >\n <div\n style={{\n flex: \"1 1 0\",\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"1px\",\n padding: \"1px 12px\",\n }}\n >\n <ObjectInspector data={state} theme={theme} />\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showHistory}\n setOpen={setShowHistory}\n title=\"History\"\n colorScheme={colorScheme}\n >\n <div\n ref={historyContainerRef}\n style={{\n flex: \"1 1 0\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div\n id={`${HISTORY_ELEMENT_PREFIX}0`}\n style={{\n borderBottom: `1px solid ${solidBorderColor}`,\n fontSize: \"12px\",\n fontFamily: \"Menlo, monospace\",\n padding: \"2px 12px 1px\",\n display: \"flex\",\n alignItems: \"center\",\n background:\n historySnapshot.historyIndex === 0\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n Initial state\n </span>\n </div>\n {historySnapshot.history.map((entry, index) => (\n <div\n id={`${HISTORY_ELEMENT_PREFIX}${index + 1}`}\n key={index}\n style={{\n padding: \"0px 12px 1px\",\n borderBottom: `1px solid ${solidBorderColor}`,\n background:\n index + 1 === historySnapshot.historyIndex\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n {entry.redoPatches?.map((patch, j) => (\n <pre\n key={j}\n style={{\n fontSize: \"11px\",\n display: \"flex\",\n flexWrap: \"wrap\",\n }}\n >\n {patch.op === \"add\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"replace\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"remove\" && (\n <>\n <span style={{ color: theme.OBJECT_VALUE_STRING_COLOR }}>\n delete{\" \"}\n </span>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n </>\n )}\n </pre>\n ))}\n </div>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showEvents}\n setOpen={setShowEvents}\n title=\"Events\"\n colorScheme={colorScheme}\n >\n <div\n ref={eventsContainerRef}\n style={{\n flex: \"1 1 0\",\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {connectionEvents?.map((event, index) => (\n <div\n key={index}\n style={{\n borderBottom: `1px solid ${borderColor}`,\n }}\n >\n {event.type === \"stateChange\" ? (\n <div\n style={{\n padding: \"2px 12px\",\n background:\n colorScheme === \"light\"\n ? \"rgba(0,0,0,0.05)\"\n : \"rgba(255,255,255,0.05)\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n connection:{\" \"}\n <span style={{ fontStyle: \"italic\" }}>\n {event.state.toLowerCase()}\n </span>\n </span>\n </div>\n ) : (\n <div\n style={{\n padding: \"0px 12px 1px\",\n background:\n event.type === \"send\"\n ? \"rgba(0,255,0,0.1)\"\n : \"rgba(255,0,0,0.1)\",\n }}\n >\n <ObjectInspector\n data={event.message}\n theme={theme}\n nodeRenderer={({\n depth,\n name,\n data,\n isNonenumerable,\n expanded,\n }: any) => {\n const direction = event.type === \"send\" ? \"up\" : \"down\";\n\n return depth === 0 ? (\n <ObjectRootLabel direction={direction} data={data} />\n ) : (\n <ObjectLabel\n direction={direction}\n name={name}\n data={data}\n isNonenumerable={isNonenumerable}\n />\n );\n }}\n />\n </div>\n )}\n </div>\n ))}\n {!connectionEvents && (\n <div\n style={{\n padding: \"12px\",\n fontSize: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n }}\n >\n <span>No recorded events</span>\n </div>\n )}\n </div>\n </DisclosureSection>\n </div>\n );\n});\n\ntype MessageDirection = \"up\" | \"down\";\n\nconst ObjectRootLabel: FC<{\n name?: string;\n data: any;\n direction?: MessageDirection;\n}> = ({ name, data, direction }) => {\n if (typeof name === \"string\") {\n return (\n <span>\n <ObjectName name={name} />\n <span>: </span>\n <ObjectPreview data={data} />\n </span>\n );\n }\n if (direction === \"up\" || direction === \"down\") {\n const arrow = direction === \"up\" ? \"↑\" : \"↓\";\n\n return (\n <span>\n <span\n style={{\n background:\n direction === \"up\" ? \"rgba(0,255,0,0.2)\" : \"rgba(255,0,0,0.2)\",\n // color: \"white\",\n width: 12,\n height: 12,\n borderRadius: 2,\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n marginRight: 4,\n lineHeight: \"12px\",\n }}\n >\n {arrow}\n </span>\n <ObjectPreview data={data} />\n </span>\n );\n } else {\n return <ObjectPreview data={data} />;\n }\n};\n\n// Rotates ▶️ or ▼ based on expanded state\nfunction Arrow({\n expanded,\n onClick,\n style,\n}: {\n expanded: boolean;\n onClick?: () => void;\n style?: CSSProperties;\n}) {\n return (\n <span\n role=\"button\"\n onClick={onClick}\n style={{\n display: \"inline-block\",\n textAlign: \"center\",\n transform: expanded ? \"rotate(0deg)\" : \"rotate(-90deg)\",\n fontFamily: \"Menlo, monospace\",\n ...style,\n }}\n >\n {\"▼\"}\n </span>\n );\n}\n\n// <div className=\"flex py-px flex-col-reverse\">\n// <button\n// type=\"button\"\n// className={cx(\n// \"px-4 py-2 cursor-pointer text-left\",\n// 0 === historySnapshot.historyIndex && \"bg-orange-500/25\"\n// )}\n// onClick={() => {\n// // stateManager.goToHistoryIndex(0);\n// }}\n// >\n// <div className=\"flex justify-between gap-2\">\n// <span>Initial State</span>\n// </div>\n// </button>\n// {historySnapshot.history.map((entry, index) => (\n// <button\n// key={index}\n// type=\"button\"\n// className={cx(\n// \"px-4 py-2 cursor-pointer text-left\",\n// index === historySnapshot.historyIndex - 1 &&\n// \"bg-orange-500/25\"\n// )}\n// onClick={() => {\n// // stateManager.goToHistoryIndex(index + 1);\n// }}\n// >\n// <div className=\"flex justify-between gap-2\">\n// <span>\n// {index + 1}. {entry.metadata.name}\n// </span>\n// <span>\n// {new Date(\n// entry.metadata.timestamp\n// ).toLocaleTimeString()}\n// </span>\n// </div>\n// <div className=\"font-mono text-xs\">\n// {entry.redoPatches?.map((patch, index) => (\n// <pre key={index} className=\"max-w-full\">\n// {patch.op === \"remove\"\n// ? `Delete ${pathToString(patch.path)}`\n// : `${pathToString(patch.path)} = ${JSON.stringify(\n// patch.value,\n// null,\n// 2\n// )}`}\n// </pre>\n// ))}\n// </div>\n// </button>\n// ))}\n// </div>\n\nfunction pathToString(extendedPath: ExtendedPathKey[]) {\n return extendedPath\n .map((key) =>\n typeof key === \"object\"\n ? `:${ellipsis(key.id.toString(), 8, \"middle\")}`\n : key\n )\n .map((key, index) =>\n index === 0 || (typeof key === \"string\" && key.startsWith(\":\"))\n ? key\n : `.${key}`\n )\n .join(\"\");\n}\n\ntype EllipsisPosition = \"start\" | \"middle\" | \"end\";\n\nfunction ellipsis(\n str: string,\n maxLength: number,\n position: EllipsisPosition = \"end\"\n) {\n if (str.length <= maxLength) return str;\n\n switch (position) {\n case \"start\":\n return `…${str.slice(str.length - maxLength)}`;\n case \"middle\":\n const halfLength = Math.floor(maxLength / 2);\n return `${str.slice(0, halfLength)}…${str.slice(str.length - halfLength)}`;\n case \"end\":\n return `${str.slice(0, maxLength)}…`;\n }\n}\n","import React from \"react\";\n\nconst localStorage = typeof window !== \"undefined\" ? window.localStorage : null;\n\nexport function useLocalStorageState<S>(\n key: string,\n defaultValue: S\n): [S, (value: S) => void] {\n const [state, setState] = React.useState<S>(() => {\n const value = localStorage?.getItem(key);\n let result = defaultValue;\n if (value) {\n try {\n result = JSON.parse(value);\n } catch (error) {\n console.error(\"Error parsing localStorage value\", error);\n }\n }\n return result;\n });\n\n const setLocalStorageState = (value: S) => {\n localStorage?.setItem(key, JSON.stringify(value));\n setState(value);\n };\n\n return [state, setLocalStorageState];\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","React","React","StateInspector","React","root"]}
|