@joydle/ui 0.1.0

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 (161) hide show
  1. package/dist/controls/ActionButton.d.ts +18 -0
  2. package/dist/controls/ActionButton.d.ts.map +1 -0
  3. package/dist/controls/ActionButton.js +108 -0
  4. package/dist/controls/ActionButton.js.map +1 -0
  5. package/dist/controls/ActionButtonGroup.d.ts +15 -0
  6. package/dist/controls/ActionButtonGroup.d.ts.map +1 -0
  7. package/dist/controls/ActionButtonGroup.js +55 -0
  8. package/dist/controls/ActionButtonGroup.js.map +1 -0
  9. package/dist/controls/Joystick.d.ts +9 -0
  10. package/dist/controls/Joystick.d.ts.map +1 -0
  11. package/dist/controls/Joystick.js +168 -0
  12. package/dist/controls/Joystick.js.map +1 -0
  13. package/dist/controls/SwipeZone.d.ts +10 -0
  14. package/dist/controls/SwipeZone.d.ts.map +1 -0
  15. package/dist/controls/SwipeZone.js +84 -0
  16. package/dist/controls/SwipeZone.js.map +1 -0
  17. package/dist/controls/TouchDPad.d.ts +9 -0
  18. package/dist/controls/TouchDPad.d.ts.map +1 -0
  19. package/dist/controls/TouchDPad.js +90 -0
  20. package/dist/controls/TouchDPad.js.map +1 -0
  21. package/dist/controls/index.d.ts +6 -0
  22. package/dist/controls/index.d.ts.map +1 -0
  23. package/dist/controls/index.js +9 -0
  24. package/dist/controls/index.js.map +1 -0
  25. package/dist/core/GameShell.d.ts +43 -0
  26. package/dist/core/GameShell.d.ts.map +1 -0
  27. package/dist/core/GameShell.js +91 -0
  28. package/dist/core/GameShell.js.map +1 -0
  29. package/dist/core/GameState.d.ts +35 -0
  30. package/dist/core/GameState.d.ts.map +1 -0
  31. package/dist/core/GameState.js +74 -0
  32. package/dist/core/GameState.js.map +1 -0
  33. package/dist/core/InputManager.d.ts +39 -0
  34. package/dist/core/InputManager.d.ts.map +1 -0
  35. package/dist/core/InputManager.js +149 -0
  36. package/dist/core/InputManager.js.map +1 -0
  37. package/dist/core/ScaleManager.d.ts +38 -0
  38. package/dist/core/ScaleManager.d.ts.map +1 -0
  39. package/dist/core/ScaleManager.js +106 -0
  40. package/dist/core/ScaleManager.js.map +1 -0
  41. package/dist/core/index.d.ts +9 -0
  42. package/dist/core/index.d.ts.map +1 -0
  43. package/dist/core/index.js +14 -0
  44. package/dist/core/index.js.map +1 -0
  45. package/dist/core/types.d.ts +113 -0
  46. package/dist/core/types.d.ts.map +1 -0
  47. package/dist/core/types.js +5 -0
  48. package/dist/core/types.js.map +1 -0
  49. package/dist/core/useGame.d.ts +22 -0
  50. package/dist/core/useGame.d.ts.map +1 -0
  51. package/dist/core/useGame.js +40 -0
  52. package/dist/core/useGame.js.map +1 -0
  53. package/dist/core/useGameLoop.d.ts +16 -0
  54. package/dist/core/useGameLoop.d.ts.map +1 -0
  55. package/dist/core/useGameLoop.js +35 -0
  56. package/dist/core/useGameLoop.js.map +1 -0
  57. package/dist/core/useGameSetup.d.ts +16 -0
  58. package/dist/core/useGameSetup.d.ts.map +1 -0
  59. package/dist/core/useGameSetup.js +27 -0
  60. package/dist/core/useGameSetup.js.map +1 -0
  61. package/dist/hud/BottomHint.d.ts +17 -0
  62. package/dist/hud/BottomHint.d.ts.map +1 -0
  63. package/dist/hud/BottomHint.js +68 -0
  64. package/dist/hud/BottomHint.js.map +1 -0
  65. package/dist/hud/ComboLabel.d.ts +18 -0
  66. package/dist/hud/ComboLabel.d.ts.map +1 -0
  67. package/dist/hud/ComboLabel.js +125 -0
  68. package/dist/hud/ComboLabel.js.map +1 -0
  69. package/dist/hud/HUD.d.ts +18 -0
  70. package/dist/hud/HUD.d.ts.map +1 -0
  71. package/dist/hud/HUD.js +72 -0
  72. package/dist/hud/HUD.js.map +1 -0
  73. package/dist/hud/Lives.d.ts +21 -0
  74. package/dist/hud/Lives.d.ts.map +1 -0
  75. package/dist/hud/Lives.js +92 -0
  76. package/dist/hud/Lives.js.map +1 -0
  77. package/dist/hud/Meter.d.ts +24 -0
  78. package/dist/hud/Meter.d.ts.map +1 -0
  79. package/dist/hud/Meter.js +133 -0
  80. package/dist/hud/Meter.js.map +1 -0
  81. package/dist/hud/MiniMap.d.ts +41 -0
  82. package/dist/hud/MiniMap.d.ts.map +1 -0
  83. package/dist/hud/MiniMap.js +103 -0
  84. package/dist/hud/MiniMap.js.map +1 -0
  85. package/dist/hud/Score.d.ts +15 -0
  86. package/dist/hud/Score.d.ts.map +1 -0
  87. package/dist/hud/Score.js +74 -0
  88. package/dist/hud/Score.js.map +1 -0
  89. package/dist/hud/Timer.d.ts +21 -0
  90. package/dist/hud/Timer.d.ts.map +1 -0
  91. package/dist/hud/Timer.js +111 -0
  92. package/dist/hud/Timer.js.map +1 -0
  93. package/dist/hud/WaveLabel.d.ts +15 -0
  94. package/dist/hud/WaveLabel.d.ts.map +1 -0
  95. package/dist/hud/WaveLabel.js +70 -0
  96. package/dist/hud/WaveLabel.js.map +1 -0
  97. package/dist/hud/index.d.ts +10 -0
  98. package/dist/hud/index.d.ts.map +1 -0
  99. package/dist/hud/index.js +13 -0
  100. package/dist/hud/index.js.map +1 -0
  101. package/dist/index.d.ts +8 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +13 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/screens/GameOverScreen.d.ts +36 -0
  106. package/dist/screens/GameOverScreen.d.ts.map +1 -0
  107. package/dist/screens/GameOverScreen.js +255 -0
  108. package/dist/screens/GameOverScreen.js.map +1 -0
  109. package/dist/screens/LoadingScreen.d.ts +21 -0
  110. package/dist/screens/LoadingScreen.d.ts.map +1 -0
  111. package/dist/screens/LoadingScreen.js +129 -0
  112. package/dist/screens/LoadingScreen.js.map +1 -0
  113. package/dist/screens/LobbyScreen.d.ts +39 -0
  114. package/dist/screens/LobbyScreen.d.ts.map +1 -0
  115. package/dist/screens/LobbyScreen.js +266 -0
  116. package/dist/screens/LobbyScreen.js.map +1 -0
  117. package/dist/screens/PauseOverlay.d.ts +29 -0
  118. package/dist/screens/PauseOverlay.d.ts.map +1 -0
  119. package/dist/screens/PauseOverlay.js +158 -0
  120. package/dist/screens/PauseOverlay.js.map +1 -0
  121. package/dist/screens/ScreenManager.d.ts +26 -0
  122. package/dist/screens/ScreenManager.d.ts.map +1 -0
  123. package/dist/screens/ScreenManager.js +61 -0
  124. package/dist/screens/ScreenManager.js.map +1 -0
  125. package/dist/screens/TitleScreen.d.ts +30 -0
  126. package/dist/screens/TitleScreen.d.ts.map +1 -0
  127. package/dist/screens/TitleScreen.js +263 -0
  128. package/dist/screens/TitleScreen.js.map +1 -0
  129. package/dist/screens/index.d.ts +7 -0
  130. package/dist/screens/index.d.ts.map +1 -0
  131. package/dist/screens/index.js +10 -0
  132. package/dist/screens/index.js.map +1 -0
  133. package/dist/theme/ThemeProvider.d.ts +25 -0
  134. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  135. package/dist/theme/ThemeProvider.js +51 -0
  136. package/dist/theme/ThemeProvider.js.map +1 -0
  137. package/dist/theme/index.d.ts +4 -0
  138. package/dist/theme/index.d.ts.map +1 -0
  139. package/dist/theme/index.js +7 -0
  140. package/dist/theme/index.js.map +1 -0
  141. package/dist/theme/palettes.d.ts +10 -0
  142. package/dist/theme/palettes.d.ts.map +1 -0
  143. package/dist/theme/palettes.js +173 -0
  144. package/dist/theme/palettes.js.map +1 -0
  145. package/dist/theme/theme.d.ts +24 -0
  146. package/dist/theme/theme.d.ts.map +1 -0
  147. package/dist/theme/theme.js +29 -0
  148. package/dist/theme/theme.js.map +1 -0
  149. package/dist/transitions/ScreenTransition.d.ts +19 -0
  150. package/dist/transitions/ScreenTransition.d.ts.map +1 -0
  151. package/dist/transitions/ScreenTransition.js +105 -0
  152. package/dist/transitions/ScreenTransition.js.map +1 -0
  153. package/dist/transitions/index.d.ts +3 -0
  154. package/dist/transitions/index.d.ts.map +1 -0
  155. package/dist/transitions/index.js +6 -0
  156. package/dist/transitions/index.js.map +1 -0
  157. package/dist/transitions/presets.d.ts +21 -0
  158. package/dist/transitions/presets.d.ts.map +1 -0
  159. package/dist/transitions/presets.js +37 -0
  160. package/dist/transitions/presets.js.map +1 -0
  161. package/package.json +62 -0
@@ -0,0 +1,9 @@
1
+ export type { BridgeInstance, InputAdapter, InputState, FrameStats, ThemeConfig, GlowStrength, ScreenTransition, GameStateShape, } from './types';
2
+ export { GameState } from './GameState';
3
+ export { InputManager } from './InputManager';
4
+ export { ScaleManager, type ScaleMode } from './ScaleManager';
5
+ export { GameShell, GameContext, type GameShellProps, type GameContextValue } from './GameShell';
6
+ export { useGame, type UseGameReturn } from './useGame';
7
+ export { useGameSetup } from './useGameSetup';
8
+ export { useGameLoop } from './useGameLoop';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG9D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGjG,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,14 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @joydle/ui/core — barrel export
3
+ // ---------------------------------------------------------------------------
4
+ // Classes
5
+ export { GameState } from './GameState';
6
+ export { InputManager } from './InputManager';
7
+ export { ScaleManager } from './ScaleManager';
8
+ // Components
9
+ export { GameShell, GameContext } from './GameShell';
10
+ // Hooks
11
+ export { useGame } from './useGame';
12
+ export { useGameSetup } from './useGameSetup';
13
+ export { useGameLoop } from './useGameLoop';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAc9E,UAAU;AACV,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAkB,MAAM,gBAAgB,CAAC;AAE9D,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,WAAW,EAA8C,MAAM,aAAa,CAAC;AAEjG,QAAQ;AACR,OAAO,EAAE,OAAO,EAAsB,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,113 @@
1
+ import type { InputManager } from './InputManager';
2
+ /**
3
+ * Renderer-agnostic bridge that connects any canvas renderer (Three.js,
4
+ * PixiJS, raw WebGL, etc.) to the Joydle UI overlay layer.
5
+ *
6
+ * Every renderer plug-in must implement this interface.
7
+ */
8
+ export interface BridgeInstance {
9
+ /** The <canvas> element owned by the renderer. */
10
+ canvas: HTMLCanvasElement;
11
+ /** Mount the renderer canvas into the given container element. */
12
+ mount(container: HTMLElement): void;
13
+ /** Tear down the renderer and release all GPU / DOM resources. */
14
+ dispose(): void;
15
+ /** Notify the renderer that the logical size changed. */
16
+ resize(width: number, height: number): void;
17
+ /**
18
+ * Register a per-frame update callback.
19
+ * @param callback Receives `dt` in seconds since last frame.
20
+ */
21
+ onUpdate(callback: (dt: number) => void): void;
22
+ /** Remove a previously registered update callback. */
23
+ removeUpdate(callback: (dt: number) => void): void;
24
+ /** Return the renderer's input adapter (for pointer / device bridging). */
25
+ getInputAdapter(): InputAdapter;
26
+ /** Register a callback invoked after the renderer finishes a frame. */
27
+ onFrameEnd(callback: () => void): void;
28
+ /** Return a serialisable snapshot of the current scene graph (debug). */
29
+ getSceneGraph(): object;
30
+ /** Return live performance counters for the current frame. */
31
+ getFrameStats(): FrameStats;
32
+ /** Capture the current canvas contents as a Blob (screenshot). */
33
+ capture(): Promise<Blob>;
34
+ }
35
+ /**
36
+ * Adapter that a renderer provides so it can translate low-level pointer /
37
+ * device events into the normalised InputState consumed by game code.
38
+ */
39
+ export interface InputAdapter {
40
+ /** Start forwarding events from the renderer to the InputManager. */
41
+ attach(inputManager: InputManager, canvas: HTMLCanvasElement): void;
42
+ /** Stop forwarding events. */
43
+ detach(): void;
44
+ }
45
+ /**
46
+ * Snapshot of all input axes and buttons at a given instant.
47
+ * Written by InputManager, read by game code every frame.
48
+ */
49
+ export interface InputState {
50
+ left: boolean;
51
+ right: boolean;
52
+ up: boolean;
53
+ down: boolean;
54
+ dirX: -1 | 0 | 1;
55
+ dirY: -1 | 0 | 1;
56
+ action: boolean;
57
+ action2: boolean;
58
+ action3: boolean;
59
+ pause: boolean;
60
+ pointerX: number;
61
+ pointerY: number;
62
+ pointerDown: boolean;
63
+ pointerActive: boolean;
64
+ }
65
+ export interface FrameStats {
66
+ fps: number;
67
+ drawCalls: number;
68
+ triangles: number;
69
+ entities: number;
70
+ }
71
+ /** How strongly glow effects are rendered. */
72
+ export type GlowStrength = 'none' | 'subtle' | 'medium' | 'strong';
73
+ /** Transition effect used when switching screens. */
74
+ export type ScreenTransition = 'fade' | 'slide' | 'zoom' | 'none';
75
+ /**
76
+ * Complete theme configuration consumed by the Joydle UI layer.
77
+ *
78
+ * All colour values are CSS colour strings. The `theme()` factory in
79
+ * `@joydle/ui/theme` merges a partial config with sensible defaults.
80
+ */
81
+ export interface ThemeConfig {
82
+ /** Page / canvas background colour. */
83
+ bg: string;
84
+ /** Primary brand colour. */
85
+ primary: string;
86
+ /** Accent colour (call-to-action, highlights). */
87
+ accent: string;
88
+ /** Secondary / supporting colour. */
89
+ secondary: string;
90
+ /** Gold / reward colour. */
91
+ gold: string;
92
+ /** Success / positive feedback colour. */
93
+ success: string;
94
+ /** Danger / error colour. */
95
+ danger: string;
96
+ /** Main text colour. */
97
+ text: string;
98
+ /** Dimmed / secondary text colour. */
99
+ textDim: string;
100
+ /** CSS font-family stack. */
101
+ font: string;
102
+ /** Glow intensity applied to interactive elements. */
103
+ glowStrength: GlowStrength;
104
+ /** Border radius in pixels. */
105
+ borderRadius: number;
106
+ /** Transition effect when navigating between screens. */
107
+ screenTransition: ScreenTransition;
108
+ }
109
+ /**
110
+ * Constraint for game state objects — must be a plain record.
111
+ */
112
+ export type GameStateShape = Record<string, unknown>;
113
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @joydle/ui — Core type definitions
3
+ // ---------------------------------------------------------------------------
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,sCAAsC;AACtC,8EAA8E"}
@@ -0,0 +1,22 @@
1
+ import type { GameStateShape } from './types';
2
+ import type { InputManager } from './InputManager';
3
+ export interface UseGameReturn<T extends GameStateShape> {
4
+ /** Reactive snapshot of the current game state. */
5
+ state: T;
6
+ /** Merge partial updates into the game state. */
7
+ setState: (partial: Partial<T>) => void;
8
+ /** The InputManager instance (from GameContext). */
9
+ input: InputManager;
10
+ }
11
+ /**
12
+ * Central hook for game components.
13
+ *
14
+ * Creates (or reuses) a `GameState<T>` instance, subscribes to changes so
15
+ * the component re-renders on state updates, and exposes the InputManager
16
+ * from the nearest `<GameShell>`.
17
+ *
18
+ * @param initialState Initial values for the game state store.
19
+ * A new GameState is created once (first render).
20
+ */
21
+ export declare function useGame<T extends GameStateShape>(initialState: T): UseGameReturn<T>;
22
+ //# sourceMappingURL=useGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGame.d.ts","sourceRoot":"","sources":["../../src/core/useGame.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,cAAc;IACrD,mDAAmD;IACnD,KAAK,EAAE,CAAC,CAAC;IACT,iDAAiD;IACjD,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACxC,oDAAoD;IACpD,KAAK,EAAE,YAAY,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,cAAc,EAC9C,YAAY,EAAE,CAAC,GACd,aAAa,CAAC,CAAC,CAAC,CA4BlB"}
@@ -0,0 +1,40 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @joydle/ui — Central game hook
3
+ // ---------------------------------------------------------------------------
4
+ import { useState, useEffect, useContext } from 'preact/hooks';
5
+ import { GameState } from './GameState';
6
+ import { GameContext } from './GameShell';
7
+ /**
8
+ * Central hook for game components.
9
+ *
10
+ * Creates (or reuses) a `GameState<T>` instance, subscribes to changes so
11
+ * the component re-renders on state updates, and exposes the InputManager
12
+ * from the nearest `<GameShell>`.
13
+ *
14
+ * @param initialState Initial values for the game state store.
15
+ * A new GameState is created once (first render).
16
+ */
17
+ export function useGame(initialState) {
18
+ // Create the store once. We intentionally ignore `initialState` on
19
+ // subsequent renders — the store is a stable singleton for the lifetime
20
+ // of the component tree.
21
+ const [store] = useState(() => new GameState(initialState));
22
+ // Reactive snapshot that drives re-renders.
23
+ const [snapshot, setSnapshot] = useState(() => store.getAll());
24
+ useEffect(() => {
25
+ const unsub = store.subscribe((s) => setSnapshot({ ...s }));
26
+ return unsub;
27
+ }, [store]);
28
+ // Pull the InputManager from the closest GameShell.
29
+ const ctx = useContext(GameContext);
30
+ if (!ctx) {
31
+ throw new Error('useGame() must be used inside a <GameShell>. ' +
32
+ 'Wrap your component tree with <GameShell renderer={bridge}>.');
33
+ }
34
+ return {
35
+ state: snapshot,
36
+ setState: (partial) => store.set(partial),
37
+ input: ctx.inputManager,
38
+ };
39
+ }
40
+ //# sourceMappingURL=useGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGame.js","sourceRoot":"","sources":["../../src/core/useGame.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa1C;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CACrB,YAAe;IAEf,oEAAoE;IACpE,wEAAwE;IACxE,yBAAyB;IACzB,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,SAAS,CAAI,YAAY,CAAC,CAAC,CAAC;IAE/D,4CAA4C;IAC5C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAI,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAO,CAAC,CAAC;IAEvE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,oDAAoD;IACpD,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,gDAAgD;YAChD,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;QACzC,KAAK,EAAE,GAAG,CAAC,YAAY;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { BridgeInstance } from './types';
2
+ /**
3
+ * Registers a per-frame update callback on the bridge.
4
+ *
5
+ * The callback ref is kept up-to-date so the latest closure is always
6
+ * invoked — no stale-closure problems.
7
+ *
8
+ * ```tsx
9
+ * useGameLoop(bridge, (dt) => {
10
+ * // dt is seconds since last frame
11
+ * player.x += speed * dt;
12
+ * });
13
+ * ```
14
+ */
15
+ export declare function useGameLoop(bridge: BridgeInstance | null | undefined, callback: (dt: number) => void): void;
16
+ //# sourceMappingURL=useGameLoop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGameLoop.d.ts","sourceRoot":"","sources":["../../src/core/useGameLoop.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EACzC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAC7B,IAAI,CAkBN"}
@@ -0,0 +1,35 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @joydle/ui — Per-frame update hook
3
+ // ---------------------------------------------------------------------------
4
+ import { useEffect, useRef } from 'preact/hooks';
5
+ /**
6
+ * Registers a per-frame update callback on the bridge.
7
+ *
8
+ * The callback ref is kept up-to-date so the latest closure is always
9
+ * invoked — no stale-closure problems.
10
+ *
11
+ * ```tsx
12
+ * useGameLoop(bridge, (dt) => {
13
+ * // dt is seconds since last frame
14
+ * player.x += speed * dt;
15
+ * });
16
+ * ```
17
+ */
18
+ export function useGameLoop(bridge, callback) {
19
+ // Always points at the latest callback.
20
+ const callbackRef = useRef(callback);
21
+ callbackRef.current = callback;
22
+ useEffect(() => {
23
+ if (!bridge)
24
+ return;
25
+ // Stable wrapper that delegates to the latest callback.
26
+ const wrapper = (dt) => {
27
+ callbackRef.current(dt);
28
+ };
29
+ bridge.onUpdate(wrapper);
30
+ return () => {
31
+ bridge.removeUpdate(wrapper);
32
+ };
33
+ }, [bridge]);
34
+ }
35
+ //# sourceMappingURL=useGameLoop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGameLoop.js","sourceRoot":"","sources":["../../src/core/useGameLoop.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,sCAAsC;AACtC,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGjD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CACzB,MAAyC,EACzC,QAA8B;IAE9B,wCAAwC;IACxC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IAE/B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,wDAAwD;QACxD,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,EAAE;YAC7B,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzB,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { BridgeInstance } from './types';
2
+ /**
3
+ * Runs a setup callback exactly once when the bridge instance is available.
4
+ *
5
+ * Use this for one-time initialisation that requires the renderer (loading
6
+ * assets, creating scene objects, etc.).
7
+ *
8
+ * ```tsx
9
+ * useGameSetup(bridge, (b) => {
10
+ * // Load assets, create scene objects, etc.
11
+ * const scene = b.getSceneGraph();
12
+ * });
13
+ * ```
14
+ */
15
+ export declare function useGameSetup(bridge: BridgeInstance | null | undefined, setup: (bridge: BridgeInstance) => void | (() => void)): void;
16
+ //# sourceMappingURL=useGameSetup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGameSetup.d.ts","sourceRoot":"","sources":["../../src/core/useGameSetup.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EACzC,KAAK,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GACrD,IAAI,CAON"}
@@ -0,0 +1,27 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @joydle/ui — One-time setup hook
3
+ // ---------------------------------------------------------------------------
4
+ import { useEffect } from 'preact/hooks';
5
+ /**
6
+ * Runs a setup callback exactly once when the bridge instance is available.
7
+ *
8
+ * Use this for one-time initialisation that requires the renderer (loading
9
+ * assets, creating scene objects, etc.).
10
+ *
11
+ * ```tsx
12
+ * useGameSetup(bridge, (b) => {
13
+ * // Load assets, create scene objects, etc.
14
+ * const scene = b.getSceneGraph();
15
+ * });
16
+ * ```
17
+ */
18
+ export function useGameSetup(bridge, setup) {
19
+ useEffect(() => {
20
+ if (!bridge)
21
+ return;
22
+ const cleanup = setup(bridge);
23
+ return typeof cleanup === 'function' ? cleanup : undefined;
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally one-shot
25
+ }, [bridge]);
26
+ }
27
+ //# sourceMappingURL=useGameSetup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGameSetup.js","sourceRoot":"","sources":["../../src/core/useGameSetup.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oCAAoC;AACpC,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAyC,EACzC,KAAsD;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3D,iFAAiF;IACnF,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ComponentChildren } from 'preact';
2
+ import type { JSX } from 'preact';
3
+ export interface BottomHintProps {
4
+ children?: ComponentChildren;
5
+ }
6
+ /**
7
+ * Hint text positioned at the bottom-center of the HUD grid (row 3).
8
+ * Fades in with a slight upward slide on mount via GSAP.
9
+ *
10
+ * ```tsx
11
+ * <HUD>
12
+ * <BottomHint>Press SPACE to start</BottomHint>
13
+ * </HUD>
14
+ * ```
15
+ */
16
+ export declare function BottomHint({ children }: BottomHintProps): JSX.Element;
17
+ //# sourceMappingURL=BottomHint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomHint.d.ts","sourceRoot":"","sources":["../../src/hud/BottomHint.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAclC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAoBD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CAsCrE"}
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx } from "preact/jsx-runtime";
2
+ // ---------------------------------------------------------------------------
3
+ // @joydle/ui — Bottom hint text with GSAP fade-in on mount
4
+ // ---------------------------------------------------------------------------
5
+ import { useRef, useEffect } from 'preact/hooks';
6
+ // ---- GSAP helper ----------------------------------------------------------
7
+ function getGsap() {
8
+ try {
9
+ return globalThis.gsap ?? require('gsap').default;
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ // ---- Styles ---------------------------------------------------------------
16
+ const HINT_STYLE = {
17
+ gridColumn: '1 / -1',
18
+ gridRow: '3',
19
+ display: 'flex',
20
+ justifyContent: 'center',
21
+ alignItems: 'flex-end',
22
+ color: 'var(--joydle-text-dim, rgba(255,255,255,0.5))',
23
+ fontSize: '0.75em',
24
+ lineHeight: 1.3,
25
+ userSelect: 'none',
26
+ whiteSpace: 'nowrap',
27
+ paddingBottom: 4,
28
+ };
29
+ // ---- Component ------------------------------------------------------------
30
+ /**
31
+ * Hint text positioned at the bottom-center of the HUD grid (row 3).
32
+ * Fades in with a slight upward slide on mount via GSAP.
33
+ *
34
+ * ```tsx
35
+ * <HUD>
36
+ * <BottomHint>Press SPACE to start</BottomHint>
37
+ * </HUD>
38
+ * ```
39
+ */
40
+ export function BottomHint({ children }) {
41
+ const elRef = useRef(null);
42
+ const tweenRef = useRef(null);
43
+ useEffect(() => {
44
+ const el = elRef.current;
45
+ if (!el)
46
+ return;
47
+ const gsap = getGsap();
48
+ if (!gsap)
49
+ return;
50
+ tweenRef.current = gsap.fromTo(el, { opacity: 0, y: 10 }, {
51
+ opacity: 1,
52
+ y: 0,
53
+ duration: 0.4,
54
+ ease: 'power2.out',
55
+ onComplete() {
56
+ tweenRef.current = null;
57
+ },
58
+ });
59
+ return () => {
60
+ if (tweenRef.current) {
61
+ tweenRef.current.kill();
62
+ tweenRef.current = null;
63
+ }
64
+ };
65
+ }, []);
66
+ return (_jsx("div", { ref: elRef, class: "joydle-bottom-hint", style: HINT_STYLE, children: children }));
67
+ }
68
+ //# sourceMappingURL=BottomHint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomHint.js","sourceRoot":"","sources":["../../src/hud/BottomHint.tsx"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAE9E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIjD,8EAA8E;AAE9E,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAQ,UAAkB,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAQD,8EAA8E;AAE9E,MAAM,UAAU,GAAoC;IAClD,UAAU,EAAE,QAAQ;IACpB,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,MAAM;IACf,cAAc,EAAE,QAAQ;IACxB,UAAU,EAAE,UAAU;IACtB,KAAK,EAAE,+CAA+C;IACtD,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,GAAG;IACf,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,QAAQ;IACpB,aAAa,EAAE,CAAC;CACjB,CAAC;AAEF,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAmB;IACtD,MAAM,KAAK,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAM,IAAI,CAAC,CAAC;IAEnC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;QACzB,IAAI,CAAC,EAAE;YAAE,OAAO;QAEhB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAC5B,EAAE,EACF,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EACrB;YACE,OAAO,EAAE,CAAC;YACV,CAAC,EAAE,CAAC;YACJ,QAAQ,EAAE,GAAG;YACb,IAAI,EAAE,YAAY;YAClB,UAAU;gBACR,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,CAAC;SACF,CACF,CAAC;QAEF,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACxB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,cAAK,GAAG,EAAE,KAAK,EAAE,KAAK,EAAC,oBAAoB,EAAC,KAAK,EAAE,UAAU,YAC1D,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { JSX } from 'preact';
2
+ export interface ComboLabelProps {
3
+ /** Current combo count. */
4
+ combo: number;
5
+ /** Maximum combo for colour interpolation (default: `10`). */
6
+ max?: number;
7
+ }
8
+ /**
9
+ * Auto-shows when `combo >= 2` with a GSAP scale entrance. Auto-hides
10
+ * with a fade-out when combo drops below 2. The text colour interpolates
11
+ * from `--joydle-text` toward `--joydle-accent` as combo approaches `max`.
12
+ *
13
+ * ```tsx
14
+ * <ComboLabel combo={5} max={20} />
15
+ * ```
16
+ */
17
+ export declare function ComboLabel({ combo, max, }: ComboLabelProps): JSX.Element | null;
18
+ //# sourceMappingURL=ComboLabel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComboLabel.d.ts","sourceRoot":"","sources":["../../src/hud/ComboLabel.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAclC,MAAM,WAAW,eAAe;IAC9B,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,GAAQ,GACT,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAoHtC"}
@@ -0,0 +1,125 @@
1
+ import { jsxs as _jsxs } from "preact/jsx-runtime";
2
+ // ---------------------------------------------------------------------------
3
+ // @joydle/ui — Combo counter with GSAP scale-in / fade-out
4
+ // ---------------------------------------------------------------------------
5
+ import { useRef, useEffect } from 'preact/hooks';
6
+ // ---- GSAP helper ----------------------------------------------------------
7
+ function getGsap() {
8
+ try {
9
+ return globalThis.gsap ?? require('gsap').default;
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ // ---- Component ------------------------------------------------------------
16
+ /**
17
+ * Auto-shows when `combo >= 2` with a GSAP scale entrance. Auto-hides
18
+ * with a fade-out when combo drops below 2. The text colour interpolates
19
+ * from `--joydle-text` toward `--joydle-accent` as combo approaches `max`.
20
+ *
21
+ * ```tsx
22
+ * <ComboLabel combo={5} max={20} />
23
+ * ```
24
+ */
25
+ export function ComboLabel({ combo, max = 10, }) {
26
+ const elRef = useRef(null);
27
+ const prevComboRef = useRef(combo);
28
+ const visibleRef = useRef(combo >= 2);
29
+ const tweenRef = useRef(null);
30
+ // Determine if label should be showing.
31
+ const shouldShow = combo >= 2;
32
+ useEffect(() => {
33
+ const el = elRef.current;
34
+ if (!el)
35
+ return;
36
+ const gsap = getGsap();
37
+ const wasVisible = visibleRef.current;
38
+ if (shouldShow && !wasVisible) {
39
+ // Enter: scale in.
40
+ visibleRef.current = true;
41
+ el.style.display = 'inline-block';
42
+ if (gsap) {
43
+ if (tweenRef.current)
44
+ tweenRef.current.kill();
45
+ tweenRef.current = gsap.fromTo(el, { scale: 0, opacity: 0 }, {
46
+ scale: 1,
47
+ opacity: 1,
48
+ duration: 0.25,
49
+ ease: 'back.out(1.7)',
50
+ onComplete() {
51
+ tweenRef.current = null;
52
+ },
53
+ });
54
+ }
55
+ }
56
+ else if (!shouldShow && wasVisible) {
57
+ // Exit: fade out.
58
+ visibleRef.current = false;
59
+ if (gsap) {
60
+ if (tweenRef.current)
61
+ tweenRef.current.kill();
62
+ tweenRef.current = gsap.to(el, {
63
+ scale: 0.8,
64
+ opacity: 0,
65
+ duration: 0.2,
66
+ ease: 'power2.in',
67
+ onComplete() {
68
+ el.style.display = 'none';
69
+ tweenRef.current = null;
70
+ },
71
+ });
72
+ }
73
+ else {
74
+ el.style.display = 'none';
75
+ }
76
+ }
77
+ else if (shouldShow && wasVisible && combo !== prevComboRef.current) {
78
+ // Already visible but combo changed — quick pop.
79
+ if (gsap) {
80
+ if (tweenRef.current)
81
+ tweenRef.current.kill();
82
+ tweenRef.current = gsap.fromTo(el, { scale: 1.2 }, {
83
+ scale: 1,
84
+ duration: 0.15,
85
+ ease: 'back.out(1.7)',
86
+ onComplete() {
87
+ tweenRef.current = null;
88
+ },
89
+ });
90
+ }
91
+ }
92
+ prevComboRef.current = combo;
93
+ }, [combo, shouldShow]);
94
+ // Cleanup on unmount.
95
+ useEffect(() => {
96
+ return () => {
97
+ if (tweenRef.current) {
98
+ tweenRef.current.kill();
99
+ tweenRef.current = null;
100
+ }
101
+ };
102
+ }, []);
103
+ // Colour interpolation: t from 0 to 1 based on combo/max.
104
+ const t = max > 2 ? Math.min(1, (combo - 2) / (max - 2)) : 0;
105
+ // Font size scales slightly with combo: 1em base, up to 1.4em.
106
+ const fontSize = `${1 + t * 0.4}em`;
107
+ const style = {
108
+ display: shouldShow ? 'inline-block' : 'none',
109
+ fontWeight: 'bold',
110
+ fontSize,
111
+ lineHeight: 1,
112
+ userSelect: 'none',
113
+ whiteSpace: 'nowrap',
114
+ // Interpolate colour: shift from text to accent as combo rises.
115
+ color: t < 0.5
116
+ ? 'var(--joydle-text, #ffffff)'
117
+ : 'var(--joydle-accent, #ff2d7b)',
118
+ textShadow: t > 0.3
119
+ ? '0 0 8px var(--joydle-accent, #ff2d7b)'
120
+ : 'none',
121
+ transformOrigin: 'center center',
122
+ };
123
+ return (_jsxs("span", { ref: elRef, class: "joydle-combo", style: style, children: ["x", combo] }));
124
+ }
125
+ //# sourceMappingURL=ComboLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComboLabel.js","sourceRoot":"","sources":["../../src/hud/ComboLabel.tsx"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAE9E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGjD,8EAA8E;AAE9E,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAQ,UAAkB,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAWD,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,GAAG,GAAG,EAAE,GACQ;IAChB,MAAM,KAAK,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,CAAS,KAAK,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAU,KAAK,IAAI,CAAC,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAM,IAAI,CAAC,CAAC;IAEnC,wCAAwC;IACxC,MAAM,UAAU,GAAG,KAAK,IAAI,CAAC,CAAC;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;QACzB,IAAI,CAAC,EAAE;YAAE,OAAO;QAEhB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC;QAEtC,IAAI,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;YAC9B,mBAAmB;YACnB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,cAAc,CAAC;YAElC,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,QAAQ,CAAC,OAAO;oBAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9C,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAC5B,EAAE,EACF,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EACxB;oBACE,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,CAAC;oBACV,QAAQ,EAAE,IAAI;oBACd,IAAI,EAAE,eAAe;oBACrB,UAAU;wBACR,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;oBAC1B,CAAC;iBACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,UAAU,IAAI,UAAU,EAAE,CAAC;YACrC,kBAAkB;YAClB,UAAU,CAAC,OAAO,GAAG,KAAK,CAAC;YAE3B,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,QAAQ,CAAC,OAAO;oBAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9C,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;oBAC7B,KAAK,EAAE,GAAG;oBACV,OAAO,EAAE,CAAC;oBACV,QAAQ,EAAE,GAAG;oBACb,IAAI,EAAE,WAAW;oBACjB,UAAU;wBACR,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;wBAC1B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;oBAC1B,CAAC;iBACF,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;YAC5B,CAAC;QACH,CAAC;aAAM,IAAI,UAAU,IAAI,UAAU,IAAI,KAAK,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;YACtE,iDAAiD;YACjD,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,QAAQ,CAAC,OAAO;oBAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9C,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAC5B,EAAE,EACF,EAAE,KAAK,EAAE,GAAG,EAAE,EACd;oBACE,KAAK,EAAE,CAAC;oBACR,QAAQ,EAAE,IAAI;oBACd,IAAI,EAAE,eAAe;oBACrB,UAAU;wBACR,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;oBAC1B,CAAC;iBACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;IAC/B,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAExB,sBAAsB;IACtB,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACxB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,0DAA0D;IAC1D,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,+DAA+D;IAC/D,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC;IAEpC,MAAM,KAAK,GAAoC;QAC7C,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM;QAC7C,UAAU,EAAE,MAAM;QAClB,QAAQ;QACR,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,QAAQ;QACpB,gEAAgE;QAChE,KAAK,EAAE,CAAC,GAAG,GAAG;YACZ,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,+BAA+B;QACnC,UAAU,EAAE,CAAC,GAAG,GAAG;YACjB,CAAC,CAAC,uCAAuC;YACzC,CAAC,CAAC,MAAM;QACV,eAAe,EAAE,eAAe;KACjC,CAAC;IAEF,OAAO,CACL,gBAAM,GAAG,EAAE,KAAK,EAAE,KAAK,EAAC,cAAc,EAAC,KAAK,EAAE,KAAK,kBAC/C,KAAK,IACF,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ComponentChildren, FunctionComponent } from 'preact';
2
+ interface SlotProps {
3
+ children?: ComponentChildren;
4
+ }
5
+ declare const Left: FunctionComponent<SlotProps>;
6
+ declare const Center: FunctionComponent<SlotProps>;
7
+ declare const Right: FunctionComponent<SlotProps>;
8
+ export interface HUDProps {
9
+ children?: ComponentChildren;
10
+ }
11
+ interface HUDComponent extends FunctionComponent<HUDProps> {
12
+ Left: typeof Left;
13
+ Center: typeof Center;
14
+ Right: typeof Right;
15
+ }
16
+ export declare const HUD: HUDComponent;
17
+ export {};
18
+ //# sourceMappingURL=HUD.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HUD.d.ts","sourceRoot":"","sources":["../../src/hud/HUD.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAInE,UAAU,SAAS;IACjB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAiDD,QAAA,MAAM,IAAI,EAAE,iBAAiB,CAAC,SAAS,CAItC,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,iBAAiB,CAAC,SAAS,CAIxC,CAAC;AAEF,QAAA,MAAM,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAIvC,CAAC;AAIF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAID,UAAU,YAAa,SAAQ,iBAAiB,CAAC,QAAQ,CAAC;IACxD,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,KAAK,CAAC;CACrB;AA4BD,eAAO,MAAM,GAAG,EAAE,YAIhB,CAAC"}