@noya-app/noya-multiplayer-react 0.1.38 → 0.1.40
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 +14 -15
- package/CHANGELOG.md +15 -0
- package/dist/index.bundle.js +7 -7
- package/dist/index.d.ts +54 -16
- package/dist/index.js +127 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +128 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/NoyaStateContext.tsx +234 -0
- package/src/__tests__/NoyaStateContext.test.ts +43 -0
- package/src/hooks.ts +12 -3
- package/src/index.ts +1 -0
- package/src/useObservable.ts +6 -6
- package/dist/index.d.mts +0 -168
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { GetAtPath, ObservableOptions, PathKey } from "@noya-app/observable";
|
|
2
|
+
import {
|
|
3
|
+
AssetManager,
|
|
4
|
+
MultiplayerStateManager,
|
|
5
|
+
StateManagerOptions,
|
|
6
|
+
Static,
|
|
7
|
+
TSchema,
|
|
8
|
+
} from "@noya-app/state-manager";
|
|
9
|
+
import React, {
|
|
10
|
+
createContext,
|
|
11
|
+
SetStateAction,
|
|
12
|
+
useCallback,
|
|
13
|
+
useContext,
|
|
14
|
+
useMemo,
|
|
15
|
+
} from "react";
|
|
16
|
+
import { useNoyaState, UseNoyaStateOptions } from "./noyaApp";
|
|
17
|
+
import { useObservable } from "./useObservable";
|
|
18
|
+
|
|
19
|
+
interface NoyaStateProviderProps<S, M, E>
|
|
20
|
+
extends Omit<UseNoyaStateOptions<S, M, E>, "schema" | "mergeHistoryEntries"> {
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
initialState?: S;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const AnyNoyaStateContext = createContext<
|
|
26
|
+
| { ms: MultiplayerStateManager<any, any>; assetManager: AssetManager }
|
|
27
|
+
| undefined
|
|
28
|
+
>(undefined);
|
|
29
|
+
|
|
30
|
+
function useAnyNoyaStateContext() {
|
|
31
|
+
const value = useContext(AnyNoyaStateContext);
|
|
32
|
+
|
|
33
|
+
if (!value) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
"useNoyaStateContext must be used within a NoyaStateProvider"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function useAssets() {
|
|
43
|
+
const { assetManager } = useAnyNoyaStateContext();
|
|
44
|
+
return useObservable(assetManager.assets$);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function useAsset(id: string | undefined) {
|
|
48
|
+
const { assetManager } = useAnyNoyaStateContext();
|
|
49
|
+
const observable = useMemo(
|
|
50
|
+
() => assetManager.assets$.map((assets) => assets.find((a) => a.id === id)),
|
|
51
|
+
[assetManager, id]
|
|
52
|
+
);
|
|
53
|
+
return useObservable(observable);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function useAssetManager() {
|
|
57
|
+
const { assetManager } = useAnyNoyaStateContext();
|
|
58
|
+
return useMemo(
|
|
59
|
+
() => ({
|
|
60
|
+
create: assetManager.create,
|
|
61
|
+
delete: assetManager.delete,
|
|
62
|
+
}),
|
|
63
|
+
[assetManager]
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function createNoyaContext<Schema extends TSchema, M = void, E = void>({
|
|
68
|
+
schema,
|
|
69
|
+
mergeHistoryEntries,
|
|
70
|
+
}: {
|
|
71
|
+
schema: Schema;
|
|
72
|
+
mergeHistoryEntries?: StateManagerOptions<
|
|
73
|
+
Static<Schema>,
|
|
74
|
+
M
|
|
75
|
+
>["mergeHistoryEntries"];
|
|
76
|
+
}) {
|
|
77
|
+
type S = Static<Schema>;
|
|
78
|
+
|
|
79
|
+
const NoyaStateContext = AnyNoyaStateContext as React.Context<
|
|
80
|
+
| {
|
|
81
|
+
ms: MultiplayerStateManager<S, M>;
|
|
82
|
+
assetManager: AssetManager;
|
|
83
|
+
}
|
|
84
|
+
| undefined
|
|
85
|
+
>;
|
|
86
|
+
|
|
87
|
+
function NoyaStateProvider({
|
|
88
|
+
children,
|
|
89
|
+
initialState,
|
|
90
|
+
...options
|
|
91
|
+
}: NoyaStateProviderProps<S, M, E>) {
|
|
92
|
+
const [, , { multiplayerStateManager, assetManager }] = useNoyaState(
|
|
93
|
+
initialState,
|
|
94
|
+
{
|
|
95
|
+
...(options as any),
|
|
96
|
+
schema,
|
|
97
|
+
mergeHistoryEntries,
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const value = useMemo(
|
|
102
|
+
() => ({
|
|
103
|
+
ms: multiplayerStateManager as MultiplayerStateManager<any, any>,
|
|
104
|
+
assetManager,
|
|
105
|
+
}),
|
|
106
|
+
[multiplayerStateManager, assetManager]
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<AnyNoyaStateContext.Provider value={value}>
|
|
111
|
+
{children}
|
|
112
|
+
</AnyNoyaStateContext.Provider>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function useValue(): S;
|
|
117
|
+
function useValue<A>(
|
|
118
|
+
selector: (value: S) => A,
|
|
119
|
+
options?: Pick<ObservableOptions, "isEqual">
|
|
120
|
+
): A;
|
|
121
|
+
function useValue<P extends PathKey[] | string>(path: P): GetAtPath<S, P>;
|
|
122
|
+
function useValue(
|
|
123
|
+
path?: PathKey[] | string | ((value: S) => any),
|
|
124
|
+
options?: Pick<ObservableOptions, "isEqual">
|
|
125
|
+
) {
|
|
126
|
+
const { ms } = useAnyNoyaStateContext();
|
|
127
|
+
|
|
128
|
+
let actualPath: PathKey[] | string =
|
|
129
|
+
typeof path === "function" || !path ? "" : path;
|
|
130
|
+
|
|
131
|
+
const mappedObservable = useMemo(() => {
|
|
132
|
+
if (typeof path === "function") {
|
|
133
|
+
return ms.optimisticState$.map(path, { isEqual: options?.isEqual });
|
|
134
|
+
}
|
|
135
|
+
return ms.optimisticState$;
|
|
136
|
+
}, [ms, path, options?.isEqual]);
|
|
137
|
+
|
|
138
|
+
const value = useObservable(mappedObservable, actualPath);
|
|
139
|
+
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function useSetValue(): M extends {}
|
|
144
|
+
? (metadata: M, value: SetStateAction<S>) => void
|
|
145
|
+
: (value: SetStateAction<S>) => void;
|
|
146
|
+
function useSetValue<P extends PathKey[] | string>(
|
|
147
|
+
path: P
|
|
148
|
+
): M extends {}
|
|
149
|
+
? (metadata: M, value: SetStateAction<GetAtPath<S, P>>) => void
|
|
150
|
+
: (value: SetStateAction<GetAtPath<S, P>>) => void;
|
|
151
|
+
function useSetValue<P extends PathKey[] | string>(path?: P) {
|
|
152
|
+
const { ms } = useAnyNoyaStateContext();
|
|
153
|
+
|
|
154
|
+
const setValue = useCallback(
|
|
155
|
+
(
|
|
156
|
+
...args: M extends {}
|
|
157
|
+
? [metadata: M, value: SetStateAction<GetAtPath<S, P>>]
|
|
158
|
+
: [value: SetStateAction<GetAtPath<S, P>>]
|
|
159
|
+
): void => {
|
|
160
|
+
const [metadata, value] =
|
|
161
|
+
args.length === 2 ? args : [undefined as M, args[0]];
|
|
162
|
+
|
|
163
|
+
const setStateAtPath = ms.setStateAtPath as (
|
|
164
|
+
metadata: M,
|
|
165
|
+
path: P,
|
|
166
|
+
value: GetAtPath<S, P>
|
|
167
|
+
) => void;
|
|
168
|
+
|
|
169
|
+
setStateAtPath(metadata, (path ?? "") as P, value as never);
|
|
170
|
+
},
|
|
171
|
+
[ms, path]
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
return setValue as M extends {}
|
|
175
|
+
? (metadata: M, value: SetStateAction<GetAtPath<S, P>>) => void
|
|
176
|
+
: (value: SetStateAction<GetAtPath<S, P>>) => void;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function useValueState(): [
|
|
180
|
+
S,
|
|
181
|
+
M extends {}
|
|
182
|
+
? (metadata: M, value: SetStateAction<S>) => void
|
|
183
|
+
: (value: SetStateAction<S>) => void,
|
|
184
|
+
];
|
|
185
|
+
function useValueState<A>(
|
|
186
|
+
selector: (value: S) => A,
|
|
187
|
+
options?: ObservableOptions
|
|
188
|
+
): [
|
|
189
|
+
A,
|
|
190
|
+
M extends {}
|
|
191
|
+
? (metadata: M, value: SetStateAction<S>) => void
|
|
192
|
+
: (value: SetStateAction<S>) => void,
|
|
193
|
+
];
|
|
194
|
+
function useValueState<P extends PathKey[] | string>(
|
|
195
|
+
path?: P
|
|
196
|
+
): [
|
|
197
|
+
GetAtPath<S, P>,
|
|
198
|
+
M extends {}
|
|
199
|
+
? (metadata: M, value: SetStateAction<GetAtPath<S, P>>) => void
|
|
200
|
+
: (value: SetStateAction<GetAtPath<S, P>>) => void,
|
|
201
|
+
];
|
|
202
|
+
function useValueState<P extends PathKey[] | string>(
|
|
203
|
+
...args: [P?] | [selector: (value: S) => any, options?: ObservableOptions]
|
|
204
|
+
) {
|
|
205
|
+
const [selector, options, path] =
|
|
206
|
+
args.length >= 1 && typeof args[0] === "function"
|
|
207
|
+
? [args[0], args[1], undefined]
|
|
208
|
+
: [undefined, undefined, args[0] as P | undefined];
|
|
209
|
+
|
|
210
|
+
const value = useValue((selector ?? path ?? "") as any, options);
|
|
211
|
+
const setValue = useSetValue(path ?? "");
|
|
212
|
+
return [value, setValue];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function useStateManager() {
|
|
216
|
+
const { ms } = useAnyNoyaStateContext() as {
|
|
217
|
+
ms: MultiplayerStateManager<S, M>;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
return ms;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
Context: NoyaStateContext,
|
|
225
|
+
Provider: NoyaStateProvider,
|
|
226
|
+
useValue,
|
|
227
|
+
useSetValue,
|
|
228
|
+
useValueState,
|
|
229
|
+
useStateManager,
|
|
230
|
+
// useAssets,
|
|
231
|
+
// useAssetManager,
|
|
232
|
+
// useAsset,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Type } from "@noya-app/state-manager";
|
|
2
|
+
import { it } from "bun:test";
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import { createNoyaContext } from "../NoyaStateContext";
|
|
5
|
+
|
|
6
|
+
it("typechecks", () => {
|
|
7
|
+
const testSchema = Type.Object({
|
|
8
|
+
count: Type.Number(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const { useValue, useSetValue, useValueState } = createNoyaContext({
|
|
12
|
+
schema: testSchema,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// For type checking
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
17
|
+
function TestComponent() {
|
|
18
|
+
const state = useValue();
|
|
19
|
+
const count = useValue("count");
|
|
20
|
+
const setValue = useSetValue();
|
|
21
|
+
const setCount = useSetValue("count");
|
|
22
|
+
setValue({ count: 1 });
|
|
23
|
+
setCount(1);
|
|
24
|
+
setCount((prev) => prev + 1);
|
|
25
|
+
const [count2, setCount2] = useValueState("count");
|
|
26
|
+
setCount2(1);
|
|
27
|
+
setCount2((prev) => prev + 1);
|
|
28
|
+
const count3 = useValue(useCallback((state) => state.count, []));
|
|
29
|
+
const [count4, setValue2] = useValueState(
|
|
30
|
+
useCallback((state) => state.count, [])
|
|
31
|
+
);
|
|
32
|
+
setValue2({ count: 1 });
|
|
33
|
+
setValue2((prev) => ({ count: prev.count + 1 }));
|
|
34
|
+
|
|
35
|
+
expectType<{ count: number }>(state);
|
|
36
|
+
expectType<number>(count);
|
|
37
|
+
expectType<number>(count2);
|
|
38
|
+
expectType<number>(count3);
|
|
39
|
+
expectType<number>(count4);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
function expectType<T>(value: T): void {}
|
package/src/hooks.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { GetAtPath } from "@noya-app/observable";
|
|
3
4
|
import {
|
|
4
5
|
ActionHandler,
|
|
5
6
|
AssetManager,
|
|
6
7
|
ConnectionEvent,
|
|
7
8
|
EphemeralUserData,
|
|
8
|
-
Get,
|
|
9
9
|
MultiplayerStateManager,
|
|
10
10
|
MultiplayerStateManagerError,
|
|
11
11
|
MultiplayerStateManagerOptions,
|
|
@@ -38,7 +38,7 @@ export function useSyncStateManager<S, M>(stateManager: StateManager<S, M>): S;
|
|
|
38
38
|
export function useSyncStateManager<S, M, P extends string>(
|
|
39
39
|
stateManager: StateManager<S, M>,
|
|
40
40
|
path: P
|
|
41
|
-
):
|
|
41
|
+
): GetAtPath<S, P>;
|
|
42
42
|
export function useSyncStateManager<S, M>(
|
|
43
43
|
stateManager: StateManager<S, M>,
|
|
44
44
|
path?: string
|
|
@@ -241,6 +241,7 @@ export function useMultiplayerState<S, M = void, E = void>(
|
|
|
241
241
|
ephemeralUserData,
|
|
242
242
|
multiplayerStateManager,
|
|
243
243
|
assets,
|
|
244
|
+
assetManager,
|
|
244
245
|
createAsset: assetManager.create,
|
|
245
246
|
deleteAsset: assetManager.delete,
|
|
246
247
|
// evaluate: async (code: string) => {
|
|
@@ -338,7 +339,15 @@ export function useMultiplayerState<S, M = void, E = void>(
|
|
|
338
339
|
|
|
339
340
|
useEffect(() => {
|
|
340
341
|
return multiplayerStateManager.errorEmitter.addListener((error) => {
|
|
341
|
-
|
|
342
|
+
switch (error.reason) {
|
|
343
|
+
case "invalidDataType":
|
|
344
|
+
case "schemaMismatch":
|
|
345
|
+
case "outdatedSchema":
|
|
346
|
+
case "dataMigrationFailure":
|
|
347
|
+
case "schemaMigration":
|
|
348
|
+
setUnrecoverableError(error);
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
342
351
|
});
|
|
343
352
|
}, [multiplayerStateManager]);
|
|
344
353
|
|
package/src/index.ts
CHANGED
package/src/useObservable.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GetAtPath, Observable, PathKey } from "@noya-app/observable";
|
|
2
2
|
import { useMemo, useSyncExternalStore } from "react";
|
|
3
3
|
|
|
4
4
|
export function useObservable<T>(observable: Observable<T>): T;
|
|
5
|
-
export function useObservable<T, P extends PathKey[]>(
|
|
5
|
+
export function useObservable<T, P extends PathKey[] | string>(
|
|
6
6
|
observable: Observable<T>,
|
|
7
7
|
path: P
|
|
8
|
-
):
|
|
8
|
+
): GetAtPath<T, P>;
|
|
9
9
|
export function useObservable<T, P extends PathKey[]>(
|
|
10
10
|
observable: Observable<T>,
|
|
11
11
|
path?: P
|
|
12
12
|
) {
|
|
13
13
|
const { get, listen } = useMemo(() => {
|
|
14
14
|
const listen = path
|
|
15
|
-
? (callback: (value:
|
|
16
|
-
observable.
|
|
17
|
-
: observable.
|
|
15
|
+
? (callback: (value: GetAtPath<T, P>) => void) =>
|
|
16
|
+
observable.subscribe(path, callback)
|
|
17
|
+
: observable.subscribe;
|
|
18
18
|
|
|
19
19
|
const get: () => void = path ? () => observable.get(path) : observable.get;
|
|
20
20
|
|
package/dist/index.d.mts
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import * as _noya_app_state_manager from '@noya-app/state-manager';
|
|
2
|
-
import { MultiplayerUser, EphemeralUserData, ConnectionEvent, Task, MultiplayerStateManager, AssetManager, StateManager, Get, StateManagerOptions, MultiplayerStateManagerOptions, SyncAdapterOptions, TSchema, Static } from '@noya-app/state-manager';
|
|
3
|
-
export * from '@noya-app/state-manager';
|
|
4
|
-
import React, { SetStateAction } from 'react';
|
|
5
|
-
import { Observable, PathKey, GetWithPath } from '@noya-app/observable';
|
|
6
|
-
|
|
7
|
-
declare function getAvatarInitials(name: string): string;
|
|
8
|
-
/**
|
|
9
|
-
* Create a background color and initials from a name
|
|
10
|
-
*
|
|
11
|
-
* Adapted from https://mui.com/material-ui/react-avatar/
|
|
12
|
-
*/
|
|
13
|
-
declare function getAvatarStyle(name: string): {
|
|
14
|
-
color: string;
|
|
15
|
-
backgroundColor: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
type Point = {
|
|
19
|
-
x: number;
|
|
20
|
-
y: number;
|
|
21
|
-
};
|
|
22
|
-
type UserPointerData = {
|
|
23
|
-
pointer?: Point;
|
|
24
|
-
};
|
|
25
|
-
type UserPointerProps<E extends UserPointerData> = {
|
|
26
|
-
user: MultiplayerUser;
|
|
27
|
-
ephemeralUserData: EphemeralUserData<E>;
|
|
28
|
-
hideAfter?: number;
|
|
29
|
-
};
|
|
30
|
-
declare const UserPointer: <E extends UserPointerData>({ user, ephemeralUserData, hideAfter, }: UserPointerProps<E>) => React.JSX.Element | null;
|
|
31
|
-
declare const UserPointerContainer: React.NamedExoticComponent<{
|
|
32
|
-
point: Point;
|
|
33
|
-
children: React.ReactNode;
|
|
34
|
-
show?: boolean | undefined;
|
|
35
|
-
}>;
|
|
36
|
-
declare const UserNameTag: React.NamedExoticComponent<{
|
|
37
|
-
background: string;
|
|
38
|
-
children: React.ReactNode;
|
|
39
|
-
}>;
|
|
40
|
-
type UserPointersOverlayProps<E extends UserPointerData> = {
|
|
41
|
-
connectedUsers: MultiplayerUser[];
|
|
42
|
-
ephemeralUserData: EphemeralUserData<E>;
|
|
43
|
-
};
|
|
44
|
-
declare const UserPointersOverlay: React.MemoExoticComponent<(<E extends UserPointerData>({ connectedUsers, ephemeralUserData }: UserPointersOverlayProps<E>) => React.JSX.Element)>;
|
|
45
|
-
declare const UserPointerIcon: React.NamedExoticComponent<{
|
|
46
|
-
color?: string | undefined;
|
|
47
|
-
}>;
|
|
48
|
-
|
|
49
|
-
type StateInspectorAnchor = "left" | "right" | "bottom left" | "bottom right";
|
|
50
|
-
type StateInspectorOptions = {
|
|
51
|
-
colorScheme?: "light" | "dark";
|
|
52
|
-
anchor?: StateInspectorAnchor;
|
|
53
|
-
};
|
|
54
|
-
declare const StateInspector: React.MemoExoticComponent<(<S, M, E>({ state, connectionEvents, connectedUsers, tasks, userId, unstyled, colorScheme, multiplayerStateManager, assetManager, ephemeralUserData, anchor, forceInit, ...props }: {
|
|
55
|
-
state: S;
|
|
56
|
-
connectionEvents?: ConnectionEvent<S>[] | undefined;
|
|
57
|
-
connectedUsers?: MultiplayerUser[] | undefined;
|
|
58
|
-
tasks?: Task[] | undefined;
|
|
59
|
-
userId?: string | undefined;
|
|
60
|
-
unstyled?: boolean | undefined;
|
|
61
|
-
multiplayerStateManager: MultiplayerStateManager<S, M>;
|
|
62
|
-
assetManager: AssetManager;
|
|
63
|
-
ephemeralUserData: EphemeralUserData<E>;
|
|
64
|
-
forceInit: () => void;
|
|
65
|
-
} & StateInspectorOptions & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">) => React.JSX.Element | null)>;
|
|
66
|
-
|
|
67
|
-
declare function useSyncStateManager<S, M>(stateManager: StateManager<S, M>): S;
|
|
68
|
-
declare function useSyncStateManager<S, M, P extends string>(stateManager: StateManager<S, M>, path: P): Get<S, P, unknown>;
|
|
69
|
-
declare function useManagedState<S, 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>];
|
|
70
|
-
declare function useManagedHistory<S, M = void>(stateManager: StateManager<S, M>): _noya_app_state_manager.HistorySnapshot<S, M>;
|
|
71
|
-
declare function useSyncMultiplayerStateManager<S, M = void>(multiplayerStateManager: MultiplayerStateManager<S, M>): S;
|
|
72
|
-
declare function useEphemeralUserData<E>(ephemeralUserData: EphemeralUserData<E>, options?: {
|
|
73
|
-
throttle?: number;
|
|
74
|
-
}): {
|
|
75
|
-
data: Record<string, E | undefined>;
|
|
76
|
-
metadata: Record<string, _noya_app_state_manager.EphemeralUserMetadata | undefined>;
|
|
77
|
-
currentUserId: string | undefined;
|
|
78
|
-
};
|
|
79
|
-
type UseMultiplayerStateOptions<S, M = void, E = void> = MultiplayerStateManagerOptions<S, M> & {
|
|
80
|
-
sync?: (options: Pick<SyncAdapterOptions<S, M, E>, "ms" | "ephemeralUserData" | "assetManager">) => void;
|
|
81
|
-
trackConnectionEvents?: boolean;
|
|
82
|
-
trackTasks?: boolean;
|
|
83
|
-
inspector?: boolean | StateInspectorOptions;
|
|
84
|
-
};
|
|
85
|
-
declare function useMultiplayerState<S, M = void, E = void>(initialState: S | (() => S), options?: UseMultiplayerStateOptions<S, M, E>): readonly [S, (...args: M extends {} ? [metadata: M, action: S | ((prevState: S) => S)] : [action: S | ((prevState: S) => S)]) => void, {
|
|
86
|
-
tasks: Task[];
|
|
87
|
-
userId: string | undefined;
|
|
88
|
-
connectionEvents: ConnectionEvent<S>[] | undefined;
|
|
89
|
-
connectedUsers: MultiplayerUser[];
|
|
90
|
-
ephemeralUserData: EphemeralUserData<E>;
|
|
91
|
-
multiplayerStateManager: MultiplayerStateManager<S, M>;
|
|
92
|
-
assets: _noya_app_state_manager.Asset[];
|
|
93
|
-
createAsset: (options: Uint8Array | _noya_app_state_manager.CreateAssetOptions) => Promise<_noya_app_state_manager.Asset>;
|
|
94
|
-
deleteAsset: (id: string) => Promise<void>;
|
|
95
|
-
}];
|
|
96
|
-
|
|
97
|
-
type AppViewType = "editable" | "readOnly" | "preview";
|
|
98
|
-
type AppTheme = "light" | "dark";
|
|
99
|
-
type AppData<State> = {
|
|
100
|
-
multiplayerUrl?: string;
|
|
101
|
-
theme: AppTheme;
|
|
102
|
-
viewType: AppViewType;
|
|
103
|
-
initialState: State;
|
|
104
|
-
inspector: boolean | StateInspectorOptions;
|
|
105
|
-
};
|
|
106
|
-
declare function createDefaultAppData<State>(initialState: State): AppData<State>;
|
|
107
|
-
type GetAppDataOptions = {
|
|
108
|
-
window?: {
|
|
109
|
-
location: {
|
|
110
|
-
hash: string;
|
|
111
|
-
};
|
|
112
|
-
};
|
|
113
|
-
overrideExistingState?: boolean;
|
|
114
|
-
};
|
|
115
|
-
declare function enforceSchema<State>(initialState: State, schema?: TSchema): State;
|
|
116
|
-
declare function parseAppDataParameter(options?: GetAppDataOptions): AppData<unknown> | null;
|
|
117
|
-
declare function getAppData<State>(initialState: State | (() => State), schema?: TSchema, options?: GetAppDataOptions): AppData<State>;
|
|
118
|
-
type IframeToHostMessage = {
|
|
119
|
-
type: "application.setMenuItems";
|
|
120
|
-
payload: {
|
|
121
|
-
menuItems: any[];
|
|
122
|
-
};
|
|
123
|
-
} | {
|
|
124
|
-
type: "multiplayer.setUsers";
|
|
125
|
-
payload: {
|
|
126
|
-
users: any[];
|
|
127
|
-
};
|
|
128
|
-
};
|
|
129
|
-
type HostToIframeMessage = {
|
|
130
|
-
type: "application.selectMenuItem";
|
|
131
|
-
payload: {
|
|
132
|
-
value: string;
|
|
133
|
-
};
|
|
134
|
-
};
|
|
135
|
-
declare function useBroadcastConnectedUsers(connectedUsers: MultiplayerUser[]): void;
|
|
136
|
-
declare function useBroadcastMenuItems<T>(menuItems: any[], handleSelectMenuItem: (value: T) => void): void;
|
|
137
|
-
declare function isEmbeddedApp(): boolean;
|
|
138
|
-
type UseNoyaStateOptions<S, M = void, E = void> = UseMultiplayerStateOptions<S, M, E> & {
|
|
139
|
-
offlineStorageKey?: string;
|
|
140
|
-
};
|
|
141
|
-
type UseNoyaStateResult<S, M = void, E = void> = [
|
|
142
|
-
ReturnType<typeof useMultiplayerState<S, M, E>>[0],
|
|
143
|
-
ReturnType<typeof useMultiplayerState<S, M, E>>[1],
|
|
144
|
-
ReturnType<typeof useMultiplayerState<S, M, E>>[2] & {
|
|
145
|
-
theme: AppTheme;
|
|
146
|
-
viewType: AppViewType;
|
|
147
|
-
}
|
|
148
|
-
];
|
|
149
|
-
/**
|
|
150
|
-
* Sync data locally or to a multiplayer server.
|
|
151
|
-
*
|
|
152
|
-
* There are 3 ways to use this hook:
|
|
153
|
-
*
|
|
154
|
-
* 1. Pass an initial state: `useNoyaState(initialState)`
|
|
155
|
-
* 2. Pass an initial state and a schema: `useNoyaState(initialState, { schema })`
|
|
156
|
-
* 3. Pass only a schema, and a conforming initial state is created automatically: `useNoyaState({ schema })`
|
|
157
|
-
*/
|
|
158
|
-
declare function useNoyaState<S, M = void, E = void, O extends UseNoyaStateOptions<S, M, E> = UseNoyaStateOptions<S, M, E>>(...args: [
|
|
159
|
-
initialState: O["schema"] extends TSchema ? Static<O["schema"]> | (() => Static<O["schema"]>) : S | (() => S),
|
|
160
|
-
options?: O
|
|
161
|
-
] | [options: O & {
|
|
162
|
-
schema: TSchema;
|
|
163
|
-
}]): UseNoyaStateResult<O["schema"] extends TSchema ? Static<O["schema"]> : S, M, E>;
|
|
164
|
-
|
|
165
|
-
declare function useObservable<T>(observable: Observable<T>): T;
|
|
166
|
-
declare function useObservable<T, P extends PathKey[]>(observable: Observable<T>, path: P): GetWithPath<T, P>;
|
|
167
|
-
|
|
168
|
-
export { type AppData, type AppTheme, type AppViewType, type GetAppDataOptions, type HostToIframeMessage, type IframeToHostMessage, StateInspector, type StateInspectorAnchor, type StateInspectorOptions, type UseMultiplayerStateOptions, type UseNoyaStateOptions, type UseNoyaStateResult, UserNameTag, UserPointer, UserPointerContainer, type UserPointerData, UserPointerIcon, type UserPointerProps, UserPointersOverlay, type UserPointersOverlayProps, createDefaultAppData, enforceSchema, getAppData, getAvatarInitials, getAvatarStyle, isEmbeddedApp, parseAppDataParameter, useBroadcastConnectedUsers, useBroadcastMenuItems, useEphemeralUserData, useManagedHistory, useManagedState, useMultiplayerState, useNoyaState, useObservable, useSyncMultiplayerStateManager, useSyncStateManager };
|