@noya-app/noya-multiplayer-react 0.1.24 → 0.1.25
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 +10 -10
- package/CHANGELOG.md +11 -0
- package/dist/index.d.mts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +208 -114
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +168 -73
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/ErrorOverlay.tsx +89 -0
- package/src/hooks.ts +39 -14
- package/src/inspector/StateInspector.tsx +2 -6
- package/src/inspector/useStateInspector.tsx +1 -1
- package/src/noyaApp.ts +3 -3
package/src/hooks.ts
CHANGED
|
@@ -6,16 +6,18 @@ import {
|
|
|
6
6
|
EphemeralUserData,
|
|
7
7
|
Get,
|
|
8
8
|
MultiplayerStateManager,
|
|
9
|
+
MultiplayerStateManagerError,
|
|
9
10
|
MultiplayerStateManagerOptions,
|
|
10
11
|
MultiplayerUser,
|
|
11
12
|
StateManager,
|
|
12
13
|
StateManagerOptions,
|
|
14
|
+
stubSync,
|
|
13
15
|
SyncAdapter,
|
|
14
16
|
SyncAdapterOptions,
|
|
15
17
|
Task,
|
|
16
|
-
stubSync,
|
|
17
18
|
} from "@noya-app/state-manager";
|
|
18
19
|
import {
|
|
20
|
+
createElement,
|
|
19
21
|
SetStateAction,
|
|
20
22
|
useCallback,
|
|
21
23
|
useEffect,
|
|
@@ -24,19 +26,19 @@ import {
|
|
|
24
26
|
useState,
|
|
25
27
|
useSyncExternalStore,
|
|
26
28
|
} from "react";
|
|
29
|
+
import { createRoot } from "react-dom/client";
|
|
30
|
+
import { ErrorOverlay } from "./components/ErrorOverlay";
|
|
27
31
|
import { shouldTrackEvents$, shouldTrackTasks$ } from "./globals";
|
|
28
32
|
import { StateInspectorOptions } from "./inspector/StateInspector";
|
|
29
33
|
import { useStateInspector } from "./inspector/useStateInspector";
|
|
30
34
|
import { useObservable } from "./useObservable";
|
|
31
35
|
|
|
32
|
-
export function useSyncStateManager<S
|
|
33
|
-
|
|
34
|
-
): S;
|
|
35
|
-
export function useSyncStateManager<S extends object, M, P extends string>(
|
|
36
|
+
export function useSyncStateManager<S, M>(stateManager: StateManager<S, M>): S;
|
|
37
|
+
export function useSyncStateManager<S, M, P extends string>(
|
|
36
38
|
stateManager: StateManager<S, M>,
|
|
37
39
|
path: P
|
|
38
40
|
): Get<S, P, unknown>;
|
|
39
|
-
export function useSyncStateManager<S
|
|
41
|
+
export function useSyncStateManager<S, M>(
|
|
40
42
|
stateManager: StateManager<S, M>,
|
|
41
43
|
path?: string
|
|
42
44
|
) {
|
|
@@ -55,7 +57,7 @@ export function useSyncStateManager<S extends object, M>(
|
|
|
55
57
|
);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
export function useManagedState<S
|
|
60
|
+
export function useManagedState<S, M = void>(
|
|
59
61
|
createInitialState: () => S,
|
|
60
62
|
options?: StateManagerOptions<S, M>
|
|
61
63
|
) {
|
|
@@ -79,7 +81,7 @@ export function useManagedState<S extends object, M = void>(
|
|
|
79
81
|
handler: ActionHandler<S>
|
|
80
82
|
) => void;
|
|
81
83
|
|
|
82
|
-
if (
|
|
84
|
+
if (action instanceof Function) {
|
|
83
85
|
performActionNoMetadata({
|
|
84
86
|
run: action,
|
|
85
87
|
undo: () => state,
|
|
@@ -96,7 +98,7 @@ export function useManagedState<S extends object, M = void>(
|
|
|
96
98
|
handler: ActionHandler<S>
|
|
97
99
|
) => void;
|
|
98
100
|
|
|
99
|
-
if (
|
|
101
|
+
if (action instanceof Function) {
|
|
100
102
|
performActionWithMetadata(metadata, {
|
|
101
103
|
run: action,
|
|
102
104
|
undo: () => state,
|
|
@@ -115,7 +117,7 @@ export function useManagedState<S extends object, M = void>(
|
|
|
115
117
|
return [state, setState, stateManager] as const;
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
export function useManagedHistory<S
|
|
120
|
+
export function useManagedHistory<S, M = void>(
|
|
119
121
|
stateManager: StateManager<S, M>
|
|
120
122
|
) {
|
|
121
123
|
return useSyncExternalStore(
|
|
@@ -125,7 +127,7 @@ export function useManagedHistory<S extends object, M = void>(
|
|
|
125
127
|
);
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
export function useSyncMultiplayerStateManager<S
|
|
130
|
+
export function useSyncMultiplayerStateManager<S, M = void>(
|
|
129
131
|
multiplayerStateManager: MultiplayerStateManager<S, M>
|
|
130
132
|
) {
|
|
131
133
|
return useSyncExternalStore(
|
|
@@ -189,7 +191,7 @@ export function useEphemeralUserData<E>(
|
|
|
189
191
|
const defaultStubSync = stubSync();
|
|
190
192
|
|
|
191
193
|
export type UseMultiplayerStateOptions<
|
|
192
|
-
S
|
|
194
|
+
S,
|
|
193
195
|
M = void,
|
|
194
196
|
E = void,
|
|
195
197
|
> = MultiplayerStateManagerOptions<S, M> & {
|
|
@@ -201,7 +203,7 @@ export type UseMultiplayerStateOptions<
|
|
|
201
203
|
inspector?: boolean | StateInspectorOptions;
|
|
202
204
|
};
|
|
203
205
|
|
|
204
|
-
export function useMultiplayerState<S
|
|
206
|
+
export function useMultiplayerState<S, M = void, E = void>(
|
|
205
207
|
initialState: S | (() => S),
|
|
206
208
|
options?: UseMultiplayerStateOptions<S, M, E>
|
|
207
209
|
) {
|
|
@@ -312,12 +314,35 @@ export function useMultiplayerState<S extends object, M = void, E = void>(
|
|
|
312
314
|
|
|
313
315
|
const forceInit = useCallback(() => {
|
|
314
316
|
const state =
|
|
315
|
-
|
|
317
|
+
initialState instanceof Function ? initialState() : initialState;
|
|
316
318
|
const schema = options?.schema;
|
|
317
319
|
multiplayerStateManager.sm.clearHistory();
|
|
318
320
|
multiplayerStateManager.sendInit({ force: true, state, schema });
|
|
319
321
|
}, [initialState, multiplayerStateManager, options?.schema]);
|
|
320
322
|
|
|
323
|
+
const [unrecoverableError, setUnrecoverableError] = useState<
|
|
324
|
+
MultiplayerStateManagerError | undefined
|
|
325
|
+
>();
|
|
326
|
+
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
return multiplayerStateManager.errorEmitter.addListener((error) => {
|
|
329
|
+
setUnrecoverableError(error);
|
|
330
|
+
});
|
|
331
|
+
}, [multiplayerStateManager]);
|
|
332
|
+
|
|
333
|
+
useEffect(() => {
|
|
334
|
+
if (!unrecoverableError) return;
|
|
335
|
+
const el = document.createElement("div");
|
|
336
|
+
el.id = "noya-multiplayer-react-error-overlay";
|
|
337
|
+
document.body.appendChild(el);
|
|
338
|
+
const root = createRoot(el);
|
|
339
|
+
root.render(createElement(ErrorOverlay, { error: unrecoverableError }));
|
|
340
|
+
return () => {
|
|
341
|
+
root.unmount();
|
|
342
|
+
el.remove();
|
|
343
|
+
};
|
|
344
|
+
});
|
|
345
|
+
|
|
321
346
|
useStateInspector({
|
|
322
347
|
ephemeralUserData,
|
|
323
348
|
multiplayerStateManager,
|
|
@@ -249,11 +249,7 @@ export type StateInspectorOptions = {
|
|
|
249
249
|
anchor?: StateInspectorAnchor;
|
|
250
250
|
};
|
|
251
251
|
|
|
252
|
-
export const StateInspector = memo(function StateInspector<
|
|
253
|
-
S extends object,
|
|
254
|
-
M,
|
|
255
|
-
E,
|
|
256
|
-
>({
|
|
252
|
+
export const StateInspector = memo(function StateInspector<S, M, E>({
|
|
257
253
|
state,
|
|
258
254
|
connectionEvents,
|
|
259
255
|
connectedUsers,
|
|
@@ -757,7 +753,7 @@ export const StateInspector = memo(function StateInspector<
|
|
|
757
753
|
}}
|
|
758
754
|
>
|
|
759
755
|
<ObjectInspector
|
|
760
|
-
data={event.message}
|
|
756
|
+
data={event.type === "error" ? event.error : event.message}
|
|
761
757
|
theme={theme}
|
|
762
758
|
nodeRenderer={({
|
|
763
759
|
depth,
|
package/src/noyaApp.ts
CHANGED
|
@@ -63,13 +63,13 @@ type AppDataOptions = {
|
|
|
63
63
|
/**
|
|
64
64
|
* Get data from host app. Fall back to default data.
|
|
65
65
|
*/
|
|
66
|
-
export function useAppData<S
|
|
66
|
+
export function useAppData<S>(
|
|
67
67
|
initialState: S,
|
|
68
68
|
{ schema }: AppDataOptions = {}
|
|
69
69
|
) {
|
|
70
70
|
const appData = useMemo(() => {
|
|
71
71
|
return getAppData(
|
|
72
|
-
schema ? createValue(schema, initialState) : initialState
|
|
72
|
+
schema ? (createValue(schema, initialState) as S) : initialState
|
|
73
73
|
);
|
|
74
74
|
}, [initialState, schema]);
|
|
75
75
|
|
|
@@ -142,7 +142,7 @@ export function isEmbeddedApp() {
|
|
|
142
142
|
return window.self !== window.top;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
export function useNoyaAppState<S
|
|
145
|
+
export function useNoyaAppState<S, M = void, E = void>(
|
|
146
146
|
initialState: S | (() => S),
|
|
147
147
|
options: UseMultiplayerStateOptions<S, M, E> & {
|
|
148
148
|
localStorageKey?: string;
|