@jgengine/shell 0.13.0 → 0.15.0-next.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 (124) hide show
  1. package/CHANGELOG.md +529 -1
  2. package/dist/CombatPresentation.js +2 -1
  3. package/dist/GamePlayerShell.js +25 -5
  4. package/dist/Shell3dPresentation.d.ts +6 -6
  5. package/dist/Shell3dPresentation.js +4 -4
  6. package/dist/camera/ControllerCameraShake.d.ts +31 -0
  7. package/dist/camera/ControllerCameraShake.js +34 -0
  8. package/dist/camera/GameCameraRig.js +10 -5
  9. package/dist/camera/GameOrbitCamera.js +1 -10
  10. package/dist/camera/cameraRigs.js +16 -4
  11. package/dist/camera/index.d.ts +1 -0
  12. package/dist/camera/index.js +1 -0
  13. package/dist/camera/rigMath.d.ts +2 -0
  14. package/dist/camera/rigMath.js +7 -0
  15. package/dist/devtools/CollisionDebugWorld.js +15 -1
  16. package/dist/devtools/DevtoolsOverlay.js +2 -0
  17. package/dist/devtools/collisionDebugMath.d.ts +8 -0
  18. package/dist/devtools/collisionDebugMath.js +14 -5
  19. package/dist/drivers/FrameDriver.d.ts +4 -1
  20. package/dist/drivers/FrameDriver.js +5 -3
  21. package/dist/environment/DayNightSky.d.ts +33 -0
  22. package/dist/environment/DayNightSky.js +51 -0
  23. package/dist/environment/Daylight.d.ts +3 -1
  24. package/dist/environment/Daylight.js +7 -3
  25. package/dist/environment/EnvironmentScene.js +6 -6
  26. package/dist/environment/RoadJunctions.d.ts +8 -4
  27. package/dist/environment/RoadJunctions.js +16 -15
  28. package/dist/environment/RoadRibbons.d.ts +42 -6
  29. package/dist/environment/RoadRibbons.js +150 -27
  30. package/dist/environment/VolumetricClouds.js +3 -3
  31. package/dist/environment/index.d.ts +1 -0
  32. package/dist/environment/index.js +1 -0
  33. package/dist/gameKit.d.ts +7 -4
  34. package/dist/gameKit.js +8 -5
  35. package/dist/inputSink.js +14 -0
  36. package/dist/materialOverride.js +30 -0
  37. package/dist/postfx/PostProcessing.d.ts +3 -2
  38. package/dist/postfx/PostProcessing.js +38 -5
  39. package/dist/postfx/ScreenEffectsOverlay.d.ts +32 -0
  40. package/dist/postfx/ScreenEffectsOverlay.js +70 -0
  41. package/dist/postfx/postfxOverlay.d.ts +24 -0
  42. package/dist/postfx/postfxOverlay.js +35 -0
  43. package/dist/presentationResolve.d.ts +3 -2
  44. package/dist/presentationResolve.js +11 -6
  45. package/dist/render/CascadedShadows.d.ts +13 -0
  46. package/dist/render/CascadedShadows.js +96 -0
  47. package/dist/render/EntityPreview.d.ts +53 -0
  48. package/dist/render/EntityPreview.js +23 -0
  49. package/dist/render/EnvironmentLighting.d.ts +23 -7
  50. package/dist/render/EnvironmentLighting.js +69 -10
  51. package/dist/render/PartMotion.js +4 -4
  52. package/dist/render/SceneLighting.js +7 -0
  53. package/dist/render/SceneModels.d.ts +37 -1
  54. package/dist/render/SceneModels.js +52 -10
  55. package/dist/render/measureBounds.js +4 -0
  56. package/dist/render/measureCollisionMesh.d.ts +26 -0
  57. package/dist/render/measureCollisionMesh.js +108 -0
  58. package/dist/render/modelLoad.d.ts +41 -5
  59. package/dist/render/modelLoad.js +85 -18
  60. package/dist/render/sceneCapture.d.ts +27 -0
  61. package/dist/render/sceneCapture.js +43 -0
  62. package/dist/render/useDisposable.d.ts +16 -0
  63. package/dist/render/useDisposable.js +24 -0
  64. package/dist/render/useModelAnimation.js +47 -4
  65. package/dist/scene/AuthoredScene.js +14 -24
  66. package/dist/scene/CityRenderer.js +103 -36
  67. package/dist/scene/GrassFieldRenderer.js +4 -1
  68. package/dist/scene/PoleLineRenderer.js +7 -16
  69. package/dist/settings/QuickControls.js +5 -3
  70. package/dist/settings/SettingsMenu.js +6 -3
  71. package/dist/settings/appliedSettings.d.ts +3 -1
  72. package/dist/settings/appliedSettings.js +17 -5
  73. package/dist/settings/settingsController.js +11 -5
  74. package/dist/shellMovement.d.ts +15 -1
  75. package/dist/shellMovement.js +15 -1
  76. package/dist/structures/GeneratedBuilding.js +4 -5
  77. package/dist/structures/TransformGizmo.js +6 -5
  78. package/dist/terrain/CarvedTerrain.js +3 -7
  79. package/dist/terrain/GrassField.js +2 -2
  80. package/dist/terrain/ProceduralGround.js +3 -5
  81. package/dist/terrain/grassMaterial.d.ts +8 -2
  82. package/dist/terrain/grassMaterial.js +24 -5
  83. package/dist/terrain/index.d.ts +1 -1
  84. package/dist/terrain/terrainDetailMaterial.js +11 -2
  85. package/dist/terrain/terrainMath.d.ts +38 -1
  86. package/dist/terrain/terrainMath.js +86 -64
  87. package/dist/touch/TouchControlsOverlay.d.ts +6 -2
  88. package/dist/touch/TouchControlsOverlay.js +136 -17
  89. package/dist/vfx/ParticleField.d.ts +32 -0
  90. package/dist/vfx/ParticleField.js +91 -0
  91. package/dist/vfx/WorldFloatingText.d.ts +32 -0
  92. package/dist/vfx/WorldFloatingText.js +32 -0
  93. package/dist/water/Ocean.js +3 -6
  94. package/dist/weather/LightningStrike.js +3 -9
  95. package/dist/weather/RainField.js +3 -7
  96. package/dist/weather/SnowField.js +3 -7
  97. package/dist/world/DataObjects.js +3 -6
  98. package/dist/world/GridWorldScene.js +3 -6
  99. package/dist/world/InstancedBodies.js +3 -6
  100. package/dist/world/InstancedJoints.js +2 -2
  101. package/dist/world/SpriteBatch.js +3 -6
  102. package/dist/world/WorldEntityFrames.d.ts +47 -0
  103. package/dist/world/WorldEntityFrames.js +75 -0
  104. package/dist/world/WorldHud.js +7 -5
  105. package/dist/world/WorldPings.d.ts +26 -0
  106. package/dist/world/WorldPings.js +68 -0
  107. package/dist/world/WorldScene.js +9 -4
  108. package/dist/world/pingPulse.d.ts +21 -0
  109. package/dist/world/pingPulse.js +17 -0
  110. package/package.json +5 -5
  111. package/skills/ce-handoff/SKILL.md +149 -0
  112. package/skills/game-design/SKILL.md +2 -0
  113. package/skills/jgengine/SKILL.md +7 -3
  114. package/skills/jgengine/api.md +17 -7
  115. package/skills/jgengine/capabilities.md +12 -0
  116. package/skills/jgengine/recipes/minimal-game.md +7 -4
  117. package/skills/jgengine-ui/SKILL.md +8 -3
  118. package/skills/jgengine-ui/api.md +732 -23
  119. package/skills/jgengine-ui/capabilities.md +371 -2
  120. package/skills/jgengine-ui/recipes/overhead-entity-frames.md +136 -0
  121. package/skills/jgengine-ui/reference.md +7 -4
  122. package/skills/jgengine-world/api.md +408 -12
  123. package/skills/jgengine-world/capabilities.md +127 -2
  124. package/skills/jgengine-world/reference.md +15 -1
@@ -4,6 +4,22 @@
4
4
 
5
5
  Reach for these before hand-rolling. Each row is *the thing you need* → *the primitive that already does it*.
6
6
 
7
+ ## accessibility-provider — apply accessibility preferences to a subtree — text-scale CSS var, reduced-motion/high-contrast/colorblind/captions data attrs, and the colorblind color-matrix filter
8
+
9
+ - `AccessibilityProvider` (function) · `import { AccessibilityProvider } from "@jgengine/react"`
10
+
11
+ ## accessibility-store — serializable, observable accessibility preferences (reduced motion, high contrast, text scale, colorblind mode, captions) a game binds to its settings and presentation
12
+
13
+ - `createAccessibilityStore` (function) · `import { createAccessibilityStore } from "@jgengine/core/ui"`
14
+
15
+ ## achievement-gallery — responsive achievement/trophy grid with unlocked/locked state, counter progress bars, secret masking, and a completion/score header
16
+
17
+ - `AchievementGallery` (function) · `import { AchievementGallery } from "@jgengine/react"`
18
+
19
+ ## achievement-toast — unlock-moment banner (icon, heading, name, points) for an achievement toast queue
20
+
21
+ - `AchievementToast` (function) · `import { AchievementToast } from "@jgengine/react"`
22
+
7
23
  ## action-bar — optional skinned action-bar composition over the headless model — games own chrome
8
24
 
9
25
  - `ActionBar` (function) · `import { ActionBar } from "@jgengine/react"`
@@ -28,10 +44,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
28
44
 
29
45
  - `ActionTooltip` (function) · `import { ActionTooltip } from "@jgengine/react"`
30
46
 
47
+ ## auto-scroll — pin a log/chat/console panel to its newest line as entries arrive — no hand-rolled scrollTop effects
48
+
49
+ - `useAutoScroll` (function) · `import { useAutoScroll } from "@jgengine/react"`
50
+
51
+ ## camera-shake-meter — HUD readout for a core camera-shake controller — a trauma meter plus current impact-kind label, reskinnable and kind-labelled
52
+
53
+ - `CameraShakeMeter` (function) · `import { CameraShakeMeter } from "@jgengine/react"`
54
+
31
55
  ## camera-transparent-decor — let author decor pass through the orbit spring-arm; a child opts back in with jgCameraCollide
32
56
 
33
57
  - `isCameraOccluderTransparent` (function) · `import { isCameraOccluderTransparent } from "@jgengine/shell/camera"`
34
58
 
59
+ ## capture-canvas — read the live R3F frame to a PNG data URL (needs preserveDrawingBuffer)
60
+
61
+ - `captureCanvas` (function) · `import { captureCanvas } from "@jgengine/shell/render/sceneCapture"`
62
+
35
63
  ## character-paperdoll — equip-slot paperdoll — flanking columns around a portrait, activatable slots
36
64
 
37
65
  - `Paperdoll` (function) · `import { Paperdoll } from "@jgengine/react"`
@@ -49,22 +77,102 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
49
77
  - `formatDelta` (function) · `import { formatDelta } from "@jgengine/core/ui"`
50
78
  - `formatDuration` (function) · `import { formatDuration } from "@jgengine/core/ui"`
51
79
 
80
+ ## coach-mark — single onboarding callout — title/body, N-of-M counter, Next + Skip controls, theme-reskinnable
81
+
82
+ - `CoachMark` (function) · `import { CoachMark } from "@jgengine/react"`
83
+
84
+ ## coach-mark-host — full-screen onboarding coach-mark host — anchored/centered callout, dimmed spotlight backdrop, Next/Skip wired to the sequence
85
+
86
+ - `CoachMarkHost` (function) · `import { CoachMarkHost } from "@jgengine/react"`
87
+
88
+ ## coach-marks — ordered, gated, persist-once onboarding coach-marks/tutorial callouts — anchored or centered steps with a seen set and Next/Skip
89
+
90
+ - `createCoachMarkSequence` (function) · `import { createCoachMarkSequence } from "@jgengine/core/ui"`
91
+
92
+ ## codex-gallery — codex/bestiary gallery with category tabs, discovered/locked cards, secret masking, and a completion header
93
+
94
+ - `Codex` (function) · `import { Codex } from "@jgengine/react"`
95
+
96
+ ## colorblind-filters — SVG feColorMatrix defs (protanopia/deuteranopia/tritanopia/grayscale) referenced by the accessibility colorblind filter
97
+
98
+ - `ColorblindFilters` (function) · `import { ColorblindFilters } from "@jgengine/react"`
99
+
100
+ ## combo-meter-hud — drop-in HUD for a core combo meter — big live count, free-string tier label, derived multiplier, and a draining decay-window bar, per-tier colored from a caller map and HudTheme-token skinnable
101
+
102
+ - `ComboMeterHud` (function) · `import { ComboMeterHud } from "@jgengine/react"`
103
+
104
+ ## confirm-dialog — generic themeable confirm/cancel dialog — title, body, two buttons, danger styling
105
+
106
+ - `ConfirmDialog` (function) · `import { ConfirmDialog } from "@jgengine/react"`
107
+
108
+ ## controller-camera-shake — R3F consumer that applies a core camera-shake controller's pooled per-frame offset to the active camera (translation + pitch/yaw/roll) so the view visibly shakes
109
+
110
+ - `ControllerCameraShake` (function) · `import { ControllerCameraShake } from "@jgengine/shell/camera"`
111
+
52
112
  ## controls-list — keybind-derived control legend that hides on touch
53
113
 
54
114
  - `ControlsList` (function) · `import { ControlsList } from "@jgengine/react"`
55
115
 
116
+ ## credits-screen — drop-in credits view over a CreditsDocument — headed sections, optional links, HudTheme-skinned
117
+
118
+ - `CreditsScreen` (function) · `import { CreditsScreen } from "@jgengine/react/creditsScreen"`
119
+
120
+ ## cutscene-letterbox — reskinnable cinematic letterbox + skip overlay for a cutscene — animated bars, caption/dialogue slot, progress line, Skip button
121
+
122
+ - `CutsceneLetterbox` (function) · `import { CutsceneLetterbox } from "@jgengine/react"`
123
+
124
+ ## damage-direction-overlay — drop-in hit-from damage-direction overlay — SVG arcs flaring around a center reticle toward each recent hit and fading over time, colored per `kind`/HudTheme, pointer-events none
125
+
126
+ - `DamageDirectionOverlay` (function) · `import { DamageDirectionOverlay } from "@jgengine/react"`
127
+
128
+ ## day-night-sky — drop-in R3F presenter that drives the engine's existing sky dome and lights from a serializable day-night cycle for a moving, color-graded day-night look
129
+
130
+ - `DayNightSky` (function) · `import { DayNightSky } from "@jgengine/shell/environment"`
131
+
132
+ ## debounced-commit — bind a slider/number/color control to an expensive commit path (scene-document patch, settings persist) — instant local mirror, one trailing commit per pause, flush on release/blur/unmount; no raw onChange→patch wiring
133
+
134
+ - `useDebouncedCommit` (function) · `import { useDebouncedCommit } from "@jgengine/react"`
135
+
56
136
  ## default-look — one field that lights a scene like a shipped game (opt out with "flat")
57
137
 
58
138
  - `LookPreset` (type) · `import { LookPreset } from "@jgengine/core/ui"`
59
139
 
140
+ ## default-walk-codes — stock WASD + jump key codes for the shell walk controller
141
+
142
+ - `DEFAULT_WALK_CODES` (const) · `import { DEFAULT_WALK_CODES } from "@jgengine/shell/shellMovement"`
143
+
144
+ ## dialogue-view — drop-in branching conversation UI — speaker + portrait slot, current line, clickable response choices that advance a DialogueRun
145
+
146
+ - `DialogueView` (function) · `import { DialogueView } from "@jgengine/react"`
147
+
148
+ ## disposable-resource — memoize a three.js GPU resource (or tuple) with automatic dispose on change/unmount — no hand-rolled useMemo + dispose-effect pairs
149
+
150
+ - `useDisposable` (function) · `import { useDisposable } from "@jgengine/shell/render/useDisposable"`
151
+
60
152
  ## distance-format — render meters as m or km for HUD stats, telemetry, and range readouts
61
153
 
62
154
  - `formatDistance` (function) · `import { formatDistance } from "@jgengine/core/ui"`
63
155
 
156
+ ## dom-event — attach a window/document/element event listener with automatic cleanup and a stable handler ref — no hand-rolled addEventListener effects
157
+
158
+ - `useDomEvent` (function) · `import { useDomEvent } from "@jgengine/react"`
159
+
160
+ ## entity-frames — overlay that renders caller-composed frames over on-screen entities
161
+
162
+ - `EntityFrames` (function) · `import { EntityFrames } from "@jgengine/react"`
163
+ - `EntityScreenProjection` (interface) · `import { EntityScreenProjection } from "@jgengine/react"`
164
+ - `WorldEntityFrames` (function) · `import { WorldEntityFrames } from "@jgengine/shell/world/WorldEntityFrames"`
165
+ - `projectWorldToScreen` (function) · `import { projectWorldToScreen } from "@jgengine/shell/world/WorldEntityFrames"`
166
+ - `useWorldProjection` (function) · `import { useWorldProjection } from "@jgengine/shell/world/WorldEntityFrames"`
167
+
64
168
  ## entity-portrait — selectable entity portrait tile with vitals and selected/focus states
65
169
 
66
170
  - `EntityPortrait` (function) · `import { EntityPortrait } from "@jgengine/react"`
67
171
 
172
+ ## entity-preview — live 3D entity portrait — nested Canvas + context bridge + studio stage, driven by the game's own renderEntity
173
+
174
+ - `EntityPreview` (function) · `import { EntityPreview } from "@jgengine/shell/render/EntityPreview"`
175
+
68
176
  ## entity-render-cues — live velocity/bob/fire/reload/hit/death cues for a custom renderEntity or viewmodel component
69
177
 
70
178
  - `useEntityRenderCues` (function) · `import { useEntityRenderCues } from "@jgengine/shell/render/useEntityRenderCues"`
@@ -77,6 +185,26 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
77
185
 
78
186
  - `useEventMeter` (function) · `import { useEventMeter } from "@jgengine/react"`
79
187
 
188
+ ## fast-travel-menu — discovered-destinations picker grouped by region with distances, a discovery counter, and a travel callback
189
+
190
+ - `FastTravelMenu` (function) · `import { FastTravelMenu } from "@jgengine/react"`
191
+
192
+ ## floating-text — overlay that renders on-screen floating combat text with per-kind color, alpha, and pop-in scale
193
+
194
+ - `FloatingText` (function) · `import { FloatingText } from "@jgengine/react"`
195
+ - `FloatingTextPlacement` (interface) · `import { FloatingTextPlacement } from "@jgengine/react"`
196
+ - `WorldFloatingText` (function) · `import { WorldFloatingText } from "@jgengine/shell/vfx/WorldFloatingText"`
197
+ - `createFloatingTextField` (function) · `import { createFloatingTextField } from "@jgengine/core/ui/floatingText"`
198
+ - `layoutFloatingText` (function) · `import { layoutFloatingText } from "@jgengine/react"`
199
+
200
+ ## fullscreen-map — fullscreen pan/zoom world-map overlay over WorldMapSurface — wheel-zoom, drag-pan, click-to-place, and a freehand draw tool (onStrokeComplete)
201
+
202
+ - `FullscreenMap` (function) · `import { FullscreenMap } from "@jgengine/react"`
203
+
204
+ ## game-context-bridge — re-provide the GameContext across a nested Canvas/reconciler boundary
205
+
206
+ - `GameContextBridge` (function) · `import { GameContextBridge } from "@jgengine/react"`
207
+
80
208
  ## heightfield-mesh-update — in-place partial update of a displaced ground plane mesh
81
209
 
82
210
  - `displaceHeightfieldGeometry` (function) · `import { displaceHeightfieldGeometry } from "@jgengine/shell/terrain"`
@@ -129,27 +257,67 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
129
257
 
130
258
  - `StatBar` (function) · `import { StatBar } from "@jgengine/react"`
131
259
 
132
- ## hud-theme — game-authored token object for bars, frames, slots, and minimap ring
260
+ ## hud-theme — game-authored token object covering bars, frames, slots, chrome, text, status colors, fonts, and rarity
133
261
 
134
262
  - `HudThemePalette` (interface) · `import { HudThemePalette } from "@jgengine/react"`
135
263
 
264
+ ## hud-theme-author — fill a full HudTheme from per-group partial overrides
265
+
266
+ - `hudTheme` (function) · `import { hudTheme } from "@jgengine/react"`
267
+
268
+ ## hud-theme-derive — build a full HudTheme from an accent + surface seed pair
269
+
270
+ - `deriveHudTheme` (function) · `import { deriveHudTheme } from "@jgengine/react"`
271
+
272
+ ## hud-ticker — re-render a HUD element at a steady hz for time-derived readouts (cooldowns, cast/swing bars) — no hand-rolled setInterval effects
273
+
274
+ - `useTicker` (function) · `import { useTicker } from "@jgengine/react"`
275
+
136
276
  ## hud-vitals — atomic purpose-named vitals bars (token-themed parts, not a finished HUD)
137
277
 
138
278
  - `BarTokens` (interface) · `import { BarTokens } from "@jgengine/react"`
139
279
  - `barTokens` (function) · `import { barTokens } from "@jgengine/react"`
140
280
 
281
+ ## i18n — translate a message catalog with fallback-locale lookup, `{param}` interpolation, and Intl pluralization; observable active-locale switching
282
+
283
+ - `createI18n` (function) · `import { createI18n } from "@jgengine/core/ui"`
284
+
285
+ ## interaction-prompt-host — screen-anchored "press E to…" callout rendering a prompt registry's active interactable — keybind cap+label, gauge hold bar, or plain label, theme- and per-prompt-accent skinnable
286
+
287
+ - `InteractionPrompt` (function) · `import { InteractionPrompt } from "@jgengine/react"`
288
+
141
289
  ## key-hint — keyboard/mouse control hint that hides itself on touch
142
290
 
143
291
  - `KeyHint` (function) · `import { KeyHint } from "@jgengine/react"`
144
292
 
293
+ ## keybinding-menu — drop-in controls-settings surface over a rebind session — click-to-capture rows with key glyphs, conflict badges, per-row and reset-all, HudTheme-skinnable
294
+
295
+ - `KeybindingMenu` (function) · `import { KeybindingMenu } from "@jgengine/react"`
296
+
145
297
  ## keycap — styled keyboard/mouse key cap for control hints
146
298
 
147
299
  - `Keycap` (function) · `import { Keycap } from "@jgengine/react"`
148
300
 
301
+ ## kill-feed — vertical event/kill-feed ticker rendering a core event-ticker as a fading, newest-on-top stack of per-kind iconned, accent-colored rows over HudTheme tokens
302
+
303
+ - `KillFeed` (function) · `import { KillFeed } from "@jgengine/react"`
304
+
149
305
  ## live-markers — a self-ticking MarkerSet kept in sync from the live scene each HUD tick — pass a rebuild(markers, ctx) that clears+repopulates, no hand-rolled setInterval
150
306
 
151
307
  - `useLiveMarkers` (function) · `import { useLiveMarkers } from "@jgengine/react"`
152
308
 
309
+ ## map-legend — marker-kind key (glyph + color + label per kind) sharing the map's kindStyles
310
+
311
+ - `MapLegend` (function) · `import { MapLegend } from "@jgengine/react"`
312
+
313
+ ## menu-router — screen stack for a game front-end — push/back/replace/reset with optional Escape-to-back
314
+
315
+ - `useMenuRouter` (function) · `import { useMenuRouter } from "@jgengine/react/menuRouter"`
316
+
317
+ ## menu-stack-reducer — pure push/back/replace/reset transitions for a menu screen stack
318
+
319
+ - `menuStackReducer` (function) · `import { menuStackReducer } from "@jgengine/react/menuRouter"`
320
+
153
321
  ## minimap — framed circular minimap with terrain bake, fog, markers, and facing arrow
154
322
 
155
323
  - `Minimap` (function) · `import { Minimap } from "@jgengine/react"`
@@ -166,10 +334,39 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
166
334
 
167
335
  - `MinimapTrack` (function) · `import { MinimapTrack } from "@jgengine/react"`
168
336
 
337
+ ## modal-host — full-screen modal/dialog host over a modal stack — dimmed backdrop, focus trap, Esc/backdrop-to-cancel, aria-modal dialog
338
+
339
+ - `ModalHost` (function) · `import { ModalHost } from "@jgengine/react"`
340
+
341
+ ## modal-stack — serializable, observable stack of opaque modal/dialog records — push/pop/resolve blocking overlays (pause menu, confirm dialog) with optional auto-dismiss; never interprets kind or result
342
+
343
+ - `createModalStack` (function) · `import { createModalStack } from "@jgengine/core/ui"`
344
+
169
345
  ## nameplates — billboarded name + HP bar over nearby entities
170
346
 
171
347
  - `WorldNameplates` (function) · `import { WorldNameplates } from "@jgengine/shell/world/WorldHud"`
172
348
 
349
+ ## notification-bell — icon button with a live unread-count badge over a notification store
350
+
351
+ - `NotificationBell` (function) · `import { NotificationBell } from "@jgengine/react"`
352
+
353
+ ## notification-center-panel — scrollable notification log with kind markers, read tracking, relative time, and mark-all-read/clear
354
+
355
+ - `NotificationCenter` (function) · `import { NotificationCenter } from "@jgengine/react"`
356
+
357
+ ## objective-banner — serializable, clock-driven stage/objective banner queue — flies a big transient centered title + optional subtitle in, holds, and fades out one at a time, with phase + progress for animation, free-string kinds the game styles, and snapshot/restore
358
+
359
+ - `createObjectiveBanner` (function) · `import { createObjectiveBanner } from "@jgengine/core/ui"`
360
+
361
+ ## objective-banner-host — full-screen overlay that renders a core objective-banner controller as a fly-in / hold / fade-out centered title + subtitle stamp, theme- and per-kind-skinnable
362
+
363
+ - `ObjectiveBannerHost` (function) · `import { ObjectiveBannerHost } from "@jgengine/react"`
364
+
365
+ ## offscreen-markers — serializable waypoint tracker + pure edge-clamp/bearing math for on-screen pins and off-screen directional arrows with distance
366
+
367
+ - `createWaypointTracker` (function) · `import { createWaypointTracker } from "@jgengine/core/ui"`
368
+ - `layoutScreenMarker` (function) · `import { layoutScreenMarker } from "@jgengine/core/ui"`
369
+
173
370
  ## ordinal-format — format a placement number as 1st/2nd/3rd for HUD ranks
174
371
 
175
372
  - `formatOrdinal` (function) · `import { formatOrdinal } from "@jgengine/core/ui"`
@@ -186,7 +383,7 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
186
383
 
187
384
  - `focusPanel` (function) · `import { focusPanel } from "@jgengine/core/ui"`
188
385
 
189
- ## panel-host — render a manager's open windows as draggable, closable, z-stacked dialogs
386
+ ## panel-host — render a manager's open windows as draggable, closable, z-stacked dialogs above the HUD
190
387
 
191
388
  - `PanelHost` (function) · `import { PanelHost } from "@jgengine/react"`
192
389
 
@@ -214,6 +411,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
214
411
 
215
412
  - `togglePanel` (function) · `import { togglePanel } from "@jgengine/core/ui"`
216
413
 
414
+ ## particle-field — render a core particle system as a soft-point GPU cloud with per-particle size, color, and alpha
415
+
416
+ - `ParticleField` (function) · `import { ParticleField } from "@jgengine/shell/vfx/ParticleField"`
417
+
418
+ ## pause-menu — reskinnable pause-menu building block — Resume plus a game-filled Settings/Quit slot list, HudTheme-driven
419
+
420
+ - `PauseMenu` (function) · `import { PauseMenu } from "@jgengine/react"`
421
+
422
+ ## photo-mode — observable photo-mode state (active + hide-HUD) a game binds its screenshot/camera flow to
423
+
424
+ - `createPhotoModeStore` (function) · `import { createPhotoModeStore } from "@jgengine/core/ui"`
425
+
426
+ ## photo-mode-controls — photo-mode toolbar (hide-HUD toggle, capture, exit) bound to a photo-mode store
427
+
428
+ - `PhotoModeControls` (function) · `import { PhotoModeControls } from "@jgengine/react"`
429
+
217
430
  ## placement-ghost — render valid/invalid placement preview mesh
218
431
 
219
432
  - `PlacementGhost` (function) · `import { PlacementGhost } from "@jgengine/shell/structures"`
@@ -222,10 +435,46 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
222
435
 
223
436
  - `Popover` (function) · `import { Popover } from "@jgengine/react"`
224
437
 
438
+ ## quest-tracker — compact quest/objective HUD tracker — titles + labelled objective progress from describeTrackedQuest views
439
+
440
+ - `QuestTracker` (function) · `import { QuestTracker } from "@jgengine/react"`
441
+
442
+ ## quick-menu — multi-form quick menu (radial / arc / list / grid) over one item model with hotkeys, badges, cooldowns, sections, and nested submenus
443
+
444
+ - `QuickMenu` (function) · `import { QuickMenu } from "@jgengine/react"`
445
+
446
+ ## radial-menu — pointer/stick-driven radial or arc quick menu (weapon/emote wheel) — angular slice selection with hotkeys, badges, cooldowns, and a neutral hub
447
+
448
+ - `RadialMenu` (function) · `import { RadialMenu } from "@jgengine/react"`
449
+
450
+ ## radial-select — map a pointer/stick vector to a radial-menu slice index, with a neutral dead zone and optional arc bounds
451
+
452
+ - `radialIndexFromVector` (function) · `import { radialIndexFromVector } from "@jgengine/core/ui"`
453
+
454
+ ## raf-loop — run a cancellable requestAnimationFrame loop for DOM-side animation with delta seconds — no hand-rolled RAF effects
455
+
456
+ - `useRafLoop` (function) · `import { useRafLoop } from "@jgengine/react"`
457
+
225
458
  ## resolve-game-look — expand a look preset into concrete lighting/backdrop/post knobs
226
459
 
227
460
  - `resolveGameLook` (function) · `import { resolveGameLook } from "@jgengine/core/ui"`
228
461
 
462
+ ## save-slot-menu — drop-in save-select / profile menu that renders a core save-slots index as New / Continue / Load / Delete cards with free-string meta chips and relative save times, theme-skinnable
463
+
464
+ - `SaveSlotMenu` (function) · `import { SaveSlotMenu } from "@jgengine/react"`
465
+
466
+ ## scene-capture-binding — expose the in-Canvas scene-capture function to outside-Canvas HUD (photo mode)
467
+
468
+ - `SceneCaptureBinding` (function) · `import { SceneCaptureBinding } from "@jgengine/shell/render/sceneCapture"`
469
+
470
+ ## scoreboard-table — reskinnable ranked-score / leaderboard table over the rankLeaderboard selector — medal-colored podium, local-row highlight, HudTheme-token driven
471
+
472
+ - `Scoreboard` (function) · `import { Scoreboard } from "@jgengine/react"`
473
+
474
+ ## screen-effects-overlay — shell DOM overlay that renders a core screen-effects controller as full-screen flash / edge-vignette / low-health-pulse color-grade layers
475
+
476
+ - `ScreenEffectsOverlay` (function) · `import { ScreenEffectsOverlay } from "@jgengine/shell/postfx/ScreenEffectsOverlay"`
477
+
229
478
  ## selection-collection — accessible portrait-strip / group-chip renderer over a selection model
230
479
 
231
480
  - `SelectionCollectionChrome` (function) · `import { SelectionCollectionChrome } from "@jgengine/react"`
@@ -242,6 +491,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
242
491
 
243
492
  - `SelectionPanel` (function) · `import { SelectionPanel } from "@jgengine/react"`
244
493
 
494
+ ## shop-grid-host — drop-in vendor/shop grid over a caller-owned wallet — item cards with icon/price/stock, afford-aware Buy, optional Sell, and a balance readout, token-themed
495
+
496
+ - `ShopGrid` (function) · `import { ShopGrid } from "@jgengine/react"`
497
+
245
498
  ## speed-format — render a m/s speed as km/h, mph, knots, or m/s for speedometers and telemetry HUDs
246
499
 
247
500
  - `formatSpeed` (function) · `import { formatSpeed } from "@jgengine/core/ui"`
@@ -250,26 +503,142 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
250
503
 
251
504
  - `StartScreen` (function) · `import { StartScreen } from "@jgengine/react"`
252
505
 
506
+ ## status-effect-bar — timeline HUD row of active statuses — icon + radial countdown ring + stack badge, driven off the status model, HudTheme-skinned
507
+
508
+ - `StatusEffectBar` (function) · `import { StatusEffectBar } from "@jgengine/react"`
509
+
253
510
  ## studio-stage — cinematic lighting rig + backdrop + turntable for parametric studios
254
511
 
255
512
  - `StudioStage` (function) · `import { StudioStage } from "@jgengine/shell/scene/StudioStage"`
256
513
 
514
+ ## talent-tree — drop-in skill/talent/upgrade-tree widget — pass `nodes`+`tree` for point-spend or a precomputed `view` for any unlock rule; branch/tier layout, SVG prerequisite edges, learned/available/locked/maxed styling, icon + rank, onLearn
515
+
516
+ - `TalentTree` (function) · `import { TalentTree } from "@jgengine/react"`
517
+
518
+ ## timer-readout — live digital mm:ss/m:ss.d timer readout bound to a TimerSet
519
+
520
+ - `TimerReadout` (function) · `import { TimerReadout } from "@jgengine/react"`
521
+
522
+ ## timer-readout-format — format milliseconds as digital timer text (mm:ss / m:ss.d / ss.d)
523
+
524
+ - `formatTimerMs` (function) · `import { formatTimerMs } from "@jgengine/react"`
525
+
526
+ ## timer-ring — radial SVG charge/cooldown ring bound to a TimerSet's progress
527
+
528
+ - `TimerRing` (function) · `import { TimerRing } from "@jgengine/react"`
529
+
530
+ ## trans — inline translated-message component bound to the active locale
531
+
532
+ - `Trans` (function) · `import { Trans } from "@jgengine/react"`
533
+
257
534
  ## transform-gizmo — in-game select/move/rotate/scale gizmo
258
535
 
259
536
  - `TransformGizmo` (const) · `import { TransformGizmo } from "@jgengine/shell/structures"`
260
537
 
538
+ ## use-camera-shake — React hook binding a camera-shake controller — subscribes for live trauma/kind and can self-drive its decay on a frame loop
539
+
540
+ - `useCameraShake` (function) · `import { useCameraShake } from "@jgengine/react"`
541
+
542
+ ## use-coach-marks — React hook binding a coach-mark sequence to a component — re-renders on advance/skip/gate changes
543
+
544
+ - `useCoachMarks` (function) · `import { useCoachMarks } from "@jgengine/react"`
545
+
546
+ ## use-combo-meter — React hook binding a combo meter — re-renders per frame so the decay-window bar drains live and returns the current combo view
547
+
548
+ - `useComboMeter` (function) · `import { useComboMeter } from "@jgengine/react"`
549
+
550
+ ## use-damage-direction — React hook that animates a damage-direction tracker's fade with requestAnimationFrame and re-renders its live indicators
551
+
552
+ - `useDamageDirection` (function) · `import { useDamageDirection } from "@jgengine/react"`
553
+
554
+ ## use-dialogue-run — React hook binding a branching dialogue run to a component — re-renders as the player advances the conversation
555
+
556
+ - `useDialogueRun` (function) · `import { useDialogueRun } from "@jgengine/react"`
557
+
558
+ ## use-event-ticker — React hook binding an event-ticker — re-renders per frame so entries fade and drop live, returning the current newest-first views
559
+
560
+ - `useEventTicker` (function) · `import { useEventTicker } from "@jgengine/react"`
561
+
562
+ ## use-fast-travel — re-render a component when a fast-travel network's discovery state changes
563
+
564
+ - `useFastTravel` (function) · `import { useFastTravel } from "@jgengine/react"`
565
+
566
+ ## use-interaction-prompt — React hook binding a prompt registry to a moving player — resolves the nearest interactable prompt and returns the active one
567
+
568
+ - `useInteractionPrompt` (function) · `import { useInteractionPrompt } from "@jgengine/react"`
569
+
570
+ ## use-modal-stack — React hook binding a modal stack to a component — re-renders on push/pop/resolve
571
+
572
+ - `useModalStack` (function) · `import { useModalStack } from "@jgengine/react"`
573
+
574
+ ## use-objective-banner — React hook binding an objective-banner controller — advances its clock per frame and returns the current banner view
575
+
576
+ - `useObjectiveBanner` (function) · `import { useObjectiveBanner } from "@jgengine/react"`
577
+
261
578
  ## use-panels — headless toggleable-window manager with keybind + ESC handling over the core panel model
262
579
 
263
580
  - `usePanels` (function) · `import { usePanels } from "@jgengine/react"`
264
581
 
582
+ ## use-rebind-session — React hook that re-renders a component whenever a rebind session changes
583
+
584
+ - `useRebindSession` (function) · `import { useRebindSession } from "@jgengine/react"`
585
+
586
+ ## use-save-slots — React hook binding a save-slots metadata index — re-renders on change and returns the ordered slot list
587
+
588
+ - `useSaveSlots` (function) · `import { useSaveSlots } from "@jgengine/react"`
589
+
590
+ ## use-sequence-director — React hook that drives a cutscene director's per-frame tick loop and exposes playhead/progress + play/pause/skip controls
591
+
592
+ - `useSequenceDirector` (function) · `import { useSequenceDirector } from "@jgengine/react"`
593
+
594
+ ## use-shop-stock — React hook binding a shop-stock model — re-renders on any stock change and returns the entry list
595
+
596
+ - `useShopStock` (function) · `import { useShopStock } from "@jgengine/react"`
597
+
598
+ ## use-timer — React hook binding one timer to a component with a per-frame re-read
599
+
600
+ - `useTimerRead` (function) · `import { useTimerRead } from "@jgengine/react"`
601
+
602
+ ## use-translate — live `t(key, params)` translator bound to the active locale, re-rendering on locale change
603
+
604
+ - `useT` (function) · `import { useT } from "@jgengine/react"`
605
+
606
+ ## use-wave-runner — React hook that subscribes to a wave runner and returns its pooled current-wave view
607
+
608
+ - `useWaveRunner` (function) · `import { useWaveRunner } from "@jgengine/react"`
609
+
610
+ ## use-waypoints — React binding that returns a waypoint tracker's live list (or a passthrough array)
611
+
612
+ - `useWaypoints` (function) · `import { useWaypoints } from "@jgengine/react"`
613
+
265
614
  ## vital-bar — compact current/max vital meter for an entity summary
266
615
 
267
616
  - `VitalBar` (function) · `import { VitalBar } from "@jgengine/react"`
268
617
 
618
+ ## wave-hud — drop-in wave/spawn HUD over a wave runner — big WAVE N label, wave-progress bar, spawned/total + budget + alert readouts, theme-skinnable
619
+
620
+ - `WaveHud` (function) · `import { WaveHud } from "@jgengine/react"`
621
+
622
+ ## waypoint-arrow — on-screen HUD guide arrow to a tracked waypoint, rotated by facing-relative bearing with a distance readout
623
+
624
+ - `WaypointArrow` (function) · `import { WaypointArrow } from "@jgengine/react"`
625
+
626
+ ## waypoint-markers — overlay rendering world waypoints as on-screen pins and off-screen edge-clamped directional arrows with distance, colored per game-owned kind
627
+
628
+ - `WaypointMarkers` (function) · `import { WaypointMarkers } from "@jgengine/react"`
629
+
269
630
  ## window — standalone draggable, closable window primitive over HudFrame — no manager required
270
631
 
271
632
  - `Window` (function) · `import { Window } from "@jgengine/react"`
272
633
 
634
+ ## world-intersections — inspect turns and junction meshes in a deterministic preview fixture
635
+
636
+ - `StreetGeometryPreview` (function) · `import { StreetGeometryPreview } from "@jgengine/react"`
637
+
273
638
  ## world-object-highlights — ground-ring highlight over every selected placed object
274
639
 
275
640
  - `WorldObjectHighlights` (function) · `import { WorldObjectHighlights } from "@jgengine/shell/world/WorldHud"`
641
+
642
+ ## world-pings — in-scene ping markers — a bobbing downward arrowhead, ground ring, and billboarded callout per marker, colored by kind and fading over the marker's lifetime
643
+
644
+ - `WorldPings` (function) · `import { WorldPings } from "@jgengine/shell/world/WorldPings"`
@@ -0,0 +1,136 @@
1
+ # Overhead enemy nameplates and health bars
2
+
3
+ Use this recipe when a game needs floating world-anchored frames over entities —
4
+ enemy nameplates with a health bar, interaction prompts, objective pips. The
5
+ game keeps owning its entities; JGengine owns only the reusable behavior:
6
+ projecting a world position to the screen, offsetting above the head, culling
7
+ frames that are off-screen or behind the camera, and stacking nearer frames over
8
+ farther ones. You compose the frame markup itself from the shipped bars, so the
9
+ look is the game's, not a prefab.
10
+
11
+ The seam is data-first and caller-owned: pass an array of
12
+ `{ id, worldPosition, ... }` and a projector. Nothing is mirrored into a store.
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ bun add @jgengine/core @jgengine/react
18
+ # @jgengine/shell only for the R3F projection convenience below
19
+ bun add @jgengine/shell
20
+ ```
21
+
22
+ `@jgengine/react/entityFrames` imports neither Three.js nor React Three Fiber and
23
+ needs no `GameProvider`. The `@jgengine/shell` piece is a thin R3F convenience.
24
+
25
+ ## R3F game: one component from your own entity array
26
+
27
+ `WorldEntityFrames` mounts inside the R3F scene, samples the live camera each
28
+ frame, and renders the frames through a fullscreen overlay. Pass the entities you
29
+ already have and a `renderFrame` that composes the shipped `HealthBar` plus a
30
+ name. Projection, culling, and stacking come for free.
31
+
32
+ ```tsx
33
+ import { WorldEntityFrames } from "@jgengine/shell/world/WorldEntityFrames";
34
+ import { HealthBar, barTokens } from "@jgengine/react/bars";
35
+
36
+ interface Enemy {
37
+ id: string;
38
+ name: string;
39
+ position: [number, number, number];
40
+ hp: number;
41
+ maxHp: number;
42
+ }
43
+
44
+ export function EnemyNameplates({ enemies }: { enemies: readonly Enemy[] }) {
45
+ const entries = enemies.map((e) => ({
46
+ id: e.id,
47
+ // Anchor over the head: lift the world Y by the entity's height.
48
+ worldPosition: [e.position[0], e.position[1] + 2.2, e.position[2]] as const,
49
+ enemy: e,
50
+ }));
51
+
52
+ return (
53
+ <WorldEntityFrames
54
+ entries={entries}
55
+ maxCount={24} // keep the nearest 24 when a crowd is on screen
56
+ renderFrame={({ enemy }) => (
57
+ <div style={{ ...barTokens({ health: "#e5484d" }), textAlign: "center" }}>
58
+ <span
59
+ style={{
60
+ fontSize: 12,
61
+ fontWeight: 700,
62
+ color: "#f1f5f9",
63
+ textShadow: "0 1px 3px rgba(0,0,0,0.9)",
64
+ whiteSpace: "nowrap",
65
+ }}
66
+ >
67
+ {enemy.name}
68
+ </span>
69
+ <HealthBar value={enemy.hp} max={enemy.maxHp} width={78} showValue={false} shape="pill" />
70
+ </div>
71
+ )}
72
+ />
73
+ );
74
+ }
75
+ ```
76
+
77
+ Reskin the whole set with one `HudTheme`/`barTokens` object on an ancestor —
78
+ health color, frame material, radius, and glow flow to every plate's `HealthBar`.
79
+ The `enemy` payload rides along on each entry, so `renderFrame` reads live values
80
+ without a second lookup.
81
+
82
+ ## Non-R3F game: bring your own projector
83
+
84
+ Outside R3F (a 2D or custom-renderer game), use the headless
85
+ `EntityFrames` directly and pass a `project` that maps a world position to a
86
+ screen point — return `null`, or `{ behind: true }`, to cull an entry. `depth`
87
+ (larger = farther) drives stacking.
88
+
89
+ ```tsx
90
+ import { EntityFrames, type ProjectEntity } from "@jgengine/react/entityFrames";
91
+ import { HealthBar } from "@jgengine/react/bars";
92
+
93
+ const project: ProjectEntity = (world) => {
94
+ const screen = myCamera.worldToScreen(world); // your renderer's projection
95
+ if (screen === null) return null; // outside the frustum → culled
96
+ return { x: screen.x, y: screen.y, depth: screen.distance, behind: screen.behind };
97
+ };
98
+
99
+ export function Nameplates({ enemies }: { enemies: readonly Enemy[] }) {
100
+ return (
101
+ <EntityFrames
102
+ entries={enemies.map((e) => ({ id: e.id, worldPosition: e.position, enemy: e }))}
103
+ project={project}
104
+ offsetY={-24}
105
+ viewport={{ width: window.innerWidth, height: window.innerHeight }}
106
+ renderFrame={({ enemy }) => (
107
+ <HealthBar value={enemy.hp} max={enemy.maxHp} width={78} showValue={false} />
108
+ )}
109
+ />
110
+ );
111
+ }
112
+ ```
113
+
114
+ Mount either component inside `HudCanvas` (or any positioned ancestor) so the
115
+ overlay is bounded to the viewport.
116
+
117
+ ## Ownership
118
+
119
+ The game still owns its entities, their positions, health, updates, camera, and
120
+ the render cadence. JGengine owns the projection→offset→cull→stack behavior
121
+ (`layoutEntityFrames`, unit-tested) and, for R3F, the camera→screen projector
122
+ (`useWorldProjection` / `projectWorldToScreen`). The frame markup is yours.
123
+
124
+ ## Common traps
125
+
126
+ - Pass a fresh `entries` array each frame (or memo it on your live data). The
127
+ component re-projects on the R3F frame loop; the pure `EntityFrames` re-projects
128
+ whenever it re-renders.
129
+ - Lift `worldPosition` by the entity's height for an overhead anchor — the seam
130
+ does not guess a height.
131
+ - Set `maxCount` for crowds so a battlefield of entities does not render hundreds
132
+ of plates; the nearest are kept.
133
+ - Do not mirror entities into a `GameProvider`/entity store to use this. If the
134
+ game *does* run the JGengine entity store, `WorldNameplates`
135
+ (`@jgengine/shell/world/WorldHud`) is the store-driven counterpart.
136
+ - Keep `renderFrame` cheap — it runs per visible entity per refresh.