@seriousgaming/sdk 0.0.0-stage → 1.0.0-alpha.2

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.
Files changed (170) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +1 -0
  3. package/README.md +33 -2
  4. package/lib/build/callbacks.d.ts +998 -0
  5. package/lib/build/callbacks.js +32 -0
  6. package/lib/build/context-merge.d.ts +59 -0
  7. package/lib/build/context-merge.js +118 -0
  8. package/lib/build/document.d.ts +36 -0
  9. package/lib/build/document.js +8 -0
  10. package/lib/build/encoding.d.ts +26 -0
  11. package/lib/build/encoding.js +78 -0
  12. package/lib/build/endpoints.d.ts +421 -0
  13. package/lib/build/endpoints.js +46 -0
  14. package/lib/build/hooks.d.ts +74 -0
  15. package/lib/build/hooks.js +1 -0
  16. package/lib/build/index.d.ts +18 -0
  17. package/lib/build/index.js +16 -0
  18. package/lib/build/llm.d.ts +166 -0
  19. package/lib/build/llm.js +17 -0
  20. package/lib/build/resource-schema.d.ts +1048 -0
  21. package/lib/build/resource-schema.js +7 -0
  22. package/lib/build/scheduling.d.ts +112 -0
  23. package/lib/build/scheduling.js +217 -0
  24. package/lib/build/seed.d.ts +51 -0
  25. package/lib/build/seed.js +89 -0
  26. package/lib/build/signatures.d.ts +372 -0
  27. package/lib/build/signatures.js +1 -0
  28. package/lib/build/speech.d.ts +102 -0
  29. package/lib/build/speech.js +11 -0
  30. package/lib/build/tick-validation.d.ts +23 -0
  31. package/lib/build/tick-validation.js +96 -0
  32. package/lib/build/timer.d.ts +74 -0
  33. package/lib/build/timer.js +1 -0
  34. package/lib/build/validators.d.ts +116 -0
  35. package/lib/build/validators.js +1 -0
  36. package/lib/commands.d.ts +357 -0
  37. package/lib/commands.js +14 -0
  38. package/lib/e2e.d.ts +238 -0
  39. package/lib/e2e.js +248 -0
  40. package/lib/projection.d.ts +266 -0
  41. package/lib/projection.js +23 -0
  42. package/lib/testing/index.d.ts +13 -0
  43. package/lib/testing/index.js +13 -0
  44. package/lib/testing/logic-args.d.ts +177 -0
  45. package/lib/testing/logic-args.js +229 -0
  46. package/lib/testing/stub-services.d.ts +41 -0
  47. package/lib/testing/stub-services.js +176 -0
  48. package/lib/ui/CrossTeamDataContext.d.ts +36 -0
  49. package/lib/ui/CrossTeamDataContext.js +32 -0
  50. package/lib/ui/PresentationContext.d.ts +72 -0
  51. package/lib/ui/PresentationContext.js +13 -0
  52. package/lib/ui/PresentationWrapper.d.ts +12 -0
  53. package/lib/ui/PresentationWrapper.js +78 -0
  54. package/lib/ui/SessionUserInterfaceCallbacksContext.d.ts +3 -0
  55. package/lib/ui/SessionUserInterfaceCallbacksContext.js +7 -0
  56. package/lib/ui/SessionUserInterfaceDataContext.d.ts +103 -0
  57. package/lib/ui/SessionUserInterfaceDataContext.js +17 -0
  58. package/lib/ui/SessionUserInterfaceHookFailuresContext.d.ts +44 -0
  59. package/lib/ui/SessionUserInterfaceHookFailuresContext.js +15 -0
  60. package/lib/ui/SessionUserInterfaceHostOverlaysContext.d.ts +23 -0
  61. package/lib/ui/SessionUserInterfaceHostOverlaysContext.js +23 -0
  62. package/lib/ui/SessionUserInterfaceLocaleContext.d.ts +11 -0
  63. package/lib/ui/SessionUserInterfaceLocaleContext.js +13 -0
  64. package/lib/ui/SessionUserInterfaceMetaContext.d.ts +39 -0
  65. package/lib/ui/SessionUserInterfaceMetaContext.js +13 -0
  66. package/lib/ui/SessionUserInterfaceParticipantsContext.d.ts +12 -0
  67. package/lib/ui/SessionUserInterfaceParticipantsContext.js +16 -0
  68. package/lib/ui/SessionUserInterfaceTeamConfigurationContext.d.ts +53 -0
  69. package/lib/ui/SessionUserInterfaceTeamConfigurationContext.js +23 -0
  70. package/lib/ui/SessionUserInterfaceTeamLinksContext.d.ts +56 -0
  71. package/lib/ui/SessionUserInterfaceTeamLinksContext.js +12 -0
  72. package/lib/ui/SessionUserInterfaceTeamsContext.d.ts +13 -0
  73. package/lib/ui/SessionUserInterfaceTeamsContext.js +13 -0
  74. package/lib/ui/SessionUserInterfaceThemeContext.d.ts +9 -0
  75. package/lib/ui/SessionUserInterfaceThemeContext.js +7 -0
  76. package/lib/ui/SessionUserInterfaceThemePreferenceContext.d.ts +3 -0
  77. package/lib/ui/SessionUserInterfaceThemePreferenceContext.js +7 -0
  78. package/lib/ui/SessionUserInterfaceWalkthroughLinkContext.d.ts +42 -0
  79. package/lib/ui/SessionUserInterfaceWalkthroughLinkContext.js +26 -0
  80. package/lib/ui/SessionUserInterfaceWrapper.d.ts +8 -0
  81. package/lib/ui/SessionUserInterfaceWrapper.js +321 -0
  82. package/lib/ui/SettingsEditorCallbacksContext.d.ts +3 -0
  83. package/lib/ui/SettingsEditorCallbacksContext.js +7 -0
  84. package/lib/ui/SettingsEditorContext.d.ts +33 -0
  85. package/lib/ui/SettingsEditorContext.js +16 -0
  86. package/lib/ui/SettingsEditorLocaleContext.d.ts +13 -0
  87. package/lib/ui/SettingsEditorLocaleContext.js +15 -0
  88. package/lib/ui/SettingsEditorThemeContext.d.ts +9 -0
  89. package/lib/ui/SettingsEditorThemeContext.js +7 -0
  90. package/lib/ui/SettingsEditorThemePreferenceContext.d.ts +3 -0
  91. package/lib/ui/SettingsEditorThemePreferenceContext.js +7 -0
  92. package/lib/ui/SettingsEditorWrapper.d.ts +13 -0
  93. package/lib/ui/SettingsEditorWrapper.js +74 -0
  94. package/lib/ui/UserInterfaceCallbacksContext.d.ts +3 -0
  95. package/lib/ui/UserInterfaceCallbacksContext.js +7 -0
  96. package/lib/ui/UserInterfaceDataContext.d.ts +78 -0
  97. package/lib/ui/UserInterfaceDataContext.js +11 -0
  98. package/lib/ui/UserInterfaceLocaleContext.d.ts +13 -0
  99. package/lib/ui/UserInterfaceLocaleContext.js +15 -0
  100. package/lib/ui/UserInterfaceOwnTeamContext.d.ts +25 -0
  101. package/lib/ui/UserInterfaceOwnTeamContext.js +26 -0
  102. package/lib/ui/UserInterfaceOwnTeamJoinLinkContext.d.ts +52 -0
  103. package/lib/ui/UserInterfaceOwnTeamJoinLinkContext.js +13 -0
  104. package/lib/ui/UserInterfaceParticipantContext.d.ts +16 -0
  105. package/lib/ui/UserInterfaceParticipantContext.js +24 -0
  106. package/lib/ui/UserInterfaceParticipantsContext.d.ts +12 -0
  107. package/lib/ui/UserInterfaceParticipantsContext.js +13 -0
  108. package/lib/ui/UserInterfaceRunKindContext.d.ts +31 -0
  109. package/lib/ui/UserInterfaceRunKindContext.js +31 -0
  110. package/lib/ui/UserInterfaceTeamsContext.d.ts +12 -0
  111. package/lib/ui/UserInterfaceTeamsContext.js +13 -0
  112. package/lib/ui/UserInterfaceThemeContext.d.ts +9 -0
  113. package/lib/ui/UserInterfaceThemeContext.js +7 -0
  114. package/lib/ui/UserInterfaceThemePreferenceContext.d.ts +3 -0
  115. package/lib/ui/UserInterfaceThemePreferenceContext.js +7 -0
  116. package/lib/ui/UserInterfaceTimerContext.d.ts +10 -0
  117. package/lib/ui/UserInterfaceTimerContext.js +12 -0
  118. package/lib/ui/UserInterfaceValidationContext.d.ts +25 -0
  119. package/lib/ui/UserInterfaceValidationContext.js +14 -0
  120. package/lib/ui/UserInterfaceViewerRoleContext.d.ts +14 -0
  121. package/lib/ui/UserInterfaceViewerRoleContext.js +17 -0
  122. package/lib/ui/UserInterfaceWrapper.d.ts +8 -0
  123. package/lib/ui/UserInterfaceWrapper.js +219 -0
  124. package/lib/ui/expectedParentOrigin.d.ts +10 -0
  125. package/lib/ui/expectedParentOrigin.js +32 -0
  126. package/lib/ui/index.d.ts +50 -0
  127. package/lib/ui/index.js +52 -0
  128. package/lib/ui/internal/SurfaceGate.d.ts +19 -0
  129. package/lib/ui/internal/SurfaceGate.js +17 -0
  130. package/lib/ui/internal/SurfaceScope.d.ts +17 -0
  131. package/lib/ui/internal/SurfaceScope.js +16 -0
  132. package/lib/ui/internal/createContexts.d.ts +50 -0
  133. package/lib/ui/internal/createContexts.js +32 -0
  134. package/lib/ui/internal/document-attributes.d.ts +9 -0
  135. package/lib/ui/internal/document-attributes.js +87 -0
  136. package/lib/ui/internal/surface-timer.d.ts +3 -0
  137. package/lib/ui/internal/surface-timer.js +11 -0
  138. package/lib/ui/internal/useLatestRef.d.ts +7 -0
  139. package/lib/ui/internal/useLatestRef.js +11 -0
  140. package/lib/ui/internal/useOptimisticMerge.d.ts +19 -0
  141. package/lib/ui/internal/useOptimisticMerge.js +28 -0
  142. package/lib/ui/internal/useSurfaceControls.d.ts +52 -0
  143. package/lib/ui/internal/useSurfaceControls.js +19 -0
  144. package/lib/ui/internal/useTypedPastState.d.ts +17 -0
  145. package/lib/ui/internal/useTypedPastState.js +17 -0
  146. package/lib/ui/mutation-commit.d.ts +32 -0
  147. package/lib/ui/mutation-commit.js +1 -0
  148. package/lib/ui/mutation-outcome.d.ts +66 -0
  149. package/lib/ui/mutation-outcome.js +49 -0
  150. package/lib/ui/request-id.d.ts +18 -0
  151. package/lib/ui/request-id.js +44 -0
  152. package/lib/ui/testing.d.ts +365 -0
  153. package/lib/ui/testing.js +572 -0
  154. package/lib/ui/tick-snapshot.d.ts +28 -0
  155. package/lib/ui/tick-snapshot.js +34 -0
  156. package/lib/ui/ui-protocol.d.ts +799 -0
  157. package/lib/ui/ui-protocol.js +50 -0
  158. package/lib/ui/useAsset.d.ts +80 -0
  159. package/lib/ui/useAsset.js +139 -0
  160. package/lib/ui/useEndpointCallbacks.d.ts +31 -0
  161. package/lib/ui/useEndpointCallbacks.js +68 -0
  162. package/lib/ui/useHostChannel.d.ts +90 -0
  163. package/lib/ui/useHostChannel.js +338 -0
  164. package/lib/ui/useMutationReporter.d.ts +100 -0
  165. package/lib/ui/useMutationReporter.js +97 -0
  166. package/lib/ui/usePastState.d.ts +39 -0
  167. package/lib/ui/usePastState.js +63 -0
  168. package/lib/ui/useViewerStorage.d.ts +54 -0
  169. package/lib/ui/useViewerStorage.js +141 -0
  170. package/package.json +89 -3
@@ -0,0 +1,78 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useState } from 'react';
3
+ import { useDocumentAttributes } from './internal/document-attributes.js';
4
+ import { SurfaceGate } from './internal/SurfaceGate.js';
5
+ import { SurfaceScope } from './internal/SurfaceScope.js';
6
+ import { useTypedPastState } from './internal/useTypedPastState.js';
7
+ import { PresentationContext, } from './PresentationContext.js';
8
+ import { useHostChannel } from './useHostChannel.js';
9
+ /**
10
+ * The session, or the news that there is none, gates first paint like the
11
+ * rest: a deck that painted before knowing would flash its 'no session yet'
12
+ * placeholders at a room that is mid-game.
13
+ */
14
+ const REQUIRED_MESSAGES = [
15
+ 'setPresentation',
16
+ 'setSettings',
17
+ 'setTheme',
18
+ 'setLocale',
19
+ 'setAssetUrls',
20
+ ];
21
+ /**
22
+ * Wrap a presentation bundle (§6.15). Read-only: there is nothing here to
23
+ * write with, and the host would refuse it if there were.
24
+ */
25
+ export function PresentationWrapper({ children, fallback = _jsx("div", { children: "Loading..." }), targetWindow = window.parent, }) {
26
+ const [game, setGame] = useState(undefined);
27
+ const [session, setSession] = useState(null);
28
+ const [settings, setSettings] = useState(undefined);
29
+ const [theme, setTheme] = useState(undefined);
30
+ const [locale, setLocale] = useState(undefined);
31
+ const { isInitialized, expectedParentOrigin, getPastState: getPastStateRaw, getAssetUrl, assetUrls, sessionKey, } = useHostChannel({
32
+ targetWindow,
33
+ label: 'PresentationWrapper',
34
+ requiredMessages: REQUIRED_MESSAGES,
35
+ onMessage: (msg, { markReceived }) => {
36
+ if (msg.type === 'setPresentation') {
37
+ setGame(msg.payload.game);
38
+ setSession(msg.payload.session);
39
+ markReceived('setPresentation');
40
+ }
41
+ else if (msg.type === 'setSettings') {
42
+ setSettings(msg.payload);
43
+ markReceived('setSettings');
44
+ }
45
+ else if (msg.type === 'setTheme') {
46
+ setTheme(msg.payload);
47
+ markReceived('setTheme');
48
+ }
49
+ else if (msg.type === 'setLocale') {
50
+ setLocale(msg.payload);
51
+ markReceived('setLocale');
52
+ }
53
+ },
54
+ });
55
+ useDocumentAttributes(locale?.locale, theme?.mode);
56
+ const hasSession = session !== null;
57
+ const guardedRaw = useCallback((query) => hasSession
58
+ ? getPastStateRaw(query)
59
+ : Promise.reject(new Error('There is no session, so there are no past rounds to read')), [hasSession, getPastStateRaw]);
60
+ const getPastState = useTypedPastState(guardedRaw);
61
+ const value = useMemo(() => game && theme && locale
62
+ ? {
63
+ game,
64
+ session: session,
65
+ settings: settings ?? {},
66
+ theme,
67
+ locale,
68
+ getPastState,
69
+ getAssetUrl,
70
+ }
71
+ : undefined, [game, session, settings, theme, locale, getPastState, getAssetUrl]);
72
+ const storageScope = useMemo(() => ({
73
+ sessionKey,
74
+ surface: 'presentation',
75
+ viewer: 'facilitator',
76
+ }), [sessionKey]);
77
+ return (_jsx(SurfaceGate, { expectedParentOrigin: expectedParentOrigin, ready: isInitialized && value !== undefined, fallback: fallback, children: _jsx(SurfaceScope, { storage: storageScope, assetUrls: assetUrls, getAssetUrl: getAssetUrl, locale: locale?.locale, getPastState: getPastState, children: _jsx(PresentationContext.Provider, { value: value, children: children }) }) }));
78
+ }
@@ -0,0 +1,3 @@
1
+ import type { SessionUserInterfaceCallbacks } from '../build/callbacks.js';
2
+ export declare const SessionUserInterfaceCallbacksContext: import("react").Context<SessionUserInterfaceCallbacks | undefined>;
3
+ export declare const useSessionUserInterfaceCallbacks: () => SessionUserInterfaceCallbacks;
@@ -0,0 +1,7 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceCallbacks',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceCallbacksContext = Context;
7
+ export const useSessionUserInterfaceCallbacks = useValue;
@@ -0,0 +1,103 @@
1
+ import type { ContextUpdate } from '../build/context-merge.js';
2
+ import type { TimerState } from '../build/timer.js';
3
+ import type { SetDataOptions } from './UserInterfaceDataContext.js';
4
+ /**
5
+ * Session-level data context for session user interfaces.
6
+ *
7
+ * Unlike the player data context (which holds a single team's context),
8
+ * this holds `SessionData`: the shared store once, and every team's own
9
+ * context keyed by teamId.
10
+ */
11
+ export type TeamState<TTeamContext = Record<string, unknown>> = {
12
+ /**
13
+ * This team's own context, projected onto the capabilities this surface
14
+ * declared in `reads` and `writes`. Team and private scope only: shared
15
+ * capabilities are in `SessionData.shared`, once.
16
+ */
17
+ context: TTeamContext;
18
+ /** The number of ticks this team has completed: the same count a player surface reads as `completedTicks`. */
19
+ completedTicks: number;
20
+ /**
21
+ * Timer state for this team: the same `TimerState` a player surface reads
22
+ * from `useUserInterfaceTimer()`.
23
+ */
24
+ timer: TimerState;
25
+ /**
26
+ * Monotonic version of this team's state, incremented by the host on every
27
+ * delivery. The wrapper reads it to detect an update it never received and
28
+ * ask for a fresh snapshot.
29
+ *
30
+ * Required, so the wrapper always has a baseline to compare a delta
31
+ * against. It was optional briefly, which bought one branch that adopted a
32
+ * delta unconditionally when no baseline existed: silent last-write-wins,
33
+ * and the only place in the delta design that resolved a conflict by
34
+ * guessing. A surface never reads this field; `makeTeamState` exists so a
35
+ * test fixture need not think about it.
36
+ */
37
+ revision: number;
38
+ };
39
+ export type SharedState<TSharedContext = Record<string, unknown>> = {
40
+ /**
41
+ * The session's shared store, projected onto the shared-scope capabilities
42
+ * this surface declared in `reads` and `writes`. One value per capability,
43
+ * however many teams there are, and present when there are none.
44
+ */
45
+ context: TSharedContext;
46
+ /**
47
+ * Monotonic version of the shared state, incremented by the host on every
48
+ * delivery, read by the wrapper exactly as it reads `TeamState.revision`.
49
+ */
50
+ revision: number;
51
+ };
52
+ /**
53
+ * Everything a session surface is shown of the session's state.
54
+ *
55
+ * Type it with the generated `SessionData` in the surface's `types.ts`, which
56
+ * fills both parameters from the surface's declarations.
57
+ */
58
+ export type SessionData<TTeamContext = Record<string, unknown>, TSharedContext = Record<string, unknown>> = {
59
+ /** The shared store, once for the session. */
60
+ shared: SharedState<TSharedContext>;
61
+ /** Per-team state keyed by teamId (e.g. "team-1") */
62
+ teams: Record<string, TeamState<TTeamContext>>;
63
+ };
64
+ type SessionUserInterfaceDataContextValue<T extends SessionData<object, object>, A, S extends Record<string, unknown> = Record<string, unknown>, W extends Record<string, unknown> = Record<string, unknown>> = {
65
+ sessionData: T;
66
+ /** The settings resources this surface declared, keyed by identifier (§8). */
67
+ settings: A;
68
+ /**
69
+ * Write context data. The two-argument form deep-merges into one team's
70
+ * context (send only the fields you changed — object values merge
71
+ * recursively, arrays and scalars replace). The one-argument form writes
72
+ * shared-scope capabilities session-wide: the host fans the value out to
73
+ * every team atomically, and only capabilities this UI declares in
74
+ * `writes` are accepted. Type the shared form with the generated
75
+ * `SharedWrites` as `S`, and the team form with the generated `TeamWrites`
76
+ * as `W`, so a team write naming a shared capability fails to compile
77
+ * rather than being refused at run time.
78
+ *
79
+ * Both forms take `deletes`, paths removed after the update merges, as a
80
+ * player surface's `setData` does. A team form's delete must name a
81
+ * team-scope capability this UI declares in `writes`, and a shared form's
82
+ * a shared one; anything else is refused.
83
+ *
84
+ * ```typescript
85
+ * setData(teamId, {}, { deletes: [['pinboard', 'Notes', noteId]] });
86
+ * setData({}, { deletes: ['market.Offers.o-17'] });
87
+ * ```
88
+ */
89
+ setData: {
90
+ (teamId: string, update: ContextUpdate<W>, options?: SetDataOptions): Promise<void>;
91
+ (update: ContextUpdate<S>, options?: SetDataOptions): Promise<void>;
92
+ };
93
+ };
94
+ declare const SessionUserInterfaceDataContext: import("react").Context<SessionUserInterfaceDataContextValue<SessionData<object, object>, unknown, Record<string, unknown>, Record<string, unknown>> | undefined>;
95
+ /**
96
+ * The session's data and the session surface's `setData`.
97
+ *
98
+ * Type it with the generated types in the surface's `types.ts`:
99
+ * `useSessionUserInterfaceData<SessionData, Settings, SharedWrites, TeamWrites>()`.
100
+ * Each parameter may be left at its default, which accepts any capability.
101
+ */
102
+ declare function useSessionUserInterfaceData<T extends SessionData<object, object> = SessionData, A = unknown, S extends Record<string, unknown> = Record<string, unknown>, W extends Record<string, unknown> = Record<string, unknown>>(): SessionUserInterfaceDataContextValue<T, A, S, W>;
103
+ export { useSessionUserInterfaceData, SessionUserInterfaceDataContext };
@@ -0,0 +1,17 @@
1
+ import { createContext, useContext } from 'react';
2
+ const SessionUserInterfaceDataContext = createContext(undefined);
3
+ /**
4
+ * The session's data and the session surface's `setData`.
5
+ *
6
+ * Type it with the generated types in the surface's `types.ts`:
7
+ * `useSessionUserInterfaceData<SessionData, Settings, SharedWrites, TeamWrites>()`.
8
+ * Each parameter may be left at its default, which accepts any capability.
9
+ */
10
+ function useSessionUserInterfaceData() {
11
+ const ctx = useContext(SessionUserInterfaceDataContext);
12
+ if (!ctx) {
13
+ throw new Error('useSessionUserInterfaceData must be used inside a SessionUserInterfaceWrapper');
14
+ }
15
+ return ctx;
16
+ }
17
+ export { useSessionUserInterfaceData, SessionUserInterfaceDataContext };
@@ -0,0 +1,44 @@
1
+ import type { HookSignal } from '../build/resource-schema.js';
2
+ /**
3
+ * A hook chain that threw, reported to the session surface after the fact.
4
+ *
5
+ * Hooks fire *after* the runtime applies the lifecycle change, so a throwing
6
+ * hook never prevents the change: a participant that moved has moved, and the
7
+ * mutation that moved them has already settled `ok: true`. What failed is a
8
+ * consequence, not the mutation, which is why this arrives as its own push
9
+ * rather than as a failed `mutation:response`.
10
+ *
11
+ * Whether the session is left inconsistent depends on what the hook was doing.
12
+ * A hook seeding per-participant state is the usual case, and the usual
13
+ * remedy is to tell the facilitator that this team's state may be stale rather
14
+ * than to retry anything.
15
+ */
16
+ export interface SessionHookFailure {
17
+ /** The signal whose chain threw, e.g. `participantMove`. */
18
+ signal: HookSignal;
19
+ /** The team whose context the failing chain was running against. */
20
+ teamId: string;
21
+ /** The error the hook threw, as the host reported it. */
22
+ message: string;
23
+ }
24
+ /**
25
+ * Value exposed to consumers of {@link useSessionUserInterfaceHookFailures}.
26
+ *
27
+ * `failures` accumulates until cleared, because a facilitator who looked away
28
+ * should still find out that something went wrong. `clearFailures` empties the
29
+ * buffer once they have been shown.
30
+ */
31
+ export interface SessionUserInterfaceHookFailuresValue {
32
+ failures: SessionHookFailure[];
33
+ clearFailures: () => void;
34
+ }
35
+ export declare const SessionUserInterfaceHookFailuresContext: import("react").Context<SessionUserInterfaceHookFailuresValue | undefined>;
36
+ /**
37
+ * Subscribe to hook chains that threw anywhere in the session.
38
+ *
39
+ * The host also surfaces these to the operator in its own chrome, so a surface
40
+ * that renders nothing is not hiding them. Render them anyway when your game's
41
+ * hooks carry state the surface displays: the facilitator who caused the
42
+ * failure is looking at your surface, not the host's.
43
+ */
44
+ export declare const useSessionUserInterfaceHookFailures: () => SessionUserInterfaceHookFailuresValue;
@@ -0,0 +1,15 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceHookFailures',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceHookFailuresContext = Context;
7
+ /**
8
+ * Subscribe to hook chains that threw anywhere in the session.
9
+ *
10
+ * The host also surfaces these to the operator in its own chrome, so a surface
11
+ * that renders nothing is not hiding them. Render them anyway when your game's
12
+ * hooks carry state the surface displays: the facilitator who caused the
13
+ * failure is looking at your surface, not the host's.
14
+ */
15
+ export const useSessionUserInterfaceHookFailures = useValue;
@@ -0,0 +1,23 @@
1
+ import type { HostOverlay } from '../build/callbacks.js';
2
+ export type { HostOverlay };
3
+ export declare const SessionUserInterfaceHostOverlaysContext: import("react").Context<HostOverlay[]>;
4
+ /**
5
+ * Hook listing the host overlays this host offers for this session.
6
+ *
7
+ * Render a control only for an overlay in this list. An empty list is the
8
+ * honest default before the host has answered, and also the correct answer for
9
+ * a host that delegates none of them, so a surface that renders a guide button
10
+ * unconditionally shows a facilitator a button that cannot work.
11
+ *
12
+ * ```tsx
13
+ * const overlays = useSessionUserInterfaceHostOverlays();
14
+ * const { openHostOverlay } = useSessionUserInterfaceCallbacks();
15
+ *
16
+ * {overlays.includes('facilitator-guide') && (
17
+ * <Button onClick={() => void openHostOverlay('facilitator-guide')}>Guide</Button>
18
+ * )}
19
+ * ```
20
+ *
21
+ * @returns The overlays this host offers, empty until the host answers
22
+ */
23
+ export declare const useSessionUserInterfaceHostOverlays: () => HostOverlay[];
@@ -0,0 +1,23 @@
1
+ import { createDefaultedContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createDefaultedContext([]);
3
+ export const SessionUserInterfaceHostOverlaysContext = Context;
4
+ /**
5
+ * Hook listing the host overlays this host offers for this session.
6
+ *
7
+ * Render a control only for an overlay in this list. An empty list is the
8
+ * honest default before the host has answered, and also the correct answer for
9
+ * a host that delegates none of them, so a surface that renders a guide button
10
+ * unconditionally shows a facilitator a button that cannot work.
11
+ *
12
+ * ```tsx
13
+ * const overlays = useSessionUserInterfaceHostOverlays();
14
+ * const { openHostOverlay } = useSessionUserInterfaceCallbacks();
15
+ *
16
+ * {overlays.includes('facilitator-guide') && (
17
+ * <Button onClick={() => void openHostOverlay('facilitator-guide')}>Guide</Button>
18
+ * )}
19
+ * ```
20
+ *
21
+ * @returns The overlays this host offers, empty until the host answers
22
+ */
23
+ export const useSessionUserInterfaceHostOverlays = useValue;
@@ -0,0 +1,11 @@
1
+ export type SessionUserInterfaceLocale = {
2
+ locale: string;
3
+ };
4
+ export declare const SessionUserInterfaceLocaleContext: import("react").Context<SessionUserInterfaceLocale | undefined>;
5
+ /**
6
+ * Hook to access the current locale in a manage session user interface component.
7
+ *
8
+ * @returns Current locale object with locale string
9
+ * @throws Error if used outside SessionUserInterfaceWrapper
10
+ */
11
+ export declare const useSessionUserInterfaceLocale: () => SessionUserInterfaceLocale;
@@ -0,0 +1,13 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceLocale',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceLocaleContext = Context;
7
+ /**
8
+ * Hook to access the current locale in a manage session user interface component.
9
+ *
10
+ * @returns Current locale object with locale string
11
+ * @throws Error if used outside SessionUserInterfaceWrapper
12
+ */
13
+ export const useSessionUserInterfaceLocale = useValue;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The session's identity and lifecycle state, pushed on connect and again
3
+ * whenever any of it changes.
4
+ */
5
+ export type SessionMeta = {
6
+ sessionId: string;
7
+ /** Operator-facing session name. */
8
+ name: string;
9
+ /**
10
+ * The session is frozen and the host will refuse every mutation.
11
+ *
12
+ * A courtesy signal, not a security boundary: the host enforces the freeze
13
+ * itself on every write. Use it to disable controls and explain why, rather
14
+ * than offering affordances that will be denied.
15
+ */
16
+ readOnly: boolean;
17
+ /**
18
+ * Whether the session's waiting room is open. This is the read side of
19
+ * `setWaitingRoom`. The host usually renders its own waiting-room control
20
+ * too, so render from this value rather than from an optimistic local one.
21
+ */
22
+ waitingRoomOpen: boolean;
23
+ /**
24
+ * The code participants enter to join, or `null` when joining needs none
25
+ * or the runtime does not show one. How joining is secured is the
26
+ * runtime's choice, so this need not be a PIN, and a game must render it
27
+ * as an opaque string. Never embedded in a join URL: a facilitator reads
28
+ * the two out separately.
29
+ */
30
+ joinPin: string | null;
31
+ };
32
+ export declare const SessionUserInterfaceMetaContext: import("react").Context<SessionMeta | undefined>;
33
+ /**
34
+ * Hook to access the session's identity and lifecycle state.
35
+ *
36
+ * @returns The current {@link SessionMeta}
37
+ * @throws Error if used outside SessionUserInterfaceWrapper
38
+ */
39
+ export declare const useSessionUserInterfaceMeta: () => SessionMeta;
@@ -0,0 +1,13 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceMeta',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceMetaContext = Context;
7
+ /**
8
+ * Hook to access the session's identity and lifecycle state.
9
+ *
10
+ * @returns The current {@link SessionMeta}
11
+ * @throws Error if used outside SessionUserInterfaceWrapper
12
+ */
13
+ export const useSessionUserInterfaceMeta = useValue;
@@ -0,0 +1,12 @@
1
+ import type { Participant } from '../build/callbacks.js';
2
+ export declare const SessionUserInterfaceParticipantsContext: import("react").Context<Participant[] | undefined>;
3
+ /**
4
+ * Hook to access all participants across all teams in the session.
5
+ *
6
+ * Each participant has a `teamId` field for grouping by team. Updates
7
+ * reactively as participants join or leave.
8
+ *
9
+ * @returns Array of all participants across all teams
10
+ * @throws Error if used outside SessionUserInterfaceWrapper
11
+ */
12
+ export declare const useSessionUserInterfaceParticipants: () => Participant[];
@@ -0,0 +1,16 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceParticipants',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceParticipantsContext = Context;
7
+ /**
8
+ * Hook to access all participants across all teams in the session.
9
+ *
10
+ * Each participant has a `teamId` field for grouping by team. Updates
11
+ * reactively as participants join or leave.
12
+ *
13
+ * @returns Array of all participants across all teams
14
+ * @throws Error if used outside SessionUserInterfaceWrapper
15
+ */
16
+ export const useSessionUserInterfaceParticipants = useValue;
@@ -0,0 +1,53 @@
1
+ import type { SessionMode } from '../build/signatures.js';
2
+ /**
3
+ * How teams work in this session: the interaction mode, and the bounds the host
4
+ * will hold the surface to.
5
+ *
6
+ * Every bound here is for rendering honest affordances, not for enforcement.
7
+ * The host checks all of them itself on every mutation, so a surface that
8
+ * disables its own 'add team' control at the maximum is being polite, not
9
+ * authoritative, and must still handle a denial.
10
+ */
11
+ export type TeamConfiguration = {
12
+ mode: SessionMode;
13
+ /**
14
+ * Minimum team count the game is designed for. Enforced by the host at
15
+ * session creation only, and advisory thereafter, so treat it as guidance
16
+ * to display rather than a rule to block on.
17
+ */
18
+ min?: number;
19
+ /**
20
+ * The **effective** maximum team count, already resolved by the host as the
21
+ * lower of the game's declared maximum and the platform's own ceiling. It
22
+ * is not the number the manifest declared, and a surface that sourced the
23
+ * manifest value instead would disable its controls at the wrong point.
24
+ */
25
+ max: number;
26
+ /**
27
+ * Per-team participant guidance. Advisory: the host does not currently
28
+ * bound joining or participant moves on these, so use them for guidance
29
+ * text rather than to block a move.
30
+ */
31
+ perTeam?: {
32
+ minParticipants?: number;
33
+ maxParticipants?: number;
34
+ };
35
+ };
36
+ /**
37
+ * The value a surface holds before the host has sent `setTeamConfiguration`.
38
+ *
39
+ * `max: 0` is deliberately a value no game could mean, so a surface reading it
40
+ * is reading a bound that never applied. It should be unreachable in practice:
41
+ * `setTeamConfiguration` gates a session surface's first paint (#365), so the
42
+ * host has always spoken before any component renders. It survives as the
43
+ * context's default because a defaulted context needs one, and because a test
44
+ * rendering this provider directly should not silently inherit real bounds.
45
+ */
46
+ export declare const DEFAULT_TEAM_CONFIGURATION: TeamConfiguration;
47
+ export declare const SessionUserInterfaceTeamConfigurationContext: import("react").Context<TeamConfiguration>;
48
+ /**
49
+ * Hook to access the session's interaction mode and team bounds.
50
+ *
51
+ * @returns The current {@link TeamConfiguration}
52
+ */
53
+ export declare const useSessionUserInterfaceTeamConfiguration: () => TeamConfiguration;
@@ -0,0 +1,23 @@
1
+ import { createDefaultedContext } from './internal/createContexts.js';
2
+ /**
3
+ * The value a surface holds before the host has sent `setTeamConfiguration`.
4
+ *
5
+ * `max: 0` is deliberately a value no game could mean, so a surface reading it
6
+ * is reading a bound that never applied. It should be unreachable in practice:
7
+ * `setTeamConfiguration` gates a session surface's first paint (#365), so the
8
+ * host has always spoken before any component renders. It survives as the
9
+ * context's default because a defaulted context needs one, and because a test
10
+ * rendering this provider directly should not silently inherit real bounds.
11
+ */
12
+ export const DEFAULT_TEAM_CONFIGURATION = {
13
+ mode: 'independent',
14
+ max: 0,
15
+ };
16
+ const { Context, useValue } = createDefaultedContext(DEFAULT_TEAM_CONFIGURATION);
17
+ export const SessionUserInterfaceTeamConfigurationContext = Context;
18
+ /**
19
+ * Hook to access the session's interaction mode and team bounds.
20
+ *
21
+ * @returns The current {@link TeamConfiguration}
22
+ */
23
+ export const useSessionUserInterfaceTeamConfiguration = useValue;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * A team's facilitator-only links: how participants join it, and how to watch
3
+ * it without joining.
4
+ *
5
+ * These are facilitator-only. The host sends them to the session surface and to
6
+ * nothing else, because a join URL together with the session PIN is joinable
7
+ * capability. That is why they travel on their own message rather than riding
8
+ * on `TeamInfo`, which player surfaces also receive.
9
+ *
10
+ * There is no session-level entry. Every one names a team.
11
+ */
12
+ export type TeamLinks = {
13
+ teamId: string;
14
+ /**
15
+ * The join URL to render.
16
+ *
17
+ * A host may have several forms of the same link — a shortened one, a
18
+ * longer one on another domain, a canonical one carrying opaque ids — and
19
+ * choosing between them, including deciding a short link has expired, is
20
+ * the host's business. It sends the form it wants used, so a game never has
21
+ * to know which form it received. Encode *this* one in a QR code: the host
22
+ * chose the short form because a denser code is harder to scan across a
23
+ * room.
24
+ */
25
+ joinUrl: string;
26
+ /**
27
+ * An alternative for the one failure a game can help with: some networks
28
+ * block URL shorteners, and the facilitator who discovers that is standing
29
+ * in front of your surface. Absent when the host has no distinct
30
+ * alternative.
31
+ *
32
+ * Show it on request rather than beside `joinUrl` with equal weight. Two
33
+ * URLs on a projector is worse than one.
34
+ */
35
+ fallbackJoinUrl?: string;
36
+ /**
37
+ * Opens the team's player surface as an observer: a facilitator watching
38
+ * without joining, with no participant identity and no presence.
39
+ *
40
+ * Always present. Observing is required of every compliant host, because a
41
+ * facilitator has to be able to see what a team sees and a session UI that
42
+ * owns the canvas leaves nowhere else to put that. It admits nobody to the
43
+ * session, so unlike a join URL it is tooling rather than capability.
44
+ */
45
+ observeUrl: string;
46
+ };
47
+ export declare const SessionUserInterfaceTeamLinksContext: import("react").Context<TeamLinks[]>;
48
+ /**
49
+ * Hook to access each team's join and observe links.
50
+ *
51
+ * Does not gate first paint, so the list is empty until the host delivers it.
52
+ * Render a placeholder for that first frame rather than assuming a link exists.
53
+ *
54
+ * @returns One {@link TeamLinks} per team, or an empty array before they arrive
55
+ */
56
+ export declare const useSessionUserInterfaceTeamLinks: () => TeamLinks[];
@@ -0,0 +1,12 @@
1
+ import { createDefaultedContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createDefaultedContext([]);
3
+ export const SessionUserInterfaceTeamLinksContext = Context;
4
+ /**
5
+ * Hook to access each team's join and observe links.
6
+ *
7
+ * Does not gate first paint, so the list is empty until the host delivers it.
8
+ * Render a placeholder for that first frame rather than assuming a link exists.
9
+ *
10
+ * @returns One {@link TeamLinks} per team, or an empty array before they arrive
11
+ */
12
+ export const useSessionUserInterfaceTeamLinks = useValue;
@@ -0,0 +1,13 @@
1
+ import type { TeamInfo } from '../build/callbacks.js';
2
+ export type { TeamInfo };
3
+ export declare const SessionUserInterfaceTeamsContext: import("react").Context<TeamInfo[]>;
4
+ /**
5
+ * Hook to access the session's teams, sorted by stable index.
6
+ *
7
+ * The interaction mode and team bounds live in
8
+ * `useSessionUserInterfaceTeamConfiguration()` rather than here, so there is
9
+ * one home for how teams work and one for which teams exist.
10
+ *
11
+ * @returns Array of {@link TeamInfo}
12
+ */
13
+ export declare const useSessionUserInterfaceTeams: () => TeamInfo[];
@@ -0,0 +1,13 @@
1
+ import { createDefaultedContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createDefaultedContext([]);
3
+ export const SessionUserInterfaceTeamsContext = Context;
4
+ /**
5
+ * Hook to access the session's teams, sorted by stable index.
6
+ *
7
+ * The interaction mode and team bounds live in
8
+ * `useSessionUserInterfaceTeamConfiguration()` rather than here, so there is
9
+ * one home for how teams work and one for which teams exist.
10
+ *
11
+ * @returns Array of {@link TeamInfo}
12
+ */
13
+ export const useSessionUserInterfaceTeams = useValue;
@@ -0,0 +1,9 @@
1
+ import { type SurfaceModeColors } from './internal/createContexts.js';
2
+ export type SessionUserInterfaceModeColors = SurfaceModeColors;
3
+ export type SessionUserInterfaceTheme = {
4
+ mode: 'dark' | 'light';
5
+ dark: SessionUserInterfaceModeColors;
6
+ light: SessionUserInterfaceModeColors;
7
+ };
8
+ export declare const SessionUserInterfaceThemeContext: import("react").Context<SessionUserInterfaceTheme | undefined>;
9
+ export declare const useSessionUserInterfaceTheme: () => SessionUserInterfaceTheme;
@@ -0,0 +1,7 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceTheme',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceThemeContext = Context;
7
+ export const useSessionUserInterfaceTheme = useValue;
@@ -0,0 +1,3 @@
1
+ import type { ThemePreference } from '../build/callbacks.js';
2
+ export declare const SessionUserInterfaceThemePreferenceContext: import("react").Context<ThemePreference | undefined>;
3
+ export declare const useSessionUserInterfaceThemePreference: () => ThemePreference;
@@ -0,0 +1,7 @@
1
+ import { createRequiredContext } from './internal/createContexts.js';
2
+ const { Context, useValue } = createRequiredContext({
3
+ hookName: 'useSessionUserInterfaceThemePreference',
4
+ wrapperName: 'SessionUserInterfaceWrapper',
5
+ });
6
+ export const SessionUserInterfaceThemePreferenceContext = Context;
7
+ export const useSessionUserInterfaceThemePreference = useValue;