@noya-app/noya-multiplayer-react 0.1.47 → 0.1.49

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.
@@ -1,3 +1,4 @@
1
+ import { MenuItem } from "@noya-app/noya-designsystem";
1
2
  import {
2
3
  GetAtPath,
3
4
  Observable,
@@ -21,7 +22,12 @@ import React, {
21
22
  useEffect,
22
23
  useMemo,
23
24
  } from "react";
24
- import { useNoyaState, UseNoyaStateOptions } from "./noyaApp";
25
+ import {
26
+ AppTheme,
27
+ AppViewType,
28
+ useNoyaState,
29
+ UseNoyaStateOptions,
30
+ } from "./noyaApp";
25
31
  import { useObservable } from "./useObservable";
26
32
 
27
33
  interface NoyaStateProviderProps<
@@ -39,10 +45,15 @@ interface NoyaStateProviderProps<
39
45
  }
40
46
 
41
47
  const AnyNoyaStateContext = createContext<
42
- NoyaManager<any, any, any, any> | undefined
48
+ | {
49
+ noyaManager: NoyaManager<any, any, any, any>;
50
+ theme: AppTheme;
51
+ viewType: AppViewType;
52
+ }
53
+ | undefined
43
54
  >(undefined);
44
55
 
45
- function useAnyNoyaStateContext() {
56
+ export function useAnyNoyaStateContext() {
46
57
  const value = useContext(AnyNoyaStateContext);
47
58
 
48
59
  if (!value) {
@@ -54,81 +65,99 @@ function useAnyNoyaStateContext() {
54
65
  return value;
55
66
  }
56
67
 
68
+ export function useAnyNoyaManager() {
69
+ const { noyaManager } = useAnyNoyaStateContext();
70
+ return noyaManager as NoyaManager<any, any, any, any>;
71
+ }
72
+
73
+ export function useColorScheme() {
74
+ const { theme } = useAnyNoyaStateContext();
75
+ return theme;
76
+ }
77
+
78
+ export function useViewType() {
79
+ const { viewType } = useAnyNoyaStateContext();
80
+ return viewType;
81
+ }
82
+
57
83
  export function useAssets() {
58
- const { assetManager } = useAnyNoyaStateContext();
59
- return useObservable(assetManager.assets$);
84
+ const { noyaManager } = useAnyNoyaStateContext();
85
+ return useObservable(noyaManager.assetManager.assets$);
60
86
  }
61
87
 
62
88
  export function useAsset(id: string | undefined) {
63
- const { assetManager } = useAnyNoyaStateContext();
89
+ const { noyaManager } = useAnyNoyaStateContext();
64
90
  const observable = useMemo(
65
- () => assetManager.assets$.map((assets) => assets.find((a) => a.id === id)),
66
- [assetManager, id]
91
+ () =>
92
+ noyaManager.assetManager.assets$.map((assets) =>
93
+ assets.find((a) => a.id === id)
94
+ ),
95
+ [noyaManager, id]
67
96
  );
68
97
  return useObservable(observable);
69
98
  }
70
99
 
71
100
  export function useAssetManager() {
72
- const { assetManager } = useAnyNoyaStateContext();
101
+ const { noyaManager } = useAnyNoyaStateContext();
102
+ const isInitialized = useObservable(noyaManager.assetManager.isInitialized$);
73
103
  return useMemo(
74
104
  () => ({
75
- create: assetManager.create,
76
- delete: assetManager.delete,
105
+ create: noyaManager.assetManager.create,
106
+ delete: noyaManager.assetManager.delete,
107
+ isInitialized,
77
108
  }),
78
- [assetManager]
109
+ [noyaManager, isInitialized]
79
110
  );
80
111
  }
81
112
 
82
113
  export function useAIManager() {
83
- const { aiManager } = useAnyNoyaStateContext();
84
- return aiManager;
114
+ const { noyaManager } = useAnyNoyaStateContext();
115
+ return noyaManager.aiManager;
85
116
  }
86
117
 
87
118
  export function useSecretManager() {
88
- const { secretManager } = useAnyNoyaStateContext();
89
- return secretManager;
119
+ const { noyaManager } = useAnyNoyaStateContext();
120
+ return noyaManager.secretManager;
90
121
  }
91
122
 
92
123
  export function useSecrets() {
93
- const { secretManager } = useAnyNoyaStateContext();
94
- return useObservable(secretManager.secrets$);
124
+ const { noyaManager } = useAnyNoyaStateContext();
125
+ return useObservable(noyaManager.secretManager.secrets$);
95
126
  }
96
127
 
97
128
  export function useSecret(name: string) {
98
- const { secretManager } = useAnyNoyaStateContext();
129
+ const { noyaManager } = useAnyNoyaStateContext();
99
130
 
100
131
  return useObservable(
101
- secretManager.secrets$,
132
+ noyaManager.secretManager.secrets$,
102
133
  useCallback((secrets) => secrets.find((s) => s.name === name), [name])
103
134
  );
104
135
  }
105
136
 
106
137
  export function useIsInitialized() {
107
- const {
108
- multiplayerStateManager: ms,
109
- secretManager,
110
- assetManager,
111
- } = useAnyNoyaStateContext();
138
+ const { noyaManager, viewType } = useAnyNoyaStateContext();
112
139
 
113
140
  const isInitializedObservable = useMemo(
114
141
  () =>
115
142
  Observable.combine(
116
143
  [
117
- ms.isInitialized$,
118
- secretManager.isInitialized$,
119
- assetManager.isInitialized$,
144
+ ...(viewType === "preview"
145
+ ? []
146
+ : [noyaManager.multiplayerStateManager.isInitialized$]),
147
+ noyaManager.secretManager.isInitialized$,
148
+ noyaManager.assetManager.isInitialized$,
120
149
  ],
121
150
  (values) => values.every((v) => v)
122
151
  ),
123
- [ms, secretManager, assetManager]
152
+ [noyaManager, viewType]
124
153
  );
125
154
 
126
155
  return useObservable(isInitializedObservable);
127
156
  }
128
157
 
129
158
  export function useWorkflowManager() {
130
- const { workflowManager } = useAnyNoyaStateContext();
131
- return workflowManager;
159
+ const { noyaManager } = useAnyNoyaStateContext();
160
+ return noyaManager.workflowManager;
132
161
  }
133
162
 
134
163
  export const ConnectedUsersContext = createContext<
@@ -195,14 +224,26 @@ export function createNoyaContext<
195
224
  initialState,
196
225
  ...options
197
226
  }: NoyaStateProviderProps<S, M, E, MenuT>) {
198
- const [, , { noyaManager }] = useNoyaState<S, M, E, MenuT>(initialState, {
199
- ...(options as any),
200
- schema,
201
- mergeHistoryEntries,
202
- });
227
+ const [, , { noyaManager, theme, viewType }] = useNoyaState<S, M, E, MenuT>(
228
+ initialState,
229
+ {
230
+ ...(options as any),
231
+ schema,
232
+ mergeHistoryEntries,
233
+ }
234
+ );
235
+
236
+ const contextValue = useMemo(
237
+ () => ({
238
+ noyaManager,
239
+ theme,
240
+ viewType,
241
+ }),
242
+ [noyaManager, theme, viewType]
243
+ );
203
244
 
204
245
  return (
205
- <AnyNoyaStateContext.Provider value={noyaManager}>
246
+ <AnyNoyaStateContext.Provider value={contextValue}>
206
247
  <ConnectedUsersContext.Provider
207
248
  value={noyaManager.connectedUsersManager}
208
249
  >
@@ -232,17 +273,19 @@ export function createNoyaContext<
232
273
  path?: PathKey[] | string | ((value: S) => any),
233
274
  options?: Pick<ObservableOptions, "isEqual">
234
275
  ) {
235
- const { multiplayerStateManager: ms } = useAnyNoyaStateContext();
276
+ const { noyaManager } = useAnyNoyaStateContext();
236
277
 
237
278
  let actualPath: PathKey[] | string =
238
279
  typeof path === "function" || !path ? "" : path;
239
280
 
240
281
  const mappedObservable = useMemo(() => {
241
282
  if (typeof path === "function") {
242
- return ms.optimisticState$.map(path, { isEqual: options?.isEqual });
283
+ return noyaManager.multiplayerStateManager.optimisticState$.map(path, {
284
+ isEqual: options?.isEqual,
285
+ });
243
286
  }
244
- return ms.optimisticState$;
245
- }, [ms, path, options?.isEqual]);
287
+ return noyaManager.multiplayerStateManager.optimisticState$;
288
+ }, [noyaManager, path, options?.isEqual]);
246
289
 
247
290
  const value = useObservable(mappedObservable, actualPath);
248
291
 
@@ -262,7 +305,7 @@ export function createNoyaContext<
262
305
  | [value: SetStateAction<GetAtPath<S, P>>]
263
306
  ) => void;
264
307
  function useSetValue<P extends PathKey[] | string>(path?: P) {
265
- const { multiplayerStateManager: ms } = useAnyNoyaStateContext();
308
+ const { noyaManager } = useAnyNoyaStateContext();
266
309
 
267
310
  const setValue = useCallback(
268
311
  (
@@ -272,9 +315,13 @@ export function createNoyaContext<
272
315
  ): void => {
273
316
  const [metadata, value] = args.length === 2 ? args : [{}, args[0]];
274
317
 
275
- ms.setStateAtPath(metadata, (path ?? "") as P, value as never);
318
+ noyaManager.multiplayerStateManager.setStateAtPath(
319
+ metadata,
320
+ (path ?? "") as P,
321
+ value as never
322
+ );
276
323
  },
277
- [ms, path]
324
+ [noyaManager, path]
278
325
  );
279
326
 
280
327
  return setValue;
@@ -323,9 +370,9 @@ export function createNoyaContext<
323
370
  }
324
371
 
325
372
  function useStateManager() {
326
- const { multiplayerStateManager: ms } = useAnyNoyaStateContext();
373
+ const { noyaManager } = useAnyNoyaStateContext();
327
374
 
328
- return ms as MultiplayerStateManager<S, M>;
375
+ return noyaManager.multiplayerStateManager as MultiplayerStateManager<S, M>;
329
376
  }
330
377
 
331
378
  function useEphemeralUserDataManager() {
@@ -341,19 +388,41 @@ export function createNoyaContext<
341
388
  }
342
389
 
343
390
  function useNoyaManager() {
344
- return useAnyNoyaStateContext() as NoyaManager<S, M, E, MenuT>;
391
+ return useAnyNoyaStateContext().noyaManager as NoyaManager<S, M, E, MenuT>;
345
392
  }
346
393
 
347
394
  function useLeftMenuItems() {
348
395
  const { menuManager } = useNoyaManager();
396
+
349
397
  return useObservable(menuManager.leftMenuItems$);
350
398
  }
351
399
 
400
+ function useSetLeftMenuItems(leftMenuItems?: MenuItem<MenuT>[]) {
401
+ const { menuManager } = useNoyaManager();
402
+
403
+ useEffect(() => {
404
+ if (leftMenuItems) {
405
+ menuManager.setLeftMenuItems(leftMenuItems);
406
+ }
407
+ }, [menuManager, leftMenuItems]);
408
+ }
409
+
352
410
  function useRightMenuItems() {
353
411
  const { menuManager } = useNoyaManager();
412
+
354
413
  return useObservable(menuManager.rightMenuItems$);
355
414
  }
356
415
 
416
+ function useSetRightMenuItems(rightMenuItems?: MenuItem<MenuT>[]) {
417
+ const { menuManager } = useNoyaManager();
418
+
419
+ useEffect(() => {
420
+ if (rightMenuItems) {
421
+ menuManager.setRightMenuItems(rightMenuItems);
422
+ }
423
+ }, [menuManager, rightMenuItems]);
424
+ }
425
+
357
426
  function useHandleMenuItem(callback: (type: MenuT) => void) {
358
427
  const { menuManager } = useNoyaManager();
359
428
 
@@ -368,6 +437,20 @@ export function createNoyaContext<
368
437
  return useCallback((type: MenuT) => menuManager.emit(type), [menuManager]);
369
438
  }
370
439
 
440
+ function useMenu(options: {
441
+ leftMenuItems?: MenuItem<MenuT>[];
442
+ rightMenuItems?: MenuItem<MenuT>[];
443
+ onSelectMenuItem?: (type: MenuT) => void;
444
+ }) {
445
+ const { leftMenuItems, rightMenuItems, onSelectMenuItem } = options;
446
+
447
+ useSetLeftMenuItems(leftMenuItems);
448
+ useSetRightMenuItems(rightMenuItems);
449
+
450
+ const noop = useCallback(() => {}, []);
451
+ useHandleMenuItem(onSelectMenuItem ?? noop);
452
+ }
453
+
371
454
  return {
372
455
  Context: NoyaStateContext,
373
456
  Provider: NoyaStateProvider,
@@ -377,9 +460,12 @@ export function createNoyaContext<
377
460
  useStateManager,
378
461
  useEphemeralUserDataManager,
379
462
  useLeftMenuItems,
463
+ useSetLeftMenuItems,
380
464
  useRightMenuItems,
465
+ useSetRightMenuItems,
381
466
  useHandleMenuItem,
382
467
  useOnSelectMenuItemCallback,
383
468
  useNoyaManager,
469
+ useMenu,
384
470
  };
385
471
  }
package/src/noyaApp.ts CHANGED
@@ -180,7 +180,10 @@ export function useNoyaState<
180
180
  return isEmbeddedApp()
181
181
  ? parentFrameSync<S, M, E, MenuT>({ debug: options?.debug })
182
182
  : multiplayerUrl
183
- ? webSocketSync<S, M, E, MenuT>(multiplayerUrl)
183
+ ? webSocketSync<S, M, E, MenuT>({
184
+ url: multiplayerUrl,
185
+ debug: options?.debug,
186
+ })
184
187
  : options?.offlineStorageKey
185
188
  ? localStorageSync<S, M, E, MenuT>({ key: options.offlineStorageKey })
186
189
  : stubSync<S, M, E, MenuT>();