@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.
- package/dist/controls/ActionButton.d.ts +18 -0
- package/dist/controls/ActionButton.d.ts.map +1 -0
- package/dist/controls/ActionButton.js +108 -0
- package/dist/controls/ActionButton.js.map +1 -0
- package/dist/controls/ActionButtonGroup.d.ts +15 -0
- package/dist/controls/ActionButtonGroup.d.ts.map +1 -0
- package/dist/controls/ActionButtonGroup.js +55 -0
- package/dist/controls/ActionButtonGroup.js.map +1 -0
- package/dist/controls/Joystick.d.ts +9 -0
- package/dist/controls/Joystick.d.ts.map +1 -0
- package/dist/controls/Joystick.js +168 -0
- package/dist/controls/Joystick.js.map +1 -0
- package/dist/controls/SwipeZone.d.ts +10 -0
- package/dist/controls/SwipeZone.d.ts.map +1 -0
- package/dist/controls/SwipeZone.js +84 -0
- package/dist/controls/SwipeZone.js.map +1 -0
- package/dist/controls/TouchDPad.d.ts +9 -0
- package/dist/controls/TouchDPad.d.ts.map +1 -0
- package/dist/controls/TouchDPad.js +90 -0
- package/dist/controls/TouchDPad.js.map +1 -0
- package/dist/controls/index.d.ts +6 -0
- package/dist/controls/index.d.ts.map +1 -0
- package/dist/controls/index.js +9 -0
- package/dist/controls/index.js.map +1 -0
- package/dist/core/GameShell.d.ts +43 -0
- package/dist/core/GameShell.d.ts.map +1 -0
- package/dist/core/GameShell.js +91 -0
- package/dist/core/GameShell.js.map +1 -0
- package/dist/core/GameState.d.ts +35 -0
- package/dist/core/GameState.d.ts.map +1 -0
- package/dist/core/GameState.js +74 -0
- package/dist/core/GameState.js.map +1 -0
- package/dist/core/InputManager.d.ts +39 -0
- package/dist/core/InputManager.d.ts.map +1 -0
- package/dist/core/InputManager.js +149 -0
- package/dist/core/InputManager.js.map +1 -0
- package/dist/core/ScaleManager.d.ts +38 -0
- package/dist/core/ScaleManager.d.ts.map +1 -0
- package/dist/core/ScaleManager.js +106 -0
- package/dist/core/ScaleManager.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +113 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +5 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/useGame.d.ts +22 -0
- package/dist/core/useGame.d.ts.map +1 -0
- package/dist/core/useGame.js +40 -0
- package/dist/core/useGame.js.map +1 -0
- package/dist/core/useGameLoop.d.ts +16 -0
- package/dist/core/useGameLoop.d.ts.map +1 -0
- package/dist/core/useGameLoop.js +35 -0
- package/dist/core/useGameLoop.js.map +1 -0
- package/dist/core/useGameSetup.d.ts +16 -0
- package/dist/core/useGameSetup.d.ts.map +1 -0
- package/dist/core/useGameSetup.js +27 -0
- package/dist/core/useGameSetup.js.map +1 -0
- package/dist/hud/BottomHint.d.ts +17 -0
- package/dist/hud/BottomHint.d.ts.map +1 -0
- package/dist/hud/BottomHint.js +68 -0
- package/dist/hud/BottomHint.js.map +1 -0
- package/dist/hud/ComboLabel.d.ts +18 -0
- package/dist/hud/ComboLabel.d.ts.map +1 -0
- package/dist/hud/ComboLabel.js +125 -0
- package/dist/hud/ComboLabel.js.map +1 -0
- package/dist/hud/HUD.d.ts +18 -0
- package/dist/hud/HUD.d.ts.map +1 -0
- package/dist/hud/HUD.js +72 -0
- package/dist/hud/HUD.js.map +1 -0
- package/dist/hud/Lives.d.ts +21 -0
- package/dist/hud/Lives.d.ts.map +1 -0
- package/dist/hud/Lives.js +92 -0
- package/dist/hud/Lives.js.map +1 -0
- package/dist/hud/Meter.d.ts +24 -0
- package/dist/hud/Meter.d.ts.map +1 -0
- package/dist/hud/Meter.js +133 -0
- package/dist/hud/Meter.js.map +1 -0
- package/dist/hud/MiniMap.d.ts +41 -0
- package/dist/hud/MiniMap.d.ts.map +1 -0
- package/dist/hud/MiniMap.js +103 -0
- package/dist/hud/MiniMap.js.map +1 -0
- package/dist/hud/Score.d.ts +15 -0
- package/dist/hud/Score.d.ts.map +1 -0
- package/dist/hud/Score.js +74 -0
- package/dist/hud/Score.js.map +1 -0
- package/dist/hud/Timer.d.ts +21 -0
- package/dist/hud/Timer.d.ts.map +1 -0
- package/dist/hud/Timer.js +111 -0
- package/dist/hud/Timer.js.map +1 -0
- package/dist/hud/WaveLabel.d.ts +15 -0
- package/dist/hud/WaveLabel.d.ts.map +1 -0
- package/dist/hud/WaveLabel.js +70 -0
- package/dist/hud/WaveLabel.js.map +1 -0
- package/dist/hud/index.d.ts +10 -0
- package/dist/hud/index.d.ts.map +1 -0
- package/dist/hud/index.js +13 -0
- package/dist/hud/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/screens/GameOverScreen.d.ts +36 -0
- package/dist/screens/GameOverScreen.d.ts.map +1 -0
- package/dist/screens/GameOverScreen.js +255 -0
- package/dist/screens/GameOverScreen.js.map +1 -0
- package/dist/screens/LoadingScreen.d.ts +21 -0
- package/dist/screens/LoadingScreen.d.ts.map +1 -0
- package/dist/screens/LoadingScreen.js +129 -0
- package/dist/screens/LoadingScreen.js.map +1 -0
- package/dist/screens/LobbyScreen.d.ts +39 -0
- package/dist/screens/LobbyScreen.d.ts.map +1 -0
- package/dist/screens/LobbyScreen.js +266 -0
- package/dist/screens/LobbyScreen.js.map +1 -0
- package/dist/screens/PauseOverlay.d.ts +29 -0
- package/dist/screens/PauseOverlay.d.ts.map +1 -0
- package/dist/screens/PauseOverlay.js +158 -0
- package/dist/screens/PauseOverlay.js.map +1 -0
- package/dist/screens/ScreenManager.d.ts +26 -0
- package/dist/screens/ScreenManager.d.ts.map +1 -0
- package/dist/screens/ScreenManager.js +61 -0
- package/dist/screens/ScreenManager.js.map +1 -0
- package/dist/screens/TitleScreen.d.ts +30 -0
- package/dist/screens/TitleScreen.d.ts.map +1 -0
- package/dist/screens/TitleScreen.js +263 -0
- package/dist/screens/TitleScreen.js.map +1 -0
- package/dist/screens/index.d.ts +7 -0
- package/dist/screens/index.d.ts.map +1 -0
- package/dist/screens/index.js +10 -0
- package/dist/screens/index.js.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +25 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +51 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +7 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/palettes.d.ts +10 -0
- package/dist/theme/palettes.d.ts.map +1 -0
- package/dist/theme/palettes.js +173 -0
- package/dist/theme/palettes.js.map +1 -0
- package/dist/theme/theme.d.ts +24 -0
- package/dist/theme/theme.d.ts.map +1 -0
- package/dist/theme/theme.js +29 -0
- package/dist/theme/theme.js.map +1 -0
- package/dist/transitions/ScreenTransition.d.ts +19 -0
- package/dist/transitions/ScreenTransition.d.ts.map +1 -0
- package/dist/transitions/ScreenTransition.js +105 -0
- package/dist/transitions/ScreenTransition.js.map +1 -0
- package/dist/transitions/index.d.ts +3 -0
- package/dist/transitions/index.d.ts.map +1 -0
- package/dist/transitions/index.js +6 -0
- package/dist/transitions/index.js.map +1 -0
- package/dist/transitions/presets.d.ts +21 -0
- package/dist/transitions/presets.d.ts.map +1 -0
- package/dist/transitions/presets.js +37 -0
- package/dist/transitions/presets.js.map +1 -0
- package/package.json +62 -0
package/dist/hud/HUD.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
// ---- Styles ---------------------------------------------------------------
|
|
3
|
+
const HUD_STYLE = {
|
|
4
|
+
position: 'absolute',
|
|
5
|
+
top: 0,
|
|
6
|
+
left: 0,
|
|
7
|
+
right: 0,
|
|
8
|
+
bottom: 0,
|
|
9
|
+
zIndex: 10,
|
|
10
|
+
pointerEvents: 'none',
|
|
11
|
+
display: 'grid',
|
|
12
|
+
gridTemplateColumns: '1fr auto 1fr',
|
|
13
|
+
gridTemplateRows: 'auto 1fr auto',
|
|
14
|
+
padding: 12,
|
|
15
|
+
boxSizing: 'border-box',
|
|
16
|
+
fontFamily: 'var(--joydle-font, sans-serif)',
|
|
17
|
+
};
|
|
18
|
+
const LEFT_STYLE = {
|
|
19
|
+
gridColumn: '1',
|
|
20
|
+
gridRow: '1',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
flexDirection: 'column',
|
|
23
|
+
alignItems: 'flex-start',
|
|
24
|
+
gap: 8,
|
|
25
|
+
};
|
|
26
|
+
const CENTER_STYLE = {
|
|
27
|
+
gridColumn: '2',
|
|
28
|
+
gridRow: '1',
|
|
29
|
+
display: 'flex',
|
|
30
|
+
flexDirection: 'column',
|
|
31
|
+
alignItems: 'center',
|
|
32
|
+
gap: 8,
|
|
33
|
+
};
|
|
34
|
+
const RIGHT_STYLE = {
|
|
35
|
+
gridColumn: '3',
|
|
36
|
+
gridRow: '1',
|
|
37
|
+
display: 'flex',
|
|
38
|
+
flexDirection: 'column',
|
|
39
|
+
alignItems: 'flex-end',
|
|
40
|
+
gap: 8,
|
|
41
|
+
};
|
|
42
|
+
// ---- Sub-components -------------------------------------------------------
|
|
43
|
+
const Left = ({ children }) => (_jsx("div", { class: "joydle-hud-left", style: LEFT_STYLE, children: children }));
|
|
44
|
+
const Center = ({ children }) => (_jsx("div", { class: "joydle-hud-center", style: CENTER_STYLE, children: children }));
|
|
45
|
+
const Right = ({ children }) => (_jsx("div", { class: "joydle-hud-right", style: RIGHT_STYLE, children: children }));
|
|
46
|
+
/**
|
|
47
|
+
* HUD layout container with Left, Center, Right slot sub-components.
|
|
48
|
+
*
|
|
49
|
+
* Renders as an absolute-positioned overlay (z-index: 10) with pointer-events
|
|
50
|
+
* disabled. Individual HUD widgets opt in to pointer-events as needed.
|
|
51
|
+
*
|
|
52
|
+
* ```tsx
|
|
53
|
+
* <HUD>
|
|
54
|
+
* <HUD.Left>
|
|
55
|
+
* <Lives current={3} max={5} />
|
|
56
|
+
* </HUD.Left>
|
|
57
|
+
* <HUD.Center>
|
|
58
|
+
* <Score value={12500} />
|
|
59
|
+
* </HUD.Center>
|
|
60
|
+
* <HUD.Right>
|
|
61
|
+
* <Timer seconds={90} />
|
|
62
|
+
* </HUD.Right>
|
|
63
|
+
* </HUD>
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
const HUDBase = ({ children }) => (_jsx("div", { class: "joydle-hud", style: HUD_STYLE, children: children }));
|
|
67
|
+
export const HUD = Object.assign(HUDBase, {
|
|
68
|
+
Left,
|
|
69
|
+
Center,
|
|
70
|
+
Right,
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=HUD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HUD.js","sourceRoot":"","sources":["../../src/hud/HUD.tsx"],"names":[],"mappings":";AAYA,8EAA8E;AAE9E,MAAM,SAAS,GAAoC;IACjD,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,EAAE;IACV,aAAa,EAAE,MAAM;IACrB,OAAO,EAAE,MAAM;IACf,mBAAmB,EAAE,cAAc;IACnC,gBAAgB,EAAE,eAAe;IACjC,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,YAAY;IACvB,UAAU,EAAE,gCAAgC;CAC7C,CAAC;AAEF,MAAM,UAAU,GAAoC;IAClD,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,UAAU,EAAE,YAAY;IACxB,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,MAAM,YAAY,GAAoC;IACpD,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,UAAU,EAAE,QAAQ;IACpB,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,MAAM,WAAW,GAAoC;IACnD,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,UAAU,EAAE,UAAU;IACtB,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,8EAA8E;AAE9E,MAAM,IAAI,GAAiC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC3D,cAAK,KAAK,EAAC,iBAAiB,EAAC,KAAK,EAAE,UAAU,YAC3C,QAAQ,GACL,CACP,CAAC;AAEF,MAAM,MAAM,GAAiC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC7D,cAAK,KAAK,EAAC,mBAAmB,EAAC,KAAK,EAAE,YAAY,YAC/C,QAAQ,GACL,CACP,CAAC;AAEF,MAAM,KAAK,GAAiC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC5D,cAAK,KAAK,EAAC,kBAAkB,EAAC,KAAK,EAAE,WAAW,YAC7C,QAAQ,GACL,CACP,CAAC;AAgBF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,GAAgC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC7D,cAAK,KAAK,EAAC,YAAY,EAAC,KAAK,EAAE,SAAS,YACrC,QAAQ,GACL,CACP,CAAC;AAEF,MAAM,CAAC,MAAM,GAAG,GAAiB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;IACtD,IAAI;IACJ,MAAM;IACN,KAAK;CACN,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
export type LivesIcon = 'heart' | 'shield' | 'diamond' | 'star';
|
|
3
|
+
export interface LivesProps {
|
|
4
|
+
/** Number of lives remaining. */
|
|
5
|
+
current: number;
|
|
6
|
+
/** Maximum number of lives. */
|
|
7
|
+
max: number;
|
|
8
|
+
/** Icon character to display (default: `"heart"`). */
|
|
9
|
+
icon?: LivesIcon;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Renders a row of life icons. Filled icons represent remaining lives,
|
|
13
|
+
* faded icons represent lost ones. A GSAP elastic shake plays on the
|
|
14
|
+
* container when lives decrease.
|
|
15
|
+
*
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Lives current={3} max={5} icon="heart" />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function Lives({ current, max, icon, }: LivesProps): JSX.Element;
|
|
21
|
+
//# sourceMappingURL=Lives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Lives.d.ts","sourceRoot":"","sources":["../../src/hud/Lives.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAclC,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAiCD;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EACpB,OAAO,EACP,GAAG,EACH,IAAc,GACf,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,CAgE1B"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @joydle/ui — Icon-based lives display with GSAP shake on decrease
|
|
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
|
+
// ---- Icon map -------------------------------------------------------------
|
|
16
|
+
const ICON_MAP = {
|
|
17
|
+
heart: '\u2665', // black heart suit
|
|
18
|
+
shield: '\uD83D\uDEE1', // shield emoji
|
|
19
|
+
diamond: '\u25C6', // black diamond
|
|
20
|
+
star: '\u2605', // black star
|
|
21
|
+
};
|
|
22
|
+
// ---- Styles ---------------------------------------------------------------
|
|
23
|
+
const ROW_STYLE = {
|
|
24
|
+
display: 'flex',
|
|
25
|
+
gap: 4,
|
|
26
|
+
lineHeight: 1,
|
|
27
|
+
userSelect: 'none',
|
|
28
|
+
};
|
|
29
|
+
const ICON_STYLE_FILLED = {
|
|
30
|
+
color: 'var(--joydle-danger, #ff4444)',
|
|
31
|
+
fontSize: '1.2em',
|
|
32
|
+
transition: 'opacity 0.15s',
|
|
33
|
+
};
|
|
34
|
+
const ICON_STYLE_EMPTY = {
|
|
35
|
+
...ICON_STYLE_FILLED,
|
|
36
|
+
opacity: 0.3,
|
|
37
|
+
};
|
|
38
|
+
// ---- Component ------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Renders a row of life icons. Filled icons represent remaining lives,
|
|
41
|
+
* faded icons represent lost ones. A GSAP elastic shake plays on the
|
|
42
|
+
* container when lives decrease.
|
|
43
|
+
*
|
|
44
|
+
* ```tsx
|
|
45
|
+
* <Lives current={3} max={5} icon="heart" />
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function Lives({ current, max, icon = 'heart', }) {
|
|
49
|
+
const rowRef = useRef(null);
|
|
50
|
+
const prevRef = useRef(current);
|
|
51
|
+
const tweenRef = useRef(null);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
const el = rowRef.current;
|
|
54
|
+
if (!el)
|
|
55
|
+
return;
|
|
56
|
+
// Only animate on decrease.
|
|
57
|
+
if (current < prevRef.current) {
|
|
58
|
+
const gsap = getGsap();
|
|
59
|
+
if (gsap) {
|
|
60
|
+
if (tweenRef.current) {
|
|
61
|
+
tweenRef.current.kill();
|
|
62
|
+
}
|
|
63
|
+
tweenRef.current = gsap.fromTo(el, { x: -6 }, {
|
|
64
|
+
x: 0,
|
|
65
|
+
duration: 0.3,
|
|
66
|
+
ease: 'elastic.out(1, 0.3)',
|
|
67
|
+
onComplete() {
|
|
68
|
+
tweenRef.current = null;
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
prevRef.current = current;
|
|
74
|
+
}, [current]);
|
|
75
|
+
// Cleanup on unmount.
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
return () => {
|
|
78
|
+
if (tweenRef.current) {
|
|
79
|
+
tweenRef.current.kill();
|
|
80
|
+
tweenRef.current = null;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}, []);
|
|
84
|
+
const glyph = ICON_MAP[icon];
|
|
85
|
+
const icons = [];
|
|
86
|
+
for (let i = 0; i < max; i++) {
|
|
87
|
+
const filled = i < current;
|
|
88
|
+
icons.push(_jsx("span", { style: filled ? ICON_STYLE_FILLED : ICON_STYLE_EMPTY, children: glyph }, i));
|
|
89
|
+
}
|
|
90
|
+
return (_jsx("div", { ref: rowRef, class: "joydle-lives", style: ROW_STYLE, children: icons }));
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=Lives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Lives.js","sourceRoot":"","sources":["../../src/hud/Lives.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
export interface MeterProps {
|
|
3
|
+
/** Current value. */
|
|
4
|
+
value: number;
|
|
5
|
+
/** Maximum value. */
|
|
6
|
+
max: number;
|
|
7
|
+
/** CSS custom property name for the fill colour (default: `"--joydle-primary"`). */
|
|
8
|
+
color?: string;
|
|
9
|
+
/** Optional label rendered above the bar. */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** Bar width in pixels (default: `60`). */
|
|
12
|
+
width?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A horizontal fill-bar meter. The fill width is animated with GSAP on
|
|
16
|
+
* every value change. When value drops below 20% of max a brief white
|
|
17
|
+
* flash overlay fires as a warning.
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <Meter value={hp} max={100} label="HP" color="--joydle-danger" />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function Meter({ value, max, color, label, width, }: MeterProps): JSX.Element;
|
|
24
|
+
//# sourceMappingURL=Meter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Meter.d.ts","sourceRoot":"","sources":["../../src/hud/Meter.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAclC,MAAM,WAAW,UAAU;IACzB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,GAAG,EACH,KAA0B,EAC1B,KAAK,EACL,KAAU,GACX,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,CA0I1B"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @joydle/ui — Fill bar meter with GSAP tween and flash on deplete
|
|
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
|
+
* A horizontal fill-bar meter. The fill width is animated with GSAP on
|
|
18
|
+
* every value change. When value drops below 20% of max a brief white
|
|
19
|
+
* flash overlay fires as a warning.
|
|
20
|
+
*
|
|
21
|
+
* ```tsx
|
|
22
|
+
* <Meter value={hp} max={100} label="HP" color="--joydle-danger" />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function Meter({ value, max, color = '--joydle-primary', label, width = 60, }) {
|
|
26
|
+
const fillRef = useRef(null);
|
|
27
|
+
const flashRef = useRef(null);
|
|
28
|
+
const prevRef = useRef(value);
|
|
29
|
+
const fillTweenRef = useRef(null);
|
|
30
|
+
const flashTweenRef = useRef(null);
|
|
31
|
+
const pct = max > 0 ? Math.max(0, Math.min(100, (value / max) * 100)) : 0;
|
|
32
|
+
const prevPct = max > 0 ? Math.max(0, Math.min(100, (prevRef.current / max) * 100)) : 0;
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const fillEl = fillRef.current;
|
|
35
|
+
if (!fillEl)
|
|
36
|
+
return;
|
|
37
|
+
const gsap = getGsap();
|
|
38
|
+
if (!gsap) {
|
|
39
|
+
// Fallback: set width directly without animation.
|
|
40
|
+
fillEl.style.width = `${pct}%`;
|
|
41
|
+
prevRef.current = value;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Kill any in-progress fill tween.
|
|
45
|
+
if (fillTweenRef.current) {
|
|
46
|
+
fillTweenRef.current.kill();
|
|
47
|
+
}
|
|
48
|
+
fillTweenRef.current = gsap.fromTo(fillEl, { width: `${prevPct}%` }, {
|
|
49
|
+
width: `${pct}%`,
|
|
50
|
+
duration: 0.3,
|
|
51
|
+
ease: 'power2.out',
|
|
52
|
+
onComplete() {
|
|
53
|
+
fillTweenRef.current = null;
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
// Flash when dropping below 20%.
|
|
57
|
+
const flashEl = flashRef.current;
|
|
58
|
+
if (flashEl && value < prevRef.current && pct < 20 && prevPct >= 20) {
|
|
59
|
+
if (flashTweenRef.current) {
|
|
60
|
+
flashTweenRef.current.kill();
|
|
61
|
+
}
|
|
62
|
+
flashTweenRef.current = gsap.fromTo(flashEl, { opacity: 0.6 }, {
|
|
63
|
+
opacity: 0,
|
|
64
|
+
duration: 0.25,
|
|
65
|
+
ease: 'power2.out',
|
|
66
|
+
onComplete() {
|
|
67
|
+
flashTweenRef.current = null;
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
prevRef.current = value;
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [value, max]);
|
|
74
|
+
// Cleanup on unmount.
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
return () => {
|
|
77
|
+
if (fillTweenRef.current) {
|
|
78
|
+
fillTweenRef.current.kill();
|
|
79
|
+
fillTweenRef.current = null;
|
|
80
|
+
}
|
|
81
|
+
if (flashTweenRef.current) {
|
|
82
|
+
flashTweenRef.current.kill();
|
|
83
|
+
flashTweenRef.current = null;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}, []);
|
|
87
|
+
// ---- Styles (inline) ----------------------------------------------------
|
|
88
|
+
const containerStyle = {
|
|
89
|
+
display: 'inline-flex',
|
|
90
|
+
flexDirection: 'column',
|
|
91
|
+
gap: 2,
|
|
92
|
+
userSelect: 'none',
|
|
93
|
+
};
|
|
94
|
+
const labelStyle = {
|
|
95
|
+
fontSize: '0.6em',
|
|
96
|
+
color: 'var(--joydle-text-dim, rgba(255,255,255,0.5))',
|
|
97
|
+
lineHeight: 1,
|
|
98
|
+
whiteSpace: 'nowrap',
|
|
99
|
+
};
|
|
100
|
+
const outerStyle = {
|
|
101
|
+
position: 'relative',
|
|
102
|
+
width,
|
|
103
|
+
height: 8,
|
|
104
|
+
borderRadius: 4,
|
|
105
|
+
border: '1px solid rgba(255,255,255,0.3)',
|
|
106
|
+
overflow: 'hidden',
|
|
107
|
+
background: 'rgba(255,255,255,0.1)',
|
|
108
|
+
boxSizing: 'border-box',
|
|
109
|
+
};
|
|
110
|
+
const fillStyle = {
|
|
111
|
+
position: 'absolute',
|
|
112
|
+
top: 0,
|
|
113
|
+
left: 0,
|
|
114
|
+
height: '100%',
|
|
115
|
+
width: `${pct}%`,
|
|
116
|
+
background: `var(${color}, #00f5ff)`,
|
|
117
|
+
borderRadius: 3,
|
|
118
|
+
transition: 'none', // GSAP handles the transition
|
|
119
|
+
};
|
|
120
|
+
const flashStyle = {
|
|
121
|
+
position: 'absolute',
|
|
122
|
+
top: 0,
|
|
123
|
+
left: 0,
|
|
124
|
+
width: '100%',
|
|
125
|
+
height: '100%',
|
|
126
|
+
background: '#ffffff',
|
|
127
|
+
opacity: 0,
|
|
128
|
+
borderRadius: 3,
|
|
129
|
+
pointerEvents: 'none',
|
|
130
|
+
};
|
|
131
|
+
return (_jsxs("div", { class: "joydle-meter", style: containerStyle, children: [label && _jsx("span", { style: labelStyle, children: label }), _jsxs("div", { style: outerStyle, children: [_jsx("div", { ref: fillRef, style: fillStyle }), _jsx("div", { ref: flashRef, style: flashStyle })] })] }));
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=Meter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Meter.js","sourceRoot":"","sources":["../../src/hud/Meter.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
export interface MiniMapEntity {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
color: string;
|
|
6
|
+
}
|
|
7
|
+
export interface MiniMapBounds {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
export interface MiniMapProps {
|
|
12
|
+
/** Array of entity positions and colours to render as dots. */
|
|
13
|
+
entities: MiniMapEntity[];
|
|
14
|
+
/** World bounds used to scale entity positions to minimap space. */
|
|
15
|
+
bounds: MiniMapBounds;
|
|
16
|
+
/** Current player position (rendered as a larger, brighter dot). */
|
|
17
|
+
playerPos: {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
};
|
|
21
|
+
/** Minimap size in pixels (default: `100`). Both width and height. */
|
|
22
|
+
size?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Small canvas-based minimap that renders entity dots proportionally scaled
|
|
26
|
+
* within world bounds. The player dot is drawn larger and brighter.
|
|
27
|
+
*
|
|
28
|
+
* The component has `pointer-events: auto` so it can receive interactions
|
|
29
|
+
* (e.g. click-to-ping in the future).
|
|
30
|
+
*
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <MiniMap
|
|
33
|
+
* entities={[{ x: 100, y: 200, color: '#ff0000' }]}
|
|
34
|
+
* bounds={{ width: 1000, height: 1000 }}
|
|
35
|
+
* playerPos={{ x: 500, y: 500 }}
|
|
36
|
+
* size={120}
|
|
37
|
+
* />
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function MiniMap({ entities, bounds, playerPos, size, }: MiniMapProps): JSX.Element;
|
|
41
|
+
//# sourceMappingURL=MiniMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MiniMap.d.ts","sourceRoot":"","sources":["../../src/hud/MiniMap.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAIlC,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,oEAAoE;IACpE,MAAM,EAAE,aAAa,CAAC;IACtB,oEAAoE;IACpE,SAAS,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAYD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,IAAU,GACX,EAAE,YAAY,GAAG,GAAG,CAAC,OAAO,CA2F5B"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @joydle/ui — Mini-map canvas overlay with entity dots
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
import { useRef, useEffect } from 'preact/hooks';
|
|
6
|
+
// ---- Constants ------------------------------------------------------------
|
|
7
|
+
const ENTITY_RADIUS = 2;
|
|
8
|
+
const PLAYER_RADIUS = 3.5;
|
|
9
|
+
const BG_COLOR = 'rgba(0, 0, 0, 0.55)';
|
|
10
|
+
const BORDER_COLOR = 'rgba(255, 255, 255, 0.25)';
|
|
11
|
+
const PLAYER_COLOR = '#ffffff';
|
|
12
|
+
// ---- Component ------------------------------------------------------------
|
|
13
|
+
/**
|
|
14
|
+
* Small canvas-based minimap that renders entity dots proportionally scaled
|
|
15
|
+
* within world bounds. The player dot is drawn larger and brighter.
|
|
16
|
+
*
|
|
17
|
+
* The component has `pointer-events: auto` so it can receive interactions
|
|
18
|
+
* (e.g. click-to-ping in the future).
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <MiniMap
|
|
22
|
+
* entities={[{ x: 100, y: 200, color: '#ff0000' }]}
|
|
23
|
+
* bounds={{ width: 1000, height: 1000 }}
|
|
24
|
+
* playerPos={{ x: 500, y: 500 }}
|
|
25
|
+
* size={120}
|
|
26
|
+
* />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function MiniMap({ entities, bounds, playerPos, size = 100, }) {
|
|
30
|
+
const canvasRef = useRef(null);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const canvas = canvasRef.current;
|
|
33
|
+
if (!canvas)
|
|
34
|
+
return;
|
|
35
|
+
const ctx = canvas.getContext('2d');
|
|
36
|
+
if (!ctx)
|
|
37
|
+
return;
|
|
38
|
+
const dpr = window.devicePixelRatio || 1;
|
|
39
|
+
const cssSize = size;
|
|
40
|
+
const pxSize = Math.round(cssSize * dpr);
|
|
41
|
+
// Resize backing store if needed.
|
|
42
|
+
if (canvas.width !== pxSize || canvas.height !== pxSize) {
|
|
43
|
+
canvas.width = pxSize;
|
|
44
|
+
canvas.height = pxSize;
|
|
45
|
+
}
|
|
46
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
47
|
+
// Background.
|
|
48
|
+
ctx.clearRect(0, 0, cssSize, cssSize);
|
|
49
|
+
ctx.fillStyle = BG_COLOR;
|
|
50
|
+
ctx.beginPath();
|
|
51
|
+
ctx.roundRect(0, 0, cssSize, cssSize, 4);
|
|
52
|
+
ctx.fill();
|
|
53
|
+
// Border.
|
|
54
|
+
ctx.strokeStyle = BORDER_COLOR;
|
|
55
|
+
ctx.lineWidth = 1;
|
|
56
|
+
ctx.beginPath();
|
|
57
|
+
ctx.roundRect(0.5, 0.5, cssSize - 1, cssSize - 1, 4);
|
|
58
|
+
ctx.stroke();
|
|
59
|
+
// Helper: map world coords to minimap coords with small padding.
|
|
60
|
+
const pad = 4;
|
|
61
|
+
const mapW = cssSize - pad * 2;
|
|
62
|
+
const mapH = cssSize - pad * 2;
|
|
63
|
+
const scaleX = bounds.width > 0 ? mapW / bounds.width : 1;
|
|
64
|
+
const scaleY = bounds.height > 0 ? mapH / bounds.height : 1;
|
|
65
|
+
const toMapX = (wx) => pad + wx * scaleX;
|
|
66
|
+
const toMapY = (wy) => pad + wy * scaleY;
|
|
67
|
+
// Draw entity dots.
|
|
68
|
+
for (let i = 0; i < entities.length; i++) {
|
|
69
|
+
const e = entities[i];
|
|
70
|
+
const mx = toMapX(e.x);
|
|
71
|
+
const my = toMapY(e.y);
|
|
72
|
+
ctx.fillStyle = e.color;
|
|
73
|
+
ctx.beginPath();
|
|
74
|
+
ctx.arc(mx, my, ENTITY_RADIUS, 0, Math.PI * 2);
|
|
75
|
+
ctx.fill();
|
|
76
|
+
}
|
|
77
|
+
// Draw player dot (on top).
|
|
78
|
+
const px = toMapX(playerPos.x);
|
|
79
|
+
const py = toMapY(playerPos.y);
|
|
80
|
+
ctx.fillStyle = PLAYER_COLOR;
|
|
81
|
+
ctx.shadowColor = PLAYER_COLOR;
|
|
82
|
+
ctx.shadowBlur = 4;
|
|
83
|
+
ctx.beginPath();
|
|
84
|
+
ctx.arc(px, py, PLAYER_RADIUS, 0, Math.PI * 2);
|
|
85
|
+
ctx.fill();
|
|
86
|
+
ctx.shadowBlur = 0;
|
|
87
|
+
}, [entities, bounds, playerPos, size]);
|
|
88
|
+
const containerStyle = {
|
|
89
|
+
width: size,
|
|
90
|
+
height: size,
|
|
91
|
+
pointerEvents: 'auto',
|
|
92
|
+
borderRadius: 4,
|
|
93
|
+
overflow: 'hidden',
|
|
94
|
+
flexShrink: 0,
|
|
95
|
+
};
|
|
96
|
+
const canvasStyle = {
|
|
97
|
+
width: size,
|
|
98
|
+
height: size,
|
|
99
|
+
display: 'block',
|
|
100
|
+
};
|
|
101
|
+
return (_jsx("div", { class: "joydle-minimap", style: containerStyle, children: _jsx("canvas", { ref: canvasRef, style: canvasStyle }) }));
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=MiniMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MiniMap.js","sourceRoot":"","sources":["../../src/hud/MiniMap.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
export interface ScoreProps {
|
|
3
|
+
/** Current score value. */
|
|
4
|
+
value: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Displays a formatted numeric score with a GSAP scale-pop animation
|
|
8
|
+
* whenever the value changes.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <Score value={12500} />
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function Score({ value }: ScoreProps): JSX.Element;
|
|
15
|
+
//# sourceMappingURL=Score.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Score.d.ts","sourceRoot":"","sources":["../../src/hud/Score.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAclC,MAAM,WAAW,UAAU;IACzB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAmBD;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,CAkDxD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @joydle/ui — Score display with GSAP scale-pop on change
|
|
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
|
+
// ---- Formatter ------------------------------------------------------------
|
|
16
|
+
const formatter = new Intl.NumberFormat('en-US');
|
|
17
|
+
// ---- Styles ---------------------------------------------------------------
|
|
18
|
+
const SCORE_STYLE = {
|
|
19
|
+
color: 'var(--joydle-gold, #ffd700)',
|
|
20
|
+
fontWeight: 'bold',
|
|
21
|
+
fontSize: '1.5em',
|
|
22
|
+
lineHeight: 1,
|
|
23
|
+
userSelect: 'none',
|
|
24
|
+
whiteSpace: 'nowrap',
|
|
25
|
+
};
|
|
26
|
+
// ---- Component ------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Displays a formatted numeric score with a GSAP scale-pop animation
|
|
29
|
+
* whenever the value changes.
|
|
30
|
+
*
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <Score value={12500} />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function Score({ value }) {
|
|
36
|
+
const elRef = useRef(null);
|
|
37
|
+
const prevRef = useRef(value);
|
|
38
|
+
const tweenRef = useRef(null);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const el = elRef.current;
|
|
41
|
+
if (!el)
|
|
42
|
+
return;
|
|
43
|
+
// Only animate when value actually changes.
|
|
44
|
+
if (prevRef.current === value)
|
|
45
|
+
return;
|
|
46
|
+
prevRef.current = value;
|
|
47
|
+
const gsap = getGsap();
|
|
48
|
+
if (!gsap)
|
|
49
|
+
return;
|
|
50
|
+
// Kill any in-progress tween before starting a new one.
|
|
51
|
+
if (tweenRef.current) {
|
|
52
|
+
tweenRef.current.kill();
|
|
53
|
+
}
|
|
54
|
+
tweenRef.current = gsap.fromTo(el, { scale: 1.3 }, {
|
|
55
|
+
scale: 1,
|
|
56
|
+
duration: 0.15,
|
|
57
|
+
ease: 'back.out(1.7)',
|
|
58
|
+
onComplete() {
|
|
59
|
+
tweenRef.current = null;
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}, [value]);
|
|
63
|
+
// Cleanup on unmount.
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
return () => {
|
|
66
|
+
if (tweenRef.current) {
|
|
67
|
+
tweenRef.current.kill();
|
|
68
|
+
tweenRef.current = null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
72
|
+
return (_jsx("span", { ref: elRef, class: "joydle-score", style: SCORE_STYLE, children: formatter.format(value) }));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=Score.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Score.js","sourceRoot":"","sources":["../../src/hud/Score.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;AASD,8EAA8E;AAE9E,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;AAEjD,8EAA8E;AAE9E,MAAM,WAAW,GAAoC;IACnD,KAAK,EAAE,6BAA6B;IACpC,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,OAAO;IACjB,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,QAAQ;CACrB,CAAC;AAEF,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,KAAK,EAAc;IACzC,MAAM,KAAK,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAS,KAAK,CAAC,CAAC;IACtC,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,4CAA4C;QAC5C,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK;YAAE,OAAO;QACtC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;QAExB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,wDAAwD;QACxD,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAED,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAC5B,EAAE,EACF,EAAE,KAAK,EAAE,GAAG,EAAE,EACd;YACE,KAAK,EAAE,CAAC;YACR,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,eAAe;YACrB,UAAU;gBACR,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,CAAC;SACF,CACF,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,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,OAAO,CACL,eAAM,GAAG,EAAE,KAAK,EAAE,KAAK,EAAC,cAAc,EAAC,KAAK,EAAE,WAAW,YACtD,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,GACnB,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
export type TimerFormat = 'm:ss' | 'mm:ss' | 's';
|
|
3
|
+
export interface TimerProps {
|
|
4
|
+
/** Time in seconds. */
|
|
5
|
+
seconds: number;
|
|
6
|
+
/** Display format (default: `"m:ss"`). */
|
|
7
|
+
format?: TimerFormat;
|
|
8
|
+
/** Seconds threshold below which warning pulse activates. */
|
|
9
|
+
warning?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Displays formatted time. When `seconds` drops below the `warning`
|
|
13
|
+
* threshold a repeating GSAP pulse tween animates opacity and switches
|
|
14
|
+
* the colour to `--joydle-danger`.
|
|
15
|
+
*
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Timer seconds={timeLeft} warning={10} />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function Timer({ seconds, format, warning, }: TimerProps): JSX.Element;
|
|
21
|
+
//# sourceMappingURL=Timer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Timer.d.ts","sourceRoot":"","sources":["../../src/hud/Timer.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAclC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAsCD;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EACpB,OAAO,EACP,MAAe,EACf,OAAO,GACR,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,CAiE1B"}
|