@diffenderfer-games/hub 0.0.0-stage → 2.0.0-next.1

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 (164) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +191 -3
  4. package/dist/auto.d.ts +36 -0
  5. package/dist/auto.d.ts.map +1 -0
  6. package/dist/auto.js +27 -0
  7. package/dist/auto.js.map +1 -0
  8. package/dist/daily.d.ts +2 -0
  9. package/dist/daily.js +1 -0
  10. package/dist/doctor/cli.mjs +268 -0
  11. package/dist/doctor/cli.mjs.map +1 -0
  12. package/dist/index.d.ts +12 -0
  13. package/dist/index.js +6 -0
  14. package/dist/input.d.ts +2 -0
  15. package/dist/input.js +3 -0
  16. package/dist/mp.d.ts +4 -0
  17. package/dist/mp.js +1 -0
  18. package/dist/race.d.ts +4 -0
  19. package/dist/race.js +1 -0
  20. package/dist/rooms.d.ts +4 -0
  21. package/dist/rooms.js +1 -0
  22. package/dist/shared/bridge.js +209 -0
  23. package/dist/shared/bridge.js.map +1 -0
  24. package/dist/shared/client-version.gen.js +7 -0
  25. package/dist/shared/client-version.gen.js.map +1 -0
  26. package/dist/shared/daily.d.ts +123 -0
  27. package/dist/shared/daily.d.ts.map +1 -0
  28. package/dist/shared/daily.js +191 -0
  29. package/dist/shared/daily.js.map +1 -0
  30. package/dist/shared/dom.js +48 -0
  31. package/dist/shared/dom.js.map +1 -0
  32. package/dist/shared/globals.js +102 -0
  33. package/dist/shared/globals.js.map +1 -0
  34. package/dist/shared/index.d.ts +706 -0
  35. package/dist/shared/index.d.ts.map +1 -0
  36. package/dist/shared/input.d.ts +730 -0
  37. package/dist/shared/input.d.ts.map +1 -0
  38. package/dist/shared/input.js +2718 -0
  39. package/dist/shared/input.js.map +1 -0
  40. package/dist/shared/latest-state.js +17 -0
  41. package/dist/shared/latest-state.js.map +1 -0
  42. package/dist/shared/mp.d.ts +9 -0
  43. package/dist/shared/mp.d.ts.map +1 -0
  44. package/dist/shared/mp.js +30 -0
  45. package/dist/shared/mp.js.map +1 -0
  46. package/dist/shared/multiplayer-types.d.ts +47 -0
  47. package/dist/shared/multiplayer-types.d.ts.map +1 -0
  48. package/dist/shared/page-stack.js +207 -0
  49. package/dist/shared/page-stack.js.map +1 -0
  50. package/dist/shared/race-types.d.ts +126 -0
  51. package/dist/shared/race-types.d.ts.map +1 -0
  52. package/dist/shared/race.d.ts +9 -0
  53. package/dist/shared/race.d.ts.map +1 -0
  54. package/dist/shared/race.js +53 -0
  55. package/dist/shared/race.js.map +1 -0
  56. package/dist/shared/room-types.d.ts +125 -0
  57. package/dist/shared/room-types.d.ts.map +1 -0
  58. package/dist/shared/rooms.d.ts +9 -0
  59. package/dist/shared/rooms.d.ts.map +1 -0
  60. package/dist/shared/rooms.js +62 -0
  61. package/dist/shared/rooms.js.map +1 -0
  62. package/dist/shared/runtime-opener.js +84 -0
  63. package/dist/shared/runtime-opener.js.map +1 -0
  64. package/dist/shared/social.d.ts +148 -0
  65. package/dist/shared/social.d.ts.map +1 -0
  66. package/dist/shared/social.js +73 -0
  67. package/dist/shared/social.js.map +1 -0
  68. package/dist/shared/src.js +2164 -0
  69. package/dist/shared/src.js.map +1 -0
  70. package/dist/shared/wire-types.d.ts +51 -0
  71. package/dist/shared/wire-types.d.ts.map +1 -0
  72. package/dist/social.d.ts +6 -0
  73. package/dist/social.js +3 -0
  74. package/dist/types.d.ts +1 -0
  75. package/dist/types.js +0 -0
  76. package/package.json +89 -6
  77. package/src/auto.ts +39 -0
  78. package/src/core/connection.ts +299 -0
  79. package/src/core/errors.ts +147 -0
  80. package/src/core/game-data.ts +38 -0
  81. package/src/core/hub-economy.ts +179 -0
  82. package/src/core/hub-progress.ts +205 -0
  83. package/src/core/hub.ts +131 -0
  84. package/src/core/menu-control.ts +61 -0
  85. package/src/core/offline/events.ts +50 -0
  86. package/src/core/offline/favorites.ts +21 -0
  87. package/src/core/offline/local-store.ts +261 -0
  88. package/src/core/offline/queue.ts +171 -0
  89. package/src/core/page.ts +74 -0
  90. package/src/core/rest/endpoint-types.ts +22 -0
  91. package/src/core/rest/rest-client.ts +152 -0
  92. package/src/core/rest/routes.gen.ts +90 -0
  93. package/src/core/storage/json-guards.ts +74 -0
  94. package/src/core/storage/key-value.ts +66 -0
  95. package/src/core/ticket.ts +43 -0
  96. package/src/core/types.ts +134 -0
  97. package/src/core/version/client-version.gen.ts +3 -0
  98. package/src/core/version/hub-version.ts +62 -0
  99. package/src/core/version/semver.ts +97 -0
  100. package/src/daily/daily-system.ts +161 -0
  101. package/src/daily/page-daily.ts +36 -0
  102. package/src/daily/types.ts +67 -0
  103. package/src/daily.ts +10 -0
  104. package/src/doctor/checks.ts +78 -0
  105. package/src/doctor/cli.ts +98 -0
  106. package/src/doctor/hub-version-fetch.ts +43 -0
  107. package/src/doctor/tsconfig.json +12 -0
  108. package/src/globals.ts +115 -0
  109. package/src/index.ts +50 -0
  110. package/src/input/device-state.ts +146 -0
  111. package/src/input/edges.ts +55 -0
  112. package/src/input/gamepad.ts +61 -0
  113. package/src/input/input-events.ts +32 -0
  114. package/src/input/input-registry.ts +164 -0
  115. package/src/input/input-system.ts +393 -0
  116. package/src/input/legacy-controls.ts +64 -0
  117. package/src/input/nav-state.ts +191 -0
  118. package/src/input/navigator.ts +171 -0
  119. package/src/input/on-screen-controls.ts +101 -0
  120. package/src/input/page-control.ts +43 -0
  121. package/src/input/page-input.ts +193 -0
  122. package/src/input/player-remaps.ts +77 -0
  123. package/src/input/source-values.ts +116 -0
  124. package/src/input/spatial.ts +47 -0
  125. package/src/input/types.ts +331 -0
  126. package/src/input/zero-config.ts +177 -0
  127. package/src/input.ts +22 -0
  128. package/src/mp.ts +10 -0
  129. package/src/overlay/controls-panel.ts +163 -0
  130. package/src/overlay/dom.ts +46 -0
  131. package/src/overlay/layout-clusters.ts +162 -0
  132. package/src/overlay/layout-geometry.ts +136 -0
  133. package/src/overlay/layout.ts +203 -0
  134. package/src/overlay/listener-scope.ts +23 -0
  135. package/src/overlay/on-screen-keyboard.ts +137 -0
  136. package/src/overlay/overlay.ts +208 -0
  137. package/src/overlay/styles.ts +54 -0
  138. package/src/overlay/virtual-controls.ts +262 -0
  139. package/src/race.ts +10 -0
  140. package/src/realtime/bridge.ts +121 -0
  141. package/src/realtime/cross-bundle.ts +29 -0
  142. package/src/realtime/fallback-notice.ts +48 -0
  143. package/src/realtime/hub-link.ts +65 -0
  144. package/src/realtime/latest-state.ts +33 -0
  145. package/src/realtime/multiplayer-forwarder.ts +28 -0
  146. package/src/realtime/multiplayer-types.ts +52 -0
  147. package/src/realtime/page-runtime.ts +60 -0
  148. package/src/realtime/race-forwarder.ts +59 -0
  149. package/src/realtime/race-types.ts +132 -0
  150. package/src/realtime/room-types.ts +125 -0
  151. package/src/realtime/rooms-forwarder.ts +79 -0
  152. package/src/realtime/runtime-api.ts +49 -0
  153. package/src/realtime/runtime-opener.ts +61 -0
  154. package/src/realtime/social-forwarder.ts +72 -0
  155. package/src/realtime/social-types.ts +78 -0
  156. package/src/realtime/types.ts +53 -0
  157. package/src/realtime/wire-types.ts +72 -0
  158. package/src/rooms.ts +10 -0
  159. package/src/social.ts +18 -0
  160. package/src/types.ts +13 -0
  161. package/src/uistack/page-stack.ts +45 -0
  162. package/src/uistack/play-suspension.ts +82 -0
  163. package/src/uistack/types.ts +76 -0
  164. package/src/uistack/ui-stack.ts +144 -0
@@ -0,0 +1,730 @@
1
+ //#region src/input/types.d.ts
2
+ /**
3
+ * The input system's public shapes (`hub.input`, docs/hub.md "Input system").
4
+ * A game declares named inputs that each read as 0..1 and maps each to
5
+ * keyboard, mouse, touch and gamepad sources.
6
+ */
7
+ /** The device the player is using right now. */
8
+ type InputSource = 'keyboard' | 'mouse' | 'gamepad' | 'touch';
9
+ /** A direction or half of an axis. */
10
+ type AxisSide = '+' | '-';
11
+ /** How the mouse drives an input. */
12
+ interface MouseMapping {
13
+ /** Held while this mouse button is down. */
14
+ button?: number;
15
+ /** 1 for one frame on a double-click. */
16
+ dblclick?: boolean;
17
+ /** The pointer's position from screen centre on this axis maps to 0..1 on one side. */
18
+ centerAxis?: 'x' | 'y';
19
+ /** Which side of centre fills 0..1 (default `+`). */
20
+ centerSide?: AxisSide;
21
+ /** Relative movement on this axis, scaled by `moveScale`. */
22
+ moveAxis?: 'x' | 'y';
23
+ /** Which direction of movement counts (default `+`). */
24
+ moveSign?: AxisSide;
25
+ /** Movement scale (default 0.1). */
26
+ moveScale?: number;
27
+ /** Wheel delta in this direction (decays). */
28
+ wheel?: AxisSide;
29
+ }
30
+ /** How a gamepad drives an input. */
31
+ interface GamepadMapping {
32
+ /** A standard-gamepad button index (0/1, or a 0..1 trigger). */
33
+ button?: number;
34
+ /** An axis index and which half: `+` positive, `-` negative, `±` absolute value. */
35
+ axis?: [number, AxisSide | '±'];
36
+ }
37
+ /** How touch and the on-screen controls drive an input. */
38
+ interface TouchMapping {
39
+ /** The id of a virtual button that drives this input. */
40
+ button?: string;
41
+ /** The id of a virtual joystick. */
42
+ stick?: string;
43
+ /** Which half or axis of that stick. */
44
+ axis?: 'x+' | 'x-' | 'y+' | 'y-' | 'x' | 'y';
45
+ /** 1 for one frame on a tap anywhere on a tap control. */
46
+ tap?: boolean;
47
+ /** The last touch's position from screen centre on this axis maps to 0..1 on one side. */
48
+ centerAxis?: 'x' | 'y';
49
+ /** Which side of centre fills 0..1 (default `+`). */
50
+ centerSide?: AxisSide;
51
+ }
52
+ /** One named input and its sources. */
53
+ interface InputDef {
54
+ /** `KeyboardEvent.key` values (case-insensitive). */
55
+ keys?: string[];
56
+ /** Mouse source (counts while the mouse is the active pointer). */
57
+ mouse?: MouseMapping;
58
+ /** Gamepad source (counts while a gamepad is the active pointer). */
59
+ gamepad?: GamepadMapping;
60
+ /** Touch and on-screen control source. */
61
+ touch?: TouchMapping;
62
+ }
63
+ /**
64
+ * A named axis. Each of `x` and `y` is a `[negative, positive]` pair of input
65
+ * names (read as -1..1), or one input name read directly.
66
+ */
67
+ interface AxisDef {
68
+ /** The horizontal axis. */
69
+ x?: string | [string, string];
70
+ /** The vertical axis. */
71
+ y?: string | [string, string];
72
+ }
73
+ /** Where an on-screen control sits. */
74
+ type Anchor = 'top-left' | 'top' | 'top-right' | 'left' | 'center' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right';
75
+ /** The kinds of on-screen control. */
76
+ type VirtualControlType = 'button' | 'joystick' | 'dpad' | 'tap';
77
+ /** Pixel distances from the viewport edges. */
78
+ interface EdgeOffsets {
79
+ /** From the left edge. */
80
+ left?: number;
81
+ /** From the right edge. */
82
+ right?: number;
83
+ /** From the top edge. */
84
+ top?: number;
85
+ /** From the bottom edge. */
86
+ bottom?: number;
87
+ }
88
+ /** The inputs a dpad or button drives. */
89
+ interface VirtualInputs {
90
+ /** Up. */
91
+ up?: string;
92
+ /** Down. */
93
+ down?: string;
94
+ /** Left. */
95
+ left?: string;
96
+ /** Right. */
97
+ right?: string;
98
+ /** A press. */
99
+ press?: string;
100
+ }
101
+ /** An on-screen touch control. */
102
+ interface VirtualDef {
103
+ /** Its id (inputs reference it from `touch.button` or `touch.stick`). */
104
+ id: string;
105
+ /** What it is. */
106
+ type: VirtualControlType;
107
+ /** Its anchor for the automatic layout. */
108
+ place: Anchor;
109
+ /**
110
+ * An explicit pixel position from the viewport edges; bypasses the automatic
111
+ * layout for this control (e.g. pin a pause button just above a stick).
112
+ */
113
+ pos?: EdgeOffsets;
114
+ /**
115
+ * Nudge an auto-placed control away from its anchor's edges, in px: `x`
116
+ * moves it inward from the left/right edge, `y` away from the top/bottom
117
+ * edge. For a band every control should avoid, use `hub.input.setInsets`.
118
+ */
119
+ offset?: {
120
+ x?: number;
121
+ y?: number;
122
+ };
123
+ /** Diameter in px (or the width when `width`/`height` are given). */
124
+ size?: number;
125
+ /** Width in px; overrides `size` for non-square controls. */
126
+ width?: number;
127
+ /** Height in px; overrides `size` for non-square controls. */
128
+ height?: number;
129
+ /** Default circle for sticks, round for buttons. */
130
+ shape?: 'round' | 'circle' | 'square' | 'pill';
131
+ /** A stick's travel: `both` (default), or single-axis `x` / `y`. */
132
+ axis?: 'x' | 'y' | 'both';
133
+ /** 0..1. */
134
+ opacity?: number;
135
+ /** Accent colour (border, knob, pressed fill). */
136
+ color?: string;
137
+ /** Resting background colour. */
138
+ bg?: string;
139
+ /** Label text colour. */
140
+ text?: string;
141
+ /** Text on a button. */
142
+ label?: string;
143
+ /** Raw HTML inside a button. */
144
+ html?: string;
145
+ /** For a dpad or button: the inputs it drives. Joysticks drive the inputs that reference them. */
146
+ inputs?: VirtualInputs;
147
+ }
148
+ /** A screen rectangle in px. */
149
+ interface Rect {
150
+ /** Left. */
151
+ x: number;
152
+ /** Top. */
153
+ y: number;
154
+ /** Width. */
155
+ width: number;
156
+ /** Height. */
157
+ height: number;
158
+ }
159
+ /** What a navigable element is, for `act`. */
160
+ type NavElementKind = 'button' | 'text' | 'range' | 'custom';
161
+ /** A navigable element that isn't (only) a DOM node, e.g. a canvas-drawn button. */
162
+ interface NavElement {
163
+ /** Its id, echoed in focus/blur/act events. */
164
+ id?: string;
165
+ /** What it is (`text` opens the on-screen keyboard on act). */
166
+ kind?: NavElementKind;
167
+ /** A DOM element: bounds, click and focus come from it. */
168
+ el?: HTMLElement;
169
+ /** Its bounds, for elements without `el`. */
170
+ getBounds?: () => Rect;
171
+ /** Called when it gains the highlight. */
172
+ onFocus?: () => void;
173
+ /** Called when it loses the highlight. */
174
+ onBlur?: () => void;
175
+ /** Called when the player activates it. */
176
+ onAct?: () => void;
177
+ }
178
+ /** What a navigable group's element list may hold. */
179
+ type NavTarget = HTMLElement | NavElement;
180
+ /** Makes a group's UI navigable by gamepad and keys. */
181
+ interface NavigableDef {
182
+ /** Input that steps to the previous element. */
183
+ prev?: string;
184
+ /** Input that steps to the next element. */
185
+ next?: string;
186
+ /** Input that moves up spatially. */
187
+ up?: string;
188
+ /** Input that moves down spatially. */
189
+ down?: string;
190
+ /** Input that activates the highlighted element. */
191
+ act: string;
192
+ /** The elements, re-queried after every interaction (the DOM can change). */
193
+ elements: () => NavTarget[];
194
+ /** Wrap around at the ends (default true). */
195
+ wrap?: boolean;
196
+ }
197
+ /** A named group of inputs, enabled and disabled together. */
198
+ interface GroupDef {
199
+ /** The inputs, by name. */
200
+ inputs: Record<string, InputDef>;
201
+ /** Named axes over the inputs. */
202
+ axes?: Record<string, AxisDef>;
203
+ /** On-screen controls shown while the group is enabled. */
204
+ virtual?: VirtualDef[];
205
+ /** Makes the group's UI navigable. */
206
+ navigable?: NavigableDef;
207
+ /** Start enabled (default false; call `enable()` yourself). */
208
+ enabled?: boolean;
209
+ }
210
+ /** What `hub.input.define` takes. */
211
+ interface InputConfig {
212
+ /** The groups, by name. */
213
+ groups: Record<string, GroupDef>;
214
+ }
215
+ /** One input's reading this frame. */
216
+ interface InputReading {
217
+ /** 0..1. */
218
+ value: number;
219
+ /** Same as `value`. */
220
+ raw: number;
221
+ /** It crossed 0.5 upward this frame. */
222
+ isDown: boolean;
223
+ /** It crossed 0.5 downward this frame. */
224
+ isUp: boolean;
225
+ }
226
+ /** A 2D reading, clamped to the unit circle. */
227
+ interface Vector {
228
+ /** -1..1. */
229
+ x: number;
230
+ /** -1..1. */
231
+ y: number;
232
+ /** 0..1. */
233
+ mag: number;
234
+ }
235
+ /** A player-dragged spot: the control's top-left corner as % of the viewport. */
236
+ interface DraggedSpot {
237
+ /** % of the viewport width. */
238
+ x?: number;
239
+ /** % of the viewport height. */
240
+ y?: number;
241
+ }
242
+ /** A player's changes to a virtual control. */
243
+ type VirtualOverride = Partial<VirtualDef> & DraggedSpot;
244
+ /** The player's remaps and control customisations, persisted per game. */
245
+ interface InputOverrides {
246
+ /** Rebound inputs, by input name. */
247
+ bindings?: Record<string, Partial<InputDef>>;
248
+ /** Moved or restyled on-screen controls, by control id. */
249
+ virtual?: Record<string, VirtualOverride>;
250
+ /** The player's show/hide choice for the on-screen controls. */
251
+ showVirtual?: boolean;
252
+ }
253
+ /** The hub menu, as the input system drives it (toggle on Select, gamepad navigation inside). */
254
+ interface MenuBridge {
255
+ /** Open or close the menu; returns whether it is now open. */
256
+ toggle: () => boolean;
257
+ /** Whether the menu is open. */
258
+ isOpen: () => boolean;
259
+ /** Close the menu. */
260
+ close: () => void;
261
+ /** The menu's shadow root (its focusables are navigated). */
262
+ root: ShadowRoot | null;
263
+ }
264
+ /** A navigation focus or act event. */
265
+ interface NavFocusEvent {
266
+ /** The element's id, if it has one. */
267
+ id?: string | undefined;
268
+ /** The DOM element, if any. */
269
+ el?: HTMLElement | undefined;
270
+ /** What it is. */
271
+ kind?: NavElementKind | undefined;
272
+ /** Its index in the list. */
273
+ index: number;
274
+ }
275
+ /** A navigation blur event. */
276
+ interface NavBlurEvent {
277
+ /** The element's id, if it has one. */
278
+ id?: string | undefined;
279
+ /** Its index in the list. */
280
+ index: number;
281
+ }
282
+ /** Events `hub.input.on` delivers, name → payload. */
283
+ interface InputEvents {
284
+ /** An element gained the highlight. */
285
+ focus: NavFocusEvent;
286
+ /** An element lost the highlight. */
287
+ blur: NavBlurEvent;
288
+ /** The player activated an element. */
289
+ act: NavFocusEvent;
290
+ /** The active device changed. */
291
+ sourcechange: InputSource;
292
+ /** Reserved. */
293
+ navigate: NavFocusEvent;
294
+ }
295
+ /** Where the input system persists the player's remaps. */
296
+ interface InputHost {
297
+ /** This page's game slug. */
298
+ readonly slug: string | null;
299
+ /** The saved overrides, or `null`. */
300
+ loadOverrides(): InputOverrides | null;
301
+ /** Save overrides (locally, and to the cloud when signed in). */
302
+ saveOverrides(overrides: InputOverrides): void;
303
+ }
304
+ //#endregion
305
+ //#region src/overlay/controls-panel.d.ts
306
+ /** What the Controls screen drives (the input system). */
307
+ interface ControlsPanelHost {
308
+ /** The player's show/hide state of the on-screen controls. */
309
+ readonly showingVirtual: boolean;
310
+ /** Show or hide the on-screen controls (persisted). */
311
+ showVirtual(isVisible: boolean): void;
312
+ /** Force the controls visible while editing the layout. */
313
+ setVirtualEditing(isEditing: boolean): void;
314
+ /** Rebind an input (persisted). */
315
+ rebind(inputName: string, patch: Partial<InputDef>): void;
316
+ /** Forget every remap. */
317
+ resetControls(): void;
318
+ /** A readable label of an input's current binding. */
319
+ bindingLabel(inputName: string): string;
320
+ }
321
+ //#endregion
322
+ //#region src/input/page-control.d.ts
323
+ /** The cross-bundle input surface. */
324
+ interface PageInputControl {
325
+ /** Whether the game declared its inputs. */
326
+ readonly isDefined: boolean;
327
+ /** The host menu attaches itself. */
328
+ attachMenu(bridge: MenuBridge | null): void;
329
+ /** The host menu passes `game.controls`. */
330
+ setLegacyControls(controls: unknown): void;
331
+ /** The menu's Controls button. */
332
+ openControls(): void;
333
+ /** Whether a group is on. */
334
+ isEnabled(group: string): boolean;
335
+ /** Turn a group on. */
336
+ enable(group: string): void;
337
+ /** Turn a group off. */
338
+ disable(group: string): void;
339
+ /** Make elements gamepad-navigable (the runtime's dialogs). */
340
+ autoNavigate(selector: string | (() => NavTarget[]), options?: {
341
+ back?: () => void;
342
+ }): void;
343
+ /** Stop navigating them. */
344
+ clearAutoNavigate(): void;
345
+ /** Stop driving the page and hand over to `owner`. Absent on v1 copies. */
346
+ yieldPageTo?(owner: PageInputControl): void;
347
+ }
348
+ /** Whether `candidate` is some bundle's input system. */
349
+ declare function isPageInputControl(candidate: unknown): candidate is PageInputControl;
350
+ //#endregion
351
+ //#region src/input/input-system.d.ts
352
+ /** Options for the input system. */
353
+ interface InputSystemOptions {
354
+ /** Start as the page's input owner (default true). A private instance takes over when its game defines inputs. */
355
+ isPageOwner?: boolean;
356
+ /** Make this instance the page's registered input system (when a private instance takes over); returns the one replaced. */
357
+ claimPage?: (system: InputSystem) => PageInputControl | null;
358
+ }
359
+ /** The page's input system. */
360
+ declare class InputSystem implements ControlsPanelHost, PageInputControl {
361
+ private readonly host;
362
+ private readonly options;
363
+ private config;
364
+ private readonly remaps;
365
+ private readonly registry;
366
+ private readonly devices;
367
+ private readonly controls;
368
+ private readonly navigator;
369
+ private readonly repeats;
370
+ private readonly presses;
371
+ private readonly events;
372
+ private menu;
373
+ private legacyControls;
374
+ private legacyControlsSource;
375
+ private activeSource;
376
+ private isPageOwner;
377
+ private pageOwner;
378
+ constructor(host: InputHost, options?: InputSystemOptions);
379
+ /** Whether this page counts as a touch device. */
380
+ get touchDevice(): boolean;
381
+ /** Declare the game's inputs (replacing any earlier declaration). The game owns input from now on. */
382
+ define(config: InputConfig): void;
383
+ /** True once the game has declared its inputs. */
384
+ get isDefined(): boolean;
385
+ /** Turn a group on. Held keys don't fire a phantom `down` (the pause key held as play resumes). */
386
+ enable(group: string): void;
387
+ /** Turn a group off (its inputs read 0). */
388
+ disable(group: string): void;
389
+ /** Whether a group is on. */
390
+ isEnabled(group: string): boolean;
391
+ /** An input's value, 0..1. */
392
+ value(name: string): number;
393
+ /** An input's full reading this frame. */
394
+ get(name: string): InputReading;
395
+ /** Whether an input went down this frame. */
396
+ down(name: string): boolean;
397
+ /** Whether an input came up this frame. */
398
+ up(name: string): boolean;
399
+ /** Whether an input is held (≥ 0.5). */
400
+ pressed(name: string): boolean;
401
+ /** A named axis, or an ad-hoc `axis(negative, positive)` pair, as -1..1. */
402
+ axis(name: string, positive?: string): number;
403
+ /** A named axis pair as a vector clamped to the unit circle. */
404
+ vector(name: string): Vector;
405
+ /** The device the player is using right now. */
406
+ get source(): InputSource;
407
+ /** Subscribe to an input event. Returns the unsubscribe function. */
408
+ on<Name extends keyof InputEvents>(event: Name, listener: (payload: InputEvents[Name]) => void): () => void;
409
+ /** Update a button's content at runtime (e.g. an SVG reflecting game state). */
410
+ setVirtualHtml(id: string, html: string): void;
411
+ /** The player's show/hide choice for the on-screen controls (persisted). */
412
+ showVirtual(isVisible: boolean): void;
413
+ /** Flip the player's show/hide choice. */
414
+ toggleVirtual(): void;
415
+ /** Force the controls visible for layout editing, without changing the player's choice. */
416
+ setVirtualEditing(isEditing: boolean): void;
417
+ /** This game's default visibility (the player's choice still wins); `null` = shown on touch devices without a pad. */
418
+ setVirtualDefault(isVisible: boolean | null): void;
419
+ /**
420
+ * Keep auto-placed controls clear of a band along a screen edge, e.g. your
421
+ * top HUD: `setInsets({ top: hud.getBoundingClientRect().bottom })`. Px from
422
+ * each edge, merged with earlier calls (0 clears one edge). Dragged controls
423
+ * and explicit `pos` ignore it.
424
+ */
425
+ setInsets(insets: {
426
+ top?: number;
427
+ right?: number;
428
+ bottom?: number;
429
+ left?: number;
430
+ }): void;
431
+ /** What the "Show on-screen controls" toggle reflects. */
432
+ get showingVirtual(): boolean;
433
+ /** Rebind an input (persisted). */
434
+ rebind(inputName: string, patch: Partial<InputDef>): void;
435
+ /** Move or restyle an on-screen control (persisted). */
436
+ setVirtual(id: string, patch: VirtualOverride): void;
437
+ /** Open (or close) the Controls screen. */
438
+ openControls(): void;
439
+ /** Forget every remap and customisation. */
440
+ resetControls(): void;
441
+ /** A readable label of an input's current binding. */
442
+ bindingLabel(inputName: string): string;
443
+ /** Called by the injected menu: Select toggles it and a gamepad navigates it. */
444
+ attachMenu(bridge: MenuBridge | null): void;
445
+ /** Called by the injected menu with `game.controls`, for the zero-config fallback. */
446
+ setLegacyControls(controls: unknown): void;
447
+ /**
448
+ * Make a game's own on-screen menu gamepad-navigable: a CSS selector (or a
449
+ * function returning elements). While any match is visible and a gamepad is
450
+ * in use, the stick moves a highlight, A clicks, B calls `options.back`.
451
+ * Re-queried every frame, so call it once.
452
+ */
453
+ autoNavigate(selector: string | (() => NavTarget[]), options?: {
454
+ back?: () => void;
455
+ }): void;
456
+ /** Stop navigating the game's own menu. */
457
+ clearAutoNavigate(): void;
458
+ /**
459
+ * Stop driving the page because another copy's game owns it (plan §4.4):
460
+ * hand the menu and `game.controls` to `owner`, and forward the menu's calls to it.
461
+ */
462
+ yieldPageTo(owner: PageInputControl): void;
463
+ private buildControls;
464
+ private setSource;
465
+ private navigatorContext;
466
+ private tick;
467
+ /** One frame as the page owner: the menu toggle and navigation, inputs, the zero-config fallback. */
468
+ private driveFrame;
469
+ }
470
+ //#endregion
471
+ //#region src/input/page-input.d.ts
472
+ /** The cross-bundle shape number of the `input` singleton. Bump only on an incompatible change. */
473
+ declare const INPUT_SINGLETON_API = 1;
474
+ /** Whether `candidate` is some bundle's input system (v1 copies included). */
475
+ declare function isInputSystem(candidate: unknown): candidate is InputSystem;
476
+ /** How the core client connects the input system to its game. */
477
+ interface InputOptions {
478
+ /** This page's game slug (default: `window.__HUB__.slug`). */
479
+ slug?: string | null;
480
+ /** Mirror remaps to the cloud (the core client writes the `__controls` save slot). */
481
+ saveToCloud?: (overrides: InputOverrides) => void;
482
+ }
483
+ /** Saved overrides from JSON, keeping only well-formed fields. */
484
+ declare function parseInputOverrides(saved: unknown): InputOverrides;
485
+ /**
486
+ * The page-wide input system, created on first use. `options` connect it to
487
+ * the core client (its slug, the cloud save); the first call's options win.
488
+ * When another client copy with a different shape owns the page, this copy
489
+ * gets a private instance that takes the page over once its game defines
490
+ * inputs.
491
+ */
492
+ declare function getInput(options?: InputOptions): InputSystem;
493
+ //#endregion
494
+ //#region src/input/nav-state.d.ts
495
+ /** What a navigable list draws with (the overlay). */
496
+ interface NavHighlighter {
497
+ /** Ring the highlighted element. */
498
+ showHighlight(bounds: Rect): void;
499
+ /** Remove the ring. */
500
+ hideHighlight(): void;
501
+ /** Open the on-screen keyboard for a text field. */
502
+ openKeyboard(target: HTMLInputElement | HTMLTextAreaElement | null): void;
503
+ }
504
+ //#endregion
505
+ //#region src/overlay/layout-geometry.d.ts
506
+ /** A placed control: top-left corner and size, in viewport px. */
507
+ interface LayoutBox {
508
+ x: number;
509
+ y: number;
510
+ w: number;
511
+ h: number;
512
+ }
513
+ /** One control as the layout engine sees it (its rendered px size). */
514
+ interface LayoutItem {
515
+ /** The control id. */
516
+ id: string;
517
+ /** Its type. */
518
+ type: VirtualDef['type'];
519
+ /** Its anchor. */
520
+ place: Anchor;
521
+ /** Rendered width. */
522
+ w: number;
523
+ /** Rendered height. */
524
+ h: number;
525
+ /** An explicit position from the edges. */
526
+ pos?: VirtualDef['pos'] | undefined;
527
+ /** A nudge away from the anchor's edges. */
528
+ offset?: VirtualDef['offset'] | undefined;
529
+ /** The player's dragged spot: the control's top-left corner as % of the viewport. */
530
+ override?: {
531
+ x: number;
532
+ y: number;
533
+ } | undefined;
534
+ }
535
+ /** Px insets from each viewport edge. */
536
+ interface Insets {
537
+ top: number;
538
+ right: number;
539
+ bottom: number;
540
+ left: number;
541
+ }
542
+ /** The rendered size of a control: buttons and taps draw a 2px border outside their declared size; sticks draw theirs inside. */
543
+ declare function controlSize(definition: Pick<VirtualDef, 'type' | 'size' | 'width' | 'height'>): {
544
+ w: number;
545
+ h: number;
546
+ };
547
+ /** Do two boxes overlap (or come closer than `padding` px)? */
548
+ declare function boxesTouch(first: LayoutBox, second: LayoutBox, padding?: number): boolean;
549
+ //#endregion
550
+ //#region src/overlay/virtual-controls.d.ts
551
+ /** What a control reports. */
552
+ interface VirtualControlCallbacks {
553
+ /** A button went down. */
554
+ onButtonDown(id: string): void;
555
+ /** A button came up. */
556
+ onButtonUp(id: string): void;
557
+ /** A stick moved (-1..1 per axis; 0, 0 on release). */
558
+ onStick(id: string, outX: number, outY: number): void;
559
+ /** A tap region was tapped. */
560
+ onTap(): void;
561
+ /** The player dropped a dragged control: its top-left corner as % of the viewport. */
562
+ onDragged(id: string, spot: {
563
+ x: number;
564
+ y: number;
565
+ }): void;
566
+ }
567
+ //#endregion
568
+ //#region src/overlay/overlay.d.ts
569
+ /** The overlay (one per input system). */
570
+ declare class Overlay implements NavHighlighter {
571
+ private readonly shadowHost;
572
+ private readonly root;
573
+ private readonly controlsLayer;
574
+ private readonly ring;
575
+ private readonly keyboard;
576
+ private readonly controlsPanel;
577
+ private controls;
578
+ private controlScope;
579
+ private overrides;
580
+ private gameInsets;
581
+ private raceHudBands;
582
+ private safeAreaProbe;
583
+ constructor();
584
+ /** (Re)build every on-screen control from the config and the player's overrides. */
585
+ build(config: InputConfig, overrides: InputOverrides, callbacks: VirtualControlCallbacks): void;
586
+ /** Replace a button or tap control's content at runtime. Listeners live on the wrapper, so they survive. */
587
+ setControlHtml(id: string, html: string): void;
588
+ /** Show controls of the enabled groups (or of every group, with `null`, while editing). */
589
+ setVirtualVisible(isVisible: boolean, enabledGroups: ReadonlySet<string> | null): void;
590
+ /** Game insets (px) auto-placed controls keep clear of, e.g. a top HUD bar. Merged with earlier calls. */
591
+ setInsets(insets: Partial<Insets>): void;
592
+ /** Re-place every control for the current viewport, keeping the player's dragged spots. */
593
+ layout(): void;
594
+ /** Ring the highlighted element. */
595
+ showHighlight(bounds: Rect): void;
596
+ /** Remove the ring. */
597
+ hideHighlight(): void;
598
+ /** Open the on-screen keyboard for a text field. */
599
+ openKeyboard(target: HTMLInputElement | HTMLTextAreaElement | null): void;
600
+ /** Whether the on-screen keyboard is showing. */
601
+ get isKeyboardOpen(): boolean;
602
+ /** Open (or close) the Controls screen. */
603
+ toggleControls(config: InputConfig | null, host: ControlsPanelHost): void;
604
+ /** Per-frame work: gamepad navigation of the keyboard. */
605
+ afterFrame(): void;
606
+ /** The device safe-area insets (notch, home bar), via a probe element. */
607
+ private readSafeArea;
608
+ }
609
+ //#endregion
610
+ //#region src/overlay/layout.d.ts
611
+ /** Layout options. */
612
+ interface LayoutOptions {
613
+ /** Game insets (a HUD bar…): auto-placed controls keep clear of them. */
614
+ insets?: Partial<Insets>;
615
+ /** Device safe area (notch, home bar): every control stays inside it. */
616
+ safe?: Partial<Insets>;
617
+ /** Distance from the edges for auto-placed controls (default 22). */
618
+ margin?: number;
619
+ /** Space between auto-placed controls (default 14). */
620
+ gap?: number;
621
+ }
622
+ /**
623
+ * Place every control for a `viewportWidth` × `viewportHeight` viewport and
624
+ * return each control's box.
625
+ *
626
+ * 1. A game `pos` is honoured as given. A player-dragged control keeps its
627
+ * spot (as % of the viewport, re-clamped inside the safe area), nudged to
628
+ * the nearest free spot if it would land on (or within `gap` of) a stick.
629
+ * 2. Sticks sit in their anchor's corner, side by side inward.
630
+ * 3. Buttons cluster beside their corner's sticks, stacked in columns. If any
631
+ * cluster doesn't fit, every corner cluster that has sticks moves into rows
632
+ * above (below, for top corners) its sticks, first-declared button
633
+ * innermost. Any button that still collides moves to the nearest free spot.
634
+ */
635
+ declare function layoutControls(items: readonly LayoutItem[], viewportWidth: number, viewportHeight: number, options?: LayoutOptions): Record<string, LayoutBox>;
636
+ //#endregion
637
+ //#region src/uistack/types.d.ts
638
+ /**
639
+ * The overlay stack's public shapes: "is the player looking at hub UI right
640
+ * now?" (`hub.overlay`, docs/multiplayer.md §5.7).
641
+ */
642
+ /** Why the overlay opened, so a game can word its pause screen. */
643
+ type OverlayReason = 'menu' | 'chat' | 'dialog' | 'keyboard' | 'invite' | 'notify';
644
+ /** An overlay edge. */
645
+ type OverlayEdge = 'open' | 'close';
646
+ /** Payload of `open` and `close` (and of the `hub:overlay-open` / `hub:overlay-close` window events). */
647
+ interface OverlayEvent {
648
+ /** The reason of the entry that opened (for `open`) or closed last (for `close`). */
649
+ reason: OverlayReason;
650
+ /**
651
+ * False during a live online match (`hub.mp.setBusy(true)`): the game must
652
+ * keep simulating, so it should not pause.
653
+ */
654
+ canPause: boolean;
655
+ }
656
+ /** Options for {@link UiStack.autoPause}. */
657
+ interface AutoPauseOptions {
658
+ /** Pause exactly the way the game's own pause does. */
659
+ pause(): void;
660
+ /** Resume play. Only called when `resumeOnClose` is true. */
661
+ resume?(): void;
662
+ /**
663
+ * Resume automatically when the hub UI closes. Default false: action games
664
+ * should show their pause screen so the player resumes deliberately;
665
+ * turn-based and idle games may pass true.
666
+ */
667
+ resumeOnClose?: boolean;
668
+ }
669
+ /** A listener for overlay edges. */
670
+ type OverlayListener = (event: OverlayEvent) => void;
671
+ /** What an older, idle stack hands to a newer one replacing it. */
672
+ interface UiStackHandoff {
673
+ /** Its listeners, by edge. */
674
+ listeners: {
675
+ open: OverlayListener[];
676
+ close: OverlayListener[];
677
+ };
678
+ /** Its pause permission. */
679
+ canPause: boolean;
680
+ }
681
+ /**
682
+ * The page-wide overlay stack. Every piece of hub UI that covers the game
683
+ * (the menu drawer, a dialog, the chat sheet…) pushes an entry while it shows
684
+ * and pops it when it goes away; the game sees one `open` / `close` pair for
685
+ * the whole visit, however the UI nests.
686
+ */
687
+ interface UiStack {
688
+ /** Implementation version; a newer bundle replaces an older, idle instance. */
689
+ readonly version: number;
690
+ /** Register a covering piece of UI. Returns its idempotent `pop()`. */
691
+ push(reason: OverlayReason): () => void;
692
+ /** True while any hub UI covers the game. */
693
+ readonly isOpen: boolean;
694
+ /** Number of open entries (nesting depth). */
695
+ readonly depth: number;
696
+ /** Whether the game may pause right now (false during an online match). */
697
+ readonly canPause: boolean;
698
+ /** Subscribe to an edge. Returns the unsubscribe function. */
699
+ on(edge: OverlayEdge, listener: OverlayListener): () => void;
700
+ /**
701
+ * One-line adoption for games: pause on open (unless `canPause` is false),
702
+ * optionally resume on close. Returns a function that detaches it.
703
+ */
704
+ autoPause(options: AutoPauseOptions): () => void;
705
+ /** Driven by `hub.mp.setBusy`: false while a live match can't pause. */
706
+ setCanPause(canPause: boolean): void;
707
+ /** Hand listeners to a newer version replacing this (idle) instance. */
708
+ handoff(): UiStackHandoff;
709
+ }
710
+ //#endregion
711
+ //#region src/uistack/page-stack.d.ts
712
+ declare global {
713
+ interface Window {
714
+ __HUB_UI__?: unknown;
715
+ }
716
+ }
717
+ /** Whether `candidate` is some bundle's overlay stack. */
718
+ declare function isUiStack(candidate: unknown): candidate is UiStack;
719
+ /**
720
+ * The page-wide overlay stack, created on first use. Outside a browser a
721
+ * module-local instance is returned.
722
+ */
723
+ declare function getUiStack(): UiStack;
724
+ //#endregion
725
+ //#region src/uistack/ui-stack.d.ts
726
+ /** Bump when the UiStack contract gains behaviour; idle older instances are replaced. */
727
+ declare const UI_STACK_VERSION = 1;
728
+ //#endregion
729
+ export { VirtualControlType as $, AxisSide as A, InputReading as B, parseInputOverrides as C, isPageInputControl as D, PageInputControl as E, InputConfig as F, NavElement as G, MenuBridge as H, InputDef as I, NavTarget as J, NavElementKind as K, InputEvents as L, EdgeOffsets as M, GamepadMapping as N, Anchor as O, GroupDef as P, Vector as Q, InputHost as R, isInputSystem as S, InputSystemOptions as T, MouseMapping as U, InputSource as V, NavBlurEvent as W, Rect as X, NavigableDef as Y, TouchMapping as Z, boxesTouch as _, OverlayEdge as a, InputOptions as b, OverlayReason as c, LayoutOptions as d, VirtualDef as et, layoutControls as f, LayoutItem as g, LayoutBox as h, AutoPauseOptions as i, DraggedSpot as j, AxisDef as k, UiStack as l, Insets as m, getUiStack as n, VirtualOverride as nt, OverlayEvent as o, Overlay as p, NavFocusEvent as q, isUiStack as r, OverlayListener as s, UI_STACK_VERSION as t, VirtualInputs as tt, UiStackHandoff as u, controlSize as v, InputSystem as w, getInput as x, INPUT_SINGLETON_API as y, InputOverrides as z };
730
+ //# sourceMappingURL=input.d.ts.map