@rydr/game-sdk 5.0.0 → 6.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 (47) hide show
  1. package/README.md +25 -18
  2. package/dist/client/PlatformClient.d.ts +11 -10
  3. package/dist/client/PlatformClient.d.ts.map +1 -1
  4. package/dist/client/PlatformClient.js +46 -21
  5. package/dist/client/PlatformClient.js.map +1 -1
  6. package/dist/host/PlatformHost.d.ts +16 -7
  7. package/dist/host/PlatformHost.d.ts.map +1 -1
  8. package/dist/host/PlatformHost.js +3 -0
  9. package/dist/host/PlatformHost.js.map +1 -1
  10. package/dist/protocol/buttons.d.ts +62 -31
  11. package/dist/protocol/buttons.d.ts.map +1 -1
  12. package/dist/protocol/buttons.js +42 -25
  13. package/dist/protocol/buttons.js.map +1 -1
  14. package/dist/protocol/capabilities.d.ts +1 -1
  15. package/dist/protocol/messages.d.ts +22 -5
  16. package/dist/protocol/messages.d.ts.map +1 -1
  17. package/dist/protocol/perf.d.ts +37 -0
  18. package/dist/protocol/perf.d.ts.map +1 -0
  19. package/dist/protocol/perf.js +17 -0
  20. package/dist/protocol/perf.js.map +1 -0
  21. package/dist/protocol/version.d.ts +2 -2
  22. package/dist/protocol/version.d.ts.map +1 -1
  23. package/dist/protocol/version.js +31 -2
  24. package/dist/protocol/version.js.map +1 -1
  25. package/dist/three/perf-marks.d.ts +2 -21
  26. package/dist/three/perf-marks.d.ts.map +1 -1
  27. package/dist/three/perf-marks.js.map +1 -1
  28. package/dist/ui/README.md +3 -0
  29. package/dist/ui/heat-vignette.d.ts +75 -0
  30. package/dist/ui/heat-vignette.d.ts.map +1 -0
  31. package/dist/ui/heat-vignette.js +126 -0
  32. package/dist/ui/heat-vignette.js.map +1 -0
  33. package/dist/ui/index.d.ts +7 -0
  34. package/dist/ui/index.d.ts.map +1 -1
  35. package/dist/ui/index.js +7 -0
  36. package/dist/ui/index.js.map +1 -1
  37. package/dist/ui/overheat-glitch.d.ts +56 -0
  38. package/dist/ui/overheat-glitch.d.ts.map +1 -0
  39. package/dist/ui/overheat-glitch.js +177 -0
  40. package/dist/ui/overheat-glitch.js.map +1 -0
  41. package/dist/ui/overheat-hud-bar.d.ts +79 -0
  42. package/dist/ui/overheat-hud-bar.d.ts.map +1 -0
  43. package/dist/ui/overheat-hud-bar.js +302 -0
  44. package/dist/ui/overheat-hud-bar.js.map +1 -0
  45. package/dist/ui/showcase/index.js +2 -2
  46. package/dist/ui/showcase/index.js.map +1 -1
  47. package/package.json +1 -1
@@ -131,8 +131,37 @@
131
131
  // whatever went back on `DIAMOND_LEFT` must now go back on `DIAMOND_RIGHT`. Doing only the first step
132
132
  // compiles and runs while keeping the old, wrong ergonomics. Finally, replace every hardcoded button
133
133
  // letter in on-screen text with `session.buttonLabel(…)`.
134
- export const RYDR_PROTOCOL_VERSION = 26;
134
+ // Bumped 26 27: REMOVES the trigger axes `LT`/`RT` from the `input.axis` `name` vocabulary
135
+ // (BREAKING for the `AxisName` type — it narrows to the four stick axes `LX`/`LY`/`RX`/`RY`). The
136
+ // shoulder triggers are plain CLICKS on the hardware — there is no analog trigger travel — so
137
+ // `axis("LT"|"RT")` promised a reading that could never exist. The digital `LT`/`RT` ButtonNames are
138
+ // untouched. Wire-wise this is a no-op: no shell ever emitted a trigger axis (protocol-22 shells only
139
+ // ever sent stick axes), and the SDK's keyboard emulation was the sole feeder (`a`/`e` snapping 0/1),
140
+ // now removed. Migrate: `session.axis("LT"|"RT")` → `session.isDown("LT"|"RT")` (the on/off click).
141
+ // Bumped 27 → 28: adds `OPTIONS` to the `input.button` `name` vocabulary — a single extra button,
142
+ // distinct from the platform's own overlay menu (`M`/phone `MENU`/gamepad Start, which never reaches
143
+ // a game). It's the GAME's own menu/options button. Keyboard `o`, a standard gamepad's Select/Back
144
+ // button, and a new phone icon all send it; not every device has it, so never gate a required flow
145
+ // behind it alone. Additive: no existing shape or name changed, and an older game's `onButton` has no
146
+ // branch for `OPTIONS`, so it's inert there — no old-guest shield needed. (Unrelated to the wire
147
+ // vocabulary: the right stick and both stick-click buttons also moved off `i`/`j`/`k`/`l`/`f`/`o` onto
148
+ // the numeric keypad in this same release, but that's purely which PHYSICAL KEY the SDK's own keyboard
149
+ // emulation listens for — the `ButtonName`s it produces are unchanged, so it carries no protocol bump.)
150
+ // Bumped 28 → 29: adds `rydr/rider.adjustFtp` (`{ direction: 1 | -1 }`, game→platform) — the fourth
151
+ // shell-owned rider-key relay, joining `audio.adjustMaster` (T/G), `trainer.adjustResistance` (W/X)
152
+ // and `menu.toggle` (M). The keys are − and + and they step the rider's PLAYING FTP: a memory-only
153
+ // session override the shell layers on the profile FTP, so a rider can make every game harder or
154
+ // easier mid-ride without editing their profile (it resets to the profile number on reload). Like
155
+ // its three siblings it exists only because a focused game iframe swallows the keystroke before the
156
+ // shell window can see it. There is no reply message — the shell pushes the resulting FTP to every
157
+ // game as a fresh `rydr/identity.update`, so a game reads it exactly where it already reads FTP
158
+ // (`session.identity.ftp` / `onIdentityChange`). Ungated (no capability), like the other three.
159
+ // Additive: an older shell has no `onAdjustFtp` handler, so the message is a silent no-op there
160
+ // (−/+ keeps working only while the shell holds focus) and nothing existing changed. No game code
161
+ // required — but a game that snapshots `identity.ftp` at init instead of subscribing to
162
+ // `onIdentityChange` won't see mid-ride changes, which was already true for a profile edit.
163
+ export const RYDR_PROTOCOL_VERSION = 29;
135
164
  /** Semver of this SDK build. Sent in the handshake for telemetry/debugging.
136
165
  * (Bumped to 2.0.0 by `npm version major` on release — see CHANGELOG [Unreleased].) */
137
- export const RYDR_SDK_VERSION = "5.0.0";
166
+ export const RYDR_SDK_VERSION = "6.1.0";
138
167
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/protocol/version.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,8FAA8F;AAC9F,yDAAyD;AACzD,4FAA4F;AAC5F,oGAAoG;AACpG,kGAAkG;AAClG,6EAA6E;AAC7E,kGAAkG;AAClG,uGAAuG;AACvG,wFAAwF;AACxF,oGAAoG;AACpG,gGAAgG;AAChG,yFAAyF;AACzF,kHAAkH;AAClH,oGAAoG;AACpG,qGAAqG;AACrG,kGAAkG;AAClG,mGAAmG;AACnG,oGAAoG;AACpG,6FAA6F;AAC7F,gGAAgG;AAChG,uGAAuG;AACvG,mGAAmG;AACnG,kGAAkG;AAClG,+FAA+F;AAC/F,kGAAkG;AAClG,iGAAiG;AACjG,iGAAiG;AACjG,+FAA+F;AAC/F,qGAAqG;AACrG,uGAAuG;AACvG,+FAA+F;AAC/F,qGAAqG;AACrG,kGAAkG;AAClG,2BAA2B;AAC3B,mGAAmG;AACnG,mGAAmG;AACnG,gGAAgG;AAChG,iGAAiG;AACjG,oFAAoF;AACpF,oGAAoG;AACpG,kGAAkG;AAClG,oGAAoG;AACpG,iGAAiG;AACjG,sGAAsG;AACtG,wGAAwG;AACxG,qGAAqG;AACrG,uGAAuG;AACvG,sGAAsG;AACtG,wGAAwG;AACxG,qGAAqG;AACrG,uGAAuG;AACvG,uGAAuG;AACvG,mGAAmG;AACnG,kFAAkF;AAClF,yGAAyG;AACzG,oGAAoG;AACpG,uGAAuG;AACvG,0GAA0G;AAC1G,yGAAyG;AACzG,yBAAyB;AACzB,sGAAsG;AACtG,sGAAsG;AACtG,qGAAqG;AACrG,wGAAwG;AACxG,uGAAuG;AACvG,6FAA6F;AAC7F,iGAAiG;AACjG,iGAAiG;AACjG,+FAA+F;AAC/F,mGAAmG;AACnG,iGAAiG;AACjG,oGAAoG;AACpG,qCAAqC;AACrC,kGAAkG;AAClG,yGAAyG;AACzG,4GAA4G;AAC5G,sGAAsG;AACtG,oGAAoG;AACpG,oGAAoG;AACpG,qGAAqG;AACrG,mGAAmG;AACnG,mGAAmG;AACnG,gGAAgG;AAChG,+FAA+F;AAC/F,iGAAiG;AACjG,oGAAoG;AACpG,kEAAkE;AAClE,qGAAqG;AACrG,wGAAwG;AACxG,sGAAsG;AACtG,0GAA0G;AAC1G,2GAA2G;AAC3G,yGAAyG;AACzG,oGAAoG;AACpG,iFAAiF;AACjF,wGAAwG;AACxG,4GAA4G;AAC5G,0GAA0G;AAC1G,uGAAuG;AACvG,2GAA2G;AAC3G,0GAA0G;AAC1G,wGAAwG;AACxG,mGAAmG;AACnG,4GAA4G;AAC5G,0GAA0G;AAC1G,2GAA2G;AAC3G,qFAAqF;AACrF,kGAAkG;AAClG,qGAAqG;AACrG,uGAAuG;AACvG,mGAAmG;AACnG,0FAA0F;AAC1F,qGAAqG;AACrG,kGAAkG;AAClG,uGAAuG;AACvG,+EAA+E;AAC/E,uGAAuG;AACvG,uGAAuG;AACvG,gEAAgE;AAChE,2FAA2F;AAC3F,iGAAiG;AACjG,qGAAqG;AACrG,sGAAsG;AACtG,qGAAqG;AACrG,0DAA0D;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAW,CAAC;AAEjD;wFACwF;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/protocol/version.ts"],"names":[],"mappings":"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"}
@@ -17,27 +17,8 @@
17
17
  * Browser-only (uses `performance.now()` + `window`). Part of the optional
18
18
  * `@rydr/game-sdk/three` entry point.
19
19
  */
20
- /** One label's rolling stats over the last {@link SAMPLES} measures. */
21
- export interface PerfReportEntry {
22
- avg: number;
23
- max: number;
24
- n: number;
25
- }
26
- /** Snapshot of every recorded label. */
27
- export type PerfReport = Record<string, PerfReportEntry>;
28
- declare global {
29
- interface Window {
30
- __PERF__?: boolean;
31
- __perfReport?: () => PerfReport | null;
32
- }
33
- interface WindowEventMap {
34
- /** Fired by the SDK when the built-in secret button code toggles the perf overlay.
35
- * `detail.on` is the new visibility state. See `connectToPlatform`. */
36
- "rydr:perf-toggle": CustomEvent<{
37
- on: boolean;
38
- }>;
39
- }
40
- }
20
+ import type { PerfReport, PerfReportEntry } from "../protocol/perf.js";
21
+ export type { PerfReport, PerfReportEntry };
41
22
  /** Start a timing region under `label`. No-op unless `window.__PERF__` is set. */
42
23
  export declare function perfMark(label: string): void;
43
24
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"perf-marks.d.ts","sourceRoot":"","sources":["../../src/three/perf-marks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;CACX;AACD,wCAAwC;AACxC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAEzD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,UAAU,GAAG,IAAI,CAAC;KACxC;IACD,UAAU,cAAc;QACtB;gFACwE;QACxE,kBAAkB,EAAE,WAAW,CAAC;YAAE,EAAE,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KAClD;CACF;AAMD,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG5C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAY/C;AAED,iFAAiF;AACjF,wBAAgB,UAAU,IAAI,UAAU,GAAG,IAAI,CAU9C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI7C;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9C"}
1
+ {"version":3,"file":"perf-marks.d.ts","sourceRoot":"","sources":["../../src/three/perf-marks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC;AAU5C,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG5C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAY/C;AAED,iFAAiF;AACjF,wBAAgB,UAAU,IAAI,UAAU,GAAG,IAAI,CAU9C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI7C;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"perf-marks.js","sourceRoot":"","sources":["../../src/three/perf-marks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"perf-marks.js","sourceRoot":"","sources":["../../src/three/perf-marks.ts"],"names":[],"mappings":"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"}
package/dist/ui/README.md CHANGED
@@ -48,6 +48,9 @@ feed its `{x, y, onScreen}` into `setScreenPos`/`setVisible` — don't compute p
48
48
  | `mountChoiceCard(host, opts)` | fn | A player choice menu: prompt + highlighted option list (▲▼ move, A confirm). |
49
49
  | `mountRarityCard(host, opts)` / `buildRarityCard(opts)` | fn | A generic rarity-tinted item/creature card. |
50
50
  | `createPowerRace(opts)` | fn | A timed **power-vs-deadline race** overlay — the "push NOW or lose it" beat. A charge bar (∫power dt) races a clock; first to 100% wins. `start()` then `setPower(w)`+`tick(dt)` per frame; `won`/`lost` via `onResolve`. Recolour with `theme`, relabel with `text`. |
51
+ | `mountHeatVignette(host, opts)` | fn | **Screen-edge heat vignette alone** — the peripheral amber→orange→red glow that escalates with heat. Take this when your game draws its own heat bar. `setHeat(heat01, locked)` per frame. |
52
+ | `mountOverheatGlitch(host, opts)` | fn | **Lockout glitch overlay alone** — one-shot RGB chromatic burst on entry, then scanlines + red noise for the lockout. `setLocked(bool)` per frame. |
53
+ | `mountOverheatHudBar(host, opts)` | fn | **The whole overheat package**: centred inferno bar + label + COOLING DOWN countdown, composing the vignette and glitch above. One `update(heat01, locked, lockoutRemaining)` per frame. |
51
54
  | `injectCss()` | fn | Force the `.rydr-ui-*` CSS into `<head>` early (components call it for you). |
52
55
 
53
56
  Types: `DiamondButton` (`"DIAMOND_UP"\|"DIAMOND_DOWN"\|"DIAMOND_LEFT"\|"DIAMOND_RIGHT"`), `DirButton`, `KeycapVariant` (`"full"\|"solo"`),
@@ -0,0 +1,75 @@
1
+ /**
2
+ * `mountHeatVignette` — the **screen-edge heat vignette**, on its own.
3
+ *
4
+ * A peripheral "you are cooking" cue: a coloured glow bleeding in from the edges of the play area
5
+ * that escalates amber → orange → red as heat rises, pulsing faster at each stage. It reads in
6
+ * peripheral vision while the player's eyes are on the road, which is exactly what a heat mechanic
7
+ * needs — the player should feel the danger without looking at a bar.
8
+ *
9
+ * This is the vignette **alone**, deliberately separable: a game that draws its own heat bar (e.g.
10
+ * the racing game's in-canvas gauge) still wants the peripheral cue. Pair it with
11
+ * {@link mountOverheatGlitch} for the lockout flash, or take the whole pre-assembled package —
12
+ * bar + vignette + glitch — from {@link mountOverheatHudBar}.
13
+ *
14
+ * Self-contained DOM/CSS like the rest of `@rydr/game-sdk/ui`: it injects its own scoped
15
+ * `.rydr-heat-vignette*` stylesheet once into `<head>`, needs no global styles, no CSS variables and
16
+ * no three.js. It takes a **0..1 heat value**, not a `session` — the game owns its heat model and
17
+ * feeds the ratio in.
18
+ *
19
+ * ```ts
20
+ * const vignette = mountHeatVignette(hudHost);
21
+ * // every frame:
22
+ * vignette.setHeat(heat.fillRatio, heat.isLocked);
23
+ * // on teardown:
24
+ * vignette.dispose();
25
+ * ```
26
+ *
27
+ * **Host contract:** the vignette is `position: absolute; inset: 0` and sits at `z-index: 19`, so
28
+ * `host` must be positioned (and ideally `isolation: isolate`, so the z-index doesn't leak past it).
29
+ * A full-viewport `position: fixed; inset: 0; pointer-events: none; isolation: isolate` div over the
30
+ * game canvas is the intended host.
31
+ */
32
+ /** Discrete escalation stage of a heat cue. Drives the vignette colour + pulse rate. */
33
+ export type HeatStage = "idle" | "warn" | "crit" | "danger";
34
+ /**
35
+ * Default heat levels (0..1) at which each stage kicks in. `heat ∈ [warn, crit)` is a slow amber
36
+ * pulse, `[crit, danger)` a faster orange one, `[danger, 1]` the red panic pulse. Override per-mount
37
+ * with {@link HeatVignetteOptions.thresholds} when a game's own bar escalates on a different curve —
38
+ * keep the two in sync so the peripheral cue and the bar tell the same story.
39
+ */
40
+ export declare const HEAT_STAGE_THRESHOLDS: Readonly<Record<Exclude<HeatStage, "idle">, number>>;
41
+ /** Classify a 0..1 heat value into a {@link HeatStage} using `thresholds` (default {@link HEAT_STAGE_THRESHOLDS}). */
42
+ export declare function heatStageFor(heat01: number, thresholds?: Readonly<Record<Exclude<HeatStage, "idle">, number>>): HeatStage;
43
+ /** Options for {@link mountHeatVignette}. */
44
+ export interface HeatVignetteOptions {
45
+ /** Stage cut-offs (0..1). Default {@link HEAT_STAGE_THRESHOLDS}. */
46
+ thresholds?: Readonly<Record<Exclude<HeatStage, "idle">, number>>;
47
+ /**
48
+ * Stacking order inside the host. Default `19` — under {@link mountOverheatHudBar}'s bar (20) and
49
+ * glitch overlay (21), so the three compose in the intended order when used together.
50
+ */
51
+ zIndex?: number;
52
+ }
53
+ /** Live handle to a mounted heat vignette. Returned by {@link mountHeatVignette}. */
54
+ export interface HeatVignette {
55
+ /** The vignette element (already appended to the host). */
56
+ readonly root: HTMLDivElement;
57
+ /**
58
+ * Drive the vignette for one frame.
59
+ *
60
+ * @param heat01 Heat as a 0..1 ratio; classified into a stage via the mount's thresholds.
61
+ * @param locked True while the game is in its overheat lockout — forces the `danger` stage for the
62
+ * whole window, so the peripheral cue stays bright even as heat drains during a forced cooldown.
63
+ */
64
+ setHeat(heat01: number, locked?: boolean): void;
65
+ /** Force a stage directly, bypassing the heat→stage mapping (for scripted moments/cutscenes). */
66
+ setStage(stage: HeatStage): void;
67
+ /** Remove the vignette from the host. Idempotent. */
68
+ dispose(): void;
69
+ }
70
+ /**
71
+ * Mount a heat vignette into `host`. See the module header for the host contract; drive it every
72
+ * frame with {@link HeatVignette.setHeat}.
73
+ */
74
+ export declare function mountHeatVignette(host: HTMLElement, opts?: HeatVignetteOptions): HeatVignette;
75
+ //# sourceMappingURL=heat-vignette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heat-vignette.d.ts","sourceRoot":"","sources":["../../src/ui/heat-vignette.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,wFAAwF;AACxF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAChC,CAAC;AAExD,sHAAsH;AACtH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,UAAU,GAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAyB,GACvF,SAAS,CAKX;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAChD,iGAAiG;IACjG,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,qDAAqD;IACrD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE,mBAAwB,GAC7B,YAAY,CA8Bd"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * `mountHeatVignette` — the **screen-edge heat vignette**, on its own.
3
+ *
4
+ * A peripheral "you are cooking" cue: a coloured glow bleeding in from the edges of the play area
5
+ * that escalates amber → orange → red as heat rises, pulsing faster at each stage. It reads in
6
+ * peripheral vision while the player's eyes are on the road, which is exactly what a heat mechanic
7
+ * needs — the player should feel the danger without looking at a bar.
8
+ *
9
+ * This is the vignette **alone**, deliberately separable: a game that draws its own heat bar (e.g.
10
+ * the racing game's in-canvas gauge) still wants the peripheral cue. Pair it with
11
+ * {@link mountOverheatGlitch} for the lockout flash, or take the whole pre-assembled package —
12
+ * bar + vignette + glitch — from {@link mountOverheatHudBar}.
13
+ *
14
+ * Self-contained DOM/CSS like the rest of `@rydr/game-sdk/ui`: it injects its own scoped
15
+ * `.rydr-heat-vignette*` stylesheet once into `<head>`, needs no global styles, no CSS variables and
16
+ * no three.js. It takes a **0..1 heat value**, not a `session` — the game owns its heat model and
17
+ * feeds the ratio in.
18
+ *
19
+ * ```ts
20
+ * const vignette = mountHeatVignette(hudHost);
21
+ * // every frame:
22
+ * vignette.setHeat(heat.fillRatio, heat.isLocked);
23
+ * // on teardown:
24
+ * vignette.dispose();
25
+ * ```
26
+ *
27
+ * **Host contract:** the vignette is `position: absolute; inset: 0` and sits at `z-index: 19`, so
28
+ * `host` must be positioned (and ideally `isolation: isolate`, so the z-index doesn't leak past it).
29
+ * A full-viewport `position: fixed; inset: 0; pointer-events: none; isolation: isolate` div over the
30
+ * game canvas is the intended host.
31
+ */
32
+ const STYLE_ID = "rydr-heat-vignette-css";
33
+ /**
34
+ * Default heat levels (0..1) at which each stage kicks in. `heat ∈ [warn, crit)` is a slow amber
35
+ * pulse, `[crit, danger)` a faster orange one, `[danger, 1]` the red panic pulse. Override per-mount
36
+ * with {@link HeatVignetteOptions.thresholds} when a game's own bar escalates on a different curve —
37
+ * keep the two in sync so the peripheral cue and the bar tell the same story.
38
+ */
39
+ export const HEAT_STAGE_THRESHOLDS = Object.freeze({ warn: 0.5, crit: 0.65, danger: 0.8 });
40
+ /** Classify a 0..1 heat value into a {@link HeatStage} using `thresholds` (default {@link HEAT_STAGE_THRESHOLDS}). */
41
+ export function heatStageFor(heat01, thresholds = HEAT_STAGE_THRESHOLDS) {
42
+ if (heat01 >= thresholds.danger)
43
+ return "danger";
44
+ if (heat01 >= thresholds.crit)
45
+ return "crit";
46
+ if (heat01 >= thresholds.warn)
47
+ return "warn";
48
+ return "idle";
49
+ }
50
+ /**
51
+ * Mount a heat vignette into `host`. See the module header for the host contract; drive it every
52
+ * frame with {@link HeatVignette.setHeat}.
53
+ */
54
+ export function mountHeatVignette(host, opts = {}) {
55
+ injectCss();
56
+ const thresholds = opts.thresholds ?? HEAT_STAGE_THRESHOLDS;
57
+ const root = document.createElement("div");
58
+ root.className = "rydr-heat-vignette";
59
+ if (opts.zIndex !== undefined)
60
+ root.style.zIndex = String(opts.zIndex);
61
+ host.appendChild(root);
62
+ // Cache the applied stage so we only touch classList on a transition, not every frame.
63
+ let lastStage = "idle";
64
+ const setStage = (stage) => {
65
+ if (stage === lastStage)
66
+ return;
67
+ root.classList.remove("stage-warn", "stage-crit", "stage-danger");
68
+ if (stage !== "idle")
69
+ root.classList.add(`stage-${stage}`);
70
+ lastStage = stage;
71
+ };
72
+ return {
73
+ root,
74
+ setStage,
75
+ setHeat(heat01, locked = false) {
76
+ const clamped = Math.max(0, Math.min(1, heat01 || 0));
77
+ setStage(locked ? "danger" : heatStageFor(clamped, thresholds));
78
+ },
79
+ dispose() {
80
+ root.remove();
81
+ },
82
+ };
83
+ }
84
+ let cssInjected = false;
85
+ /** Inject the scoped vignette CSS once per document. */
86
+ function injectCss() {
87
+ if (cssInjected || document.getElementById(STYLE_ID)) {
88
+ cssInjected = true;
89
+ return;
90
+ }
91
+ const style = document.createElement("style");
92
+ style.id = STYLE_ID;
93
+ style.textContent = CSS;
94
+ document.head.appendChild(style);
95
+ cssInjected = true;
96
+ }
97
+ const CSS = `
98
+ .rydr-heat-vignette {
99
+ position: absolute;
100
+ inset: 0;
101
+ pointer-events: none;
102
+ z-index: 19;
103
+ opacity: 0;
104
+ transition: opacity 0.2s;
105
+ box-shadow: inset 0 0 0 0 transparent;
106
+ }
107
+ .rydr-heat-vignette.stage-warn {
108
+ opacity: 1;
109
+ box-shadow: inset 0 0 80px rgba(251, 191, 36, 0.35);
110
+ }
111
+ .rydr-heat-vignette.stage-crit {
112
+ opacity: 1;
113
+ box-shadow: inset 0 0 120px rgba(249, 115, 22, 0.55);
114
+ animation: rydr-heat-vignette-pulse 0.7s ease-in-out infinite;
115
+ }
116
+ .rydr-heat-vignette.stage-danger {
117
+ opacity: 1;
118
+ box-shadow: inset 0 0 180px rgba(239, 68, 68, 0.85);
119
+ animation: rydr-heat-vignette-pulse 0.3s ease-in-out infinite;
120
+ }
121
+ @keyframes rydr-heat-vignette-pulse {
122
+ 0%, 100% { filter: brightness(0.7); }
123
+ 50% { filter: brightness(1.25); }
124
+ }
125
+ `;
126
+ //# sourceMappingURL=heat-vignette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heat-vignette.js","sourceRoot":"","sources":["../../src/ui/heat-vignette.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,QAAQ,GAAG,wBAAwB,CAAC;AAK1C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAExD,sHAAsH;AACtH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,aAAmE,qBAAqB;IAExF,IAAI,MAAM,IAAI,UAAU,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACjD,IAAI,MAAM,IAAI,UAAU,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,MAAM,IAAI,UAAU,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC;AA+BD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAiB,EACjB,OAA4B,EAAE;IAE9B,SAAS,EAAE,CAAC;IACZ,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,qBAAqB,CAAC;IAE5D,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,SAAS,GAAG,oBAAoB,CAAC;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEvB,uFAAuF;IACvF,IAAI,SAAS,GAAc,MAAM,CAAC;IAElC,MAAM,QAAQ,GAAG,CAAC,KAAgB,EAAQ,EAAE;QAC1C,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QAChC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;QAClE,IAAI,KAAK,KAAK,MAAM;YAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;QAC3D,SAAS,GAAG,KAAK,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,OAAO,CAAC,MAAc,EAAE,MAAM,GAAG,KAAK;YACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;YACtD,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,OAAO;YACL,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,wDAAwD;AACxD,SAAS,SAAS;IAChB,IAAI,WAAW,IAAI,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,WAAW,GAAG,IAAI,CAAC;QACnB,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BX,CAAC"}
@@ -5,6 +5,10 @@
5
5
  * choice menu, a labeled diamond, a solo labeled diamond, and a generic rarity card). Games use it to show "which button to
6
6
  * press" in one consistent visual language across the library.
7
7
  *
8
+ * It also carries the **overheat HUD family** — the screen-edge heat vignette, the lockout glitch
9
+ * overlay, and the pre-assembled bar that composes both — so every game with a heat mechanic shares
10
+ * one look and can take just the pieces it needs (a game drawing its own bar takes only the cues).
11
+ *
8
12
  * Self-contained, like `@rydr/game-sdk/three`'s perf-overlay: it injects its own scoped `.rydr-ui-*`
9
13
  * CSS once into `<head>`, depends on no global styles or CSS variables, and pulls in no three.js — so
10
14
  * a game gets the look just by constructing a component. Wire any keycap to real input by passing the
@@ -33,4 +37,7 @@ export * from "./solo-labeled-diamond.js";
33
37
  export * from "./rarity-card.js";
34
38
  export * from "./power-race.js";
35
39
  export * from "./admin-nav.js";
40
+ export * from "./heat-vignette.js";
41
+ export * from "./overheat-glitch.js";
42
+ export * from "./overheat-hud-bar.js";
36
43
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
package/dist/ui/index.js CHANGED
@@ -5,6 +5,10 @@
5
5
  * choice menu, a labeled diamond, a solo labeled diamond, and a generic rarity card). Games use it to show "which button to
6
6
  * press" in one consistent visual language across the library.
7
7
  *
8
+ * It also carries the **overheat HUD family** — the screen-edge heat vignette, the lockout glitch
9
+ * overlay, and the pre-assembled bar that composes both — so every game with a heat mechanic shares
10
+ * one look and can take just the pieces it needs (a game drawing its own bar takes only the cues).
11
+ *
8
12
  * Self-contained, like `@rydr/game-sdk/three`'s perf-overlay: it injects its own scoped `.rydr-ui-*`
9
13
  * CSS once into `<head>`, depends on no global styles or CSS variables, and pulls in no three.js — so
10
14
  * a game gets the look just by constructing a component. Wire any keycap to real input by passing the
@@ -33,4 +37,7 @@ export * from "./solo-labeled-diamond.js";
33
37
  export * from "./rarity-card.js";
34
38
  export * from "./power-race.js";
35
39
  export * from "./admin-nav.js";
40
+ export * from "./heat-vignette.js";
41
+ export * from "./overheat-glitch.js";
42
+ export * from "./overheat-hud-bar.js";
36
43
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * `mountOverheatGlitch` — the **overheat lockout glitch overlay**, on its own.
3
+ *
4
+ * The "your engine just blew" screen dressing: a one-shot RGB chromatic-aberration burst on the
5
+ * frame the lockout begins (cyan slides left, red slides right, white pops in the middle, ~160 ms),
6
+ * then sustained scanlines + a red noise wash for as long as the lockout lasts. It makes a forced
7
+ * cooldown feel like a hardware failure rather than a stat change.
8
+ *
9
+ * This is the glitch **alone**, deliberately separable: a game that draws its own heat bar (e.g. the
10
+ * racing game's in-canvas gauge) still wants the lockout drama. Pair it with
11
+ * {@link mountHeatVignette} for the peripheral heat cue, or take the whole pre-assembled package —
12
+ * bar + vignette + glitch — from {@link mountOverheatHudBar}.
13
+ *
14
+ * Self-contained DOM/CSS like the rest of `@rydr/game-sdk/ui`: it injects its own scoped
15
+ * `.rydr-heat-glitch*` stylesheet once into `<head>`, needs no global styles, no CSS variables and no
16
+ * three.js. It is driven by a single boolean — the game owns the lockout state.
17
+ *
18
+ * ```ts
19
+ * const glitch = mountOverheatGlitch(hudHost);
20
+ * // every frame (edge-detected internally — cheap to call unconditionally):
21
+ * glitch.setLocked(heat.isLocked);
22
+ * // on teardown:
23
+ * glitch.dispose();
24
+ * ```
25
+ *
26
+ * **Host contract:** the overlay is `position: absolute; inset: 0` at `z-index: 21`, so `host` must
27
+ * be positioned (and ideally `isolation: isolate`, so the z-index doesn't leak past it). A
28
+ * full-viewport `position: fixed; inset: 0; pointer-events: none; isolation: isolate` div over the
29
+ * game canvas is the intended host.
30
+ */
31
+ /** Options for {@link mountOverheatGlitch}. */
32
+ export interface OverheatGlitchOptions {
33
+ /**
34
+ * Stacking order inside the host. Default `21` — above {@link mountHeatVignette} (19) and
35
+ * {@link mountOverheatHudBar}'s bar (20), so the three compose in the intended order.
36
+ */
37
+ zIndex?: number;
38
+ }
39
+ /** Live handle to a mounted glitch overlay. Returned by {@link mountOverheatGlitch}. */
40
+ export interface OverheatGlitch {
41
+ /** The overlay element (already appended to the host). */
42
+ readonly root: HTMLDivElement;
43
+ /**
44
+ * Set the lockout state. Safe to call every frame — the entry burst fires only on the
45
+ * `false → true` edge, and the sustained dressing follows the flag.
46
+ */
47
+ setLocked(locked: boolean): void;
48
+ /** Remove the overlay from the host and cancel any pending entry beat. Idempotent. */
49
+ dispose(): void;
50
+ }
51
+ /**
52
+ * Mount an overheat glitch overlay into `host`. See the module header for the host contract; drive
53
+ * it with {@link OverheatGlitch.setLocked}.
54
+ */
55
+ export declare function mountOverheatGlitch(host: HTMLElement, opts?: OverheatGlitchOptions): OverheatGlitch;
56
+ //# sourceMappingURL=overheat-glitch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overheat-glitch.d.ts","sourceRoot":"","sources":["../../src/ui/overheat-glitch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAOH,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wFAAwF;AACxF,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,sFAAsF;IACtF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE,qBAA0B,GAC/B,cAAc,CAqChB"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * `mountOverheatGlitch` — the **overheat lockout glitch overlay**, on its own.
3
+ *
4
+ * The "your engine just blew" screen dressing: a one-shot RGB chromatic-aberration burst on the
5
+ * frame the lockout begins (cyan slides left, red slides right, white pops in the middle, ~160 ms),
6
+ * then sustained scanlines + a red noise wash for as long as the lockout lasts. It makes a forced
7
+ * cooldown feel like a hardware failure rather than a stat change.
8
+ *
9
+ * This is the glitch **alone**, deliberately separable: a game that draws its own heat bar (e.g. the
10
+ * racing game's in-canvas gauge) still wants the lockout drama. Pair it with
11
+ * {@link mountHeatVignette} for the peripheral heat cue, or take the whole pre-assembled package —
12
+ * bar + vignette + glitch — from {@link mountOverheatHudBar}.
13
+ *
14
+ * Self-contained DOM/CSS like the rest of `@rydr/game-sdk/ui`: it injects its own scoped
15
+ * `.rydr-heat-glitch*` stylesheet once into `<head>`, needs no global styles, no CSS variables and no
16
+ * three.js. It is driven by a single boolean — the game owns the lockout state.
17
+ *
18
+ * ```ts
19
+ * const glitch = mountOverheatGlitch(hudHost);
20
+ * // every frame (edge-detected internally — cheap to call unconditionally):
21
+ * glitch.setLocked(heat.isLocked);
22
+ * // on teardown:
23
+ * glitch.dispose();
24
+ * ```
25
+ *
26
+ * **Host contract:** the overlay is `position: absolute; inset: 0` at `z-index: 21`, so `host` must
27
+ * be positioned (and ideally `isolation: isolate`, so the z-index doesn't leak past it). A
28
+ * full-viewport `position: fixed; inset: 0; pointer-events: none; isolation: isolate` div over the
29
+ * game canvas is the intended host.
30
+ */
31
+ const STYLE_ID = "rydr-heat-glitch-css";
32
+ /** How long the one-shot entry burst is allowed to run before its marker class is cleared (ms). */
33
+ const ENTRY_BEAT_MS = 500;
34
+ /**
35
+ * Mount an overheat glitch overlay into `host`. See the module header for the host contract; drive
36
+ * it with {@link OverheatGlitch.setLocked}.
37
+ */
38
+ export function mountOverheatGlitch(host, opts = {}) {
39
+ injectCss();
40
+ const root = document.createElement("div");
41
+ root.className = "rydr-heat-glitch";
42
+ if (opts.zIndex !== undefined)
43
+ root.style.zIndex = String(opts.zIndex);
44
+ root.innerHTML = `
45
+ <div class="rydr-heat-glitch-scanlines"></div>
46
+ <div class="rydr-heat-glitch-noise"></div>
47
+ <div class="rydr-heat-glitch-flash">
48
+ <div class="flash-cyan"></div>
49
+ <div class="flash-red"></div>
50
+ <div class="flash-white"></div>
51
+ </div>
52
+ `;
53
+ host.appendChild(root);
54
+ let lastLocked = false;
55
+ /** Timer clearing the one-shot `.entry` marker after the entry burst. */
56
+ let entryTimer = 0;
57
+ return {
58
+ root,
59
+ setLocked(locked) {
60
+ if (locked === lastLocked)
61
+ return;
62
+ lastLocked = locked;
63
+ root.classList.toggle("locked", locked);
64
+ if (!locked)
65
+ return;
66
+ root.classList.add("entry");
67
+ clearTimeout(entryTimer);
68
+ entryTimer = window.setTimeout(() => root.classList.remove("entry"), ENTRY_BEAT_MS);
69
+ },
70
+ dispose() {
71
+ clearTimeout(entryTimer);
72
+ root.remove();
73
+ },
74
+ };
75
+ }
76
+ let cssInjected = false;
77
+ /** Inject the scoped glitch CSS once per document. */
78
+ function injectCss() {
79
+ if (cssInjected || document.getElementById(STYLE_ID)) {
80
+ cssInjected = true;
81
+ return;
82
+ }
83
+ const style = document.createElement("style");
84
+ style.id = STYLE_ID;
85
+ style.textContent = CSS;
86
+ document.head.appendChild(style);
87
+ cssInjected = true;
88
+ }
89
+ const CSS = `
90
+ .rydr-heat-glitch {
91
+ position: absolute;
92
+ inset: 0;
93
+ pointer-events: none;
94
+ z-index: 21;
95
+ opacity: 0;
96
+ transition: opacity 0.2s;
97
+ }
98
+ .rydr-heat-glitch.locked { opacity: 1; }
99
+
100
+ /* ─── SUSTAINED DRESSING ──────────────────────────────────────── */
101
+ .rydr-heat-glitch-scanlines {
102
+ position: absolute;
103
+ inset: 0;
104
+ background: repeating-linear-gradient(
105
+ 0deg,
106
+ rgba(0,0,0,0.18) 0 2px,
107
+ transparent 2px 4px
108
+ );
109
+ animation: rydr-heat-glitch-scan 0.7s linear infinite;
110
+ }
111
+ @keyframes rydr-heat-glitch-scan {
112
+ from { background-position: 0 0; }
113
+ to { background-position: 0 8px; }
114
+ }
115
+ .rydr-heat-glitch-noise {
116
+ position: absolute;
117
+ inset: 0;
118
+ background:
119
+ radial-gradient(at 20% 30%, rgba(239,68,68,0.12), transparent 60%),
120
+ radial-gradient(at 80% 70%, rgba(239,68,68,0.10), transparent 55%),
121
+ radial-gradient(at 50% 90%, rgba(220,38,38,0.08), transparent 50%);
122
+ mix-blend-mode: screen;
123
+ }
124
+
125
+ /* ─── ENTRY BEAT — RGB FLASH ──────────────────────────────────────
126
+ Full-screen chromatic-aberration burst when the lockout begins. Cyan
127
+ layer slides left, red slides right, white pops in the middle. ~160 ms. */
128
+ .rydr-heat-glitch-flash {
129
+ position: absolute;
130
+ inset: 0;
131
+ opacity: 0;
132
+ pointer-events: none;
133
+ }
134
+ .rydr-heat-glitch-flash .flash-cyan,
135
+ .rydr-heat-glitch-flash .flash-red,
136
+ .rydr-heat-glitch-flash .flash-white {
137
+ position: absolute;
138
+ inset: 0;
139
+ mix-blend-mode: screen;
140
+ }
141
+ .rydr-heat-glitch-flash .flash-cyan { background: rgba(0, 220, 255, 0.40); }
142
+ .rydr-heat-glitch-flash .flash-red { background: rgba(255, 0, 80, 0.40); }
143
+ .rydr-heat-glitch-flash .flash-white { background: rgba(255, 255, 255, 0.35); }
144
+
145
+ .rydr-heat-glitch.entry .rydr-heat-glitch-flash {
146
+ animation: rydr-heat-glitch-flash-shell 0.16s ease-out forwards;
147
+ }
148
+ .rydr-heat-glitch.entry .rydr-heat-glitch-flash .flash-cyan {
149
+ animation: rydr-heat-glitch-shift-left 0.16s ease-out forwards;
150
+ }
151
+ .rydr-heat-glitch.entry .rydr-heat-glitch-flash .flash-red {
152
+ animation: rydr-heat-glitch-shift-right 0.16s ease-out forwards;
153
+ }
154
+ .rydr-heat-glitch.entry .rydr-heat-glitch-flash .flash-white {
155
+ animation: rydr-heat-glitch-pop 0.16s ease-out forwards;
156
+ }
157
+ @keyframes rydr-heat-glitch-flash-shell {
158
+ 0% { opacity: 0; }
159
+ 35% { opacity: 1; }
160
+ 100% { opacity: 0; }
161
+ }
162
+ @keyframes rydr-heat-glitch-shift-left {
163
+ 0% { transform: translateX(0); }
164
+ 35% { transform: translateX(-14px); }
165
+ 100% { transform: translateX(0); }
166
+ }
167
+ @keyframes rydr-heat-glitch-shift-right {
168
+ 0% { transform: translateX(0); }
169
+ 35% { transform: translateX(14px); }
170
+ 100% { transform: translateX(0); }
171
+ }
172
+ @keyframes rydr-heat-glitch-pop {
173
+ 0%, 100% { opacity: 0; }
174
+ 35% { opacity: 1; }
175
+ }
176
+ `;
177
+ //# sourceMappingURL=overheat-glitch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overheat-glitch.js","sourceRoot":"","sources":["../../src/ui/overheat-glitch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AAExC,mGAAmG;AACnG,MAAM,aAAa,GAAG,GAAG,CAAC;AAwB1B;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAiB,EACjB,OAA8B,EAAE;IAEhC,SAAS,EAAE,CAAC;IAEZ,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,SAAS,GAAG,kBAAkB,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvE,IAAI,CAAC,SAAS,GAAG;;;;;;;;GAQhB,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEvB,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,yEAAyE;IACzE,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,OAAO;QACL,IAAI;QACJ,SAAS,CAAC,MAAe;YACvB,IAAI,MAAM,KAAK,UAAU;gBAAE,OAAO;YAClC,UAAU,GAAG,MAAM,CAAC;YACpB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5B,YAAY,CAAC,UAAU,CAAC,CAAC;YACzB,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC;QACtF,CAAC;QACD,OAAO;YACL,YAAY,CAAC,UAAU,CAAC,CAAC;YACzB,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,sDAAsD;AACtD,SAAS,SAAS;IAChB,IAAI,WAAW,IAAI,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,WAAW,GAAG,IAAI,CAAC;QACnB,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuFX,CAAC"}