@jgengine/react 0.14.0 → 0.15.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/CHANGELOG.md +500 -1
- package/dist/accessibility.d.ts +39 -0
- package/dist/accessibility.js +61 -0
- package/dist/achievements.d.ts +50 -0
- package/dist/achievements.js +94 -0
- package/dist/cameraShake.d.ts +52 -0
- package/dist/cameraShake.js +53 -0
- package/dist/coachMarks.d.ts +72 -0
- package/dist/coachMarks.js +136 -0
- package/dist/codex.d.ts +25 -0
- package/dist/codex.js +62 -0
- package/dist/comboMeter.d.ts +63 -0
- package/dist/comboMeter.js +93 -0
- package/dist/components.js +4 -3
- package/dist/creditsScreen.d.ts +19 -0
- package/dist/creditsScreen.js +31 -0
- package/dist/cutscene.d.ts +66 -0
- package/dist/cutscene.js +132 -0
- package/dist/damageDirection.d.ts +51 -0
- package/dist/damageDirection.js +103 -0
- package/dist/dialogueView.d.ts +69 -0
- package/dist/dialogueView.js +111 -0
- package/dist/entityFrames.d.ts +114 -0
- package/dist/entityFrames.js +55 -0
- package/dist/fastTravel.d.ts +36 -0
- package/dist/fastTravel.js +103 -0
- package/dist/floatingText.d.ts +84 -0
- package/dist/floatingText.js +61 -0
- package/dist/gameViewport.js +8 -12
- package/dist/hooks.d.ts +42 -0
- package/dist/hooks.js +85 -0
- package/dist/hudTheme.d.ts +104 -7
- package/dist/hudTheme.js +300 -2
- package/dist/i18n.d.ts +29 -0
- package/dist/i18n.js +44 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +34 -0
- package/dist/interactionPrompt.d.ts +80 -0
- package/dist/interactionPrompt.js +112 -0
- package/dist/keybindingMenu.d.ts +59 -0
- package/dist/keybindingMenu.js +146 -0
- package/dist/killFeed.d.ts +63 -0
- package/dist/killFeed.js +88 -0
- package/dist/map.d.ts +123 -2
- package/dist/map.js +239 -36
- package/dist/menuRouter.d.ts +51 -0
- package/dist/menuRouter.js +49 -0
- package/dist/modals.d.ts +131 -0
- package/dist/modals.js +168 -0
- package/dist/notifications.d.ts +39 -0
- package/dist/notifications.js +111 -0
- package/dist/objectiveBanner.d.ts +62 -0
- package/dist/objectiveBanner.js +129 -0
- package/dist/photoMode.d.ts +21 -0
- package/dist/photoMode.js +39 -0
- package/dist/previewFixtures.d.ts +30 -0
- package/dist/previewFixtures.js +46 -0
- package/dist/questTracker.d.ts +24 -0
- package/dist/questTracker.js +31 -0
- package/dist/quickMenu.d.ts +39 -0
- package/dist/quickMenu.js +79 -0
- package/dist/radialMenu.d.ts +50 -0
- package/dist/radialMenu.js +69 -0
- package/dist/saveSlots.d.ts +81 -0
- package/dist/saveSlots.js +138 -0
- package/dist/scoreboard.d.ts +67 -0
- package/dist/scoreboard.js +71 -0
- package/dist/settings.d.ts +9 -3
- package/dist/settings.js +10 -4
- package/dist/shopGrid.d.ts +70 -0
- package/dist/shopGrid.js +129 -0
- package/dist/statusEffectBar.d.ts +52 -0
- package/dist/statusEffectBar.js +57 -0
- package/dist/streetGeometryPreview.d.ts +7 -0
- package/dist/streetGeometryPreview.js +119 -0
- package/dist/talentTree.d.ts +60 -0
- package/dist/talentTree.js +217 -0
- package/dist/timerReadout.d.ts +90 -0
- package/dist/timerReadout.js +111 -0
- package/dist/useDebouncedCommit.d.ts +54 -0
- package/dist/useDebouncedCommit.js +81 -0
- package/dist/waveHud.d.ts +49 -0
- package/dist/waveHud.js +53 -0
- package/dist/waypointMarkers.d.ts +80 -0
- package/dist/waypointMarkers.js +116 -0
- package/package.json +3 -3
- package/skills/ce-handoff/SKILL.md +149 -0
- package/skills/jgengine/SKILL.md +3 -1
- package/skills/jgengine/api.md +17 -7
- package/skills/jgengine/capabilities.md +12 -0
- package/skills/jgengine/recipes/minimal-game.md +7 -4
- package/skills/jgengine-ui/SKILL.md +5 -3
- package/skills/jgengine-ui/api.md +708 -19
- package/skills/jgengine-ui/capabilities.md +362 -1
- package/skills/jgengine-ui/recipes/overhead-entity-frames.md +136 -0
- package/skills/jgengine-ui/reference.md +7 -4
|
@@ -22,6 +22,17 @@
|
|
|
22
22
|
- `SpeedUnit` (type): type SpeedUnit = "kmh" | "mph" | "knots" | "ms" — Target unit for {@link formatSpeed}: km/h, mph, knots, or raw m/s.
|
|
23
23
|
- `formatSpeed` (function): function formatSpeed(metersPerSecond: number, options: SpeedFormat = {}): string — Format a speed given in meters/second as a HUD-ready string in km/h, mph, knots, or m/s — the one conversion table every speedometer and telemetry readout should share.
|
|
24
24
|
|
|
25
|
+
## @jgengine/core/i18n/i18n
|
|
26
|
+
|
|
27
|
+
- `Catalog` (type): type Catalog = Readonly<Record<Locale, Messages>> — All locales' message tables, keyed by locale.
|
|
28
|
+
- `I18n` (interface): interface I18n — Runtime translator over a message {@link Catalog} — active locale, lookup with fallback, interpolation, and pluralization.
|
|
29
|
+
- `I18nOptions` (interface): interface I18nOptions — Configuration for {@link createI18n}.
|
|
30
|
+
- `Locale` (type): type Locale = string — A locale tag (e.g. `"en"`, `"es"`, `"ja"`) — a key into a {@link Catalog}.
|
|
31
|
+
- `Messages` (type): type Messages = Readonly<Record<string, string>> — Flat message table for one locale: key → template string with `{param}` slots.
|
|
32
|
+
- `TParams` (type): type TParams = Readonly<Record<string, string | number>> — Interpolation values for a message template.
|
|
33
|
+
- `createI18n` (function): function createI18n(options: I18nOptions): I18n — Create a translator over a message catalog: active-locale lookup with a fallback-locale chain, `{param}` interpolation, and `Intl.PluralRules`-based pluralization. Observable (`subscribe`) so React re-renders on `setLocale`; the catalog is caller-owned static data, the locale is the only state.
|
|
34
|
+
- `interpolate` (function): function interpolate(template: string, params?: TParams): string — Replace `{name}` placeholders in `template` with `params[name]`. Unknown placeholders are left intact. Pure and locale-independent.
|
|
35
|
+
|
|
25
36
|
## @jgengine/core/render/lookPreset
|
|
26
37
|
|
|
27
38
|
- `CINEMATIC_POST_PROCESSING` (const): const CINEMATIC_POST_PROCESSING: PostProcessingConfig — Tuned tone-map + bloom + gentle SSAO + vignette/grade stack — the shipped-game post look.
|
|
@@ -37,7 +48,8 @@
|
|
|
37
48
|
- `BloomConfig` (interface): interface BloomConfig — UnrealBloom stage — soft HDR glow around bright pixels (sun, glints, emissive).
|
|
38
49
|
- `DofConfig` (interface): interface DofConfig — Depth-of-field (bokeh) stage — throws the fore/background out of focus around a focus distance.
|
|
39
50
|
- `GradeConfig` (interface): interface GradeConfig — Final colour-grade stage: lift/gain/gamma, saturation, vignette, film grain — applied in display space after tone mapping.
|
|
40
|
-
- `
|
|
51
|
+
- `PostAaMode` (type): type PostAaMode = "smaa" | "msaa" | false — Edge antialiasing for the post chain. SMAA runs in linear-sRGB before the output tone-map and cleans alpha-tested foliage/particles that MSAA samples alone leave crawling. `"msaa"` keeps only the render-target multisample resolve; `false` disables AA stages.
|
|
52
|
+
- `PostProcessingConfig` (interface): interface PostProcessingConfig — Declarative post-processing chain (RenderPass → AO → Bloom → SMAA → tone-map output → Grade). Present on a game means the shell mounts an `EffectComposer` and owns the render; absent means the renderer draws directly (unchanged). Each stage is a config object, `false` to skip, or omitted for its default. Pure data — no three.js types leak into core.
|
|
41
53
|
- `STUDIO_STAGE_POST` (const): const STUDIO_STAGE_POST: PostProcessingConfig — A cinematic "product shot" post preset — the full chain on (contact-AO, soft bloom, a warm film grade with vignette + a touch of grain + chromatic aberration). Meant for a `StudioStage` where a single parametric asset is framed on a backdrop, so every studio reads shipped, not intern-tier. DoF is left off by default (it needs a per-scene focus distance); set `dof` to enable it.
|
|
42
54
|
- `ToneMappingMode` (type): type ToneMappingMode = "aces" | "agx" | "reinhard" | "cineon" | "linear" | "none" — Renderer tone-mapping curve applied by the post chain's output stage.
|
|
43
55
|
|
|
@@ -55,7 +67,7 @@
|
|
|
55
67
|
- `GameSettingsConfig` (interface): interface GameSettingsConfig — ⚠ undocumented
|
|
56
68
|
- `GraphicsQuality` (type): type GraphicsQuality = "low" | "medium" | "high" — ⚠ undocumented
|
|
57
69
|
- `SETTINGS_STORAGE_PREFIX` (const): const SETTINGS_STORAGE_PREFIX: "jgengine:setting:" — ⚠ undocumented
|
|
58
|
-
- `SETTING_IDS` (const): const SETTING_IDS: { readonly masterVolume: "sound.master"; readonly graphicsQuality: "graphics.quality"; readonly graphicsShadows: "graphics.shadows"; readonly graphicsUiScale: "graphics.uiScale"; readonly touchStyle: "controls.touchStyle"; } — ⚠ undocumented
|
|
70
|
+
- `SETTING_IDS` (const): const SETTING_IDS: { readonly masterVolume: "sound.master"; readonly graphicsQuality: "graphics.quality"; readonly graphicsShadows: "graphics.shadows"; readonly graphicsUiScale: "graphics.uiScale"; readonly touchStyle: "controls.touchStyle"; readonly touchJoystick: "controls.touchJoystick"; } — ⚠ undocumented
|
|
59
71
|
- `SettingCategory` (type): type SettingCategory = BuiltInSettingCategory | (string & {}) — Built-in category ids keep autocomplete; any other string makes a fresh category.
|
|
60
72
|
- `SettingCategoryDef` (interface): interface SettingCategoryDef — Declares or relabels/reorders a category tab; use it for a custom category or to reshape the built-ins.
|
|
61
73
|
- `SettingKind` (type): type SettingKind = "slider" | "toggle" | "select" — ⚠ undocumented
|
|
@@ -75,14 +87,27 @@
|
|
|
75
87
|
|
|
76
88
|
## @jgengine/core/ui
|
|
77
89
|
|
|
90
|
+
- `AccessibilityState` (interface): interface AccessibilityState — Serializable accessibility preferences a game reads to adapt its presentation.
|
|
91
|
+
- `AccessibilityStore` (interface): interface AccessibilityStore — Observable, serializable accessibility-preferences store.
|
|
78
92
|
- `ActionCooldown` (interface): interface ActionCooldown — Cooldown state for an action, expressed so a radial sweep or countdown can render directly.
|
|
79
93
|
- `ActionCost` (interface): interface ActionCost — Headless view model for a contextual action collection — the data layer behind an RTS command card, an ability action bar, a build menu, or a radial. It carries *what the buttons mean* (label, hotkey, cost, cooldown, disabled reasons, toggle state) with zero rendering opinion, so a game keeps layout, dimensions, hotkeys, catalog-id mapping, renderer, and chrome caller-owned. The React renderers in `@jgengine/react/actionHud` consume this; a game can swap either without forking the logic here.
|
|
80
94
|
- `ActionDef` (interface): interface ActionDef — A caller-authored contextual action — the DATA input to the model. Every field except `id` is optional so a build button, a stance toggle, and a cooldown ability all use the same shape. Catalog-id mapping (turning `icon`/`label` into art and copy) stays caller-owned.
|
|
81
95
|
- `ActionReason` (interface): interface ActionReason — A single blocking reason: a stable machine `code` plus caller-facing `message`.
|
|
82
96
|
- `BUILT_IN_SETTING_CATEGORIES` (const): const BUILT_IN_SETTING_CATEGORIES: readonly BuiltInSettingCategory[] — ⚠ undocumented
|
|
97
|
+
- `COLORBLIND_MATRICES` (const): const COLORBLIND_MATRICES: Record<ColorblindMode, string | null> — `feColorMatrix` `values` strings for each colorblind mode — simulate how a viewer with that condition perceives color (and a grayscale mode). `"none"` maps to `null` (no filter). Consumed by the React `ColorblindFilters` defs.
|
|
98
|
+
- `Catalog` (type): type Catalog = Readonly<Record<Locale, Messages>> — All locales' message tables, keyed by locale.
|
|
99
|
+
- `CoachMarkPlacement` (type): type CoachMarkPlacement = "top" | "bottom" | "left" | "right" | "center" — Where a coach-mark callout sits relative to its anchor (or `"center"` for an unanchored callout).
|
|
100
|
+
- `CoachMarkSequence` (interface): interface CoachMarkSequence — An ordered, observable, serializable onboarding coach-mark run.
|
|
101
|
+
- `CoachMarkSequenceOptions` (interface): interface CoachMarkSequenceOptions — Options for {@link createCoachMarkSequence}.
|
|
102
|
+
- `CoachMarkSnapshot` (interface): interface CoachMarkSnapshot — Serializable persisted state — the seen set (with timestamps) and satisfied triggers.
|
|
103
|
+
- `CoachMarkStep` (interface): interface CoachMarkStep — One onboarding hint: an ordered, optionally-anchored, optionally-gated callout.
|
|
104
|
+
- `CoachMarkView` (interface): interface CoachMarkView — The active step plus its position, returned by {@link CoachMarkSequence.current}.
|
|
105
|
+
- `ColorblindMode` (type): type ColorblindMode = "none" | "protanopia" | "deuteranopia" | "tritanopia" | "grayscale" — Colorblind simulation/daltonization modes the engine ships matrices for.
|
|
106
|
+
- `DEFAULT_ACCESSIBILITY` (const): const DEFAULT_ACCESSIBILITY: AccessibilityState — The out-of-the-box accessibility state (all assistance off, `textScale` 1).
|
|
83
107
|
- `DEFAULT_GRAPHICS_QUALITY` (const): const DEFAULT_GRAPHICS_QUALITY: GraphicsQuality — ⚠ undocumented
|
|
84
108
|
- `DEFAULT_GRAPHICS_SHADOWS` (const): const DEFAULT_GRAPHICS_SHADOWS: true — ⚠ undocumented
|
|
85
109
|
- `DEFAULT_MASTER_VOLUME` (const): const DEFAULT_MASTER_VOLUME: 1 — ⚠ undocumented
|
|
110
|
+
- `DEFAULT_PHOTO_MODE` (const): const DEFAULT_PHOTO_MODE: PhotoModeState — The out-of-the-box photo-mode state: not active, HUD hidden when it engages.
|
|
86
111
|
- `DEFAULT_UI_SCALE` (const): const DEFAULT_UI_SCALE: 1 — Player-controlled multiplier on the HUD's computed fit scale — one lever on desktop and mobile alike.
|
|
87
112
|
- `EditorUiDocument` (interface): interface EditorUiDocument — Scene-document HUD section: panel id → layout. Single source of truth for placement.
|
|
88
113
|
- `EditorUiPanelLayout` (interface): interface EditorUiPanelLayout — Authored layout for one HUD panel inside `editor.scene.json` → `ui.panels`.
|
|
@@ -107,24 +132,52 @@
|
|
|
107
132
|
- `HudResizeAxes` (type): type HudResizeAxes = "none" | "x" | "y" | "both" — Which axes a panel type may grow when resized in canvas mode. Resize is semantic — content reflows (longer track, more rows) — never a CSS scale of the whole panel.
|
|
108
133
|
- `HudSize` (interface): interface HudSize — ⚠ undocumented
|
|
109
134
|
- `HudViewportConfig` (interface): interface HudViewportConfig extends HudFitConfig — Per-game HUD viewport declaration carried on `PlayableGame.hudFit`; `mobile` overrides the fit on compact displays so the owner can tune the phone layout separately.
|
|
135
|
+
- `I18n` (interface): interface I18n — Runtime translator over a message {@link Catalog} — active locale, lookup with fallback, interpolation, and pluralization.
|
|
136
|
+
- `I18nOptions` (interface): interface I18nOptions — Configuration for {@link createI18n}.
|
|
110
137
|
- `Insets` (interface): interface Insets — Edge insets in CSS pixels (safe areas, reservations).
|
|
111
138
|
- `LayoutCollision` (interface): interface LayoutCollision — One detected forbidden/warned overlap between two regions.
|
|
112
139
|
- `LayoutCollisionPolicy` (type): type LayoutCollisionPolicy = "forbid" | "allow" | "warn" — How a region participates in collision reporting.
|
|
113
140
|
- `LayoutOrientation` (type): type LayoutOrientation = "portrait" | "landscape" — A concrete device orientation.
|
|
114
141
|
- `LayoutRect` (interface): interface LayoutRect — Axis-aligned rectangle in CSS pixels (origin top-left). Structurally compatible with a `DOMRect`'s edge fields.
|
|
115
142
|
- `LayoutRegion` (interface): interface LayoutRegion — A physical rectangle a UI subsystem occupies, published to the shared registry.
|
|
143
|
+
- `Locale` (type): type Locale = string — A locale tag (e.g. `"en"`, `"es"`, `"ja"`) — a key into a {@link Catalog}.
|
|
116
144
|
- `LookPreset` (type): type LookPreset = "cinematic" | "flat" — Named default-look preset composing the existing lighting/sky/fog/post knobs into one field. `"cinematic"` (the default when unset) draws a scene lit like a shipped game — a real day sky with a view-following shadow-casting sun + hemisphere fill, a network-free image-based-lighting environment so PBR surfaces catch soft reflections, and a tuned tone-map/bloom/AO/vignette post stack. `"flat"` opts out of the sky/IBL/post rig to the bare ambient+directional default (pre-#773). The upgraded default primitive materials — tuned roughness/metalness plus subtle procedural surface detail so un-modeled boxes/capsules stop reading as flat plastic — apply under both presets.
|
|
145
|
+
- `MODAL_CANCEL` (const): const MODAL_CANCEL: "cancel" — Conventional cancel/dismiss result (also the default auto-dismiss and pop result).
|
|
146
|
+
- `MODAL_CONFIRM` (const): const MODAL_CONFIRM: "confirm" — Conventional confirm result for a two-button dialog — a shared string, not model behavior.
|
|
147
|
+
- `Messages` (type): type Messages = Readonly<Record<string, string>> — Flat message table for one locale: key → template string with `{param}` slots.
|
|
117
148
|
- `MobileHudBehavior` (type): type MobileHudBehavior = | "persistent" | "compact" | "icon" | "transient" | "hidden" | "sheet" | "modal" — How a HUD element adapts on phones.
|
|
149
|
+
- `ModalInput` (type): type ModalInput = Omit<ModalRecord, "id"> & { id?: string } — A modal to push — {@link ModalRecord} with an optional id (auto-assigned when absent).
|
|
150
|
+
- `ModalRecord` (interface): interface ModalRecord — Headless, serializable model for a stack of modal dialogs — the data layer behind a pause menu, a "quit to menu?" confirmation, a level-up popup, or any blocking overlay a game raises over its scene. It carries an ordered stack of opaque {@link ModalRecord}s (push to open, pop/resolve to close) and nothing about how they look: the model NEVER interprets a record's `kind` or a resolution's `result` string — those are free-form game vocabulary the React chrome in `@jgengine/react` renders. Observable ({@link ModalStack.subscribe}) and round-trips through a save ({@link ModalStack.snapshot}/{@link ModalStack.restore}). An injected clock powers optional per-modal auto-dismiss timers; leave those unset and the model is pure and clockless.
|
|
151
|
+
- `ModalResolution` (interface): interface ModalResolution — The outcome of closing a modal via {@link ModalStack.resolve} (or an auto-dismiss) — the closed record's identity plus the free-form `result` string the caller chose. Delivered to the `onResolve` option and stashed as {@link ModalStack.lastResolution}.
|
|
152
|
+
- `ModalStack` (interface): interface ModalStack — An observable, serializable stack of modal dialogs. See {@link createModalStack}.
|
|
153
|
+
- `ModalStackEntry` (interface): interface ModalStackEntry — A serialized stack entry: the opaque record plus the clock time it opened (for timer restore).
|
|
154
|
+
- `ModalStackOptions` (interface): interface ModalStackOptions — Options for {@link createModalStack}.
|
|
155
|
+
- `ModalStackSnapshot` (interface): interface ModalStackSnapshot — Serializable state — the ordered entries (bottom-first) and the id counter. Plain JSON.
|
|
156
|
+
- `ObjectiveBannerAnnouncement` (interface): interface ObjectiveBannerAnnouncement — One announcement request handed to {@link ObjectiveBannerController.announce}.
|
|
157
|
+
- `ObjectiveBannerController` (interface): interface ObjectiveBannerController — A live, clock-driven objective/stage banner controller.
|
|
158
|
+
- `ObjectiveBannerOptions` (interface): interface ObjectiveBannerOptions — Options for {@link createObjectiveBanner}.
|
|
159
|
+
- `ObjectiveBannerPhase` (type): type ObjectiveBannerPhase = "in" | "hold" | "out" — Which part of its life a banner is in: flying `"in"`, holding centered, or fading `"out"`. Progress `0..1` (see {@link ObjectiveBannerView.progress}) runs within whichever phase is active — the renderer maps phase + progress to opacity/scale/translate however it likes.
|
|
160
|
+
- `ObjectiveBannerSnapshot` (interface): interface ObjectiveBannerSnapshot — Serializable state of the queue and the active banner, for save/restore.
|
|
161
|
+
- `ObjectiveBannerView` (interface): interface ObjectiveBannerView — The banner to draw right now: its content, the game-owned `kind`, the current {@link ObjectiveBannerPhase}, and `progress` `0..1` through that phase. This object is pooled and overwritten on the next {@link ObjectiveBannerController.current} call — read it, don't retain it.
|
|
118
162
|
- `PanelDef` (interface): interface PanelDef — A caller-authored panel/window declaration — the DATA input to the model. Only `id` is required so a bag, a character sheet, and a one-off dialog all share the shape.
|
|
119
163
|
- `PanelPosition` (interface): interface PanelPosition — Headless, serializable model for a set of player-toggled windows/panels — the data layer behind a WoW-style UI where B opens the bag, C the character sheet, and ESC closes the topmost window. It carries *which panels are open*, their focus/z stacking order, per-panel position overrides, and exclusive-group membership, with zero rendering opinion. The React chrome in `@jgengine/react/panels` consumes this; a game keeps layout, skin, keybinds, and window content caller-owned. Pure and immutable: every reducer returns a new state and never mutates its input.
|
|
120
164
|
- `PanelState` (interface): interface PanelState — Serializable state for a set of panels: which are `open`, their `z` focus stack (higher renders on top), optional per-panel `pos` overrides, and the `meta` registry (group/closable) captured from the defs so the reducers below need no defs argument. Plain JSON — persist and rehydrate it freely.
|
|
165
|
+
- `PhotoModeState` (interface): interface PhotoModeState — Serializable photo-mode preferences a game reads to compose its capture UI.
|
|
166
|
+
- `PhotoModeStore` (interface): interface PhotoModeStore — Observable photo-mode store — genre-agnostic state a game binds its capture flow to.
|
|
121
167
|
- `PopoverOptions` (interface): interface PopoverOptions — Options for {@link placePopover}.
|
|
122
168
|
- `PopoverPlacement` (interface): interface PopoverPlacement — The resolved popover position — the side it actually opened on and its clamped top-left.
|
|
123
169
|
- `PopoverSide` (type): type PopoverSide = "top" | "bottom" | "left" | "right" — Which side of its anchor a popover opens toward.
|
|
124
|
-
- `PostProcessingConfig` (interface): interface PostProcessingConfig — Declarative post-processing chain (RenderPass → AO → Bloom → tone-map output → Grade). Present on a game means the shell mounts an `EffectComposer` and owns the render; absent means the renderer draws directly (unchanged). Each stage is a config object, `false` to skip, or omitted for its default. Pure data — no three.js types leak into core.
|
|
170
|
+
- `PostProcessingConfig` (interface): interface PostProcessingConfig — Declarative post-processing chain (RenderPass → AO → Bloom → SMAA → tone-map output → Grade). Present on a game means the shell mounts an `EffectComposer` and owns the render; absent means the renderer draws directly (unchanged). Each stage is a config object, `false` to skip, or omitted for its default. Pure data — no three.js types leak into core.
|
|
171
|
+
- `RadialArc` (interface): interface RadialArc — Arc the slices span. Omit for a full wheel (index 0 at the top). A partial `sweep` (e.g. `Math.PI` for a bottom half, `Math.PI / 2` for a quarter) packs the slices evenly inside `[startAngle, startAngle + sweep]` — the arc/quick-bar forms. Angles are radians from "up" (−Y), clockwise.
|
|
172
|
+
- `RadialSlice` (interface): interface RadialSlice — One wedge of a radial menu — geometry for rendering a slice. Angles are radians from "up" (−Y), clockwise.
|
|
173
|
+
- `RadialVectorOptions` (interface): interface RadialVectorOptions extends RadialArc — Options for {@link radialIndexFromVector}.
|
|
125
174
|
- `ResolvedAction` (interface): interface ResolvedAction — A resolved action view model — availability computed once from cooldown, cost, `disabled`, and any caller reasons. `enabled` is the single truth a renderer gates interaction on; `reasons` is the ordered explanation (cooldown, then unmet costs, then caller reasons, then a generic disable).
|
|
126
|
-
- `SETTING_IDS` (const): const SETTING_IDS: { readonly masterVolume: "sound.master"; readonly graphicsQuality: "graphics.quality"; readonly graphicsShadows: "graphics.shadows"; readonly graphicsUiScale: "graphics.uiScale"; readonly touchStyle: "controls.touchStyle"; } — ⚠ undocumented
|
|
175
|
+
- `SETTING_IDS` (const): const SETTING_IDS: { readonly masterVolume: "sound.master"; readonly graphicsQuality: "graphics.quality"; readonly graphicsShadows: "graphics.shadows"; readonly graphicsUiScale: "graphics.uiScale"; readonly touchStyle: "controls.touchStyle"; readonly touchJoystick: "controls.touchJoystick"; } — ⚠ undocumented
|
|
127
176
|
- `STUDIO_STAGE_POST` (const): const STUDIO_STAGE_POST: PostProcessingConfig — A cinematic "product shot" post preset — the full chain on (contact-AO, soft bloom, a warm film grade with vignette + a touch of grain + chromatic aberration). Meant for a `StudioStage` where a single parametric asset is framed on a backdrop, so every studio reads shipped, not intern-tier. DoF is left off by default (it needs a per-scene focus distance); set `dof` to enable it.
|
|
177
|
+
- `ScreenMarkerLayout` (interface): interface ScreenMarkerLayout — Where and how to draw one marker, from {@link layoutScreenMarker}.
|
|
178
|
+
- `ScreenMarkerOptions` (interface): interface ScreenMarkerOptions — Options for {@link layoutScreenMarker}.
|
|
179
|
+
- `ScreenMarkerViewport` (interface): interface ScreenMarkerViewport — The `{ width, height }` of the viewport the marker is laid out within (CSS px).
|
|
180
|
+
- `ScreenProjection` (interface): interface ScreenProjection — A world position projected to screen space by the caller's camera. This is the minimal shape {@link layoutScreenMarker} consumes — deliberately a structural subset of `@jgengine/react`'s `EntityScreenProjection` (and what its `ProjectEntity`/`useWorldProjection` produce), mirrored here because `core` imports nothing higher. Feed it straight from a world→screen projector.
|
|
128
181
|
- `SelectionFocusDirection` (type): type SelectionFocusDirection = "next" | "prev" | "first" | "last" — A 1-D focus move within the selection member strip.
|
|
129
182
|
- `SelectionGroup` (interface): interface SelectionGroup — A bucket of same-`kind` entities in a large selection — the RTS "12 Marines" control chip.
|
|
130
183
|
- `SelectionView` (interface): interface SelectionView — A resolved multi-selection view model. `primary` is the focused entity's full detail; `members` is the stable-order strip; `groups` buckets members by kind (count-desc, then label) for the portrait-overflow case; `grouped` is the hint that the selection is large enough to prefer groups over per-member portraits.
|
|
@@ -138,24 +191,39 @@
|
|
|
138
191
|
- `SettingsStore` (interface): interface SettingsStore — ⚠ undocumented
|
|
139
192
|
- `SettingsSurface` (type): type SettingsSurface = "quick" — `quick` shows compact on-screen volume/graphics buttons; `false` (default) mounts no engine trigger — open the menu from your own UI with `<SettingsTrigger>` or `useSettings().open()`.
|
|
140
193
|
- `SettingsVariant` (type): type SettingsVariant = "panel" | "sheet" | "sidebar" | "fullscreen" — The four themed settings layouts, chosen with `defineGame({ settings: { variant } })`. All read the game's `--jg-*` theme tokens.
|
|
194
|
+
- `StoredObjectiveBanner` (interface): interface StoredObjectiveBanner — A persisted banner record — all announcement fields resolved, plus id and schedule.
|
|
141
195
|
- `SummarizeSelectionOptions` (interface): interface SummarizeSelectionOptions — Options for {@link summarizeSelection}.
|
|
142
196
|
- `SwingTargetInput` (interface): interface SwingTargetInput — The current target, or the fields the bar needs from it.
|
|
197
|
+
- `TEXT_SCALE_MAX` (const): const TEXT_SCALE_MAX: 2 — Maximum UI text scale.
|
|
198
|
+
- `TEXT_SCALE_MIN` (const): const TEXT_SCALE_MIN: 0.75 — Minimum UI text scale.
|
|
199
|
+
- `TParams` (type): type TParams = Readonly<Record<string, string | number>> — Interpolation values for a message template.
|
|
143
200
|
- `ToneMappingMode` (type): type ToneMappingMode = "aces" | "agx" | "reinhard" | "cineon" | "linear" | "none" — Renderer tone-mapping curve applied by the post chain's output stage.
|
|
144
201
|
- `TooltipContent` (interface): interface TooltipContent — Structured tooltip content — a renderer lays these fields out; the model owns what is shown.
|
|
145
202
|
- `UI_SCALE_MAX` (const): const UI_SCALE_MAX: 1.5 — ⚠ undocumented
|
|
146
203
|
- `UI_SCALE_MIN` (const): const UI_SCALE_MIN: 0.5 — ⚠ undocumented
|
|
147
204
|
- `UiRect` (interface): interface UiRect — A positioned rectangle (viewport/anchor space, top-left origin, pixels).
|
|
148
205
|
- `UiSize` (interface): interface UiSize — A width/height pair (pixels).
|
|
206
|
+
- `Waypoint` (interface): interface Waypoint — A tracked objective/waypoint the game wants a screen marker for.
|
|
207
|
+
- `WaypointSnapshot` (interface): interface WaypointSnapshot — Serializable state of a {@link WaypointTracker}, for save/restore.
|
|
208
|
+
- `WaypointTracker` (interface): interface WaypointTracker — An observable, serializable set of world waypoints keyed by id.
|
|
149
209
|
- `actionByHotkey` (function): function actionByHotkey(actions: readonly ResolvedAction[], key: string): string | null — Find the action whose `hotkey` matches `key`, case-insensitively — the keyboard-shortcut router for an action bar. Returns the first match's id, or null. Matching by hotkey does not consider `enabled`; the caller decides whether to fire a disabled action's feedback.
|
|
150
210
|
- `actionCooldown` (function): function actionCooldown(remainingMs: number, totalMs: number): ActionCooldown — Build an {@link ActionCooldown} from remaining/total milliseconds. `ready` when nothing remains.
|
|
151
211
|
- `actionCooldownFromFraction` (function): function actionCooldownFromFraction(remainingMs: number, fraction: number): ActionCooldown — Build an {@link ActionCooldown} from remaining milliseconds and a known remaining fraction — the shape adapters get from sources (like an ability snapshot) that report a fraction but not a total.
|
|
152
212
|
- `actionCost` (function): function actionCost(resourceId: string, amount: number, available?: number): ActionCost — Build an {@link ActionCost}. `met` is true unless `available` is provided and below `amount`.
|
|
153
213
|
- `actionTooltip` (function): function actionTooltip(action: ResolvedAction): TooltipContent — Build {@link TooltipContent} from a {@link ResolvedAction}: title from the label, the group as a subtitle, the description as the body, and the blocking reasons as warning notes. The single place an action's tooltip copy is assembled, so every renderer shows the same thing.
|
|
154
214
|
- `busVolumeSettingId` (function): function busVolumeSettingId(busId: string): string — ⚠ undocumented
|
|
215
|
+
- `clampTextScale` (function): function clampTextScale(scale: number): number — Clamp a text-scale multiplier into the supported `[TEXT_SCALE_MIN, TEXT_SCALE_MAX]` range.
|
|
155
216
|
- `closePanel` (function): function closePanel(state: PanelState, id: string): PanelState — Close panel `id`. No-op if it is already closed. Its position override is kept so reopening restores the last placement.
|
|
156
217
|
- `closeTopPanel` (function): function closeTopPanel(state: PanelState): PanelState — Close the topmost closable open panel — the ESC handler. Skips panels pinned with `closable: false` and returns the same state when nothing closable is open.
|
|
218
|
+
- `createAccessibilityStore` (function): function createAccessibilityStore(initial: Partial<AccessibilityState> = {}): AccessibilityStore — Serializable, observable store of accessibility preferences (reduced motion, high contrast, text scale, colorblind mode, captions). Genre-agnostic plumbing like input rebinding — a game binds these to its settings UI and adapts its presentation; `snapshot`/`restore` round-trip through a save or settings blob.
|
|
219
|
+
- `createCoachMarkSequence` (function): function createCoachMarkSequence(options: CoachMarkSequenceOptions): CoachMarkSequence — An onboarding coach-mark run: an ordered sequence of hint steps, each shown as a centered callout or anchored to a UI element, with a persisted "seen" set so completed onboarding stays done across sessions, and data-first condition gating so a step waits until its trigger id is satisfied. Advance/skip/dismiss drive it; `snapshot`/`restore` round-trip the seen set through a save. Purely a model — a React host renders `current()`.
|
|
220
|
+
- `createI18n` (function): function createI18n(options: I18nOptions): I18n — Create a translator over a message catalog: active-locale lookup with a fallback-locale chain, `{param}` interpolation, and `Intl.PluralRules`-based pluralization. Observable (`subscribe`) so React re-renders on `setLocale`; the catalog is caller-owned static data, the locale is the only state.
|
|
221
|
+
- `createModalStack` (function): function createModalStack(options: ModalStackOptions = {}): ModalStack — A stack of modal dialogs: push opaque records to open blocking overlays (a pause menu, a confirm prompt, a reward popup), pop or resolve them with a free-form result to close, and query the top / open / depth to gate game input. The model is deliberately vocabulary-free — it never reads a record's `kind` or a resolution's `result`, so a game owns every dialog style — and fully serializable, with an optional injected clock driving per-modal auto-dismiss. A React host renders `top()`; `subscribe` re-renders it, `snapshot`/`restore` round-trip it through a save.
|
|
222
|
+
- `createObjectiveBanner` (function): function createObjectiveBanner(options: ObjectiveBannerOptions = {}): ObjectiveBannerController — A serializable, clock-driven stage/objective banner controller: the classic transient centered title stamp ("WAVE 3", "VICTORY", "OBJECTIVE COMPLETE"). A game calls `announce({ title, subtitle?, kind? })` and the controller queues it, flies it in, holds it, and fades it out on an injected clock — one banner at a time — exposing the current banner plus its phase (in/hold/out) and `progress` `0..1` for a renderer to animate opacity/scale/translate. Nothing here is genre-specific: `kind` is a free label the game owns and styles, and all timings are parameters. Call `advance()` each frame; `current()` returns the pooled view to draw; `snapshot`/`restore` round-trips the queue through a save.
|
|
157
223
|
- `createPanelState` (function): function createPanelState(defs: readonly PanelDef[]): PanelState — Build the initial {@link PanelState} from the panel defs: panels flagged `initial` start open (in declaration order, respecting group exclusivity), and every def's group/closable is captured into the state so later reducers need no defs.
|
|
224
|
+
- `createPhotoModeStore` (function): function createPhotoModeStore(initial: Partial<PhotoModeState> = {}): PhotoModeStore — Serializable, observable photo-mode state (active + hide-HUD). Genre-agnostic plumbing — a game engages it to free its camera and hide gameplay chrome for a clean capture, and reads `hideHud` to conditionally render its HUD. Pair with React `PhotoModeControls` and shell `captureCanvas`.
|
|
158
225
|
- `createSettingsStore` (function): function createSettingsStore(storage: Pick<WebStorageLike, "getItem" | "setItem"> | null | undefined = defaultStorage()): SettingsStore — Reactive, localStorage-backed settings store shared by the shell wiring and React hooks.
|
|
226
|
+
- `createWaypointTracker` (function): function createWaypointTracker(): WaypointTracker — A serializable, observable tracker of world waypoints — the objective/point-of- interest half of offscreen markers. A game `set`s waypoints by id (each an `{ id, position, kind, label? }`, where `kind` is a free string the game styles and the model never branches on), and a React host projects each to screen space and lays it out with {@link layoutScreenMarker}: an on-screen pin, or an off-screen directional arrow clamped to the viewport edge with a distance the caller computes. Purely a model — no camera, projection, or renderer here. `snapshot`/`restore` round-trips the set through a save.
|
|
159
227
|
- `focusPanel` (function): function focusPanel(state: PanelState, id: string): PanelState — Raise open panel `id` to the top of the focus stack (assign it the highest z). No-op if it is closed or already on top, so a pointer-down that refocuses the top window returns the same state.
|
|
160
228
|
- `formatDelta` (function): function formatDelta(seconds: number, decimals: 0 | 1 | 2 = 2): string — Format a signed time gap as `+m:ss.ff` / `-m:ss.ff`, for race deltas and split times.
|
|
161
229
|
- `formatDistance` (function): function formatDistance(meters: number, options: DistanceFormat = {}): string — Format a distance given in meters as a HUD-ready string, switching to km automatically past 1000m when `unit: "auto"`.
|
|
@@ -163,7 +231,9 @@
|
|
|
163
231
|
- `formatOrdinal` (function): function formatOrdinal(value: number): string — English ordinal for a placement number: 1 → "1st", 2 → "2nd", 3 → "3rd", 11 → "11th".
|
|
164
232
|
- `formatSpeed` (function): function formatSpeed(metersPerSecond: number, options: SpeedFormat = {}): string — Format a speed given in meters/second as a HUD-ready string in km/h, mph, knots, or m/s — the one conversion table every speedometer and telemetry readout should share.
|
|
165
233
|
- `hudScaleForViewport` (function): function hudScaleForViewport(fit: Required<HudFitConfig>, viewport: HudSize): number — The one scaling rule for every display: the ratio of the live viewport to the authored design size along the limiting axis, clamped. 1 on a viewport at or above design size; smoothly below 1 down to `minScale` on phones.
|
|
234
|
+
- `interpolate` (function): function interpolate(template: string, params?: TParams): string — Replace `{name}` placeholders in `template` with `params[name]`. Unknown placeholders are left intact. Pure and locale-independent.
|
|
166
235
|
- `isOpen` (function): function isOpen(state: PanelState, id: string): boolean — Whether panel `id` is currently open.
|
|
236
|
+
- `layoutScreenMarker` (function): function layoutScreenMarker(projection: ScreenProjection, viewport: ScreenMarkerViewport, options: ScreenMarkerOptions = {}): ScreenMarkerLayout — Pure, allocation-aware screen-marker math: given a projected target point, the viewport, and a `margin`, decide whether the target is on-screen and where to draw its marker. An on-screen point passes straight through (`onScreen: true`). An off-screen — or behind-camera — point is CLAMPED to the viewport edge (inset by `margin`) with `angle` set to the bearing from screen center toward the target, so a caller can pin an arrow to the frame edge and rotate it to point the way. Behind-camera projections have mirrored coordinates, so the bearing is flipped to face the true direction. This is the edge-clamp/arrow half that `layoutEntityFrames` lacks (it culls off-screen entries instead). No allocation when an `out` object is supplied — reuse one across a whole frame's waypoints.
|
|
167
237
|
- `listHudPanelTypes` (function): function listHudPanelTypes(): HudPanelTypeDef[] — Every registered panel type, sorted by id — editor palette / agent listing.
|
|
168
238
|
- `moveGridFocus` (function): function moveGridFocus(current: number, count: number, columns: number, dir: FocusDirection, options?: GridFocusOptions): number — Pure grid focus math for keyboard and controller navigation of an action card laid out in `columns`-wide rows. Given the current index (`-1` for none) it returns the next index, clamped to `[0, count)` — or wrapped when `wrap` is set. `left/right` move within/across columns, `up/down` across rows, `next/prev` walk the flat order, `first/last` jump to the ends. Renderer-agnostic: radial and list layouts pass `columns: 1` (or `count`) to get sensible 1-D stepping.
|
|
169
239
|
- `movePanel` (function): function movePanel(state: PanelState, id: string, pos: PanelPosition): PanelState — Set panel `id`'s position override — the drag commit. Does not require the panel to be open, so a caller can pre-place a window before it is shown.
|
|
@@ -175,6 +245,11 @@
|
|
|
175
245
|
- `overflowingPanels` (function): function overflowingPanels(panels: readonly { id: string; rect: HudRect }[], viewport: HudSize, tolerance = 1.5): HudOverflow[] — Every panel rect that escapes the viewport — the data behind the HUD overflow gate. A rect is only reported when it is partly visible *and* crosses an edge; a fully off-screen (closed/hidden) surface is skipped, so parked drawers and unopened menus never raise a false alarm.
|
|
176
246
|
- `panelByHotkey` (function): function panelByHotkey(defs: readonly PanelDef[], code: string): string | null — Find the panel whose `hotkey` matches `code`, case-insensitively — the keybind router. `code` may be a `KeyboardEvent.code` (`"KeyB"`) or key (`"b"`); it is compared verbatim to each def's `hotkey`, so author the hotkey in whichever form the caller feeds in. Returns the first match's id, or null.
|
|
177
247
|
- `placePopover` (function): function placePopover(anchor: UiRect, content: UiSize, viewport: UiSize, options?: PopoverOptions): PopoverPlacement — Position a popover/tooltip of `content` size against its `anchor` rectangle inside `viewport`: open on the `preferred` side, flip to the opposite when that side lacks room and the opposite has more, then clamp the top-left so the box stays fully on screen (respecting `margin`). Pure and deterministic — no DOM reads — so it is SSR-safe and unit-testable, and the React tooltip is a thin shell over it.
|
|
248
|
+
- `radialIndexFromAngle` (function): function radialIndexFromAngle(angle: number, count: number, arc?: RadialArc): number — Map an angle to a slice index; returns -1 when the angle falls outside a partial `arc`.
|
|
249
|
+
- `radialIndexFromVector` (function): function radialIndexFromVector(dx: number, dy: number, count: number, options: RadialVectorOptions = {}): number | null — Pick the slice a pointer/stick vector points at. `dx`/`dy` are screen-space (y down): up is `(0, -1)`. Returns null inside `deadZone` or (for a partial `arc`) outside the arc, so a centered stick or a click off the arc selects nothing.
|
|
250
|
+
- `radialSlicePosition` (function): function radialSlicePosition(index: number, count: number, radius: number, arc?: RadialArc): { x: number; y: number } — Unit-circle position of a slice center (up = `(0, -1)`), scaled by `radius` — where to place a wedge's icon/label.
|
|
251
|
+
- `radialSlices` (function): function radialSlices(count: number, arc?: RadialArc): RadialSlice[] — Divide a ring (or `arc`) into `count` wedges — the geometry a radial/quick menu (weapon wheel, emote arc, ping bar) renders. A full wheel centers index 0 at the top; a partial `arc` packs the slices inside its sweep.
|
|
252
|
+
- `reducedMotionDuration` (function): function reducedMotionDuration(state: AccessibilityState, ms: number, reduced = 0): number — Return `ms` when motion is allowed, or `reduced` (default 0) when `reducedMotion` is set — the animation-duration gate.
|
|
178
253
|
- `registerHudPanelType` (function): function registerHudPanelType(def: HudPanelTypeDef): void — Register a HUD panel type so the editor can list/add/configure it and canvas resize knows axes.
|
|
179
254
|
- `resizePanelSize` (function): function resizePanelSize(current: HudSize, delta: { dw: number; dh: number }, axes: HudResizeAxes, limits?: { minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number; }): HudSize — Semantic resize: apply pixel deltas only on growable axes, clamped to min/max. Never scales content — callers reflow layout size (track length, list rows).
|
|
180
255
|
- `resolveAction` (function): function resolveAction(def: ActionDef): ResolvedAction — Resolve one {@link ActionDef} into a {@link ResolvedAction}: normalize label, compute `enabled`, and order the blocking `reasons`. Pure — the same input always yields the same view model.
|
|
@@ -188,6 +263,19 @@
|
|
|
188
263
|
- `swingTimerState` (function): function swingTimerState(player: SwingPlayerInput, target: SwingTargetInput | null, prevPeriod: number, prevTimer: number): SwingTimerState — Pure swing-timer bar state — no hidden state, no clock, no DOM. The caller threads `prevPeriod`/`prevTimer` back each frame. The period is recovered on the reset edge (when `swingTimer` jumps up = a new swing began) as `max(swingTimer, weapon.speed)`, so the fill is correct even without knowing the weapon's exact cadence. Hidden unless auto-attacking a live, non-object target.
|
|
189
264
|
- `togglePanel` (function): function togglePanel(state: PanelState, id: string): PanelState — Toggle panel `id` — open it (with group exclusivity) if closed, close it if open. The one-key behavior behind a keybind like `B` for the bag.
|
|
190
265
|
|
|
266
|
+
## @jgengine/core/ui/accessibility
|
|
267
|
+
|
|
268
|
+
- `AccessibilityState` (interface): interface AccessibilityState — Serializable accessibility preferences a game reads to adapt its presentation.
|
|
269
|
+
- `AccessibilityStore` (interface): interface AccessibilityStore — Observable, serializable accessibility-preferences store.
|
|
270
|
+
- `COLORBLIND_MATRICES` (const): const COLORBLIND_MATRICES: Record<ColorblindMode, string | null> — `feColorMatrix` `values` strings for each colorblind mode — simulate how a viewer with that condition perceives color (and a grayscale mode). `"none"` maps to `null` (no filter). Consumed by the React `ColorblindFilters` defs.
|
|
271
|
+
- `ColorblindMode` (type): type ColorblindMode = "none" | "protanopia" | "deuteranopia" | "tritanopia" | "grayscale" — Colorblind simulation/daltonization modes the engine ships matrices for.
|
|
272
|
+
- `DEFAULT_ACCESSIBILITY` (const): const DEFAULT_ACCESSIBILITY: AccessibilityState — The out-of-the-box accessibility state (all assistance off, `textScale` 1).
|
|
273
|
+
- `TEXT_SCALE_MAX` (const): const TEXT_SCALE_MAX: 2 — Maximum UI text scale.
|
|
274
|
+
- `TEXT_SCALE_MIN` (const): const TEXT_SCALE_MIN: 0.75 — Minimum UI text scale.
|
|
275
|
+
- `clampTextScale` (function): function clampTextScale(scale: number): number — Clamp a text-scale multiplier into the supported `[TEXT_SCALE_MIN, TEXT_SCALE_MAX]` range.
|
|
276
|
+
- `createAccessibilityStore` (function): function createAccessibilityStore(initial: Partial<AccessibilityState> = {}): AccessibilityStore — Serializable, observable store of accessibility preferences (reduced motion, high contrast, text scale, colorblind mode, captions). Genre-agnostic plumbing like input rebinding — a game binds these to its settings UI and adapts its presentation; `snapshot`/`restore` round-trip through a save or settings blob.
|
|
277
|
+
- `reducedMotionDuration` (function): function reducedMotionDuration(state: AccessibilityState, ms: number, reduced = 0): number — Return `ms` when motion is allowed, or `reduced` (default 0) when `reducedMotion` is set — the animation-duration gate.
|
|
278
|
+
|
|
191
279
|
## @jgengine/core/ui/actionModel
|
|
192
280
|
|
|
193
281
|
- `ActionCooldown` (interface): interface ActionCooldown — Cooldown state for an action, expressed so a radial sweep or countdown can render directly.
|
|
@@ -205,6 +293,26 @@
|
|
|
205
293
|
- `resolveAction` (function): function resolveAction(def: ActionDef): ResolvedAction — Resolve one {@link ActionDef} into a {@link ResolvedAction}: normalize label, compute `enabled`, and order the blocking `reasons`. Pure — the same input always yields the same view model.
|
|
206
294
|
- `resolveActionCollection` (function): function resolveActionCollection(defs: readonly ActionDef[]): ResolvedAction[] — Resolve an ordered list of actions, preserving input order.
|
|
207
295
|
|
|
296
|
+
## @jgengine/core/ui/coachMarks
|
|
297
|
+
|
|
298
|
+
- `CoachMarkPlacement` (type): type CoachMarkPlacement = "top" | "bottom" | "left" | "right" | "center" — Where a coach-mark callout sits relative to its anchor (or `"center"` for an unanchored callout).
|
|
299
|
+
- `CoachMarkSequence` (interface): interface CoachMarkSequence — An ordered, observable, serializable onboarding coach-mark run.
|
|
300
|
+
- `CoachMarkSequenceOptions` (interface): interface CoachMarkSequenceOptions — Options for {@link createCoachMarkSequence}.
|
|
301
|
+
- `CoachMarkSnapshot` (interface): interface CoachMarkSnapshot — Serializable persisted state — the seen set (with timestamps) and satisfied triggers.
|
|
302
|
+
- `CoachMarkStep` (interface): interface CoachMarkStep — One onboarding hint: an ordered, optionally-anchored, optionally-gated callout.
|
|
303
|
+
- `CoachMarkView` (interface): interface CoachMarkView — The active step plus its position, returned by {@link CoachMarkSequence.current}.
|
|
304
|
+
- `createCoachMarkSequence` (function): function createCoachMarkSequence(options: CoachMarkSequenceOptions): CoachMarkSequence — An onboarding coach-mark run: an ordered sequence of hint steps, each shown as a centered callout or anchored to a UI element, with a persisted "seen" set so completed onboarding stays done across sessions, and data-first condition gating so a step waits until its trigger id is satisfied. Advance/skip/dismiss drive it; `snapshot`/`restore` round-trip the seen set through a save. Purely a model — a React host renders `current()`.
|
|
305
|
+
|
|
306
|
+
## @jgengine/core/ui/floatingText
|
|
307
|
+
|
|
308
|
+
- `FloatingTextDef` (interface): interface FloatingTextDef — One text pop to spawn: what to say, where in the world, and how it moves and fades. Everything but `position` and `text` is optional and falls back to the field's defaults. `kind` is a free-form tag (`"damage"`, `"heal"`, `"crit"`, `"xp"`, `"gold"`, `"bark"`, …) the presentation layer styles — the model never interprets it, so nothing here is combat- or genre-specific.
|
|
309
|
+
- `FloatingTextField` (interface): interface FloatingTextField — A live, dt-driven field of world-anchored floating text.
|
|
310
|
+
- `FloatingTextFieldConfig` (interface): interface FloatingTextFieldConfig — Construction options for {@link createFloatingTextField}.
|
|
311
|
+
- `FloatingTextPosition` (type): type FloatingTextPosition = readonly [number, number, number] — A world-space anchor `[x, y, z]` a floating-text entry rises from.
|
|
312
|
+
- `FloatingTextSnapshot` (interface): interface FloatingTextSnapshot — Serializable state for save/restore and deterministic replay.
|
|
313
|
+
- `FloatingTextView` (interface): interface FloatingTextView — A live entry resolved for rendering: current world position and fade/scale over life.
|
|
314
|
+
- `createFloatingTextField` (function): function createFloatingTextField(config: FloatingTextFieldConfig = {}): FloatingTextField — A generic, allocation-aware field of world-anchored floating text: damage numbers, heals, crits, XP/gold gains, status pops, dialogue barks — anything a game wants to say at a point in the world for a moment. It is dt-driven (call `update(dt)` each frame) and deterministic: the only randomness is the horizontal drift jitter, which flows from the injected `seed`, so the same seed and the same emit/update sequence reproduce identical motion, and `snapshot`/`restore` round-trips the live pool. The model owns only the spawn → rise/drift → fade → reap lifecycle: `kind` is a free string and `color` a passthrough hint, so nothing here couples to combat or any genre. Presentation (projecting each entry to the screen and styling it per `kind`) lives in `@jgengine/react`'s `FloatingText`.
|
|
315
|
+
|
|
208
316
|
## @jgengine/core/ui/gameLayout
|
|
209
317
|
|
|
210
318
|
- `DetectCollisionsOptions` (interface): interface DetectCollisionsOptions — Options for `detectLayoutCollisions`.
|
|
@@ -260,6 +368,30 @@
|
|
|
260
368
|
- `rectOverflow` (function): function rectOverflow(rect: HudRect, viewport: HudSize, tolerance = 1.5): Omit<HudOverflow, "id"> | null — Non-null when any edge of `rect` falls outside `viewport` by more than `tolerance` px; each field is the overflow distance past that edge (0 when inside).
|
|
261
369
|
- `resolveHudFit` (function): function resolveHudFit(config: HudViewportConfig | undefined, mobile: boolean): Required<HudFitConfig> — ⚠ undocumented
|
|
262
370
|
|
|
371
|
+
## @jgengine/core/ui/modalStack
|
|
372
|
+
|
|
373
|
+
- `MODAL_CANCEL` (const): const MODAL_CANCEL: "cancel" — Conventional cancel/dismiss result (also the default auto-dismiss and pop result).
|
|
374
|
+
- `MODAL_CONFIRM` (const): const MODAL_CONFIRM: "confirm" — Conventional confirm result for a two-button dialog — a shared string, not model behavior.
|
|
375
|
+
- `ModalInput` (type): type ModalInput = Omit<ModalRecord, "id"> & { id?: string } — A modal to push — {@link ModalRecord} with an optional id (auto-assigned when absent).
|
|
376
|
+
- `ModalRecord` (interface): interface ModalRecord — Headless, serializable model for a stack of modal dialogs — the data layer behind a pause menu, a "quit to menu?" confirmation, a level-up popup, or any blocking overlay a game raises over its scene. It carries an ordered stack of opaque {@link ModalRecord}s (push to open, pop/resolve to close) and nothing about how they look: the model NEVER interprets a record's `kind` or a resolution's `result` string — those are free-form game vocabulary the React chrome in `@jgengine/react` renders. Observable ({@link ModalStack.subscribe}) and round-trips through a save ({@link ModalStack.snapshot}/{@link ModalStack.restore}). An injected clock powers optional per-modal auto-dismiss timers; leave those unset and the model is pure and clockless.
|
|
377
|
+
- `ModalResolution` (interface): interface ModalResolution — The outcome of closing a modal via {@link ModalStack.resolve} (or an auto-dismiss) — the closed record's identity plus the free-form `result` string the caller chose. Delivered to the `onResolve` option and stashed as {@link ModalStack.lastResolution}.
|
|
378
|
+
- `ModalStack` (interface): interface ModalStack — An observable, serializable stack of modal dialogs. See {@link createModalStack}.
|
|
379
|
+
- `ModalStackEntry` (interface): interface ModalStackEntry — A serialized stack entry: the opaque record plus the clock time it opened (for timer restore).
|
|
380
|
+
- `ModalStackOptions` (interface): interface ModalStackOptions — Options for {@link createModalStack}.
|
|
381
|
+
- `ModalStackSnapshot` (interface): interface ModalStackSnapshot — Serializable state — the ordered entries (bottom-first) and the id counter. Plain JSON.
|
|
382
|
+
- `createModalStack` (function): function createModalStack(options: ModalStackOptions = {}): ModalStack — A stack of modal dialogs: push opaque records to open blocking overlays (a pause menu, a confirm prompt, a reward popup), pop or resolve them with a free-form result to close, and query the top / open / depth to gate game input. The model is deliberately vocabulary-free — it never reads a record's `kind` or a resolution's `result`, so a game owns every dialog style — and fully serializable, with an optional injected clock driving per-modal auto-dismiss. A React host renders `top()`; `subscribe` re-renders it, `snapshot`/`restore` round-trip it through a save.
|
|
383
|
+
|
|
384
|
+
## @jgengine/core/ui/objectiveBanner
|
|
385
|
+
|
|
386
|
+
- `ObjectiveBannerAnnouncement` (interface): interface ObjectiveBannerAnnouncement — One announcement request handed to {@link ObjectiveBannerController.announce}.
|
|
387
|
+
- `ObjectiveBannerController` (interface): interface ObjectiveBannerController — A live, clock-driven objective/stage banner controller.
|
|
388
|
+
- `ObjectiveBannerOptions` (interface): interface ObjectiveBannerOptions — Options for {@link createObjectiveBanner}.
|
|
389
|
+
- `ObjectiveBannerPhase` (type): type ObjectiveBannerPhase = "in" | "hold" | "out" — Which part of its life a banner is in: flying `"in"`, holding centered, or fading `"out"`. Progress `0..1` (see {@link ObjectiveBannerView.progress}) runs within whichever phase is active — the renderer maps phase + progress to opacity/scale/translate however it likes.
|
|
390
|
+
- `ObjectiveBannerSnapshot` (interface): interface ObjectiveBannerSnapshot — Serializable state of the queue and the active banner, for save/restore.
|
|
391
|
+
- `ObjectiveBannerView` (interface): interface ObjectiveBannerView — The banner to draw right now: its content, the game-owned `kind`, the current {@link ObjectiveBannerPhase}, and `progress` `0..1` through that phase. This object is pooled and overwritten on the next {@link ObjectiveBannerController.current} call — read it, don't retain it.
|
|
392
|
+
- `StoredObjectiveBanner` (interface): interface StoredObjectiveBanner — A persisted banner record — all announcement fields resolved, plus id and schedule.
|
|
393
|
+
- `createObjectiveBanner` (function): function createObjectiveBanner(options: ObjectiveBannerOptions = {}): ObjectiveBannerController — A serializable, clock-driven stage/objective banner controller: the classic transient centered title stamp ("WAVE 3", "VICTORY", "OBJECTIVE COMPLETE"). A game calls `announce({ title, subtitle?, kind? })` and the controller queues it, flies it in, holds it, and fades it out on an injected clock — one banner at a time — exposing the current banner plus its phase (in/hold/out) and `progress` `0..1` for a renderer to animate opacity/scale/translate. Nothing here is genre-specific: `kind` is a free label the game owns and styles, and all timings are parameters. Call `advance()` each frame; `current()` returns the pooled view to draw; `snapshot`/`restore` round-trips the queue through a save.
|
|
394
|
+
|
|
263
395
|
## @jgengine/core/ui/orientation
|
|
264
396
|
|
|
265
397
|
- `GameOrientation` (type): type GameOrientation = "landscape" | "portrait" | GameOrientationConfig — The `orientation` field of a game definition. Legacy shorthand `"landscape"` / `"portrait"` stays advisory (a dismissible rotate hint, never a gate). The object form `{ mobile: "landscape-required" }` is the strict contract that blocks gameplay behind the rotate screen until the device is turned.
|
|
@@ -288,6 +420,35 @@
|
|
|
288
420
|
- `panelByHotkey` (function): function panelByHotkey(defs: readonly PanelDef[], code: string): string | null — Find the panel whose `hotkey` matches `code`, case-insensitively — the keybind router. `code` may be a `KeyboardEvent.code` (`"KeyB"`) or key (`"b"`); it is compared verbatim to each def's `hotkey`, so author the hotkey in whichever form the caller feeds in. Returns the first match's id, or null.
|
|
289
421
|
- `togglePanel` (function): function togglePanel(state: PanelState, id: string): PanelState — Toggle panel `id` — open it (with group exclusivity) if closed, close it if open. The one-key behavior behind a keybind like `B` for the bag.
|
|
290
422
|
|
|
423
|
+
## @jgengine/core/ui/photoMode
|
|
424
|
+
|
|
425
|
+
- `DEFAULT_PHOTO_MODE` (const): const DEFAULT_PHOTO_MODE: PhotoModeState — The out-of-the-box photo-mode state: not active, HUD hidden when it engages.
|
|
426
|
+
- `PhotoModeState` (interface): interface PhotoModeState — Serializable photo-mode preferences a game reads to compose its capture UI.
|
|
427
|
+
- `PhotoModeStore` (interface): interface PhotoModeStore — Observable photo-mode store — genre-agnostic state a game binds its capture flow to.
|
|
428
|
+
- `createPhotoModeStore` (function): function createPhotoModeStore(initial: Partial<PhotoModeState> = {}): PhotoModeStore — Serializable, observable photo-mode state (active + hide-HUD). Genre-agnostic plumbing — a game engages it to free its camera and hide gameplay chrome for a clean capture, and reads `hideHud` to conditionally render its HUD. Pair with React `PhotoModeControls` and shell `captureCanvas`.
|
|
429
|
+
|
|
430
|
+
## @jgengine/core/ui/radialMenu
|
|
431
|
+
|
|
432
|
+
- `RadialArc` (interface): interface RadialArc — Arc the slices span. Omit for a full wheel (index 0 at the top). A partial `sweep` (e.g. `Math.PI` for a bottom half, `Math.PI / 2` for a quarter) packs the slices evenly inside `[startAngle, startAngle + sweep]` — the arc/quick-bar forms. Angles are radians from "up" (−Y), clockwise.
|
|
433
|
+
- `RadialSlice` (interface): interface RadialSlice — One wedge of a radial menu — geometry for rendering a slice. Angles are radians from "up" (−Y), clockwise.
|
|
434
|
+
- `RadialVectorOptions` (interface): interface RadialVectorOptions extends RadialArc — Options for {@link radialIndexFromVector}.
|
|
435
|
+
- `radialIndexFromAngle` (function): function radialIndexFromAngle(angle: number, count: number, arc?: RadialArc): number — Map an angle to a slice index; returns -1 when the angle falls outside a partial `arc`.
|
|
436
|
+
- `radialIndexFromVector` (function): function radialIndexFromVector(dx: number, dy: number, count: number, options: RadialVectorOptions = {}): number | null — Pick the slice a pointer/stick vector points at. `dx`/`dy` are screen-space (y down): up is `(0, -1)`. Returns null inside `deadZone` or (for a partial `arc`) outside the arc, so a centered stick or a click off the arc selects nothing.
|
|
437
|
+
- `radialSlicePosition` (function): function radialSlicePosition(index: number, count: number, radius: number, arc?: RadialArc): { x: number; y: number } — Unit-circle position of a slice center (up = `(0, -1)`), scaled by `radius` — where to place a wedge's icon/label.
|
|
438
|
+
- `radialSlices` (function): function radialSlices(count: number, arc?: RadialArc): RadialSlice[] — Divide a ring (or `arc`) into `count` wedges — the geometry a radial/quick menu (weapon wheel, emote arc, ping bar) renders. A full wheel centers index 0 at the top; a partial `arc` packs the slices inside its sweep.
|
|
439
|
+
|
|
440
|
+
## @jgengine/core/ui/screenMarkers
|
|
441
|
+
|
|
442
|
+
- `ScreenMarkerLayout` (interface): interface ScreenMarkerLayout — Where and how to draw one marker, from {@link layoutScreenMarker}.
|
|
443
|
+
- `ScreenMarkerOptions` (interface): interface ScreenMarkerOptions — Options for {@link layoutScreenMarker}.
|
|
444
|
+
- `ScreenMarkerViewport` (interface): interface ScreenMarkerViewport — The `{ width, height }` of the viewport the marker is laid out within (CSS px).
|
|
445
|
+
- `ScreenProjection` (interface): interface ScreenProjection — A world position projected to screen space by the caller's camera. This is the minimal shape {@link layoutScreenMarker} consumes — deliberately a structural subset of `@jgengine/react`'s `EntityScreenProjection` (and what its `ProjectEntity`/`useWorldProjection` produce), mirrored here because `core` imports nothing higher. Feed it straight from a world→screen projector.
|
|
446
|
+
- `Waypoint` (interface): interface Waypoint — A tracked objective/waypoint the game wants a screen marker for.
|
|
447
|
+
- `WaypointSnapshot` (interface): interface WaypointSnapshot — Serializable state of a {@link WaypointTracker}, for save/restore.
|
|
448
|
+
- `WaypointTracker` (interface): interface WaypointTracker — An observable, serializable set of world waypoints keyed by id.
|
|
449
|
+
- `createWaypointTracker` (function): function createWaypointTracker(): WaypointTracker — A serializable, observable tracker of world waypoints — the objective/point-of- interest half of offscreen markers. A game `set`s waypoints by id (each an `{ id, position, kind, label? }`, where `kind` is a free string the game styles and the model never branches on), and a React host projects each to screen space and lays it out with {@link layoutScreenMarker}: an on-screen pin, or an off-screen directional arrow clamped to the viewport edge with a distance the caller computes. Purely a model — no camera, projection, or renderer here. `snapshot`/`restore` round-trips the set through a save.
|
|
450
|
+
- `layoutScreenMarker` (function): function layoutScreenMarker(projection: ScreenProjection, viewport: ScreenMarkerViewport, options: ScreenMarkerOptions = {}): ScreenMarkerLayout — Pure, allocation-aware screen-marker math: given a projected target point, the viewport, and a `margin`, decide whether the target is on-screen and where to draw its marker. An on-screen point passes straight through (`onScreen: true`). An off-screen — or behind-camera — point is CLAMPED to the viewport edge (inset by `margin`) with `angle` set to the bearing from screen center toward the target, so a caller can pin an arrow to the frame edge and rotate it to point the way. Behind-camera projections have mirrored coordinates, so the bearing is flipped to face the true direction. This is the edge-clamp/arrow half that `layoutEntityFrames` lacks (it culls off-screen entries instead). No allocation when an `out` object is supplied — reuse one across a whole frame's waypoints.
|
|
451
|
+
|
|
291
452
|
## @jgengine/core/ui/selectionModel
|
|
292
453
|
|
|
293
454
|
- `EntitySummaryDef` (interface): interface EntitySummaryDef — A caller-provided summary of one selectable entity — the DATA input. `kind` is the grouping key used to bucket a large selection (unit type, catalog id); `icon` is a portrait id the renderer resolves. Only `id` is required.
|
|
@@ -324,6 +485,11 @@
|
|
|
324
485
|
## @jgengine/react
|
|
325
486
|
|
|
326
487
|
- `AbilitySlotBindingOptions` (interface): interface AbilitySlotBindingOptions — ⚠ undocumented
|
|
488
|
+
- `AccessibilityProvider` (function): function AccessibilityProvider({ store, children, className, style, }: { store: AccessibilityStore; children: ReactNode; className?: string; style?: CSSProperties; }): ReactNode — Apply accessibility preferences to a subtree: exposes `--jg-text-scale` for text to scale off, sets `data-reduced-motion` / `data-high-contrast` / `data-colorblind` / `data-captions` for CSS to respond to, and wraps the tree in the selected colorblind `feColorMatrix` filter. Reads a `createAccessibilityStore` and re-renders on change; provides the state to `useAccessibility`.
|
|
489
|
+
- `AchievementGallery` (function): function AchievementGallery({ achievements, title = "Achievements", maskSecrets = true, renderIcon, columns = 2, emptyLabel = "No achievements yet.", className, style, }: AchievementGalleryProps): ReactNode — Achievement/trophy gallery — a responsive grid of cards showing unlocked vs. locked state, a progress bar for counter achievements, and a header summary of completion and score. Secret+locked entries mask their name/description. Feed it `useAchievements(tracker)`.
|
|
490
|
+
- `AchievementGalleryProps` (interface): interface AchievementGalleryProps — Props for {@link AchievementGallery}.
|
|
491
|
+
- `AchievementToast` (function): function AchievementToast({ name, description, icon, points, heading = "Achievement Unlocked", className, style, }: AchievementToastProps): ReactNode — The unlock-moment banner — icon, "Achievement Unlocked" heading, name, and optional points. Purely presentational; pair the game's `onUnlock` seam with a toast queue and render one of these per entry.
|
|
492
|
+
- `AchievementToastProps` (interface): interface AchievementToastProps — Props for {@link AchievementToast}.
|
|
327
493
|
- `ActionBar` (function): function ActionBar({ defs, columns, layout = "grid", wrap, hotkeys, itemSize, ariaLabel, onActivate, renderItem, className, style, }: { defs: readonly ActionDef[]; columns?: number; layout?: "grid" | "list"; wrap?: boolean; hotkeys?: boolean; itemSize?: number; ariaLabel?: string; onActivate?: (id: … — Convenience composition of {@link useActionBar} + glass {@link ActionBarChrome} for demos and scaffolding — not a shipped game face. Pass `defs`, choose `grid`/`list`, and hand it `onActivate`. Games that own their UI compose the headless hook + custom chrome (or swap `renderItem`) instead of shipping this default panel.
|
|
328
494
|
- `ActionBarChrome` (function): function ActionBarChrome({ model, layout = "grid", itemSize = 52, gap = 6, ariaLabel = "Actions", renderItem, className, style, }: { model: ActionBarModel; layout?: "grid" | "list"; itemSize?: number; gap?: number; ariaLabel?: string; renderItem?: (action: ResolvedAction, ctx: ActionItemContext) => … — The composable RENDERER: lay the model's actions out as a `grid` or `list` toolbar with roving tabindex, arrow-key navigation, and a moved DOM focus. `renderItem` swaps per-item chrome; omit it for {@link ActionButton}. A radial or bespoke UI can skip this entirely and read the model. Purely a wiring/behavior layer — no panel skin — so a game art-directs freely.
|
|
329
495
|
- `ActionBarKeyResult` (interface): interface ActionBarKeyResult — The intent a key press resolves to over an action bar: move focus, activate, or ignore.
|
|
@@ -342,6 +508,9 @@
|
|
|
342
508
|
- `BetterAuthSessionState` (interface): interface BetterAuthSessionState — ⚠ undocumented
|
|
343
509
|
- `BetterAuthUserShape` (interface): interface BetterAuthUserShape — ⚠ undocumented
|
|
344
510
|
- `BossBar` (function): function BossBar(props: AtomicBarProps & { name?: string }): React.JSX.Element — A wide encounter/boss health bar with the boss name at the start.
|
|
511
|
+
- `CameraShakeMeter` (function): function CameraShakeMeter({ controller, animate = false, title = "CAMERA SHAKE", kindLabels, variation = "glass", className, style, }: CameraShakeMeterProps): ReactNode — A drop-in HUD panel that visualizes a core {@link CameraShakeController}: a trauma meter (reusing the shared {@link StaminaBar} building block) plus a live percentage and the current impact `kind` label. Presentation only — it reads the controller and never interprets `kind`, mapping it through `kindLabels` for display. A shell component applies the same controller's `offset()` to the camera; this panel is the on-screen readout of how much shake is in flight.
|
|
512
|
+
- `CameraShakeMeterProps` (interface): interface CameraShakeMeterProps — Props for {@link CameraShakeMeter}.
|
|
513
|
+
- `CameraShakeReadout` (interface): interface CameraShakeReadout — A live read of a camera-shake controller: current trauma `0..1` and the last game-owned `kind`.
|
|
345
514
|
- `CaptureOdds` (function): function CaptureOdds({ chance, className, fillClassName, }: { chance: number; className?: string; fillClassName?: string; }): React.JSX.Element — ⚠ undocumented
|
|
346
515
|
- `CardFace` (function): function CardFace({ rank, suit, faceDown = false, width = 64, height = 90, className, style, children, }: { rank: Rank; suit: Suit; faceDown?: boolean; width?: number; height?: number; className?: string; style?: CSSProperties; children?: ReactNode; }): React.JSX.Element — A single playing-card face: rank + suit pips, or a patterned back when `faceDown`.
|
|
347
516
|
- `CardStack` (function): function CardStack({ pile, zone, cardOf, ...rest }: { pile: CardPileState; zone: string; cardOf: (id: string) => PlayingCard; } & Omit<Parameters<typeof StackedPile>[0], "cards">): React.JSX.Element — `StackedPile` bound to a headless `CardPileState` zone: reads the ordered card ids from `pile.zones[zone]` and resolves each to a `PlayingCard` via `cardOf`.
|
|
@@ -356,22 +525,47 @@
|
|
|
356
525
|
- `ClerkUserShape` (interface): interface ClerkUserShape — ⚠ undocumented
|
|
357
526
|
- `ClerkUserState` (interface): interface ClerkUserState — ⚠ undocumented
|
|
358
527
|
- `Clock` (function): function Clock({ format = "24h", showDay = true, controls = false, style, className, }: { format?: "24h" | "12h"; showDay?: boolean; controls?: boolean; style?: CSSProperties; className?: string; }): React.JSX.Element — A time-of-day clock reading the sim calendar — `Day N · HH:MM`, 24h or 12h. `controls` adds pause + the game's speed multipliers as clickable pills (the "fast-forward" bar), off by default so a game opts into letting the player scrub time.
|
|
528
|
+
- `CoachMark` (function): function CoachMark({ view, positionStyle, onNext, onSkip, nextLabel = "Next", doneLabel = "Got it", skipLabel = "Skip tour", theme, className, style, }: CoachMarkProps): ReactNode — A single coach-mark callout — title, body, an "N of M" counter, a Next/Got-it button, and a Skip-tour link. Presentation-only; position it with `positionStyle` or drop it into {@link CoachMarkHost}. Reskin via {@link CoachMarkTheme}.
|
|
529
|
+
- `CoachMarkHost` (function): function CoachMarkHost({ sequence, resolveAnchor, showBackdrop = true, onComplete, nextLabel, doneLabel, skipLabel, theme, className, style, }: CoachMarkHostProps): ReactNode — Full-screen coach-mark host: watches a sequence, positions the current step's callout beside its anchored element (or centered when unanchored) via `getBoundingClientRect`, and draws an optional dimmed backdrop with a spotlight cutout around the anchor. Next advances, Skip ends the tour — both persist so hints never re-show. Reskin with {@link CoachMarkTheme}.
|
|
530
|
+
- `CoachMarkHostProps` (interface): interface CoachMarkHostProps — Props for {@link CoachMarkHost}.
|
|
531
|
+
- `CoachMarkProps` (interface): interface CoachMarkProps — Props for {@link CoachMark}.
|
|
532
|
+
- `CoachMarkTheme` (interface): interface CoachMarkTheme — Reskin tokens for {@link CoachMarkHost} / {@link CoachMark}.
|
|
533
|
+
- `Codex` (function): function Codex({ entries, title = "Codex", columns = 3, maskSecrets = true, renderIcon, onSelect, emptyLabel = "Nothing discovered yet.", className, style, }: CodexProps): ReactNode — Codex / bestiary gallery — category tabs, a responsive grid of entry cards (discovered vs. locked, secret entries masked until found), and a header summarizing completion. Feed it `codex.list()`; wire `onSelect` to a detail pane.
|
|
534
|
+
- `CodexProps` (interface): interface CodexProps — Props for {@link Codex}.
|
|
359
535
|
- `Coins` (function): function Coins({ currencyId, icon = "🪙", style, className, }: { currencyId: string; icon?: ReactNode; style?: CSSProperties; className?: string; }): React.JSX.Element — A currency counter — an icon (emoji/char, default a coin) plus the live amount for `currencyId`. *
|
|
536
|
+
- `ColorblindFilters` (function): function ColorblindFilters(): ReactNode — Hidden SVG `<defs>` holding the `feColorMatrix` colorblind filters that `AccessibilityProvider` references by `filter: url(#jg-cb-<mode>)`. Rendered automatically inside the provider; export standalone for custom roots.
|
|
537
|
+
- `ComboMeterHud` (function): function ComboMeterHud({ meter, tierColors, theme, animate = true, hideWhenEmpty = true, barWidth = 220, className, style, }: ComboMeterHudProps): ReactNode — A drop-in HUD for a core {@link ComboMeter}: the big live combo count ("×12"), the current free-string tier label, the derived score multiplier, and a draining window bar (reusing the shared atomic bar) that empties as the decay window runs out and re-fills on every hit. The active tier's color — supplied by the game via `tierColors`, keyed on the free-string tier id the model never interprets — drives the count glow, the label, and the bar fill, so a game reskins the escalation ("good" → "great" → "savage") without the engine hardcoding any tier meaning. Presentation only: all counting, timing, tiers, and the multiplier live in the core model.
|
|
538
|
+
- `ComboMeterHudProps` (interface): interface ComboMeterHudProps — Props for {@link ComboMeterHud}.
|
|
539
|
+
- `ComboMeterTheme` (interface): interface ComboMeterTheme — Reskin tokens for {@link ComboMeterHud}.
|
|
360
540
|
- `Compass` (function): function Compass({ facingYaw, center, markers, width = 340, fov = (Math.PI * 2) / 3, kindStyles = DEFAULT_MARKER_KINDS, className, }: CompassProps): ReactNode — Horizontal compass strip centered on the player's facing direction, with the eight cardinals and optional marker pips from static views, an external source, or a native `MarkerSet`.
|
|
361
541
|
- `CompassProps` (interface): interface CompassProps — ⚠ undocumented
|
|
542
|
+
- `ConfirmDialog` (function): function ConfirmDialog({ title, body, confirmLabel = "Confirm", cancelLabel = "Cancel", onConfirm, onCancel, danger = false, width = 360, className, style, }: ConfirmDialogProps): ReactNode — A generic two-button confirmation dialog — title, optional body, and Cancel / Confirm buttons over a `HudTheme`-token-driven {@link HudFrame}. Presentation-only: wire `onConfirm`/`onCancel` to a modal stack's `resolve` (typically inside a {@link ModalHost} render callback) and reskin via `HudTheme` tokens or `danger` for a destructive action. It interprets nothing — the game supplies the copy.
|
|
543
|
+
- `ConfirmDialogProps` (interface): interface ConfirmDialogProps — Props for {@link ConfirmDialog}.
|
|
362
544
|
- `ControlHint` (interface): interface ControlHint — One row of a control legend. Name the game action(s) whose bound key(s) to show (`action`) so the glyphs come straight from the keybind map — never re-typed — or give literal `keys` for controls that live outside the map (`"Mouse"`, `"LMB"`). `label` says what the control does.
|
|
363
545
|
- `ControlsList` (function): function ControlsList({ bindings, controls, hideOnCoarsePointer = true, separator = " / ", className, rowClassName, keysClassName, keyClassName, separatorClassName, labelClassName, renderKey, renderRow, }: { bindings?: ActionCodesMap; controls: readonly ControlHint[]; hideOnCoarsePointer?: boolean; … — Renders a controls legend whose key glyphs come from the game's keybind map, so bindings live in one place and never drift from a hand-typed table. Hides itself on coarse-pointer devices (a touchscreen has no keyboard) via the same `data-jg-kbd-hint` marker as `KeyHint`. Headless: every part carries a `className` slot and `data-*` hook; pass `renderKey`/`renderRow` to fully own the markup.
|
|
364
546
|
- `Crosshair` (function): function Crosshair({ size = 18, gap = 5, thickness = 2, color = "rgba(255,255,255,0.85)", style, className, }: { size?: number; gap?: number; thickness?: number; color?: string; style?: CSSProperties; className?: string; }): React.JSX.Element — A minimal center crosshair reticle — four ticks around a gap. Purely presentational.
|
|
365
547
|
- `CurrencyPill` (function): function CurrencyPill({ currencyId, className }: { currencyId: string; className?: string }): React.JSX.Element — ⚠ undocumented
|
|
548
|
+
- `CutsceneLetterbox` (function): function CutsceneLetterbox({ active, caption, onSkip, skipLabel = "Skip", progress, theme, className, style, }: CutsceneLetterboxProps): ReactNode — A drop-in cinematic letterbox overlay: black bars slide in top and bottom while a cutscene is `active`, an optional caption/dialogue line sits above the lower bar with an optional progress line, and a Skip button rides the top bar. Presentation only — it never touches the director; wire `active`/`caption`/`progress`/`onSkip` from {@link useSequenceDirector} and your `onCue` handler. Reskin via {@link CutsceneLetterboxTheme}.
|
|
549
|
+
- `CutsceneLetterboxProps` (interface): interface CutsceneLetterboxProps — Props for {@link CutsceneLetterbox}.
|
|
550
|
+
- `CutsceneLetterboxTheme` (interface): interface CutsceneLetterboxTheme — Reskin tokens for {@link CutsceneLetterbox}.
|
|
366
551
|
- `DEFAULT_BAR_TOKENS` (const): const DEFAULT_BAR_TOKENS: Required<BarTokens> — Built-in default values for every vitals token — scaffolding/preview only, not a shipped look.
|
|
552
|
+
- `DamageDirectionOverlay` (function): function DamageDirectionOverlay({ tracker, colors, showReticle = true, theme, className, style, }: DamageDirectionOverlayProps): ReactNode — A drop-in "hit-from" overlay: transient red (by default) arcs that flare around a center reticle in the direction each recent hit came from and fade out over time, driven entirely by a {@link DamageDirectionTracker}. Opacity and outward push scale with each indicator's eased intensity; color comes from the hit's `kind` (via `colors`) or the theme's danger color. Renders full-screen, `pointer-events: none`, so it never intercepts input — a game drops it into its HUD and calls `tracker.registerHit(...)` on damage. Reskin via {@link DamageDirectionTheme}.
|
|
553
|
+
- `DamageDirectionOverlayProps` (interface): interface DamageDirectionOverlayProps — Props for {@link DamageDirectionOverlay}.
|
|
554
|
+
- `DamageDirectionTheme` (interface): interface DamageDirectionTheme — Reskin tokens for {@link DamageDirectionOverlay}.
|
|
367
555
|
- `DeathScreen` (function): function DeathScreen({ statId = "health", open, className, children, }: { statId?: string; open?: boolean; className?: string; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
556
|
+
- `DebounceTimer` (interface): interface DebounceTimer — Injectable timer seam so the controller is testable with a manual clock.
|
|
557
|
+
- `DebouncedCommit` (interface): interface DebouncedCommit<T> — Live-mirrored, trailing-debounced commit binding for a single control value.
|
|
368
558
|
- `DefaultEquipSlotId` (type): type DefaultEquipSlotId = | "head" | "chest" | "hands" | "legs" | "feet" | "mainHand" | "offHand" | "ring1" | "ring2" | "trinket" — Slot ids used by {@link defaultEquipLayout}'s convenience arrangement.
|
|
369
559
|
- `DialogueBox` (function): function DialogueBox({ dialogue, onChoice, rng, className, lineClassName, speakerClassName, choicesClassName, choiceClassName, checkClassName, }: { dialogue: DialogueDef; onChoice?: (choice: DialogueChoice, result: CheckResult | null) => void; rng?: () => number; className?: string; lineClassName?: … — ⚠ undocumented
|
|
370
560
|
- `DialogueCheck` (interface): interface DialogueCheck — ⚠ undocumented
|
|
371
561
|
- `DialogueChoice` (interface): interface DialogueChoice — ⚠ undocumented
|
|
372
562
|
- `DialogueDef` (interface): interface DialogueDef — ⚠ undocumented
|
|
373
563
|
- `DialogueLine` (type): type DialogueLine = { speaker: string; text: string } | { choices: readonly DialogueChoice[] } — ⚠ undocumented
|
|
564
|
+
- `DialogueView` (function): function DialogueView({ run, renderPortrait, onChoose, onClose, closeLabel = "Close", theme, className, style, speakerClassName, textClassName, choicesClassName, choiceClassName, }: DialogueViewProps): ReactNode — A drop-in branching-conversation view over a {@link DialogueRun}: renders the current node's speaker name (+ an optional portrait slot), the line, and a list of clickable response choices that advance the conversation — the game passes its dialogue graph and gets working node traversal and choice state with no hand-rolled walk. A choice with a destination advances the run; a terminal choice (or the Close control on a choiceless node) fires `onClose`. Speaker/choice `kind` are free strings surfaced as `data-*` attributes for the game to style; the view never interprets them. HudTheme-skinned via `--jg-*` tokens; reskin further with {@link DialogueViewTheme}.
|
|
565
|
+
- `DialogueViewProps` (interface): interface DialogueViewProps — Props for {@link DialogueView}.
|
|
566
|
+
- `DialogueViewTheme` (interface): interface DialogueViewTheme — Reskin tokens for {@link DialogueView}. Each defaults to a HudTheme `--jg-*` token.
|
|
374
567
|
- `DisplayProfile` (interface): interface DisplayProfile — ⚠ undocumented
|
|
568
|
+
- `DomEventTarget` (interface): interface DomEventTarget — Minimal add/removeEventListener surface accepted by useDomEvent (window, document, elements).
|
|
375
569
|
- `DragGhost` (function): function DragGhost<T>({ layer, className, style, children, }: { layer: DragLayer<T>; className?: string; style?: CSSProperties; children?: (payload: DragPayload<T>) => ReactNode; }): React.JSX.Element | null — ⚠ undocumented
|
|
376
570
|
- `DragLayer` (interface): interface DragLayer<T> — ⚠ undocumented
|
|
377
571
|
- `DragPayload` (interface): interface DragPayload<T> — ⚠ undocumented
|
|
@@ -380,7 +574,13 @@
|
|
|
380
574
|
- `DropInfo` (interface): interface DropInfo<T> — ⚠ undocumented
|
|
381
575
|
- `DropZone` (function): function DropZone<T>({ id, layer, className, activeClassName, cellSize, children, }: { id: string; layer: DragLayer<T>; className?: string; activeClassName?: string; cellSize?: number; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
382
576
|
- `EmoteWheel` (function): function EmoteWheel({ emotes, radius, open = true, className, emoteClassName, onPlayed, onRejected, renderEmote, }: { emotes: readonly string[]; radius?: number; open?: boolean; className?: string; emoteClassName?: string; onPlayed?: (emoteId: string) => void; onRejected?: (reason: string) => void; … — ⚠ undocumented
|
|
577
|
+
- `EntityFrameEntry` (interface): interface EntityFrameEntry — The minimum an entry must carry; games extend it with their own display data.
|
|
578
|
+
- `EntityFrameLayoutOptions` (interface): interface EntityFrameLayoutOptions — Anchoring, culling, and stacking options shared by the layout core and component.
|
|
579
|
+
- `EntityFramePlacement` (interface): interface EntityFramePlacement<E extends EntityFrameEntry> — One entry resolved to a screen placement, ready to render.
|
|
580
|
+
- `EntityFrames` (function): function EntityFrames<E extends EntityFrameEntry>({ entries, project, renderFrame, className, style, anchorTransform = "translate(-50%, -100%)", ...layout }: EntityFramesProps<E>): React.JSX.Element — Absolutely-positioned overlay that renders a caller-composed frame over every on-screen entry. Drop it inside `HudCanvas` (or any positioned ancestor) and feed it fresh `entries`/`project` each frame. Every part carries `data-*` hooks (`data-entity-frames`, `data-entity-frame="<id>"`) for tests and skins.
|
|
581
|
+
- `EntityFramesProps` (interface): interface EntityFramesProps<E extends EntityFrameEntry> extends EntityFrameLayoutOptions — Props for {@link EntityFrames}.
|
|
383
582
|
- `EntityPortrait` (function): function EntityPortrait({ entity, selected = false, size = 44, vitalId = "health", tabIndex, onSelect, renderIcon, className, style, }: { entity: EntitySummaryDef; selected?: boolean; size?: number; vitalId?: string; tabIndex?: number; onSelect?: (id: string) => void; renderIcon?: (entity: EntitySum… — A selectable entity portrait tile — icon/initials, an optional thin health strip, and complete selected/hover/focus states as a real `<button>` (`aria-pressed`). The unit-of-a-selection chrome; swap the face via `renderIcon`. Accessible and keyboard-focusable.
|
|
583
|
+
- `EntityScreenProjection` (interface): interface EntityScreenProjection — World-anchored entity frames — a data-first seam for floating overhead UI (enemy nameplates + health bars, interaction prompts, objective pips) that tracks entities in the 3D world. The game keeps owning its entities: it passes a plain array of `{ id, worldPosition }` entries and a `project` function that turns a world position into a screen point, and composes each frame's markup itself (typically the shipped {@link ./bars!HealthBar} plus a name) reskinned through `HudTheme`/`barTokens`. This primitive owns only the reusable behavior: projecting, offsetting, culling entries that are off-screen or behind the camera, and stacking nearer entities above farther ones.
|
|
384
584
|
- `EntitySummary` (function): function EntitySummary({ entity, renderVital, className, style, }: { entity: EntitySummaryDef; renderVital?: (vital: EntityVital) => ReactNode; className?: string; style?: CSSProperties; }): React.JSX.Element — The primary-entity detail chrome — name, tags, and full vital bars for the focused member. The "who is selected" summary a single-selection or the head of a multi-selection shows. Swap the vital rows via `renderVital`.
|
|
385
585
|
- `EquipSlot` (interface): interface EquipSlot — One named equip slot: a stable `id`, a display `label`, its worn `item` (or `null` = empty), and where it sits.
|
|
386
586
|
- `EquipSlotLayout` (type): type EquipSlotLayout = readonly EquipSlot[] — An ordered set of equip slots that make up a paperdoll. Caller-supplied; see {@link defaultEquipLayout}.
|
|
@@ -389,9 +589,17 @@
|
|
|
389
589
|
- `EventMeterView` (interface): interface EventMeterView — A rendered snapshot of an {@link EventMeter}: current value, fill fraction, active tier, and ready-to-consume flag.
|
|
390
590
|
- `EventfulEngineStore` (interface): interface EventfulEngineStore<TEventMap extends object> — ⚠ undocumented
|
|
391
591
|
- `ExperienceBar` (const): const ExperienceBar: (props: AtomicBarProps) => React.JSX.Element — Level progress / experience.
|
|
592
|
+
- `FastTravelMenu` (function): function FastTravelMenu<TMeta = unknown>({ network, from, onTravel, currentId, title = "Fast Travel", emptyLabel = "No destinations discovered yet.", onClose, className, style, }: FastTravelMenuProps<TMeta>): ReactNode — Fast-travel menu — the discovered-destinations list players pick from: points grouped by region, distance-sorted from `from`, each showing icon, name, and distance, with a header counting discovered vs. total. Selecting a row calls `onTravel`; the current location is flagged and not travelable. Bind it to a `createFastTravelNetwork`.
|
|
593
|
+
- `FastTravelMenuProps` (interface): interface FastTravelMenuProps<TMeta = unknown> — Props for {@link FastTravelMenu}.
|
|
594
|
+
- `FloatingText` (function): function FloatingText({ entries, project, styleFor, fontSizePx = 20, className, style, renderEntry, ...layout }: FloatingTextProps): React.JSX.Element — Absolutely-positioned overlay that renders every on-screen floating-text entry as text with its color, current alpha, and pop-in scale. Drop it inside a positioned ancestor (e.g. an `<Html fullscreen>` overlay or `HudCanvas`) and feed it fresh `entries`/`project` each frame. Every part carries `data-*` hooks (`data-floating-text`, `data-floating-text-entry="<id>"`, `data-kind="<kind>"`) for tests and skins.
|
|
595
|
+
- `FloatingTextLayoutOptions` (interface): interface FloatingTextLayoutOptions — Anchoring and culling options shared by the layout core and the component.
|
|
596
|
+
- `FloatingTextPlacement` (interface): interface FloatingTextPlacement — World-anchored floating text — the presentation half of the data-first `@jgengine/core/ui/floatingText` seam. The game keeps owning the simulation: it passes the field's `active()` views plus a `project` function (world → screen), exactly the transport {@link ./entityFrames!EntityFrames} uses, so an R3F game gets it for free from `useWorldProjection`. This component owns only the reusable presentation: projecting each entry, culling ones behind the camera or off-screen, and rendering absolutely-positioned text with the entry's color, current alpha, and pop-in scale — reskinnable per `kind` through `styleFor`.
|
|
597
|
+
- `FloatingTextProps` (interface): interface FloatingTextProps extends FloatingTextLayoutOptions — Props for {@link FloatingText}.
|
|
392
598
|
- `FriendRequestsList` (function): function FriendRequestsList({ className, rowClassName, acceptClassName, declineClassName, emptyState, renderRequest, }: { className?: string; rowClassName?: string; acceptClassName?: string; declineClassName?: string; emptyState?: ReactNode; renderRequest?: (request: FriendRequestEntry) => ReactNode… — ⚠ undocumented
|
|
393
599
|
- `FriendRow` (function): function FriendRow({ friend, className, dotClassName, children, }: { friend: FriendEntry; className?: string; dotClassName?: string; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
394
600
|
- `FriendsList` (function): function FriendsList({ className, rowClassName, dotClassName, emptyState, renderFriend, }: { className?: string; rowClassName?: string; dotClassName?: string; emptyState?: ReactNode; renderFriend?: (friend: FriendEntry) => ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
601
|
+
- `FullscreenMap` (function): function FullscreenMap({ open = true, bounds, contentWidth = 900, minScale = 0.5, maxScale = 8, title = "Map", onClose, onWorldClick, tool = "pan", onStrokeComplete, drawTone = "info", drawWidth = 3, children, overlayClassName, overlayStyle, ...surfaceProps }: FullscreenMapProps): ReactNode — Fullscreen pan/zoom world-map overlay — the enlarged "press M" map. Wheel to zoom (toward the cursor), drag to pan, and click to place (wire `onWorldClick` to a waypoint/annotation store). Switch `tool` to `"draw"` to freehand-draw strokes committed to `onStrokeComplete` (wire to `createAnnotationLayer`). Reuses {@link WorldMapSurface} for rendering, so terrain bake, fog, routes, zones, markers, and the player arrow all appear; a drag never fires `onWorldClick`. Compose a {@link MapLegend} or tool palette via `children`.
|
|
602
|
+
- `FullscreenMapProps` (interface): interface FullscreenMapProps extends Omit<WorldMapSurfaceProps, "canvasWidth" | "canvasHeight" | "viewport" | "width" | "height" | "style"> — Props for {@link FullscreenMap}.
|
|
395
603
|
- `GameContextBridge` (function): function GameContextBridge({ context, children, }: { context: GameContext | null; children?: ReactNode; }): React.JSX.Element — Re-provide a captured {@link GameContext} across a nested React reconciler boundary. The `<Canvas>` of `@react-three/fiber` renders its children in a *separate* React root, so a `GameProvider` in the outer tree does NOT reach inside it — hooks like `useGameContext` / `useEntityRenderCues` throw. The fix the shell already uses internally: capture the context outside the boundary (with {@link useOptionalGameContext}) and wrap the inner tree in `GameContextBridge`. A `null` context renders children unchanged, so the same code works in showcases with no running game. This is the seam behind `EntityPreview` — reach for it directly when building a bespoke nested canvas.
|
|
396
604
|
- `GameIdentityProvider` (function): function GameIdentityProvider({ source, children, }: { source: IdentitySource; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
397
605
|
- `GamePreviewComponent` (type): type GamePreviewComponent = ComponentType<GamePreviewProps> — ⚠ undocumented
|
|
@@ -399,7 +607,7 @@
|
|
|
399
607
|
- `GamePreviewStates` (type): type GamePreviewStates = Record<string, GamePreviewComponent> — ⚠ undocumented
|
|
400
608
|
- `GameProvider` (function): function GameProvider({ context, children }: { context: GameContext; children?: ReactNode }): React.JSX.Element — ⚠ undocumented
|
|
401
609
|
- `GameViewportProvider` (function): function GameViewportProvider({ platforms, className, style, children, }: { platforms?: readonly HudPlatform[]; className?: string; style?: CSSProperties; children?: ReactNode; }): React.JSX.Element — Provides the shared game viewport layout to everything it wraps. Mount it once around the whole game presentation (world, HUD, controls, system UI) so every subsystem reads one coordinated geometry and registers its rect for collision detection. Publishes live `--jg-viewport-*` / `--jg-visual-viewport-*` / `--jg-safe-*` CSS variables on its root.
|
|
402
|
-
- `HUD_THEME_PRESETS` (const): const HUD_THEME_PRESETS: { "arcane-stone": HudTheme; "survival-wood": HudTheme; "military-flat": HudTheme; "sleek-hex": HudTheme; "elemental-circle": HudTheme; "sandbox-slot": HudTheme; } — Built-in theme presets for demos/scaffold only — not product identity; games author their own theme.
|
|
610
|
+
- `HUD_THEME_PRESETS` (const): const HUD_THEME_PRESETS: { "arcane-stone": HudTheme; "survival-wood": HudTheme; "military-flat": HudTheme; "sleek-hex": HudTheme; "elemental-circle": HudTheme; "sandbox-slot": HudTheme; ember: HudTheme; synthwave: HudTheme; fieldkit: HudTheme; } — Built-in theme presets for demos/scaffold only — not product identity; games author their own theme.
|
|
403
611
|
- `HealthBar` (const): const HealthBar: (props: AtomicBarProps) => React.JSX.Element — Player/enemy health — danger-flashes to `--jg-health-low` below a quarter full.
|
|
404
612
|
- `Hotbar` (function): function Hotbar({ inventoryId, activeSlot, keys, slotSize = 46, itemIcon, style, className, }: { inventoryId: string; activeSlot?: number; keys?: readonly string[]; slotSize?: number; /** Caller-supplied item id → icon registry; return null/undefined to fall back to the default glyph. */ itemIcon?: … — A numbered hotbar bound to an inventory — painted iconed slots (a `GameIcon` glyph over a school-keyed gradient with a count badge, #1035), an active-slot highlight, and a keycap per slot. Place it and pass the `inventoryId`; `activeSlot` highlights the equipped one. Supply `itemIcon` to map your item ids to your own glyphs — the default resolves a `GameIcon` from the item id.
|
|
405
613
|
- `HudCanvas` (function): function HudCanvas({ layout, editChord, compactScale, showDuring, className, style, children, }: { layout: HudLayoutStore; editChord?: HudEditChord | false; /** Zoom applied to the whole HUD on compact displays. Default 0.85. */ compactScale?: number; /** Opt-in play-phase gate: render the HUD only … — Full-viewport HUD surface. Panels declared with `HudPanel` flow into nine anchor regions and stack automatically with a gap — no per-panel pixel offsets, no manual clearance for sibling panels, the touch-control dock (`--jg-hud-dock-clearance`), or device safe areas. On compact displays the whole surface scales down and each panel applies its `compact` behavior.
|
|
@@ -412,20 +620,31 @@
|
|
|
412
620
|
- `HudLayoutPersist` (type): type HudLayoutPersist = (id: string, panel: EditorUiPanelLayout) => void — Host-owned callback that commits one HUD panel layout into the scene document (typically an undoable `setUiPanel` dispatch). Injected by the editor so product UI never reaches for editor globals.
|
|
413
621
|
- `HudLayoutPersistProvider` (function): function HudLayoutPersistProvider({ onPanelCommit, children, }: { onPanelCommit: HudLayoutPersist; children?: ReactNode; }): React.JSX.Element — Provides {@link HudLayoutPersist} / `onPanelCommit` to descendant `useHudLayout` calls. Mount around game UI when a host can accept document UI patches (editor). Absent provider → canvas moves/resizes are no-ops for document writes.
|
|
414
622
|
- `HudPanel` (function): function HudPanel({ id, anchor = "top-left", order, compact: compactMode = "keep", chip, interactive, inset, locked, showDuring, priority, mobileBehavior, allowOverlapWith, collisionGroup, region = true, width, height, type, className, style, children, }: { id: string; anchor?: HudAnchor; /** Stack … — A HUD block that lives in one of the nine anchor regions. Panels sharing a region stack outward from the screen edge in ascending `order`. On fine pointers panels stay draggable through the edit chord; a dragged panel leaves the flow and keeps its custom placement. On compact displays custom placements are ignored and the `compact` behavior applies.
|
|
415
|
-
- `HudTheme` (interface): interface HudTheme — A full HUD theme.
|
|
623
|
+
- `HudTheme` (interface): interface HudTheme — A full HUD theme. Author one with {@link hudTheme} or {@link deriveHudTheme}.
|
|
416
624
|
- `HudThemeBar` (interface): interface HudThemeBar — Framed-trough tokens shared by every atomic bar.
|
|
625
|
+
- `HudThemeFont` (interface): interface HudThemeFont — Typography roles. Any CSS `font-family` list.
|
|
417
626
|
- `HudThemeFrame` (interface): interface HudThemeFrame — Frame material + shape tokens (panels, `HudFrame variation="themed"`).
|
|
418
|
-
- `
|
|
627
|
+
- `HudThemeOverrides` (interface): interface HudThemeOverrides — Per-group partial overrides accepted by {@link hudTheme}.
|
|
628
|
+
- `HudThemePalette` (interface): interface HudThemePalette — `HudTheme` (#1034, #1573): one token object that restyles every shared token-driven building block at once — the atomic bars (#1033), frames, slots, the minimap ring, and the chrome the registry blocks read (surfaces, edges, text, status colors, fonts, rarity). `hudThemeVars(theme)` emits the whole `--jg-*` vocabulary, so setting a **game-authored** theme on any HUD ancestor re-skins `packages/react` primitives and `registry/jgengine` components together. Purely CSS-token driven (no image assets). Tokens are not a finished UI: every game still owns composition, skin, and art direction (see AGENTS.md). Built-in presets are demo/scaffold starting points only.
|
|
419
629
|
- `HudThemePreset` (type): type HudThemePreset = keyof typeof HUD_THEME_PRESETS — Built-in demo/scaffold theme preset name — not a game identity.
|
|
420
630
|
- `HudThemePreview` (function): function HudThemePreview({ className }: { className?: string }): React.JSX.Element — Renders the default theme plus every genre preset as a deterministic matrix.
|
|
631
|
+
- `HudThemeRarity` (interface): interface HudThemeRarity — Item-rarity coloring shared by loot cards, tooltips, and inventory slots.
|
|
632
|
+
- `HudThemeSeed` (interface): interface HudThemeSeed — Seed colors for {@link deriveHudTheme}. Only `accent` and `surface` are required.
|
|
421
633
|
- `HudThemeSlot` (interface): interface HudThemeSlot — Action/inventory slot tokens.
|
|
634
|
+
- `HudThemeStatus` (interface): interface HudThemeStatus — Semantic status colors — outcome, threat, and relationship coloring.
|
|
635
|
+
- `HudThemeSurface` (interface): interface HudThemeSurface — Chrome surfaces, edges, and text — what panels, overlays, and menus are built out of.
|
|
422
636
|
- `HudViewportContextValue` (interface): interface HudViewportContextValue — ⚠ undocumented
|
|
423
637
|
- `HudViewportProvider` (function): function HudViewportProvider({ platforms, config, userScale, children, }: { platforms: readonly HudPlatform[] | undefined; config: HudViewportConfig | undefined; userScale?: number; children?: ReactNode; }): React.JSX.Element — Mounted by the shell around `GameUI` so every `HudCanvas` inside the game picks up the game's `platforms`/`hudFit` declaration and the player's UI scale setting without any game-side wiring.
|
|
638
|
+
- `I18nProvider` (function): function I18nProvider({ i18n, children }: { i18n: I18n; children: ReactNode }): ReactNode — Provide an {@link I18n} instance to the tree so `useT`/`useLocale` can read it.
|
|
424
639
|
- `IconSchool` (type): type IconSchool = | "fire" | "frost" | "arcane" | "nature" | "holy" | "tech" | "shadow" | "steel" | "neutral" — `IconTreatment` (#1035): a procedural painted-icon face — a glyph over a school-keyed radial gradient, with a vignette inset shadow, a top gloss highlight, and optional count/keycap badges. Turns the engine's flat white `GameIcon` glyphs (and game-icons.net SVGs) into painted ability / item icons that read as AAA slots, not debug UI. Theme-aware: the frame reads the `--jg-slot-*` and `--jg-accent` `HudTheme` tokens (#1034), so a theme change re-skins every treated icon.
|
|
425
640
|
- `IconTreatment` (function): function IconTreatment({ icon, glyph, school = "neutral", size = 44, count, keycap, active = false, className, style, }: IconTreatmentProps): React.JSX.Element — A painted icon face — gradient + vignette + gloss behind a glyph, with count/keycap badges.
|
|
426
641
|
- `IconTreatmentProps` (interface): interface IconTreatmentProps — Props for {@link IconTreatment}.
|
|
427
642
|
- `IconsPreview` (function): function IconsPreview({ className }: { className?: string }): React.JSX.Element — Renders the school-gradient row and a treated-icon hotbar — the deterministic #1035 fixture.
|
|
428
643
|
- `IdentitySource` (interface): interface IdentitySource — ⚠ undocumented
|
|
644
|
+
- `InteractionPrompt` (function): function InteractionPrompt({ registry, playerPosition, theme, accentFor, keyFor, gaugeProgress, anchor = "bottom-center", zIndex = 40, className, style, }: InteractionPromptProps): ReactNode — A screen-anchored "Press E to …" interaction callout that renders the active prompt of a {@link PromptRegistry}. It subscribes to the registry and — when given `playerPosition` — re-resolves as the hero moves, showing the nearest in-range interactable and switching to a closer/higher-priority one as they cross radii. Each display kind renders as itself: a `keybind` shows a key cap plus its label ("Press [E] Open"), a `gauge` shows a hold bar filling with `gaugeProgress`, and a `label` shows plain text. Presentation only — the registry never branches on a prompt's meaning; the game colors each via `accentFor` and maps action ids to key glyphs via `keyFor`. HudTheme-skinnable through `--jg-accent` and {@link InteractionPromptTheme}.
|
|
645
|
+
- `InteractionPromptAnchor` (type): type InteractionPromptAnchor = "bottom-center" | "top-center" | "center" — Where the callout sits over the scene.
|
|
646
|
+
- `InteractionPromptProps` (interface): interface InteractionPromptProps — Props for {@link InteractionPrompt}.
|
|
647
|
+
- `InteractionPromptTheme` (interface): interface InteractionPromptTheme — Reskin tokens for {@link InteractionPrompt}.
|
|
429
648
|
- `InventoryGrid` (function): function InventoryGrid({ inventoryId, columns, size = 44, gap = 6, itemIcon, onActivate, className, style, }: InventoryGridProps): React.JSX.Element — A drop-in inventory grid with drag/swap/stack-merge/split and full keyboard control, bound to `inventoryId`.
|
|
430
649
|
- `InventoryGridBinding` (interface): interface InventoryGridBinding — Live slots plus `move`/`split` actions bound to `inventoryId`, routed through the notifying `inventory.move`/`inventory.split` commands so React re-renders.
|
|
431
650
|
- `InventoryGridProps` (interface): interface InventoryGridProps — Props for {@link InventoryGrid}.
|
|
@@ -433,12 +652,23 @@
|
|
|
433
652
|
- `JoinByCode` (function): function JoinByCode({ onJoin, className, inputClassName, buttonClassName, placeholder, children, }: { onJoin: (code: string) => void; className?: string; inputClassName?: string; buttonClassName?: string; placeholder?: string; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
434
653
|
- `KeyHint` (function): function KeyHint({ children, className, style, }: { children: ReactNode; className?: string; style?: CSSProperties; }): React.JSX.Element | null — Wraps a keyboard/mouse control hint (a cap plus what it does). Renders nothing on coarse-pointer devices — a touchscreen has no keyboard, so the hint is noise and only fights the on-screen controls for space. The `data-jg-kbd-hint` marker is also hidden by an engine stylesheet as a hydration-safe backstop, so a hint stays hidden on touch even before this component's effect runs. Put the touch equivalent (a `TouchControls` dock, a tappable button) on the coarse branch instead.
|
|
435
654
|
- `KeybindRow` (function): function KeybindRow({ action, keys, className, }: { action: string; keys: readonly string[]; className?: string; }): React.JSX.Element — ⚠ undocumented
|
|
655
|
+
- `KeybindingMenu` (function): function KeybindingMenu({ session, theme, title = "Controls", resetAllLabel = "Reset All", capturePrompt = "Press a key…", onChange, className, style, }: KeybindingMenuProps): ReactNode — A drop-in controls-settings surface for a {@link RebindSession}: one row per action showing its label and current key glyph. Clicking a row arms capture ("Press a key…") and a window `keydown` listener feeds the pressed `event.code` to `session.capture`; rows that collide with another action show a conflict badge; each row has a Reset button and the panel has a Reset-all button. Presentation only — all conflict/capture/reset logic lives in the core session, and action ids/labels are the game's free strings. Reskin via {@link KeybindingMenuTheme} or ambient HudTheme tokens. A game owns its overall settings layout; this is the reusable controls block it drops in.
|
|
656
|
+
- `KeybindingMenuProps` (interface): interface KeybindingMenuProps — Props for {@link KeybindingMenu}.
|
|
657
|
+
- `KeybindingMenuTheme` (interface): interface KeybindingMenuTheme — Reskin tokens for {@link KeybindingMenu}. All fall back to HudTheme `--jg-*` vars.
|
|
436
658
|
- `Keycap` (function): function Keycap({ children, className, style, }: { children: ReactNode; className?: string; style?: CSSProperties; }): React.JSX.Element — A single keyboard/mouse key rendered as a cap. Tagged `data-jg-kbd` so tooling can find it; on its own it stays visible (hiding a lone cap would strand its label). Wrap keys + their meaning in `KeyHint` to make the whole hint vanish on touch.
|
|
659
|
+
- `KillFeed` (function): function KillFeed({ ticker, kindStyles, theme, iconSize = 18, animate = true, zIndex = 40, className, style, }: KillFeedProps): ReactNode — A vertical event/kill-feed ticker: renders an {@link EventTicker}'s recent entries as a stack of rows, newest on top, each with its `fade` `0..1` mapped to opacity so entries dim and drop as they age out. Each row shows an optional per-kind (or per-entry) {@link GameIcon} and a per-kind accent color from `kindStyles`, styled with HudTheme tokens. Presentation only: all capping/timing lives in the core ticker, and the free-string `kind`/`text`/`icon` are never interpreted here — a game colors and icons each variant via `kindStyles`.
|
|
660
|
+
- `KillFeedKindStyle` (interface): interface KillFeedKindStyle — Per-`kind` styling for a kill-feed row — accent color and an optional icon.
|
|
661
|
+
- `KillFeedProps` (interface): interface KillFeedProps — Props for {@link KillFeed}.
|
|
662
|
+
- `KillFeedTheme` (interface): interface KillFeedTheme — Reskin tokens for {@link KillFeed}.
|
|
437
663
|
- `LayoutRegionSpec` (type): type LayoutRegionSpec = Omit<LayoutRegion, "rect"> — A region descriptor without its measured rectangle — the caller supplies geometry through `useRegisterLayoutRegion`.
|
|
438
664
|
- `LeavePartyButton` (function): function LeavePartyButton({ className, children, }: { className?: string; children?: ReactNode; }): React.JSX.Element | null — ⚠ undocumented
|
|
439
665
|
- `LevelUpFlash` (function): function LevelUpFlash({ stat, durationMs = 1600, className, children, renderFlash, }: { stat?: string; durationMs?: number; className?: string; children?: ReactNode; renderFlash?: (event: StatLevelUpEvent) => ReactNode; }): React.JSX.Element | null — ⚠ undocumented
|
|
440
666
|
- `ManaBar` (const): const ManaBar: (props: AtomicBarProps) => React.JSX.Element — Spell/energy resource pool.
|
|
441
667
|
- `MapBounds` (interface): interface MapBounds — ⚠ undocumented
|
|
668
|
+
- `MapLegend` (function): function MapLegend({ kinds, labels, kindStyles = DEFAULT_MARKER_KINDS, title = "Legend", className, style, }: MapLegendProps): ReactNode — Marker-kind key for a map/minimap — glyph + color swatch per kind, labelled. Reads the same `kindStyles` the map renders with, so the legend can never drift from the pins.
|
|
669
|
+
- `MapLegendProps` (interface): interface MapLegendProps — Props for {@link MapLegend}.
|
|
670
|
+
- `MapViewport` (interface): interface MapViewport — Pan/zoom transform applied to a {@link WorldMapSurface}'s content group.
|
|
671
|
+
- `MedalToken` (type): type MedalToken = "gold" | "silver" | "bronze" — The medal tokens {@link medalFor} emits for the podium.
|
|
442
672
|
- `MicToggle` (function): function MicToggle({ voice, className, mutedLabel, unmutedLabel, }: { voice: VoiceState; className?: string; mutedLabel?: ReactNode; unmutedLabel?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
443
673
|
- `Minimap` (function): function Minimap({ markers, center, worldRadius, fog, size = 176, facingYaw = 0, rotate = false, kindStyles = DEFAULT_MARKER_KINDS, background, mapBounds, routes, zones, cellStates, onWorldClick, className, style, title = "Map", children, }: MinimapProps): ReactNode — Framed circular minimap: optional baked terrain background, reveal-on-event fog overlay, categorized marker icons, and a facing arrow. Reads static marker views, an external marker source, or a native `MarkerSet`; supply your own `kindStyles` palette to reskin. Does not require `GameProvider`.
|
|
444
674
|
- `MinimapChrome` (function): function MinimapChrome({ view, frame = false, frameColor = "rgba(148,163,184,0.4)", frameStrokeWidth = 1.5, cardinalLabel = "N", markers = [], markerColor = "#e2e8f0", markerRadius = 5, className, }: MinimapChromeProps): ReactNode — Headless minimap chrome — nests inside a game's own `<svg>`: an optional ring frame, and edge-clamped marker dots that draw as directional arrows when a marker carries a `heading` (the compass-arrow / player-blip layer ~8 games were re-drawing by hand over `projectToMinimap`/`clampToMinimapEdge`). Renders a bare `<g>` — no background, panel, or title; compose your own content layer (routes, zones, terrain) as sibling SVG nodes for full control of z-order, or call `MinimapChrome` twice (once for `frame`, again for `markers`) to sandwich custom content between the ring and the blips.
|
|
@@ -451,6 +681,18 @@
|
|
|
451
681
|
- `MinimapTrackPip` (interface): interface MinimapTrackPip — A point marker on the {@link MinimapTrack} rail at a 0..1 fraction (e.g. a gate, the exit, or the player).
|
|
452
682
|
- `MinimapTrackProps` (interface): interface MinimapTrackProps — Props for {@link MinimapTrack}.
|
|
453
683
|
- `MinimapTrackSpan` (interface): interface MinimapTrackSpan — A colored span across the {@link MinimapTrack} rail, given by 0..1 `start`/`end` fractions (e.g. from core `trackFraction`).
|
|
684
|
+
- `ModalControls` (interface): interface ModalControls — Stack-bound controls handed to a {@link ModalHost} render callback.
|
|
685
|
+
- `ModalHost` (function): function ModalHost({ stack, children, showBackdrop = true, backdrop, closeOnBackdrop = true, closeOnEsc = true, zIndexBase = 80, className, style, }: ModalHostProps): ReactNode — Full-screen modal host: watches a stack, renders only the topmost modal centered over a dimmed backdrop, and manages accessibility — the panel is a `role="dialog" aria-modal`, focus moves into it on open and is trapped with Tab/Shift+Tab cycling, Escape and (optionally) a backdrop click cancel the top modal, and focus returns to the previously focused element on close. It renders nothing when the stack is empty. Skin the panel and backdrop via `HudTheme` tokens.
|
|
686
|
+
- `ModalHostProps` (interface): interface ModalHostProps — Props for {@link ModalHost}.
|
|
687
|
+
- `ModalStackView` (interface): interface ModalStackView — React chrome over the headless modal stack (`@jgengine/core/ui/modalStack`) — the blocking-overlay layer a game raises over its scene: a pause menu, a "quit to menu?" confirm, a reward popup. {@link useModalStack} is the DATA/HOOK layer (subscribe + the active record), {@link ModalHost} renders the top modal with a backdrop, focus trap, and Esc-to-cancel, and {@link ConfirmDialog} / {@link PauseMenu} are ready-to-wire, HudTheme-token-driven building blocks. All unskinned and game-owned: the model never interprets a modal's `kind`, so a game switches on it to pick which of these (or its own) content to show, and reskins everything via `HudTheme` tokens and the frame.
|
|
688
|
+
- `NotificationBell` (function): function NotificationBell({ store, onClick, icon = "🔔", className, style }: NotificationBellProps): ReactNode — Notification bell — an icon button with an unread-count badge, bound to a notification store. Toggle a {@link NotificationCenter} panel from its click.
|
|
689
|
+
- `NotificationBellProps` (interface): interface NotificationBellProps — Props for {@link NotificationBell}.
|
|
690
|
+
- `NotificationCenter` (function): function NotificationCenter({ store, title = "Notifications", emptyLabel = "You're all caught up.", onClose, formatTime, className, style, }: NotificationCenterProps): ReactNode — Notification center panel — the scrollable log toasts don't provide: newest notifications with a kind-colored marker, title/body, relative time, and an unread highlight; a header with the unread count, mark-all-read, and clear. Clicking an entry marks it read. Bind it to a `createNotificationCenter`.
|
|
691
|
+
- `NotificationCenterProps` (interface): interface NotificationCenterProps — Props for {@link NotificationCenter}.
|
|
692
|
+
- `ObjectiveBannerHost` (function): function ObjectiveBannerHost({ controller, theme, kindThemes, animate = true, dismissOnClick = false, zIndex = 50, className, style, }: ObjectiveBannerHostProps): ReactNode — A full-screen overlay that renders an {@link ObjectiveBannerController} as the classic transient centered title stamp — "WAVE 3", "VICTORY", "OBJECTIVE COMPLETE" — flying in, holding, and fading out. It subscribes to the model, drives `advance()` on an animation frame (unless the game ticks it), and maps the current banner's phase + progress to opacity/scale/translate. Reskin the base look with {@link ObjectiveBannerTheme} and color each variant via `kindThemes` keyed on the game-owned `kind`. Presentation only: all timing and queueing live in the core model, and `kind` is never interpreted here.
|
|
693
|
+
- `ObjectiveBannerHostProps` (interface): interface ObjectiveBannerHostProps — Props for {@link ObjectiveBannerHost}.
|
|
694
|
+
- `ObjectiveBannerTheme` (interface): interface ObjectiveBannerTheme — Reskin tokens for {@link ObjectiveBannerHost}. Per-`kind` overrides layer on top.
|
|
695
|
+
- `PREVIEW_FIXTURES` (const): const PREVIEW_FIXTURES: Record<string, PreviewFixture> — Registry of deterministic, engine-level preview fixtures — the *real* exported `@jgengine/react` components (`HudThemePreview`, `BarsPreview`, `IconsPreview`, …) that render identically every time from static values, so they can be screenshotted as regression evidence without booting a game.
|
|
454
696
|
- `PanelHost` (function): function PanelHost({ manager, render, panels, variation, shape, width, zIndexBase = 40, className, windowClassName, windowStyle, bodyStyle, }: { manager: PanelsManager; /** Content for a panel by id. Takes precedence over `panels`. */ render?: (id: string) => ReactNode; /** Static content map by pan… — Renders the open panels of a {@link usePanels} manager as absolutely-positioned, draggable, closable windows in z-order — the WoW window layer. Each window uses {@link HudFrame} chrome, is dragged by its title bar, raises focus on pointer-down, and gets its content from the `render` prop (or a `panels` map). Accessible: every window is a `role="dialog"` with an `aria-label` and a focusable close button; ESC-close is wired by the manager. Unskinned — art-direct via `HudTheme` tokens and the `variation`.
|
|
455
697
|
- `PanelKeyResult` (interface): interface PanelKeyResult — React chrome over the headless panel/window model (`@jgengine/core/ui/panelModel`) — the toggleable, draggable, z-stacked windows a WoW-style UI is made of (B for bag, C for character, ESC to close). `usePanels` is the DATA/HOOK layer (open/close/toggle/focus + a keybind listener), `PanelHost` renders the open windows in z-order, and `Window` is a standalone one-off window. All unskinned and token-driven: games reskin via `HudTheme` tokens and by swapping the `HudFrame` variation.
|
|
456
698
|
- `PanelsManager` (interface): interface PanelsManager — The live panel manager returned by {@link usePanels} and consumed by {@link PanelHost}.
|
|
@@ -459,28 +701,52 @@
|
|
|
459
701
|
- `PartyFrame` (function): function PartyFrame({ className, rowClassName, dotClassName, emptyState, renderMember, }: { className?: string; rowClassName?: string; dotClassName?: string; emptyState?: ReactNode; renderMember?: (member: PartyMemberEntry) => ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
460
702
|
- `PartyInviteToast` (function): function PartyInviteToast({ className, acceptClassName, declineClassName, renderInvite, }: { className?: string; acceptClassName?: string; declineClassName?: string; renderInvite?: (invite: PartyInviteEntry) => ReactNode; }): React.JSX.Element | null — ⚠ undocumented
|
|
461
703
|
- `PartyMemberRow` (function): function PartyMemberRow({ member, className, dotClassName, children, }: { member: PartyMemberEntry; className?: string; dotClassName?: string; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
704
|
+
- `PauseMenu` (function): function PauseMenu({ title = "Paused", onResume, resumeLabel = "Resume", items = [], width = 300, className, style, }: PauseMenuProps): ReactNode — A reskinnable pause-menu building block: a primary Resume button plus a game-filled list of slot items (Settings, Save, Quit, …), stacked in a `HudTheme`-token-driven {@link HudFrame}. It ships the common shape every game's pause screen needs and nothing genre-specific — the game supplies the title, item labels/order, and destructive styling, and reskins with `HudTheme` tokens. Drop it into a {@link ModalHost} keyed on a `"pause"` modal, or render it standalone.
|
|
705
|
+
- `PauseMenuItem` (interface): interface PauseMenuItem — One selectable row in a {@link PauseMenu}'s slot list (Settings, Save, Quit, …).
|
|
706
|
+
- `PauseMenuProps` (interface): interface PauseMenuProps — Props for {@link PauseMenu}.
|
|
707
|
+
- `PhotoModeControls` (function): function PhotoModeControls({ store, onCapture, className, style }: PhotoModeControlsProps): ReactNode — Photo-mode toolbar — a hide/show-HUD toggle, a capture button, and an exit button, bound to a `createPhotoModeStore`. Presentation-only: the game wires `onCapture` to shell `captureCanvas`/`downloadImage` and reads `hideHud` to drop its gameplay HUD.
|
|
708
|
+
- `PhotoModeControlsProps` (interface): interface PhotoModeControlsProps — Props for {@link PhotoModeControls}.
|
|
462
709
|
- `PlayingCard` (interface): interface PlayingCard — A single card in a stack: an id plus its face and orientation.
|
|
463
710
|
- `Popover` (function): function Popover({ open, anchorRef, side = "top", gap = 8, role = "tooltip", id, children, className, style, }: { open: boolean; anchorRef: { current: HTMLElement | null }; side?: PopoverSide; gap?: number; role?: string; id?: string; children: ReactNode; className?: string; style?: CSSProperties; }… — An accessible popover shell positioned by the pure {@link placePopover} math — flips and clamps against the viewport, renders nothing while closed, and defaults to `role="tooltip"`. Reuse it for an action's hover/focus description or any anchored panel.
|
|
464
711
|
- `PotionSlots` (function): function PotionSlots(props: SlotGridProps): React.JSX.Element — Consumable (health/shield potion) slots.
|
|
465
712
|
- `PresenceDot` (function): function PresenceDot({ userId, className }: { userId: string; className?: string }): React.JSX.Element — ⚠ undocumented
|
|
713
|
+
- `PreviewFixture` (interface): interface PreviewFixture — One entry in the engine preview-fixture registry: a deterministic, engine-level preview component keyed by a stable id.
|
|
714
|
+
- `ProjectEntity` (type): type ProjectEntity = ( worldPosition: readonly [number, number, number], ) => EntityScreenProjection | null — Projects a world position to a screen point, or returns `null` to cull the entry entirely (e.g. outside the frustum). Caller-owned so this seam never depends on a specific camera or renderer.
|
|
466
715
|
- `ProximityPrompt` (function): function ProximityPrompt({ prompt, className, }: { prompt: ProximityPromptDef; className?: string; }): React.JSX.Element — ⚠ undocumented
|
|
467
716
|
- `PushToTalkButton` (function): function PushToTalkButton({ voice, className, children, }: { voice: VoiceState; className?: string; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
468
717
|
- `QteTrack` (function): function QteTrack({ steps, startedAt, className, stepClassName, activeClassName, doneClassName, }: { steps: readonly QteStep[]; startedAt: number; className?: string; stepClassName?: string; activeClassName?: string; doneClassName?: string; }): React.JSX.Element — ⚠ undocumented
|
|
718
|
+
- `QuestTracker` (function): function QuestTracker({ quests, title = "Quests", emptyLabel = "No active quests.", maxObjectives, accent = "var(--jg-accent, #facc15)", className, style, }: QuestTrackerProps): ReactNode — Quest / objective tracker HUD — a compact panel of active quests with a title and labelled, progress-barred objectives (checked + struck when complete). Presentation-only over `describeTrackedQuest(def, instance)` views, so it stays decoupled from the `QuestJournal` runtime.
|
|
719
|
+
- `QuestTrackerProps` (interface): interface QuestTrackerProps — Props for {@link QuestTracker}.
|
|
469
720
|
- `QuickMatchButton` (function): function QuickMatchButton({ listings, onJoin, onNoMatch, filter, className, children, }: { listings: readonly SessionListing[]; onJoin: (listing: SessionListing) => void; onNoMatch?: () => void; filter?: MatchFilter; className?: string; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
721
|
+
- `QuickMenu` (function): function QuickMenu({ items, layout = "list", onSelect, onClose, title, columns = 3, arc = { startAngle: Math.PI / 2, sweep: Math.PI }, radialSize = 300, accent = "var(--jg-accent, #38bdf8)", className, style, }: QuickMenuProps): ReactNode — Versatile quick menu that takes many forms — a `radial` wheel, a partial `arc`, a vertical `list`, or a `grid` — over one item model with icons, labels, hotkeys, count badges, cooldowns, section headers, and nested submenus (drill in / back). Radial and arc forms reuse {@link RadialMenu}; list and grid render sectioned rows/tiles. The game supplies content and skin.
|
|
722
|
+
- `QuickMenuItem` (interface): interface QuickMenuItem extends RadialMenuOption — An entry on a {@link QuickMenu}: a leaf action, or (with `children`) a submenu.
|
|
723
|
+
- `QuickMenuLayout` (type): type QuickMenuLayout = "radial" | "arc" | "list" | "grid" — The forms a {@link QuickMenu} can take.
|
|
724
|
+
- `QuickMenuProps` (interface): interface QuickMenuProps — Props for {@link QuickMenu}.
|
|
470
725
|
- `RANKS` (const): const RANKS: readonly Rank[] — Ranks in ascending order, ace low.
|
|
726
|
+
- `RadialMenu` (function): function RadialMenu({ options, open = true, onSelect, onClose, size = 300, innerRadius = 52, arc, highlightIndex, accent = "var(--jg-accent, #38bdf8)", className, style, }: RadialMenuProps): ReactNode — Radial / quick menu (weapon or emote wheel) — a ring or partial `arc` of selectable wedges the player points at with the mouse (or a stick). Pointer angle drives the highlight via core `radialIndexFromVector`; click/confirm fires `onSelect`, the neutral hub closes. Options carry optional hotkeys, count badges, cooldowns, and submenu markers. The game supplies icons/labels and skins it.
|
|
727
|
+
- `RadialMenuOption` (interface): interface RadialMenuOption — One selectable entry on a radial/quick menu (weapon or emote wheel).
|
|
728
|
+
- `RadialMenuProps` (interface): interface RadialMenuProps — Props for {@link RadialMenu}.
|
|
471
729
|
- `Rank` (type): type Rank = "A" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "J" | "Q" | "K" — A playing-card rank, ace through king.
|
|
472
730
|
- `ReadableEngineStore` (interface): interface ReadableEngineStore<TState> — ⚠ undocumented
|
|
473
731
|
- `RegionRecord` (interface): interface RegionRecord extends LayoutRegion — A region registration: the full `LayoutRegion` plus the live element (dev outlining), rect measured by the shell/react side.
|
|
474
732
|
- `RequireSession` (function): function RequireSession({ fallback, loading, children, }: { fallback?: ReactNode; loading?: ReactNode; children?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
475
733
|
- `RotateDeviceScreen` (function): function RotateDeviceScreen({ title = "Turn your device", description, requiredOrientation = "landscape", accent = "var(--jg-accent, #8ea2ff)", icon, className, style, }: { /** Short headline. */ title?: string; /** One concise explanatory line. Defaults from `requiredOrientation`. */ description?: … — Full-viewport, non-dismissible rotate-device gate shown when a game requires an orientation the device isn't in.
|
|
734
|
+
- `SETTINGS_TRIGGER_CLASSNAME` (const): const SETTINGS_TRIGGER_CLASSNAME: "pointer-events-auto flex h-8 w-8 items-center justify-center rounded-md border border-[var(--jg-edge-bright)] bg-[var(--jg-surface)]/80 text-base text-[var(--jg-text-dim)] shadow-[0_1px_2px_rgba(0,0,0,0.6)] transition hover:bg-[var(--jg-surface-deep)] hover:text-[v… — Default HudTheme-token skin for {@link SettingsTrigger} — the 8×8 chrome button games re-authored seven times. Pass your own `className` only to override placement or brand chrome; the gear glyph already scales with `text-base` / `1em`.
|
|
476
735
|
- `SUITS` (const): const SUITS: readonly Suit[] — Suits in canonical order (clubs, diamonds, hearts, spades).
|
|
736
|
+
- `SaveSlotMenu` (function): function SaveSlotMenu({ model, onLoad, onNew, onDelete, onContinue, title = "Select Save", theme, now = Date.now, metaIcons, className, style, }: SaveSlotMenuProps): ReactNode — A drop-in save-select / profile menu that renders a {@link SaveSlots} index as a column of cards. A filled slot shows its name, the free-string `meta` the game supplied as chips, and a relative "saved" time, with Load and Delete actions; an empty slot shows a "New Game" affordance. A top-level Continue button targets the newest save (`model.mostRecent()`). This is a starting-point game-front-end building block — the game owns final art, wording, and layout; reskin it with {@link SaveSlotMenuTheme} or HudTheme CSS vars. Presentation only: all state lives in the core model, and `meta` keys are never interpreted.
|
|
737
|
+
- `SaveSlotMenuProps` (interface): interface SaveSlotMenuProps — Props for {@link SaveSlotMenu}.
|
|
738
|
+
- `SaveSlotMenuTheme` (interface): interface SaveSlotMenuTheme — Reskin tokens for {@link SaveSlotMenu}. All optional — each falls back to a HudTheme var then a neutral default.
|
|
477
739
|
- `SaveStoreView` (interface): interface SaveStoreView<T> — The reactive slice of a {@link SaveStore} returned by {@link useSaveStore} — the live value plus bound save actions, all re-rendering on change.
|
|
740
|
+
- `Scoreboard` (function): function Scoreboard({ entries, rows, options, title, scoreLabel = "Score", nameFor, formatScore, medalIcon, theme, className, style, }: ScoreboardProps): ReactNode — A reskinnable ranked-score table for the {@link rankLeaderboard} selector: a rank column (medal icon/color for the top three via {@link medalFor}, otherwise the number), a name column, and a score column. The local player's row (`isLocal`) is washed and accented so "you" stands out. Feed it already-ranked `entries`, or raw `rows` plus `options` and it ranks them for you. All colors and spacing come from {@link ScoreboardTheme} / HudTheme `--jg-*` tokens — the component reads the model and never styles by game meaning.
|
|
741
|
+
- `ScoreboardProps` (interface): interface ScoreboardProps — Props for {@link Scoreboard}. Pass either `entries` (already ranked) or `rows` + `options`.
|
|
742
|
+
- `ScoreboardTheme` (interface): interface ScoreboardTheme — Reskin tokens for {@link Scoreboard}. Every color/spacing value reads a `--jg-*` token first.
|
|
478
743
|
- `Screen` (function): function Screen({ id, open = true, className, children, }: { id: string; open?: boolean; className?: string; children?: ReactNode; }): React.JSX.Element | null — ⚠ undocumented
|
|
479
744
|
- `SelectionCollectionChrome` (function): function SelectionCollectionChrome({ model, itemSize = 44, gap = 4, windowSize, scroll = 0, ariaLabel = "Selection", renderMember, renderGroup, onGroupSelect, className, style, }: { model: SelectionModel; itemSize?: number; gap?: number; /** Cap the mounted portraits; the model virtualizes past this… — The composable RENDERER for the member collection: a portrait strip for a small selection, or the same-kind group chips once the model is `grouped`. Roving tabindex + arrow-key focus. Swap `renderMember`/`renderGroup` for custom chrome, or read the model and lay it out yourself. No panel skin — a behavior/accessibility layer only.
|
|
480
745
|
- `SelectionGroupChip` (function): function SelectionGroupChip({ group, onSelect, renderIcon, className, style, }: { group: SelectionGroup; onSelect?: (group: SelectionGroup) => void; renderIcon?: (group: SelectionGroup) => ReactNode; className?: string; style?: CSSProperties; }): React.JSX.Element — A same-kind selection chip — icon plus count — for the grouped large-selection view. The default chrome {@link SelectionCollectionChrome} renders per group; swap it via `renderGroup`.
|
|
481
746
|
- `SelectionKeyEvent` (interface): interface SelectionKeyEvent — A minimal keyboard-event shape — a real `KeyboardEvent`/React synthetic satisfies it.
|
|
482
747
|
- `SelectionModel` (interface): interface SelectionModel — The live selection model returned by {@link useSelectionView}.
|
|
483
748
|
- `SelectionPanel` (function): function SelectionPanel({ members, model: providedModel, groupThreshold, labelOf, windowSize, renderPrimary, renderMember, renderVital, onFocusChange, className, style, }: { members?: readonly EntitySummaryDef[]; model?: SelectionModel; groupThreshold?: number; labelOf?: (kind: string) => string; wi… — Convenience composition: skinned glass panel with {@link EntitySummary} for the primary member beside {@link SelectionCollectionChrome} for the rest — demos/scaffold only, not a finished game face. Pass `members` (or a prebuilt `model`); swap sub-renderers or compose the headless pieces under game-owned chrome for product UI.
|
|
749
|
+
- `SequenceDirectorBinding` (interface): interface SequenceDirectorBinding extends SequenceState — The live playback state plus bound controls returned by {@link useSequenceDirector}.
|
|
484
750
|
- `SettingsActionView` (interface): interface SettingsActionView — A resolved game-state action — `run` is already bound to the game context and closes the menu.
|
|
485
751
|
- `SettingsCategoryView` (interface): interface SettingsCategoryView — A settings menu category with its rows and keybinds, ready to render.
|
|
486
752
|
- `SettingsController` (interface): interface SettingsController — The live settings controller — every category/row/keybind/action plus open-state. Render it any way you like or drive the engine menu.
|
|
@@ -488,8 +754,11 @@
|
|
|
488
754
|
- `SettingsKeybindRow` (interface): interface SettingsKeybindRow — One rebindable action row rendered in the controls settings category.
|
|
489
755
|
- `SettingsProvider` (function): function SettingsProvider({ store, children }: { store: SettingsStore; children: ReactNode }): React.JSX.Element — ⚠ undocumented
|
|
490
756
|
- `SettingsRow` (interface): interface SettingsRow — One editable setting rendered in a settings menu category.
|
|
491
|
-
- `SettingsTrigger` (function): function SettingsTrigger({ className, children, label = "Settings", }: { className?: string; children?: ReactNode; label?: string; }): React.JSX.Element | null — Inline settings entry — drop it anywhere in your game's menu or HUD; it opens the themed settings menu. Headless: pass `className`
|
|
757
|
+
- `SettingsTrigger` (function): function SettingsTrigger({ className = SETTINGS_TRIGGER_CLASSNAME, children, label = "Settings", }: { className?: string; children?: ReactNode; label?: string; }): React.JSX.Element | null — Inline settings entry — drop it anywhere in your game's menu or HUD; it opens the themed settings menu. Headless: pass `className` only when overriding the default HudTheme skin; pass `children` to replace the gear glyph. Renders nothing when the game has no settings to show, so it never leaves a dead button behind.
|
|
492
758
|
- `ShieldBar` (const): const ShieldBar: (props: AtomicBarProps) => React.JSX.Element — Absorb/armor shield overlay.
|
|
759
|
+
- `ShopGrid` (function): function ShopGrid({ shop, wallet, onWalletChange, theme, currencyIcons, iconFor, showSell = false, walletCurrencies, title = "Shop", labelFor, minCardWidth = "140px", className, style, }: ShopGridProps): ReactNode — A drop-in vendor/shop grid: item cards (icon, name, price with a currency glyph, stock count or "∞") over a caller-owned wallet, plus a wallet balance readout. Each card's Buy button disables when the wallet cannot afford it (`shop.canAfford`) or the item is sold out; an optional Sell button appears for entries with a `sellPrice`. Buying/selling routes through the core shop model and hands the debited/credited wallet back via `onWalletChange` — the component never owns the wallet. Purely token-driven presentation (shared `--jg-*` HudTheme tokens, reskinnable via {@link ShopGridTheme}); `kind` and `currency` are free strings the game styles, never interpreted.
|
|
760
|
+
- `ShopGridProps` (interface): interface ShopGridProps — Props for {@link ShopGrid}.
|
|
761
|
+
- `ShopGridTheme` (interface): interface ShopGridTheme — Reskin tokens for {@link ShopGrid}. Falls back to shared `--jg-*` HudTheme tokens, then neutral defaults.
|
|
493
762
|
- `SignOutButton` (function): function SignOutButton({ className, children, }: { className?: string; children?: ReactNode; }): React.JSX.Element | null — ⚠ undocumented
|
|
494
763
|
- `SkillCheckBar` (function): function SkillCheckBar({ config, startedAt, className, trackClassName, zoneClassName, markerClassName, renderStatus, }: { config: SkillCheckConfig; startedAt: number; className?: string; trackClassName?: string; zoneClassName?: string; markerClassName?: string; renderStatus?: (result: SkillCheckResu… — ⚠ undocumented
|
|
495
764
|
- `SlotGrid` (function): function SlotGrid({ inventoryId, className, renderSlot, }: { inventoryId: string; className?: string; renderSlot?: (slot: InventorySlot, index: number) => ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
@@ -508,8 +777,22 @@
|
|
|
508
777
|
- `StatMeter` (function): function StatMeter({ instanceId, statId, className, fillClassName, }: { instanceId: string; statId: string; className?: string; fillClassName?: string; }): React.JSX.Element | null — A headless, unstyled stat meter — an accessible `role="progressbar"` you paint entirely through `className`/`fillClassName`. This is the class-hook primitive for teams supplying their own CSS; for a batteries-included themed bar use the atomic, token-styled components in `@jgengine/react/bars` (`HealthBar`, `ShieldBar`, …). Renamed from `HealthBar` in #1033 so the purpose-named atomic bar owns that name and no two components share it.
|
|
509
778
|
- `StatRow` (interface): interface StatRow — One derived-stat row. `group` optionally buckets rows under a small header.
|
|
510
779
|
- `StatTone` (type): type StatTone = keyof typeof TONES — A stat tone — picks the bar's color ramp.
|
|
780
|
+
- `StatusEffectBar` (function): function StatusEffectBar({ effects, size = 44, gap = 8, iconFor, colorFor, schoolFor, labelFor, showTimer = true, ringWidth = 3, className, style, }: StatusEffectBarProps): ReactNode — A horizontal timeline of active status effects — one countdown-ring icon per effect. Presentation only and pure over its `effects` prop, so it renders straight off the status model's snapshot. `kind` is a free string the game styles (icon / color / label); the component never interprets buff-vs-debuff semantics. Ring, track, and frame read `HudTheme` tokens, so a theme change reskins the whole row.
|
|
781
|
+
- `StatusEffectBarProps` (interface): interface StatusEffectBarProps — Props for {@link StatusEffectBar}.
|
|
782
|
+
- `StatusIconResolver` (type): type StatusIconResolver = (kind: string) => GameIconName | ReactNode | null — `StatusEffectBar` (#status-effect-hud): a drop-in timeline HUD row that renders active buffs/debuffs as painted icons, each wrapped in a radial countdown ring and a stack-count badge, driven straight off the engine's existing status model (`StatusInstance` → `StatusEffectView`). A game passes its live effect views and gets a polished, reskinnable effect bar — no re-deriving ring math or timers. `kind` is a free string the game styles: the component never interprets buff-vs-debuff semantics, it only maps `kind` to an icon/color/label the game can fully override. Ring, track, and frame read `HudTheme` tokens (`--jg-accent`, `--jg-slot-*`), so a theme change reskins the whole row.
|
|
783
|
+
- `StreetGeometryPreview` (function): function StreetGeometryPreview({ className }: { className?: string }): React.JSX.Element — Deterministic close-up gallery of the shared road/junction mesh seam.
|
|
511
784
|
- `Suit` (type): type Suit = "clubs" | "diamonds" | "hearts" | "spades" — The four French-deck suits.
|
|
785
|
+
- `TalentIcon` (type): type TalentIcon = GameIconName | ReactNode | null — How a node id resolves to display art: a built-in {@link GameIconName}, any node, or `null` for the default.
|
|
786
|
+
- `TalentTree` (function): function TalentTree<TStat extends string = string>({ view: viewProp, nodes, tree, onLearn, icon, label, branchLabel, title = "Talents", variation = "themed", nodeSize = 54, columnGap = 30, tierGap = 46, showPoints = true, className, style, }: TalentTreeProps<TStat>): ReactNode — Drop-in talent / skill-tree widget over the existing progression model (`@jgengine/core/game/talents` + its `talentTreeView` selector). The game passes its node definitions and a live `createTalentTree` instance; the widget lays nodes out by branch column and prerequisite-depth tier, draws SVG prerequisite edges, styles each node learned/available/locked/maxed, shows an icon + rank badge, and calls `onLearn(nodeId)` when the player clicks a node that is currently allocatable. All layout, edge-drawing, and eligibility come from the model/selector — the widget never re-derives topology. Unskinned and HudTheme-token driven; node ids/branches are opaque game data the game supplies icons and labels for.
|
|
787
|
+
- `TalentTreeProps` (interface): interface TalentTreeProps<TStat extends string = string> — Props for {@link TalentTree}.
|
|
788
|
+
- `TimerFormat` (type): type TimerFormat = "mm:ss" | "m:ss.d" | "ss.d" — Digital text format for a timer readout.
|
|
789
|
+
- `TimerReadout` (function): function TimerReadout({ timer, id, source = "auto", format = "mm:ss", placeholder = "--:--", active = true, className, style, }: TimerReadoutProps): ReactNode — A live digital timer readout (mm:ss / m:ss.d) driven off a {@link TimerSet}. It re-reads every frame and formats remaining or elapsed time — a round clock, a respawn countdown, or an ability charge, all the same widget. HudTheme-skinned via `--jg-bar-text`; reskin with `style` or the theme tokens.
|
|
790
|
+
- `TimerReadoutProps` (interface): interface TimerReadoutProps — Props for {@link TimerReadout}.
|
|
791
|
+
- `TimerReadoutSource` (type): type TimerReadoutSource = "auto" | "remaining" | "elapsed" — Which value a readout leads with. `"auto"` follows the timer's direction — remaining for a countdown, elapsed for a countup charge.
|
|
792
|
+
- `TimerRing` (function): function TimerRing({ timer, id, size = 72, thickness = 8, mode = "fill", color = "var(--jg-accent, #38bdf8)", trackColor = "var(--jg-bar-track, rgba(148,163,184,0.25))", children, active = true, className, style, }: TimerRingProps): ReactNode — A radial charge/cooldown ring driven off a {@link TimerSet}'s `progress01`. Re-reads every frame and sweeps an SVG arc as the timer advances — ability charge, cooldown wipe, respawn ring, capture progress, all the same widget. `mode` chooses filling vs. draining; center `children` can hold a readout. HudTheme-skinned via `--jg-accent` / `--jg-bar-track`.
|
|
793
|
+
- `TimerRingProps` (interface): interface TimerRingProps — Props for {@link TimerRing}.
|
|
512
794
|
- `ToastStack` (function): function ToastStack({ action, limit = 4, className, renderToast, }: { action: string; limit?: number; className?: string; renderToast?: (entry: FeedEntry, index: number) => ReactNode; }): React.JSX.Element | null — Render `ctx.game.feed`'s entries for `action` as a newest-first toast stack — the feed-backed sibling of `@jgengine/core/game/toasts`' `createToastQueue`. Reach for this when the message source is already an engine event bound onto `ctx.game.feed` (kill feed, quest updates, loot log); reach for a `createToastQueue` when the game raises ad-hoc messages that need their own TTL independent of the feed's ring buffer.
|
|
795
|
+
- `Trans` (function): function Trans({ k, params }: { k: string; params?: TParams }): ReactNode — Render a translated message inline: `<Trans k="hud.score" params={{ value }} />`.
|
|
513
796
|
- `UseActionBarOptions` (interface): interface UseActionBarOptions — Options for {@link useActionBar}.
|
|
514
797
|
- `UseAxisChannelResult` (interface): interface UseAxisChannelResult — ⚠ undocumented
|
|
515
798
|
- `UsePanelsOptions` (interface): interface UsePanelsOptions — Options for {@link usePanels}.
|
|
@@ -521,13 +804,23 @@
|
|
|
521
804
|
- `VoiceRoster` (function): function VoiceRoster({ voice, className, participantClassName, renderParticipant, }: { voice: VoiceState; className?: string; participantClassName?: string; renderParticipant?: (participant: VoiceParticipant, gain: number) => ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
522
805
|
- `VoiceState` (interface): interface VoiceState — ⚠ undocumented
|
|
523
806
|
- `WaveBanner` (function): function WaveBanner({ wave, label = "Wave", subtitle, style, className, }: { wave: number | string; label?: string; subtitle?: ReactNode; style?: CSSProperties; className?: string; }): React.JSX.Element — A wave / round banner — a bold centered pill for "WAVE 3" style callouts, with an optional subtitle (enemies remaining, timer). Pure display: pass the current `wave` and whatever subtitle you track.
|
|
807
|
+
- `WaveHud` (function): function WaveHud({ runner, theme, variation = "plate", width = 260, className, style }: WaveHudProps): ReactNode — A drop-in wave/spawn HUD panel over a {@link WaveRunner}: a big "WAVE N" label, a wave-progress bar (the shared {@link ExperienceBar}), and the live spawned / total, budget, and alert readouts — the visible face of "the brain behind WAVE 3". It subscribes to the runner and re-renders on change; the game drives the runner's clock. Reskin with {@link WaveHudTheme} and the shared HudTheme bar tokens. When the final wave finishes it shows a "WAVES CLEARED" state. Presentation only: the schedule, budget, and RNG live in the core model, and spawn `kind`s are never read.
|
|
808
|
+
- `WaveHudProps` (interface): interface WaveHudProps — Props for {@link WaveHud}.
|
|
809
|
+
- `WaveHudTheme` (interface): interface WaveHudTheme — Reskin tokens for {@link WaveHud}. All optional; each falls back to a sensible default.
|
|
810
|
+
- `WaypointArrow` (function): function WaypointArrow({ relative, distance, label, formatDistance = (value) => `${Math.round(value)}m`, size = 44, color = "#f59e0b", className, style, }: WaypointArrowProps): ReactNode — On-screen guide arrow to the tracked waypoint — a HUD compass needle rotated by the facing-relative bearing, with an optional label and distance readout. Pair with `WaypointStore.guidance(playerXZ, facingYaw)`.
|
|
811
|
+
- `WaypointArrowProps` (interface): interface WaypointArrowProps — Props for {@link WaypointArrow}.
|
|
812
|
+
- `WaypointMarkerTheme` (interface): interface WaypointMarkerTheme — Reskin tokens for {@link WaypointMarkers}. Per-`kind` color layers on top via `kindColors`.
|
|
813
|
+
- `WaypointMarkers` (function): function WaypointMarkers({ entries, project, viewport, distanceOf, distanceFormat, theme, kindColors, margin = 28, showPinLabels = true, className, style, }: WaypointMarkersProps): ReactNode — Off-screen objective / waypoint markers: an absolutely-positioned overlay that turns a set of world waypoints into on-screen pins and off-screen directional arrows. For each waypoint it calls the caller's `project` to get a screen point, then {@link layoutScreenMarker} to decide: an in-view target renders a pin (and optional label) at its projected spot; an off-screen or behind-camera target renders an arrow clamped to the viewport edge, rotated to point the way, with an optional distance label from `distanceOf`. Color comes from `theme` plus a per-`kind` `kindColors` map the game owns — the model never interprets `kind`. Presentation only: tracking, projection, and distance are all caller-supplied.
|
|
814
|
+
- `WaypointMarkersProps` (interface): interface WaypointMarkersProps — Props for {@link WaypointMarkers}.
|
|
524
815
|
- `WeaponSlots` (function): function WeaponSlots(props: SlotGridProps): React.JSX.Element — Weapon loadout slots.
|
|
525
816
|
- `Window` (function): function Window({ title, ariaLabel, closable = true, onClose, x, y, onMove, z, width, variation, shape, className, style, bodyStyle, children, }: { title: ReactNode; ariaLabel?: string; closable?: boolean; onClose?: () => void; /** Initial (uncontrolled) or current (controlled, with `onMove`) x posi… — A single standalone window — title bar, close button, and title-bar drag over {@link HudFrame} chrome — usable without the {@link usePanels} manager for a one-off dialog. Position is uncontrolled (seeded by `x`/`y`) unless both `x`/`y` and `onMove` are supplied, in which case the caller owns placement. Accessible: `role="dialog"` with an `aria-label` and a focusable close button.
|
|
526
817
|
- `WorldBrowser` (function): function WorldBrowser({ listings, onJoin, className, rowClassName, joinClassName, emptyState, renderListing, }: { listings: readonly SessionListing[]; onJoin: (listing: SessionListing) => void; className?: string; rowClassName?: string; joinClassName?: string; emptyState?: ReactNode; renderListing?:… — ⚠ undocumented
|
|
527
818
|
- `WorldBrowserState` (interface): interface WorldBrowserState — ⚠ undocumented
|
|
528
819
|
- `WorldInviteToast` (function): function WorldInviteToast({ className, acceptClassName, declineClassName, onAccepted, renderInvite, }: { className?: string; acceptClassName?: string; declineClassName?: string; onAccepted: (target: WorldInviteTarget) => void; renderInvite?: (invite: WorldInvite) => ReactNode; }): React.JSX.Element … — ⚠ undocumented
|
|
529
|
-
- `WorldMap` (function): function WorldMap({ markers, bounds, player, facingYaw = 0, fog, background, width = 520, height, kindStyles = DEFAULT_MARKER_KINDS, routes, zones, cellStates, onWorldClick, className, title = "World Map", onClose, }: WorldMapProps): ReactNode — Full-bounds top-down world map (the "press M" overlay): baked terrain background, reveal-on-event fog, all markers with labels, and the player. Rectangular linear projection over the supplied world `bounds`.
|
|
820
|
+
- `WorldMap` (function): function WorldMap({ markers, bounds, player, facingYaw = 0, fog, background, width = 520, height, kindStyles = DEFAULT_MARKER_KINDS, routes, zones, cellStates, onWorldClick, className, title = "World Map", onClose, }: WorldMapProps): ReactNode — Full-bounds top-down world map (the "press M" overlay): baked terrain background, reveal-on-event fog, all markers with labels, and the player. Rectangular linear projection over the supplied world `bounds`. Framed panel wrapper over {@link WorldMapSurface}.
|
|
530
821
|
- `WorldMapProps` (interface): interface WorldMapProps — ⚠ undocumented
|
|
822
|
+
- `WorldMapSurface` (function): function WorldMapSurface({ markers, bounds, player, facingYaw = 0, fog, background, width = 520, height, kindStyles = DEFAULT_MARKER_KINDS, routes, zones, cellStates, onWorldClick, canvasWidth, canvasHeight, viewport = IDENTITY_VIEWPORT, style, }: WorldMapSurfaceProps): ReactNode — The bare top-down map `<svg>` shared by {@link WorldMap} (framed panel) and {@link FullscreenMap} (pan/zoom overlay): baked terrain background, fog, map layers, markers with labels, and the player arrow, drawn under an optional viewport transform. Rectangular linear projection over the world `bounds`.
|
|
823
|
+
- `WorldMapSurfaceProps` (interface): interface WorldMapSurfaceProps — Props for {@link WorldMapSurface}.
|
|
531
824
|
- `abilityKitNeedsHeartbeat` (function): function abilityKitNeedsHeartbeat(kit: AbilityKit, resourceAvailable?: number): boolean — ⚠ undocumented
|
|
532
825
|
- `actionBarKeyAction` (function): function actionBarKeyAction(actions: readonly ResolvedAction[], focusedId: string | null, columns: number, key: string, options?: { wrap?: boolean }): ActionBarKeyResult — Pure keyboard/controller resolver for an action bar: arrows/Home/End move grid focus, Enter/Space activate the focused action, and any other single key routes through {@link actionByHotkey}. Returns the resulting intent without touching the DOM, so it unit-tests headless and `useActionBar` is a thin shell over it.
|
|
533
826
|
- `actionFromAbilitySlot` (function): function actionFromAbilitySlot(slot: AbilitySlotSnapshot, extra?: Partial<ActionDef> & { resourceId?: string }): ActionDef — Composable React renderers over the headless action view model (`@jgengine/core/ui/actionModel`) — the data/renderer/chrome split for an RTS command card, an ability action bar, a build menu, or a radial. `useActionBar` is the DATA/HOOK layer (resolution + focus/hover/keyboard/hotkey), `ActionBarChrome` is the composable RENDERER (swap `renderItem` for custom chrome, or ignore it and consume the model directly for a radial), and `ActionBar` is the batteries-included default. A game swaps renderer or chrome without forking the logic. Layout, dimensions, hotkeys, and catalog-id mapping stay caller-owned.
|
|
@@ -538,16 +831,24 @@
|
|
|
538
831
|
- `createHeldKeyTracker` (function): function createHeldKeyTracker(target: HeldKeyEventTarget): { isDown: (code: string) => boolean; dispose: () => void; } — ⚠ undocumented
|
|
539
832
|
- `defaultEquipLayout` (function): function defaultEquipLayout(items: Partial<Record<DefaultEquipSlotId, SlotItem | null>> = {}): EquipSlot[] — A sensible default paperdoll arrangement — worn armor down the left flank, held gear and jewelry down the right — that the game fills by passing worn items keyed by slot id. Every id is optional; unfilled slots render empty. Games that need a different slot set pass their own {@link EquipSlotLayout}.
|
|
540
833
|
- `defaultHudTheme` (const): const defaultHudTheme: HudTheme — Default theme tokens for previews/scaffold — not a finished game look; author a custom theme.
|
|
834
|
+
- `deriveHudTheme` (function): function deriveHudTheme(seed: HudThemeSeed): HudTheme — Derives a coherent full theme from an accent/surface pair — shades, edges, dim text, frames, bar troughs, and slots all fall out of the seed, so a game gets one consistent look across the `packages/react` primitives and the `registry/jgengine` blocks without naming 50 tokens. Hex seeds only (`#rgb` or `#rrggbb`).
|
|
541
835
|
- `eventMeterNeedsHeartbeat` (function): function eventMeterNeedsHeartbeat(meter: EventMeter, previous: EventMeterView | null): boolean — True when `meter`'s value/fraction/tier/ready diverge from `previous` — the re-render check `useEventMeter` polls on its heartbeat.
|
|
836
|
+
- `formatTimerMs` (function): function formatTimerMs(ms: number, format: TimerFormat = "mm:ss"): string — Format a millisecond duration as digital timer text — `mm:ss` (default), `m:ss.d` (with tenths), or `ss.d` (seconds + tenths). Negative inputs clamp to zero. No genre meaning: the same helper serves a round clock, a respawn countdown, or an ability charge readout.
|
|
542
837
|
- `guestIdentity` (function): function guestIdentity(seed?: string): IdentitySource — ⚠ undocumented
|
|
838
|
+
- `hudTheme` (function): function hudTheme(overrides: HudThemeOverrides): HudTheme — Builds a full {@link HudTheme} from per-group partials, filling the rest from {@link defaultHudTheme}. Reach for this when a game wants to name exact values; use {@link deriveHudTheme} when a seed color pair is enough.
|
|
543
839
|
- `hudThemeVars` (function): function hudThemeVars(theme: HudTheme): CSSProperties — Emits the CSS custom properties for a theme — spread onto any HUD ancestor to re-skin the subtree.
|
|
544
840
|
- `hudVisibleInPhase` (function): function hudVisibleInPhase(showDuring: readonly GamePhase[] | undefined, phase: GamePhase): boolean — Whether a HUD element opted into `showDuring` is visible in the current phase; `undefined` = always visible (default).
|
|
545
841
|
- `isRedSuit` (function): function isRedSuit(suit: Suit): boolean — True for the red suits (hearts, diamonds).
|
|
546
842
|
- `latestChatBubbles` (function): function latestChatBubbles(messages: readonly ChatMessage[], nowMs: number, ttlMs: number): ChatBubble[] — ⚠ undocumented
|
|
843
|
+
- `layoutEntityFrames` (function): function layoutEntityFrames<E extends EntityFrameEntry>(entries: readonly E[], project: ProjectEntity, options: EntityFrameLayoutOptions = {}): EntityFramePlacement<E>[] — Pure layout core: projects each entry, drops the ones behind the camera, off-screen (when `viewport` is set), or beyond `maxCount`, and returns the survivors sorted farthest-first so nearer frames render last (on top). Stable for equal depths via `id`. No React, no DOM — unit-testable in isolation.
|
|
844
|
+
- `layoutFloatingText` (function): function layoutFloatingText(views: readonly FloatingTextView[], project: ProjectEntity, options: FloatingTextLayoutOptions = {}): FloatingTextPlacement[] — Pure layout core: projects each view, drops the ones behind the camera or (when `viewport` is set) off-screen, and returns the survivors sorted farthest-first so nearer text paints on top. No React, no DOM — unit-testable.
|
|
547
845
|
- `localPlayerEntity` (function): function localPlayerEntity(ctx: GameContext): SceneEntity | null — ⚠ undocumented
|
|
548
846
|
- `panelKeyAction` (function): function panelKeyAction(defs: readonly PanelDef[], state: PanelState, event: { code?: string; key?: string }): PanelKeyResult — Pure keybind resolver for a panel set: ESC resolves to `closeTop` when a closable window is open, and any other key routes through {@link panelByHotkey} (trying `code` then `key`) to a `toggle`. Returns the intent without touching the DOM, so it unit-tests headless and `usePanels` is a thin shell over it.
|
|
847
|
+
- `previewFixtureNames` (function): function previewFixtureNames(): string[] — Sorted list of registered fixture names, for discovery/listing.
|
|
848
|
+
- `relativeSavedAt` (function): function relativeSavedAt(savedAt: number, nowMs = Date.now()): string — Turn a `savedAt` timestamp into a compact relative label ("just now", "4m ago", "2d ago"). Presentation-only helper — the model stores raw ms.
|
|
549
849
|
- `resolveDialogueInvoke` (function): function resolveDialogueInvoke(choice: DialogueChoice, result: CheckResult | null): { command: string; args?: unknown } | null — ⚠ undocumented
|
|
550
850
|
- `resolveHudTheme` (function): function resolveHudTheme(theme?: HudThemePreset | HudTheme): HudTheme — Resolves a preset name (or a full theme) to a `HudTheme`; falls back to the default theme.
|
|
851
|
+
- `resolvePreviewFixture` (function): function resolvePreviewFixture(name: string): PreviewFixture | undefined — Resolve a fixture by name, or `undefined` when it is not registered.
|
|
551
852
|
- `runDialogueChoice` (function): function runDialogueChoice(commands: { run(name: string, input?: unknown): unknown }, choice: DialogueChoice, result: CheckResult | null): void — Route a {@link DialogueBox} choice through the `features.dialogue` bridge: resolve the choice's invoke (honoring a skill-check `result`), run that command, and otherwise close the dialogue — the write side that replaces a per-game `onChoice` that hand-rolls `resolveDialogueInvoke` + `dialogue.close`.
|
|
552
853
|
- `schoolForAction` (function): function schoolForAction(action: string): IconSchool — Infers an {@link IconSchool} from an action id (keyword match); `neutral` when nothing matches.
|
|
553
854
|
- `schoolForItem` (function): function schoolForItem(itemId: string): IconSchool — Infers an {@link IconSchool} from an item id (keyword match); `neutral` when nothing matches.
|
|
@@ -555,17 +856,29 @@
|
|
|
555
856
|
- `treatedItemIcon` (function): function treatedItemIcon(itemId: string, options: { size?: number; count?: number; keycap?: string } = {}): ReactNode — Maps an item id to a treated icon — resolves a `GameIcon` glyph and an inferred school.
|
|
556
857
|
- `useAbilitySlot` (function): function useAbilitySlot(kit: AbilityKit, slotId: string, resourceAvailable?: number, options?: AbilitySlotBindingOptions): AbilitySlotSnapshot | null — ⚠ undocumented
|
|
557
858
|
- `useAbilitySlots` (function): function useAbilitySlots(kit: AbilityKit, resourceAvailable?: number, options?: AbilitySlotBindingOptions): AbilitySlotSnapshot[] — ⚠ undocumented
|
|
859
|
+
- `useAccessibility` (function): function useAccessibility(): AccessibilityContextValue — Read the live accessibility state + its store; throws without an {@link AccessibilityProvider} above.
|
|
860
|
+
- `useAchievements` (function): function useAchievements(tracker: AchievementTracker): readonly AchievementView[] — Subscribe a component to an achievement tracker's live view list. The list keeps a stable identity between changes, so this re-renders only on unlock or progress — not every frame.
|
|
558
861
|
- `useActionBar` (function): function useActionBar(defs: readonly ActionDef[], options?: UseActionBarOptions): ActionBarModel — The DATA/HOOK layer: resolve `defs` into a live view model with focus, hover, keyboard grid navigation, and hotkey activation. Rendering-agnostic — feed the returned model to {@link ActionBarChrome}, or read it directly to lay out a radial or a bespoke card.
|
|
559
862
|
- `useActivePrompt` (function): function useActivePrompt<T extends PositionedPrompt>(prompts?: readonly T[]): T | null — ⚠ undocumented
|
|
560
863
|
- `useAuthedPlayer` (function): function useAuthedPlayer(options?: { guestSeed?: string }): PlayerIdentity | null — ⚠ undocumented
|
|
864
|
+
- `useAutoScroll` (function): function useAutoScroll<T extends HTMLElement>(dep: unknown): React.RefObject<T | null> — Pin a scrollable element to its bottom whenever `dep` changes (typically a length or the list itself). Attach the returned ref to the scroll container. Owns the log/chat/console scroll-to-bottom effect so panels don't hand-roll it.
|
|
561
865
|
- `useAxisChannel` (function): function useAxisChannel(config: AxisChannelConfig): UseAxisChannelResult — Wires useHeldKeys into a fresh AxisChannel, ready for a per-frame `channel.sample(dt, isDown)`. The channel is recreated when `config` identity changes, so pass a stable config (useMemo/module constant at the call site) unless a rebind is intended.
|
|
866
|
+
- `useCameraShake` (function): function useCameraShake(controller: CameraShakeController, animate = true): CameraShakeReadout — Subscribe to a camera-shake controller and re-render on every change (add / decay / clear). Optionally drives `update()` on an animation frame so the trauma meter bleeds down live even when no game loop ticks the controller. Returns the current trauma + kind for a HUD readout.
|
|
562
867
|
- `useChat` (function): function useChat(channelId: string, options?: { limit?: number }): ChatMessage[] — ⚠ undocumented
|
|
563
868
|
- `useChatBubbles` (function): function useChatBubbles(options?: ChatBubblesOptions): readonly ChatBubble[] — ⚠ undocumented
|
|
869
|
+
- `useCoachMarks` (function): function useCoachMarks(sequence: CoachMarkSequence): CoachMarkView | null — Subscribe to a coach-mark sequence and re-render on every change, returning the current step view (or `null` when the tour is complete or waiting on a gate).
|
|
870
|
+
- `useComboMeter` (function): function useComboMeter(meter: ComboMeter, animate = true): ComboMeterView — Subscribe to a combo meter and re-render it each animation frame so the decay window bar drains live, returning the pooled view to draw right now. Reading the view each frame advances the meter's clock and fires window expiry, so a combo that times out visibly drops even with no further hits. The returned object is the model's pooled view — read its fields immediately, do not retain it.
|
|
564
871
|
- `useCurrency` (function): function useCurrency(currencyId: string): number — ⚠ undocumented
|
|
872
|
+
- `useDamageDirection` (function): function useDamageDirection(tracker: DamageDirectionTracker): readonly DamageIndicator[] — Subscribe to a damage-direction tracker and animate. Because indicators fade continuously on a clock (not just on discrete events), this drives a `requestAnimationFrame` loop while any indicator is live and stops when the screen is clear, then wakes again on the next hit. Returns the tracker's current `active()` array (reused between frames — copy if you retain it).
|
|
873
|
+
- `useDebouncedCommit` (function): function useDebouncedCommit<T>(value: T, commit: (value: T) => void, delayMs = 180): DebouncedCommit<T> — See {@link DebouncedCommit}. `commit` and `delayMs` may change between renders (kept in refs); the binding identity stays stable except when `value` (the local mirror) changes.
|
|
874
|
+
- `useDialogueRun` (function): function useDialogueRun(run: DialogueRun): DialogueGraphView | null — Subscribe to a {@link DialogueRun} and re-render on every advance / jump / reset, returning the current node view (or `null` if the run's node id is unknown).
|
|
875
|
+
- `useDomEvent` (function): function useDomEvent<E>(resolveTarget: () => DomEventTarget | null, type: string, handler: (event: E) => void, options?: { capture?: boolean; passive?: boolean }): void — Attach a DOM event listener with automatic cleanup. `resolveTarget` runs inside the effect, so `() => window` and ref-reading resolvers are SSR-safe; return null to skip attaching. The handler is kept in a ref, so a fresh closure per render never re-binds the listener. Re-binds only when `type` or `options.capture`/`options.passive` change.
|
|
565
876
|
- `useDragLayer` (function): function useDragLayer<T>(options?: { onDrop?: (info: DropInfo<T>) => void; }): DragLayer<T> — ⚠ undocumented
|
|
566
877
|
- `useEntityChatBubble` (function): function useEntityChatBubble(instanceId: string, options?: ChatBubblesOptions): ChatBubble | null — ⚠ undocumented
|
|
567
878
|
- `useEntityStat` (function): function useEntityStat(instanceId: string, statId: string): StatValue | null — ⚠ undocumented
|
|
568
879
|
- `useEventMeter` (function): function useEventMeter(meter: EventMeter, options?: AbilitySlotBindingOptions): EventMeterView — Bind a `createEventMeter` (`@jgengine/core/stats/eventMeter`) heat/streak gauge to a component — the react-render half of the ult/adrenaline and streak/combo meters (`event-meter` capability) that lets a HUD gauge re-render on tick without the game hand-rolling a `useEffect`/`setInterval` heartbeat around `meter.value()`.
|
|
880
|
+
- `useEventTicker` (function): function useEventTicker(ticker: EventTicker, animate = true): EventTickerView[] — Subscribe to an event ticker and re-render it on an animation frame (unless the game already ticks it), returning the live entries newest-first with `fade` applied. Driving the frame loop is what makes entries visibly fade and drop as they age out.
|
|
881
|
+
- `useFastTravel` (function): function useFastTravel<TMeta = unknown>(network: FastTravelNetwork<TMeta>): FastTravelNetwork<TMeta> — Subscribe a component to a fast-travel network's discovery changes. Returns the network unchanged; the hook only forces a re-render when a point is discovered or the network is restored, so callers can read `destinations`/`list` in render.
|
|
569
882
|
- `useFeed` (function): function useFeed({ action, limit }: { action: string; limit?: number }): FeedEntry[] — ⚠ undocumented
|
|
570
883
|
- `useFog` (function): function useFog(fog: FogField): ReturnType<FogField["cells"]> — ⚠ undocumented
|
|
571
884
|
- `useFriendRequests` (function): function useFriendRequests(): FriendRequestEntry[] — ⚠ undocumented
|
|
@@ -584,6 +897,8 @@
|
|
|
584
897
|
- `useHudLayout` (function): function useHudLayout(options?: { storageKey?: string; snap?: number; locked?: boolean; /** * Scene-document `ui` section — source of truth for panel placement/size. * When provided, hydrates the layout store (and wins over legacy localStorage). */ documentUi?: EditorUiDocument; /** * When true (def… — Layout state for `HudCanvas` — panel placements, edit-mode drag/resize, and per-game persistence.
|
|
585
898
|
- `useHudLayoutPersist` (function): function useHudLayoutPersist(): HudLayoutPersist | null — Injected panel-commit port, or `null` when no host has provided one.
|
|
586
899
|
- `useHudViewport` (function): function useHudViewport(): HudViewportContextValue | null — ⚠ undocumented
|
|
900
|
+
- `useI18n` (function): function useI18n(): I18n — Read the current {@link I18n} from context; throws when no {@link I18nProvider} is above.
|
|
901
|
+
- `useInteractionPrompt` (function): function useInteractionPrompt(registry: PromptRegistry, playerPosition: PromptPoint): PositionedPrompt | null — Subscribe to a {@link PromptRegistry} and re-`resolve` it whenever the player moves, returning the prompt to draw right now — or `null` when the player is out of range of every interactable. The registry notifies only on active-prompt *changes*, so this re-renders on transitions rather than every frame the hero moves. Feed it the player's `{ x, z }` position each frame; identical positions do no work.
|
|
587
902
|
- `useInventory` (function): function useInventory(inventoryId: string): readonly InventorySlot[] — ⚠ undocumented
|
|
588
903
|
- `useInventoryGrid` (function): function useInventoryGrid(inventoryId: string): InventoryGridBinding — Binds a live inventory to a HUD grid: `slots` from {@link useInventory}, and `move`/`split` that run the built-in `inventory.move`/`inventory.split` commands (which notify, so the grid re-renders).
|
|
589
904
|
- `useKeyedStore` (function): function useKeyedStore<T>(handle: KeyedStoreHandle<T>, id: string): T — Subscribe a component to one owner's slot of a typed keyed-family store defined with `defineKeyedStore`. Returns the current value for `id` (or the definition's initial before any write for that id), re-rendering only when that owner's slot changes — the cast-free, boilerplate-free replacement for a hand-written `useGameStore((ctx) => ctx.game.store.get(`prefix:${id}`) as T)`.
|
|
@@ -591,38 +906,70 @@
|
|
|
591
906
|
- `useLeaderboard` (function): function useLeaderboard(stat: string, options: { scope: LeaderboardScope; limit?: number }): { userId: string; value: number }[] — ⚠ undocumented
|
|
592
907
|
- `useLiveMarkers` (function): function useLiveMarkers(rebuild: (markers: MarkerSet, ctx: GameContext) => void, options?: { intervalMs?: number; deps?: DependencyList }): MarkerSet — A self-ticking {@link MarkerSet} kept in sync with the live scene: on a heartbeat (default 100ms, and once immediately) it clears the set and calls `rebuild(markers, ctx)` to repopulate it from the current scene, so a HUD map never hand-rolls a `setInterval` + `markers.clear()` + rescan. Each heartbeat also re-renders the calling component, so player-centered props derived from the live scene each tick (`center`, `facingYaw`, zone name) stay fresh — this fully subsumes the hand-rolled ticker, not just the marker rebuild. The set is stable across renders and re-seeded whenever `ctx`, `intervalMs`, or the supplied `deps` change. SSR-safe: the heartbeat only arms when `window` is available.
|
|
593
908
|
- `useLocalPlayerDead` (function): function useLocalPlayerDead(healthStatId = "health"): boolean — ⚠ undocumented
|
|
909
|
+
- `useLocale` (function): function useLocale(): Locale — Subscribe to the active locale — re-renders on `setLocale`.
|
|
594
910
|
- `useMarkers` (function): function useMarkers<TMeta = unknown>(markers: MarkerSet<TMeta>): readonly MapMarker<TMeta>[] — Subscribe to a native marker set or external marker source, or read a static marker array.
|
|
911
|
+
- `useModalStack` (function): function useModalStack(stack: ModalStack): ModalStackView — Subscribe to a modal stack and re-render on every change, returning the active modal and depth.
|
|
595
912
|
- `useNearestWorldItem` (function): function useNearestWorldItem(radius: number): WorldItemRecord | null — Nearest ground item within `radius` of the local player — drives a pickup prompt/highlight.
|
|
913
|
+
- `useNotifications` (function): function useNotifications<TMeta = unknown>(store: NotificationStore<TMeta>): readonly NotificationEntry<TMeta>[] — Subscribe to a notification store's live list.
|
|
914
|
+
- `useObjectiveBanner` (function): function useObjectiveBanner(controller: ObjectiveBannerController, animate = true): ObjectiveBannerView | null — Subscribe to a banner controller, drive its clock on an animation frame (unless the game already ticks it), and return the banner to draw right now — or `null` when idle. Re-renders every frame while a banner is animating.
|
|
596
915
|
- `useOpenDialogueId` (function): function useOpenDialogueId(): string | null — The id of the dialogue `ctx.game.dialogue` (or a `talkable(id)` prompt) currently has open, or `null`. The read side of the `features.dialogue` bridge — a panel looks the id up in its own dialogue catalog and renders {@link DialogueBox}, with no per-game open/close store.
|
|
597
916
|
- `useOptionalGameContext` (function): function useOptionalGameContext(): GameContext | null — The game context if a `GameProvider` is present, otherwise `null` — for chrome that may render outside a running game (showcases, previews).
|
|
598
917
|
- `useOptionalGamePhase` (function): function useOptionalGamePhase(): GamePhase — Live run phase that degrades to `"playing"` when rendered outside a `GameProvider` (component showcases, previews), so phase-gated chrome never throws.
|
|
599
918
|
- `usePanels` (function): function usePanels(defs: readonly PanelDef[], options?: UsePanelsOptions): PanelsManager — The DATA/HOOK layer: wrap the core panel model in state and install a window keybind listener — per-panel hotkeys toggle their window and ESC closes the topmost closable one. Hotkeys are ignored while the player is typing in an input/textarea/contenteditable. The listener is cleaned up on unmount and SSR-safe (armed in an effect). Feed the returned manager to {@link PanelHost}, or drive a bespoke window layout from it directly.
|
|
600
919
|
- `useParty` (function): function useParty(): PartyMemberEntry[] — ⚠ undocumented
|
|
601
920
|
- `usePartyInvites` (function): function usePartyInvites(): PartyInviteEntry[] — ⚠ undocumented
|
|
921
|
+
- `usePhotoMode` (function): function usePhotoMode(store: PhotoModeStore): PhotoModeState — Subscribe to a photo-mode store's live state.
|
|
602
922
|
- `usePlayer` (function): function usePlayer(): { userId: string; isNew: boolean } — ⚠ undocumented
|
|
923
|
+
- `usePlural` (function): function usePlural(): (key: string, count: number, params?: TParams) => string — Return the plural-aware translator bound to the current locale.
|
|
924
|
+
- `usePrefersReducedMotion` (function): function usePrefersReducedMotion(): boolean — OS "reduce motion" preference (`prefers-reduced-motion: reduce`) as a live boolean — SSR-safe (defaults false). Use it to seed an accessibility store's `reducedMotion` default.
|
|
603
925
|
- `usePresence` (function): function usePresence(userId: string): PresenceInfo — ⚠ undocumented
|
|
604
926
|
- `useQuestJournal` (function): function useQuestJournal(): QuestInstance[] — ⚠ undocumented
|
|
927
|
+
- `useRafLoop` (function): function useRafLoop(onFrame: (deltaSeconds: number) => void, active = true): void — Run a requestAnimationFrame loop while `active`, calling `onFrame(deltaSeconds)` each frame. The callback is kept in a ref so re-renders never restart the loop; cleanup cancels the pending frame. For scene-graph work inside a canvas prefer R3F's useFrame — this is for DOM-side animation outside the renderer.
|
|
928
|
+
- `useRebindSession` (function): function useRebindSession(session: RebindSession): RebindSession — Subscribe to a rebind session and re-render on every change (capture, reset, arm/disarm, restore). Returns the session unchanged for convenient inline use.
|
|
605
929
|
- `useRegisterLayoutRegion` (function): function useRegisterLayoutRegion(spec: LayoutRegionSpec, ref: RefObject<HTMLElement | null>, enabled = true): void — Register the element behind `ref` as a layout region and keep its measured rectangle live (ResizeObserver + viewport changes). No-op outside a `GameViewportProvider`, so a component using it still works in isolation.
|
|
606
930
|
- `useReservedControlZones` (function): function useReservedControlZones(): readonly LayoutRect[] — Rectangles reserved by touch controls and system UI — HUD placement should avoid these.
|
|
607
931
|
- `useRoster` (function): function useRoster(userId?: string): readonly RosterEntry[] — ⚠ undocumented
|
|
932
|
+
- `useSaveSlots` (function): function useSaveSlots(model: SaveSlots): SaveSlotMeta[] — Subscribe to a {@link SaveSlots} index and re-render on any change (write, clear, rename, restore). Returns the live list of slots in menu order. Wire it into a save-select screen and mutate the model in event handlers — the menu re-renders itself.
|
|
608
933
|
- `useSaveStore` (function): function useSaveStore<T>(store: SaveStore<T>, options?: { load?: boolean }): SaveStoreView<T> — Bind a {@link SaveStore} to React: returns the live `value` and `status` and re-renders whenever either changes. By default it calls `load()` once on mount (pass `{ load: false }` to hydrate yourself). The same hook works for offline (localStorage) and cloud (Convex/DB) saves — only the store's backend differs.
|
|
609
934
|
- `useSceneEntities` (function): function useSceneEntities(): readonly SceneEntity[] — ⚠ undocumented
|
|
610
935
|
- `useSceneEntityIds` (function): function useSceneEntityIds(): readonly string[] — Membership-only entity id list: the returned array keeps a stable identity across per-frame pose writes and only changes when an entity spawns, despawns, or the store is hydrated (#625). A marker mapped from these ids reads its own live pose imperatively (useFrame), so the actor tree no longer re-reconciles every frame. Prefer this over {@link useSceneEntities} for large scenes.
|
|
611
936
|
- `useSceneObjectIds` (function): function useSceneObjectIds(): readonly string[] — Membership-only object id list — the object counterpart of {@link useSceneEntityIds}; stable across move/rotate/setVisual, changes only on place/remove.
|
|
612
937
|
- `useSceneObjects` (function): function useSceneObjects(): readonly SceneObject[] — ⚠ undocumented
|
|
613
938
|
- `useSelectionView` (function): function useSelectionView(members: readonly EntitySummaryDef[], options?: UseSelectionViewOptions): SelectionModel — The DATA/HOOK layer: summarize a selected-entity list into a live model with a focused primary, ordered members, same-kind groups, keyboard focus stepping, and a virtualization window. Rendering-agnostic — feed it to {@link SelectionPanel} or read the `view` directly.
|
|
939
|
+
- `useSequenceDirector` (function): function useSequenceDirector(director: SequenceDirector): SequenceDirectorBinding — Bind a {@link SequenceDirector} to a component: subscribe to its state, and while it is playing run a `requestAnimationFrame` loop that ticks the director each frame off the same injected clock — so a game drops in one hook and the cutscene advances itself. Returns the current playback state (playhead, progress, playing/done) plus bound `play`/`pause`/`skip`/`seek`/`stop`. Cue side effects belong on `director.onCue`, not here — the hook never interprets a cue.
|
|
614
940
|
- `useSession` (function): function useSession(): IdentitySource — ⚠ undocumented
|
|
615
941
|
- `useSetting` (function): function useSetting<T extends SettingValue>(id: string, fallback: T): readonly [T, (value: SettingValue) => void] — Read + write one persisted setting; re-renders when the value changes anywhere.
|
|
616
942
|
- `useSettings` (function): function useSettings(): SettingsController — The engine settings controller for the current game — render your own settings UI from `categories`, or open the built-in menu with `open()`. Null-safe stub when mounted outside the shell.
|
|
617
943
|
- `useSettingsStore` (function): function useSettingsStore(): SettingsStore — The shared settings store, or a standalone one when no provider is mounted (game code read outside the shell).
|
|
944
|
+
- `useShopStock` (function): function useShopStock(shop: ShopStock): ShopStockEntry[] — Subscribe to a shop's stock and re-render whenever it changes (buy, sell, restock, price, add, remove, restore). Returns the current entry list — a detached snapshot safe to map over.
|
|
618
945
|
- `useStore` (function): function useStore<T>(handle: StoreHandle<T>): T — Subscribe a component to a typed store slot defined with `defineStore`. Returns the current value (or the definition's initial before any write), re-rendering only when the slot changes — the cast-free, boilerplate-free replacement for a hand-written `useGameStore((ctx) => ctx.game.store.get(KEY) as T)`.
|
|
946
|
+
- `useT` (function): function useT(): (key: string, params?: TParams) => string — Return the translator bound to the current locale; the component re-renders when `setLocale` is called, so returned strings stay live.
|
|
619
947
|
- `useTarget` (function): function useTarget(fromInstanceId: string): string | null — ⚠ undocumented
|
|
948
|
+
- `useTicker` (function): function useTicker(hz = 10): number — Re-render at a steady rate. Returns a monotonically increasing tick count driven by a setInterval, for HUD elements that display wall-clock-derived values (cooldowns, cast bars, swing timers) without an engine subscription to hang off. `hz <= 0` disables the ticker.
|
|
949
|
+
- `useTimerRead` (function): function useTimerRead(timer: TimerSet, id: string, active = true): TimerRead | null — Subscribe to a single timer and re-read it every animation frame while mounted, so a HUD readout stays live without the game hand-rolling interval math. Reuses one read object (allocation-aware). Returns `null` for an unknown id. Pass `active={false}` to freeze the per-frame tick (e.g. an off-screen HUD).
|
|
620
950
|
- `useViewportMetrics` (function): function useViewportMetrics(): ViewportMetrics — Live visible viewport, tracking `window.visualViewport` (mobile browser chrome, pinch-zoom) with a layout-viewport fallback.
|
|
621
951
|
- `useVoice` (function): function useVoice(options?: UseVoiceOptions): VoiceState — Mic capture + push-to-talk + channel roster over the VoiceTransport signaling seam. Transmission gates the captured tracks' `enabled` flag; the media plane that actually moves audio bytes (WebRTC/SFU) stays behind the transport, host-supplied. Call once per voice channel and hand the returned state to the voice components.
|
|
952
|
+
- `useWaveRunner` (function): function useWaveRunner(runner: WaveRunner): WaveView — Subscribe to a {@link WaveRunner} and re-render whenever it notifies (wave, budget, spawns, alert change). Returns the runner's pooled {@link WaveView}. The runner is driven by the game/demo (call `runner.update(dt)`), not by this hook.
|
|
953
|
+
- `useWaypoints` (function): function useWaypoints(source: WaypointTracker | readonly Waypoint[]): readonly Waypoint[] — Subscribe to a {@link WaypointTracker} and re-render on every change, returning its current waypoints. Pass a plain array instead and it is returned as-is (no subscription), so a game can drive the host from a tracker or from its own derived state.
|
|
622
954
|
- `useWorldBrowser` (function): function useWorldBrowser(options: { fetchSessions: () => Promise<readonly SessionListing[]>; filter?: MatchFilter; limit?: number; refreshMs?: number; }): WorldBrowserState — Polls a host-supplied session fetcher (e.g. createWsBackend().browse) and filters through matchmaking's browseSessions. fetchSessions must be identity-stable (wrap in useCallback at the call site) or every render refetches.
|
|
623
955
|
- `useWorldInvites` (function): function useWorldInvites(): WorldInvite[] — ⚠ undocumented
|
|
624
956
|
- `useWorldItems` (function): function useWorldItems(): readonly WorldItemRecord[] — ⚠ undocumented
|
|
625
957
|
|
|
958
|
+
## @jgengine/react/accessibility
|
|
959
|
+
|
|
960
|
+
- `AccessibilityProvider` (function): function AccessibilityProvider({ store, children, className, style, }: { store: AccessibilityStore; children: ReactNode; className?: string; style?: CSSProperties; }): ReactNode — Apply accessibility preferences to a subtree: exposes `--jg-text-scale` for text to scale off, sets `data-reduced-motion` / `data-high-contrast` / `data-colorblind` / `data-captions` for CSS to respond to, and wraps the tree in the selected colorblind `feColorMatrix` filter. Reads a `createAccessibilityStore` and re-renders on change; provides the state to `useAccessibility`.
|
|
961
|
+
- `ColorblindFilters` (function): function ColorblindFilters(): ReactNode — Hidden SVG `<defs>` holding the `feColorMatrix` colorblind filters that `AccessibilityProvider` references by `filter: url(#jg-cb-<mode>)`. Rendered automatically inside the provider; export standalone for custom roots.
|
|
962
|
+
- `useAccessibility` (function): function useAccessibility(): AccessibilityContextValue — Read the live accessibility state + its store; throws without an {@link AccessibilityProvider} above.
|
|
963
|
+
- `usePrefersReducedMotion` (function): function usePrefersReducedMotion(): boolean — OS "reduce motion" preference (`prefers-reduced-motion: reduce`) as a live boolean — SSR-safe (defaults false). Use it to seed an accessibility store's `reducedMotion` default.
|
|
964
|
+
|
|
965
|
+
## @jgengine/react/achievements
|
|
966
|
+
|
|
967
|
+
- `AchievementGallery` (function): function AchievementGallery({ achievements, title = "Achievements", maskSecrets = true, renderIcon, columns = 2, emptyLabel = "No achievements yet.", className, style, }: AchievementGalleryProps): ReactNode — Achievement/trophy gallery — a responsive grid of cards showing unlocked vs. locked state, a progress bar for counter achievements, and a header summary of completion and score. Secret+locked entries mask their name/description. Feed it `useAchievements(tracker)`.
|
|
968
|
+
- `AchievementGalleryProps` (interface): interface AchievementGalleryProps — Props for {@link AchievementGallery}.
|
|
969
|
+
- `AchievementToast` (function): function AchievementToast({ name, description, icon, points, heading = "Achievement Unlocked", className, style, }: AchievementToastProps): ReactNode — The unlock-moment banner — icon, "Achievement Unlocked" heading, name, and optional points. Purely presentational; pair the game's `onUnlock` seam with a toast queue and render one of these per entry.
|
|
970
|
+
- `AchievementToastProps` (interface): interface AchievementToastProps — Props for {@link AchievementToast}.
|
|
971
|
+
- `useAchievements` (function): function useAchievements(tracker: AchievementTracker): readonly AchievementView[] — Subscribe a component to an achievement tracker's live view list. The list keeps a stable identity between changes, so this re-renders only on unlock or progress — not every frame.
|
|
972
|
+
|
|
626
973
|
## @jgengine/react/actionHud
|
|
627
974
|
|
|
628
975
|
- `ActionBar` (function): function ActionBar({ defs, columns, layout = "grid", wrap, hotkeys, itemSize, ariaLabel, onActivate, renderItem, className, style, }: { defs: readonly ActionDef[]; columns?: number; layout?: "grid" | "list"; wrap?: boolean; hotkeys?: boolean; itemSize?: number; ariaLabel?: string; onActivate?: (id: … — Convenience composition of {@link useActionBar} + glass {@link ActionBarChrome} for demos and scaffolding — not a shipped game face. Pass `defs`, choose `grid`/`list`, and hand it `onActivate`. Games that own their UI compose the headless hook + custom chrome (or swap `renderItem`) instead of shipping this default panel.
|
|
@@ -659,6 +1006,13 @@
|
|
|
659
1006
|
|
|
660
1007
|
- `BarsPreview` (function): function BarsPreview({ className }: { className?: string }): React.JSX.Element — Renders the atomic bar matrix twice under different token blocks to prove global re-theming.
|
|
661
1008
|
|
|
1009
|
+
## @jgengine/react/cameraShake
|
|
1010
|
+
|
|
1011
|
+
- `CameraShakeMeter` (function): function CameraShakeMeter({ controller, animate = false, title = "CAMERA SHAKE", kindLabels, variation = "glass", className, style, }: CameraShakeMeterProps): ReactNode — A drop-in HUD panel that visualizes a core {@link CameraShakeController}: a trauma meter (reusing the shared {@link StaminaBar} building block) plus a live percentage and the current impact `kind` label. Presentation only — it reads the controller and never interprets `kind`, mapping it through `kindLabels` for display. A shell component applies the same controller's `offset()` to the camera; this panel is the on-screen readout of how much shake is in flight.
|
|
1012
|
+
- `CameraShakeMeterProps` (interface): interface CameraShakeMeterProps — Props for {@link CameraShakeMeter}.
|
|
1013
|
+
- `CameraShakeReadout` (interface): interface CameraShakeReadout — A live read of a camera-shake controller: current trauma `0..1` and the last game-owned `kind`.
|
|
1014
|
+
- `useCameraShake` (function): function useCameraShake(controller: CameraShakeController, animate = true): CameraShakeReadout — Subscribe to a camera-shake controller and re-render on every change (add / decay / clear). Optionally drives `update()` on an animation frame so the trauma meter bleeds down live even when no game loop ticks the controller. Returns the current trauma + kind for a HUD readout.
|
|
1015
|
+
|
|
662
1016
|
## @jgengine/react/cards
|
|
663
1017
|
|
|
664
1018
|
- `CardFace` (function): function CardFace({ rank, suit, faceDown = false, width = 64, height = 90, className, style, children, }: { rank: Rank; suit: Suit; faceDown?: boolean; width?: number; height?: number; className?: string; style?: CSSProperties; children?: ReactNode; }): React.JSX.Element — A single playing-card face: rank + suit pips, or a patterned back when `faceDown`.
|
|
@@ -702,6 +1056,27 @@
|
|
|
702
1056
|
- `useChatBubbles` (function): function useChatBubbles(options?: ChatBubblesOptions): readonly ChatBubble[] — ⚠ undocumented
|
|
703
1057
|
- `useEntityChatBubble` (function): function useEntityChatBubble(instanceId: string, options?: ChatBubblesOptions): ChatBubble | null — ⚠ undocumented
|
|
704
1058
|
|
|
1059
|
+
## @jgengine/react/coachMarks
|
|
1060
|
+
|
|
1061
|
+
- `CoachMark` (function): function CoachMark({ view, positionStyle, onNext, onSkip, nextLabel = "Next", doneLabel = "Got it", skipLabel = "Skip tour", theme, className, style, }: CoachMarkProps): ReactNode — A single coach-mark callout — title, body, an "N of M" counter, a Next/Got-it button, and a Skip-tour link. Presentation-only; position it with `positionStyle` or drop it into {@link CoachMarkHost}. Reskin via {@link CoachMarkTheme}.
|
|
1062
|
+
- `CoachMarkHost` (function): function CoachMarkHost({ sequence, resolveAnchor, showBackdrop = true, onComplete, nextLabel, doneLabel, skipLabel, theme, className, style, }: CoachMarkHostProps): ReactNode — Full-screen coach-mark host: watches a sequence, positions the current step's callout beside its anchored element (or centered when unanchored) via `getBoundingClientRect`, and draws an optional dimmed backdrop with a spotlight cutout around the anchor. Next advances, Skip ends the tour — both persist so hints never re-show. Reskin with {@link CoachMarkTheme}.
|
|
1063
|
+
- `CoachMarkHostProps` (interface): interface CoachMarkHostProps — Props for {@link CoachMarkHost}.
|
|
1064
|
+
- `CoachMarkProps` (interface): interface CoachMarkProps — Props for {@link CoachMark}.
|
|
1065
|
+
- `CoachMarkTheme` (interface): interface CoachMarkTheme — Reskin tokens for {@link CoachMarkHost} / {@link CoachMark}.
|
|
1066
|
+
- `useCoachMarks` (function): function useCoachMarks(sequence: CoachMarkSequence): CoachMarkView | null — Subscribe to a coach-mark sequence and re-render on every change, returning the current step view (or `null` when the tour is complete or waiting on a gate).
|
|
1067
|
+
|
|
1068
|
+
## @jgengine/react/codex
|
|
1069
|
+
|
|
1070
|
+
- `Codex` (function): function Codex({ entries, title = "Codex", columns = 3, maskSecrets = true, renderIcon, onSelect, emptyLabel = "Nothing discovered yet.", className, style, }: CodexProps): ReactNode — Codex / bestiary gallery — category tabs, a responsive grid of entry cards (discovered vs. locked, secret entries masked until found), and a header summarizing completion. Feed it `codex.list()`; wire `onSelect` to a detail pane.
|
|
1071
|
+
- `CodexProps` (interface): interface CodexProps — Props for {@link Codex}.
|
|
1072
|
+
|
|
1073
|
+
## @jgengine/react/comboMeter
|
|
1074
|
+
|
|
1075
|
+
- `ComboMeterHud` (function): function ComboMeterHud({ meter, tierColors, theme, animate = true, hideWhenEmpty = true, barWidth = 220, className, style, }: ComboMeterHudProps): ReactNode — A drop-in HUD for a core {@link ComboMeter}: the big live combo count ("×12"), the current free-string tier label, the derived score multiplier, and a draining window bar (reusing the shared atomic bar) that empties as the decay window runs out and re-fills on every hit. The active tier's color — supplied by the game via `tierColors`, keyed on the free-string tier id the model never interprets — drives the count glow, the label, and the bar fill, so a game reskins the escalation ("good" → "great" → "savage") without the engine hardcoding any tier meaning. Presentation only: all counting, timing, tiers, and the multiplier live in the core model.
|
|
1076
|
+
- `ComboMeterHudProps` (interface): interface ComboMeterHudProps — Props for {@link ComboMeterHud}.
|
|
1077
|
+
- `ComboMeterTheme` (interface): interface ComboMeterTheme — Reskin tokens for {@link ComboMeterHud}.
|
|
1078
|
+
- `useComboMeter` (function): function useComboMeter(meter: ComboMeter, animate = true): ComboMeterView — Subscribe to a combo meter and re-render it each animation frame so the decay window bar drains live, returning the pooled view to draw right now. Reading the view each frame advances the meter's clock and fires window expiry, so a combo that times out visibly drops even with no further hits. The returned object is the model's pooled view — read its fields immediately, do not retain it.
|
|
1079
|
+
|
|
705
1080
|
## @jgengine/react/components
|
|
706
1081
|
|
|
707
1082
|
- `CaptureOdds` (function): function CaptureOdds({ chance, className, fillClassName, }: { chance: number; className?: string; fillClassName?: string; }): React.JSX.Element — ⚠ undocumented
|
|
@@ -725,6 +1100,32 @@
|
|
|
725
1100
|
- `runDialogueChoice` (function): function runDialogueChoice(commands: { run(name: string, input?: unknown): unknown }, choice: DialogueChoice, result: CheckResult | null): void — Route a {@link DialogueBox} choice through the `features.dialogue` bridge: resolve the choice's invoke (honoring a skill-check `result`), run that command, and otherwise close the dialogue — the write side that replaces a per-game `onChoice` that hand-rolls `resolveDialogueInvoke` + `dialogue.close`.
|
|
726
1101
|
- `useOpenDialogueId` (function): function useOpenDialogueId(): string | null — The id of the dialogue `ctx.game.dialogue` (or a `talkable(id)` prompt) currently has open, or `null`. The read side of the `features.dialogue` bridge — a panel looks the id up in its own dialogue catalog and renders {@link DialogueBox}, with no per-game open/close store.
|
|
727
1102
|
|
|
1103
|
+
## @jgengine/react/creditsScreen
|
|
1104
|
+
|
|
1105
|
+
- `CreditsScreen` (function): function CreditsScreen({ document, className, style, renderEntry, }: { document: CreditsDocument; className?: string; style?: CSSProperties; renderEntry?: (entry: CreditsEntry, index: number) => ReactNode; }): ReactNode — Renders a {@link CreditsDocument} as headed sections of credited lines. Skinned entirely through the `--jg-*` HudTheme tokens, so it inherits the game's look from the surrounding theme block; pass `renderEntry` to art-direct the line itself. Links render only when an entry carries `href`, and always open in a new tab with `noreferrer`.
|
|
1106
|
+
|
|
1107
|
+
## @jgengine/react/cutscene
|
|
1108
|
+
|
|
1109
|
+
- `CutsceneLetterbox` (function): function CutsceneLetterbox({ active, caption, onSkip, skipLabel = "Skip", progress, theme, className, style, }: CutsceneLetterboxProps): ReactNode — A drop-in cinematic letterbox overlay: black bars slide in top and bottom while a cutscene is `active`, an optional caption/dialogue line sits above the lower bar with an optional progress line, and a Skip button rides the top bar. Presentation only — it never touches the director; wire `active`/`caption`/`progress`/`onSkip` from {@link useSequenceDirector} and your `onCue` handler. Reskin via {@link CutsceneLetterboxTheme}.
|
|
1110
|
+
- `CutsceneLetterboxProps` (interface): interface CutsceneLetterboxProps — Props for {@link CutsceneLetterbox}.
|
|
1111
|
+
- `CutsceneLetterboxTheme` (interface): interface CutsceneLetterboxTheme — Reskin tokens for {@link CutsceneLetterbox}.
|
|
1112
|
+
- `SequenceDirectorBinding` (interface): interface SequenceDirectorBinding extends SequenceState — The live playback state plus bound controls returned by {@link useSequenceDirector}.
|
|
1113
|
+
- `useSequenceDirector` (function): function useSequenceDirector(director: SequenceDirector): SequenceDirectorBinding — Bind a {@link SequenceDirector} to a component: subscribe to its state, and while it is playing run a `requestAnimationFrame` loop that ticks the director each frame off the same injected clock — so a game drops in one hook and the cutscene advances itself. Returns the current playback state (playhead, progress, playing/done) plus bound `play`/`pause`/`skip`/`seek`/`stop`. Cue side effects belong on `director.onCue`, not here — the hook never interprets a cue.
|
|
1114
|
+
|
|
1115
|
+
## @jgengine/react/damageDirection
|
|
1116
|
+
|
|
1117
|
+
- `DamageDirectionOverlay` (function): function DamageDirectionOverlay({ tracker, colors, showReticle = true, theme, className, style, }: DamageDirectionOverlayProps): ReactNode — A drop-in "hit-from" overlay: transient red (by default) arcs that flare around a center reticle in the direction each recent hit came from and fade out over time, driven entirely by a {@link DamageDirectionTracker}. Opacity and outward push scale with each indicator's eased intensity; color comes from the hit's `kind` (via `colors`) or the theme's danger color. Renders full-screen, `pointer-events: none`, so it never intercepts input — a game drops it into its HUD and calls `tracker.registerHit(...)` on damage. Reskin via {@link DamageDirectionTheme}.
|
|
1118
|
+
- `DamageDirectionOverlayProps` (interface): interface DamageDirectionOverlayProps — Props for {@link DamageDirectionOverlay}.
|
|
1119
|
+
- `DamageDirectionTheme` (interface): interface DamageDirectionTheme — Reskin tokens for {@link DamageDirectionOverlay}.
|
|
1120
|
+
- `useDamageDirection` (function): function useDamageDirection(tracker: DamageDirectionTracker): readonly DamageIndicator[] — Subscribe to a damage-direction tracker and animate. Because indicators fade continuously on a clock (not just on discrete events), this drives a `requestAnimationFrame` loop while any indicator is live and stops when the screen is clear, then wakes again on the next hit. Returns the tracker's current `active()` array (reused between frames — copy if you retain it).
|
|
1121
|
+
|
|
1122
|
+
## @jgengine/react/dialogueView
|
|
1123
|
+
|
|
1124
|
+
- `DialogueView` (function): function DialogueView({ run, renderPortrait, onChoose, onClose, closeLabel = "Close", theme, className, style, speakerClassName, textClassName, choicesClassName, choiceClassName, }: DialogueViewProps): ReactNode — A drop-in branching-conversation view over a {@link DialogueRun}: renders the current node's speaker name (+ an optional portrait slot), the line, and a list of clickable response choices that advance the conversation — the game passes its dialogue graph and gets working node traversal and choice state with no hand-rolled walk. A choice with a destination advances the run; a terminal choice (or the Close control on a choiceless node) fires `onClose`. Speaker/choice `kind` are free strings surfaced as `data-*` attributes for the game to style; the view never interprets them. HudTheme-skinned via `--jg-*` tokens; reskin further with {@link DialogueViewTheme}.
|
|
1125
|
+
- `DialogueViewProps` (interface): interface DialogueViewProps — Props for {@link DialogueView}.
|
|
1126
|
+
- `DialogueViewTheme` (interface): interface DialogueViewTheme — Reskin tokens for {@link DialogueView}. Each defaults to a HudTheme `--jg-*` token.
|
|
1127
|
+
- `useDialogueRun` (function): function useDialogueRun(run: DialogueRun): DialogueGraphView | null — Subscribe to a {@link DialogueRun} and re-render on every advance / jump / reset, returning the current node view (or `null` if the run's node id is unknown).
|
|
1128
|
+
|
|
728
1129
|
## @jgengine/react/display
|
|
729
1130
|
|
|
730
1131
|
- `DisplayProfile` (interface): interface DisplayProfile — ⚠ undocumented
|
|
@@ -745,6 +1146,31 @@
|
|
|
745
1146
|
- `EventfulEngineStore` (interface): interface EventfulEngineStore<TEventMap extends object> — ⚠ undocumented
|
|
746
1147
|
- `ReadableEngineStore` (interface): interface ReadableEngineStore<TState> — ⚠ undocumented
|
|
747
1148
|
|
|
1149
|
+
## @jgengine/react/entityFrames
|
|
1150
|
+
|
|
1151
|
+
- `EntityFrameEntry` (interface): interface EntityFrameEntry — The minimum an entry must carry; games extend it with their own display data.
|
|
1152
|
+
- `EntityFrameLayoutOptions` (interface): interface EntityFrameLayoutOptions — Anchoring, culling, and stacking options shared by the layout core and component.
|
|
1153
|
+
- `EntityFramePlacement` (interface): interface EntityFramePlacement<E extends EntityFrameEntry> — One entry resolved to a screen placement, ready to render.
|
|
1154
|
+
- `EntityFrames` (function): function EntityFrames<E extends EntityFrameEntry>({ entries, project, renderFrame, className, style, anchorTransform = "translate(-50%, -100%)", ...layout }: EntityFramesProps<E>): React.JSX.Element — Absolutely-positioned overlay that renders a caller-composed frame over every on-screen entry. Drop it inside `HudCanvas` (or any positioned ancestor) and feed it fresh `entries`/`project` each frame. Every part carries `data-*` hooks (`data-entity-frames`, `data-entity-frame="<id>"`) for tests and skins.
|
|
1155
|
+
- `EntityFramesProps` (interface): interface EntityFramesProps<E extends EntityFrameEntry> extends EntityFrameLayoutOptions — Props for {@link EntityFrames}.
|
|
1156
|
+
- `EntityScreenProjection` (interface): interface EntityScreenProjection — World-anchored entity frames — a data-first seam for floating overhead UI (enemy nameplates + health bars, interaction prompts, objective pips) that tracks entities in the 3D world. The game keeps owning its entities: it passes a plain array of `{ id, worldPosition }` entries and a `project` function that turns a world position into a screen point, and composes each frame's markup itself (typically the shipped {@link ./bars!HealthBar} plus a name) reskinned through `HudTheme`/`barTokens`. This primitive owns only the reusable behavior: projecting, offsetting, culling entries that are off-screen or behind the camera, and stacking nearer entities above farther ones.
|
|
1157
|
+
- `ProjectEntity` (type): type ProjectEntity = ( worldPosition: readonly [number, number, number], ) => EntityScreenProjection | null — Projects a world position to a screen point, or returns `null` to cull the entry entirely (e.g. outside the frustum). Caller-owned so this seam never depends on a specific camera or renderer.
|
|
1158
|
+
- `layoutEntityFrames` (function): function layoutEntityFrames<E extends EntityFrameEntry>(entries: readonly E[], project: ProjectEntity, options: EntityFrameLayoutOptions = {}): EntityFramePlacement<E>[] — Pure layout core: projects each entry, drops the ones behind the camera, off-screen (when `viewport` is set), or beyond `maxCount`, and returns the survivors sorted farthest-first so nearer frames render last (on top). Stable for equal depths via `id`. No React, no DOM — unit-testable in isolation.
|
|
1159
|
+
|
|
1160
|
+
## @jgengine/react/fastTravel
|
|
1161
|
+
|
|
1162
|
+
- `FastTravelMenu` (function): function FastTravelMenu<TMeta = unknown>({ network, from, onTravel, currentId, title = "Fast Travel", emptyLabel = "No destinations discovered yet.", onClose, className, style, }: FastTravelMenuProps<TMeta>): ReactNode — Fast-travel menu — the discovered-destinations list players pick from: points grouped by region, distance-sorted from `from`, each showing icon, name, and distance, with a header counting discovered vs. total. Selecting a row calls `onTravel`; the current location is flagged and not travelable. Bind it to a `createFastTravelNetwork`.
|
|
1163
|
+
- `FastTravelMenuProps` (interface): interface FastTravelMenuProps<TMeta = unknown> — Props for {@link FastTravelMenu}.
|
|
1164
|
+
- `useFastTravel` (function): function useFastTravel<TMeta = unknown>(network: FastTravelNetwork<TMeta>): FastTravelNetwork<TMeta> — Subscribe a component to a fast-travel network's discovery changes. Returns the network unchanged; the hook only forces a re-render when a point is discovered or the network is restored, so callers can read `destinations`/`list` in render.
|
|
1165
|
+
|
|
1166
|
+
## @jgengine/react/floatingText
|
|
1167
|
+
|
|
1168
|
+
- `FloatingText` (function): function FloatingText({ entries, project, styleFor, fontSizePx = 20, className, style, renderEntry, ...layout }: FloatingTextProps): React.JSX.Element — Absolutely-positioned overlay that renders every on-screen floating-text entry as text with its color, current alpha, and pop-in scale. Drop it inside a positioned ancestor (e.g. an `<Html fullscreen>` overlay or `HudCanvas`) and feed it fresh `entries`/`project` each frame. Every part carries `data-*` hooks (`data-floating-text`, `data-floating-text-entry="<id>"`, `data-kind="<kind>"`) for tests and skins.
|
|
1169
|
+
- `FloatingTextLayoutOptions` (interface): interface FloatingTextLayoutOptions — Anchoring and culling options shared by the layout core and the component.
|
|
1170
|
+
- `FloatingTextPlacement` (interface): interface FloatingTextPlacement — World-anchored floating text — the presentation half of the data-first `@jgengine/core/ui/floatingText` seam. The game keeps owning the simulation: it passes the field's `active()` views plus a `project` function (world → screen), exactly the transport {@link ./entityFrames!EntityFrames} uses, so an R3F game gets it for free from `useWorldProjection`. This component owns only the reusable presentation: projecting each entry, culling ones behind the camera or off-screen, and rendering absolutely-positioned text with the entry's color, current alpha, and pop-in scale — reskinnable per `kind` through `styleFor`.
|
|
1171
|
+
- `FloatingTextProps` (interface): interface FloatingTextProps extends FloatingTextLayoutOptions — Props for {@link FloatingText}.
|
|
1172
|
+
- `layoutFloatingText` (function): function layoutFloatingText(views: readonly FloatingTextView[], project: ProjectEntity, options: FloatingTextLayoutOptions = {}): FloatingTextPlacement[] — Pure layout core: projects each view, drops the ones behind the camera or (when `viewport` is set) off-screen, and returns the survivors sorted farthest-first so nearer text paints on top. No React, no DOM — unit-testable.
|
|
1173
|
+
|
|
748
1174
|
## @jgengine/react/fogOverlay
|
|
749
1175
|
|
|
750
1176
|
- `FogCellRect` (interface): interface FogCellRect — ⚠ undocumented
|
|
@@ -776,6 +1202,7 @@
|
|
|
776
1202
|
## @jgengine/react/hooks
|
|
777
1203
|
|
|
778
1204
|
- `AbilitySlotBindingOptions` (interface): interface AbilitySlotBindingOptions — ⚠ undocumented
|
|
1205
|
+
- `DomEventTarget` (interface): interface DomEventTarget — Minimal add/removeEventListener surface accepted by useDomEvent (window, document, elements).
|
|
779
1206
|
- `EventMeterView` (interface): interface EventMeterView — A rendered snapshot of an {@link EventMeter}: current value, fill fraction, active tier, and ready-to-consume flag.
|
|
780
1207
|
- `InventoryGridBinding` (interface): interface InventoryGridBinding — Live slots plus `move`/`split` actions bound to `inventoryId`, routed through the notifying `inventory.move`/`inventory.split` commands so React re-renders.
|
|
781
1208
|
- `UseAxisChannelResult` (interface): interface UseAxisChannelResult — ⚠ undocumented
|
|
@@ -787,9 +1214,11 @@
|
|
|
787
1214
|
- `useAbilitySlot` (function): function useAbilitySlot(kit: AbilityKit, slotId: string, resourceAvailable?: number, options?: AbilitySlotBindingOptions): AbilitySlotSnapshot | null — ⚠ undocumented
|
|
788
1215
|
- `useAbilitySlots` (function): function useAbilitySlots(kit: AbilityKit, resourceAvailable?: number, options?: AbilitySlotBindingOptions): AbilitySlotSnapshot[] — ⚠ undocumented
|
|
789
1216
|
- `useActivePrompt` (function): function useActivePrompt<T extends PositionedPrompt>(prompts?: readonly T[]): T | null — ⚠ undocumented
|
|
1217
|
+
- `useAutoScroll` (function): function useAutoScroll<T extends HTMLElement>(dep: unknown): React.RefObject<T | null> — Pin a scrollable element to its bottom whenever `dep` changes (typically a length or the list itself). Attach the returned ref to the scroll container. Owns the log/chat/console scroll-to-bottom effect so panels don't hand-roll it.
|
|
790
1218
|
- `useAxisChannel` (function): function useAxisChannel(config: AxisChannelConfig): UseAxisChannelResult — Wires useHeldKeys into a fresh AxisChannel, ready for a per-frame `channel.sample(dt, isDown)`. The channel is recreated when `config` identity changes, so pass a stable config (useMemo/module constant at the call site) unless a rebind is intended.
|
|
791
1219
|
- `useChat` (function): function useChat(channelId: string, options?: { limit?: number }): ChatMessage[] — ⚠ undocumented
|
|
792
1220
|
- `useCurrency` (function): function useCurrency(currencyId: string): number — ⚠ undocumented
|
|
1221
|
+
- `useDomEvent` (function): function useDomEvent<E>(resolveTarget: () => DomEventTarget | null, type: string, handler: (event: E) => void, options?: { capture?: boolean; passive?: boolean }): void — Attach a DOM event listener with automatic cleanup. `resolveTarget` runs inside the effect, so `() => window` and ref-reading resolvers are SSR-safe; return null to skip attaching. The handler is kept in a ref, so a fresh closure per render never re-binds the listener. Re-binds only when `type` or `options.capture`/`options.passive` change.
|
|
793
1222
|
- `useEntityStat` (function): function useEntityStat(instanceId: string, statId: string): StatValue | null — ⚠ undocumented
|
|
794
1223
|
- `useEventMeter` (function): function useEventMeter(meter: EventMeter, options?: AbilitySlotBindingOptions): EventMeterView — Bind a `createEventMeter` (`@jgengine/core/stats/eventMeter`) heat/streak gauge to a component — the react-render half of the ult/adrenaline and streak/combo meters (`event-meter` capability) that lets a HUD gauge re-render on tick without the game hand-rolling a `useEffect`/`setInterval` heartbeat around `meter.value()`.
|
|
795
1224
|
- `useFeed` (function): function useFeed({ action, limit }: { action: string; limit?: number }): FeedEntry[] — ⚠ undocumented
|
|
@@ -813,12 +1242,14 @@
|
|
|
813
1242
|
- `usePlayer` (function): function usePlayer(): { userId: string; isNew: boolean } — ⚠ undocumented
|
|
814
1243
|
- `usePresence` (function): function usePresence(userId: string): PresenceInfo — ⚠ undocumented
|
|
815
1244
|
- `useQuestJournal` (function): function useQuestJournal(): QuestInstance[] — ⚠ undocumented
|
|
1245
|
+
- `useRafLoop` (function): function useRafLoop(onFrame: (deltaSeconds: number) => void, active = true): void — Run a requestAnimationFrame loop while `active`, calling `onFrame(deltaSeconds)` each frame. The callback is kept in a ref so re-renders never restart the loop; cleanup cancels the pending frame. For scene-graph work inside a canvas prefer R3F's useFrame — this is for DOM-side animation outside the renderer.
|
|
816
1246
|
- `useRoster` (function): function useRoster(userId?: string): readonly RosterEntry[] — ⚠ undocumented
|
|
817
1247
|
- `useSceneEntities` (function): function useSceneEntities(): readonly SceneEntity[] — ⚠ undocumented
|
|
818
1248
|
- `useSceneEntityIds` (function): function useSceneEntityIds(): readonly string[] — Membership-only entity id list: the returned array keeps a stable identity across per-frame pose writes and only changes when an entity spawns, despawns, or the store is hydrated (#625). A marker mapped from these ids reads its own live pose imperatively (useFrame), so the actor tree no longer re-reconciles every frame. Prefer this over {@link useSceneEntities} for large scenes.
|
|
819
1249
|
- `useSceneObjectIds` (function): function useSceneObjectIds(): readonly string[] — Membership-only object id list — the object counterpart of {@link useSceneEntityIds}; stable across move/rotate/setVisual, changes only on place/remove.
|
|
820
1250
|
- `useSceneObjects` (function): function useSceneObjects(): readonly SceneObject[] — ⚠ undocumented
|
|
821
1251
|
- `useTarget` (function): function useTarget(fromInstanceId: string): string | null — ⚠ undocumented
|
|
1252
|
+
- `useTicker` (function): function useTicker(hz = 10): number — Re-render at a steady rate. Returns a monotonically increasing tick count driven by a setInterval, for HUD elements that display wall-clock-derived values (cooldowns, cast bars, swing timers) without an engine subscription to hang off. `hz <= 0` disables the ticker.
|
|
822
1253
|
- `useWorldBrowser` (function): function useWorldBrowser(options: { fetchSessions: () => Promise<readonly SessionListing[]>; filter?: MatchFilter; limit?: number; refreshMs?: number; }): WorldBrowserState — Polls a host-supplied session fetcher (e.g. createWsBackend().browse) and filters through matchmaking's browseSessions. fetchSessions must be identity-stable (wrap in useCallback at the call site) or every render refetches.
|
|
823
1254
|
- `useWorldInvites` (function): function useWorldInvites(): WorldInvite[] — ⚠ undocumented
|
|
824
1255
|
- `useWorldItems` (function): function useWorldItems(): readonly WorldItemRecord[] — ⚠ undocumented
|
|
@@ -858,14 +1289,22 @@
|
|
|
858
1289
|
|
|
859
1290
|
## @jgengine/react/hudTheme
|
|
860
1291
|
|
|
861
|
-
- `HUD_THEME_PRESETS` (const): const HUD_THEME_PRESETS: { "arcane-stone": HudTheme; "survival-wood": HudTheme; "military-flat": HudTheme; "sleek-hex": HudTheme; "elemental-circle": HudTheme; "sandbox-slot": HudTheme; } — Built-in theme presets for demos/scaffold only — not product identity; games author their own theme.
|
|
862
|
-
- `HudTheme` (interface): interface HudTheme — A full HUD theme.
|
|
1292
|
+
- `HUD_THEME_PRESETS` (const): const HUD_THEME_PRESETS: { "arcane-stone": HudTheme; "survival-wood": HudTheme; "military-flat": HudTheme; "sleek-hex": HudTheme; "elemental-circle": HudTheme; "sandbox-slot": HudTheme; ember: HudTheme; synthwave: HudTheme; fieldkit: HudTheme; } — Built-in theme presets for demos/scaffold only — not product identity; games author their own theme.
|
|
1293
|
+
- `HudTheme` (interface): interface HudTheme — A full HUD theme. Author one with {@link hudTheme} or {@link deriveHudTheme}.
|
|
863
1294
|
- `HudThemeBar` (interface): interface HudThemeBar — Framed-trough tokens shared by every atomic bar.
|
|
1295
|
+
- `HudThemeFont` (interface): interface HudThemeFont — Typography roles. Any CSS `font-family` list.
|
|
864
1296
|
- `HudThemeFrame` (interface): interface HudThemeFrame — Frame material + shape tokens (panels, `HudFrame variation="themed"`).
|
|
865
|
-
- `
|
|
1297
|
+
- `HudThemeOverrides` (interface): interface HudThemeOverrides — Per-group partial overrides accepted by {@link hudTheme}.
|
|
1298
|
+
- `HudThemePalette` (interface): interface HudThemePalette — `HudTheme` (#1034, #1573): one token object that restyles every shared token-driven building block at once — the atomic bars (#1033), frames, slots, the minimap ring, and the chrome the registry blocks read (surfaces, edges, text, status colors, fonts, rarity). `hudThemeVars(theme)` emits the whole `--jg-*` vocabulary, so setting a **game-authored** theme on any HUD ancestor re-skins `packages/react` primitives and `registry/jgengine` components together. Purely CSS-token driven (no image assets). Tokens are not a finished UI: every game still owns composition, skin, and art direction (see AGENTS.md). Built-in presets are demo/scaffold starting points only.
|
|
866
1299
|
- `HudThemePreset` (type): type HudThemePreset = keyof typeof HUD_THEME_PRESETS — Built-in demo/scaffold theme preset name — not a game identity.
|
|
1300
|
+
- `HudThemeRarity` (interface): interface HudThemeRarity — Item-rarity coloring shared by loot cards, tooltips, and inventory slots.
|
|
1301
|
+
- `HudThemeSeed` (interface): interface HudThemeSeed — Seed colors for {@link deriveHudTheme}. Only `accent` and `surface` are required.
|
|
867
1302
|
- `HudThemeSlot` (interface): interface HudThemeSlot — Action/inventory slot tokens.
|
|
1303
|
+
- `HudThemeStatus` (interface): interface HudThemeStatus — Semantic status colors — outcome, threat, and relationship coloring.
|
|
1304
|
+
- `HudThemeSurface` (interface): interface HudThemeSurface — Chrome surfaces, edges, and text — what panels, overlays, and menus are built out of.
|
|
868
1305
|
- `defaultHudTheme` (const): const defaultHudTheme: HudTheme — Default theme tokens for previews/scaffold — not a finished game look; author a custom theme.
|
|
1306
|
+
- `deriveHudTheme` (function): function deriveHudTheme(seed: HudThemeSeed): HudTheme — Derives a coherent full theme from an accent/surface pair — shades, edges, dim text, frames, bar troughs, and slots all fall out of the seed, so a game gets one consistent look across the `packages/react` primitives and the `registry/jgengine` blocks without naming 50 tokens. Hex seeds only (`#rgb` or `#rrggbb`).
|
|
1307
|
+
- `hudTheme` (function): function hudTheme(overrides: HudThemeOverrides): HudTheme — Builds a full {@link HudTheme} from per-group partials, filling the rest from {@link defaultHudTheme}. Reach for this when a game wants to name exact values; use {@link deriveHudTheme} when a seed color pair is enough.
|
|
869
1308
|
- `hudThemeVars` (function): function hudThemeVars(theme: HudTheme): CSSProperties — Emits the CSS custom properties for a theme — spread onto any HUD ancestor to re-skin the subtree.
|
|
870
1309
|
- `resolveHudTheme` (function): function resolveHudTheme(theme?: HudThemePreset | HudTheme): HudTheme — Resolves a preset name (or a full theme) to a `HudTheme`; falls back to the default theme.
|
|
871
1310
|
|
|
@@ -879,6 +1318,15 @@
|
|
|
879
1318
|
- `HudViewportProvider` (function): function HudViewportProvider({ platforms, config, userScale, children, }: { platforms: readonly HudPlatform[] | undefined; config: HudViewportConfig | undefined; userScale?: number; children?: ReactNode; }): React.JSX.Element — Mounted by the shell around `GameUI` so every `HudCanvas` inside the game picks up the game's `platforms`/`hudFit` declaration and the player's UI scale setting without any game-side wiring.
|
|
880
1319
|
- `useHudViewport` (function): function useHudViewport(): HudViewportContextValue | null — ⚠ undocumented
|
|
881
1320
|
|
|
1321
|
+
## @jgengine/react/i18n
|
|
1322
|
+
|
|
1323
|
+
- `I18nProvider` (function): function I18nProvider({ i18n, children }: { i18n: I18n; children: ReactNode }): ReactNode — Provide an {@link I18n} instance to the tree so `useT`/`useLocale` can read it.
|
|
1324
|
+
- `Trans` (function): function Trans({ k, params }: { k: string; params?: TParams }): ReactNode — Render a translated message inline: `<Trans k="hud.score" params={{ value }} />`.
|
|
1325
|
+
- `useI18n` (function): function useI18n(): I18n — Read the current {@link I18n} from context; throws when no {@link I18nProvider} is above.
|
|
1326
|
+
- `useLocale` (function): function useLocale(): Locale — Subscribe to the active locale — re-renders on `setLocale`.
|
|
1327
|
+
- `usePlural` (function): function usePlural(): (key: string, count: number, params?: TParams) => string — Return the plural-aware translator bound to the current locale.
|
|
1328
|
+
- `useT` (function): function useT(): (key: string, params?: TParams) => string — Return the translator bound to the current locale; the component re-renders when `setLocale` is called, so returned strings stay live.
|
|
1329
|
+
|
|
882
1330
|
## @jgengine/react/iconTreatment
|
|
883
1331
|
|
|
884
1332
|
- `IconSchool` (type): type IconSchool = | "fire" | "frost" | "arcane" | "nature" | "holy" | "tech" | "shadow" | "steel" | "neutral" — `IconTreatment` (#1035): a procedural painted-icon face — a glyph over a school-keyed radial gradient, with a vignette inset shadow, a top gloss highlight, and optional count/keycap badges. Turns the engine's flat white `GameIcon` glyphs (and game-icons.net SVGs) into painted ability / item icons that read as AAA slots, not debug UI. Theme-aware: the frame reads the `--jg-slot-*` and `--jg-accent` `HudTheme` tokens (#1034), so a theme change re-skins every treated icon.
|
|
@@ -910,6 +1358,14 @@
|
|
|
910
1358
|
- `useAuthedPlayer` (function): function useAuthedPlayer(options?: { guestSeed?: string }): PlayerIdentity | null — ⚠ undocumented
|
|
911
1359
|
- `useSession` (function): function useSession(): IdentitySource — ⚠ undocumented
|
|
912
1360
|
|
|
1361
|
+
## @jgengine/react/interactionPrompt
|
|
1362
|
+
|
|
1363
|
+
- `InteractionPrompt` (function): function InteractionPrompt({ registry, playerPosition, theme, accentFor, keyFor, gaugeProgress, anchor = "bottom-center", zIndex = 40, className, style, }: InteractionPromptProps): ReactNode — A screen-anchored "Press E to …" interaction callout that renders the active prompt of a {@link PromptRegistry}. It subscribes to the registry and — when given `playerPosition` — re-resolves as the hero moves, showing the nearest in-range interactable and switching to a closer/higher-priority one as they cross radii. Each display kind renders as itself: a `keybind` shows a key cap plus its label ("Press [E] Open"), a `gauge` shows a hold bar filling with `gaugeProgress`, and a `label` shows plain text. Presentation only — the registry never branches on a prompt's meaning; the game colors each via `accentFor` and maps action ids to key glyphs via `keyFor`. HudTheme-skinnable through `--jg-accent` and {@link InteractionPromptTheme}.
|
|
1364
|
+
- `InteractionPromptAnchor` (type): type InteractionPromptAnchor = "bottom-center" | "top-center" | "center" — Where the callout sits over the scene.
|
|
1365
|
+
- `InteractionPromptProps` (interface): interface InteractionPromptProps — Props for {@link InteractionPrompt}.
|
|
1366
|
+
- `InteractionPromptTheme` (interface): interface InteractionPromptTheme — Reskin tokens for {@link InteractionPrompt}.
|
|
1367
|
+
- `useInteractionPrompt` (function): function useInteractionPrompt(registry: PromptRegistry, playerPosition: PromptPoint): PositionedPrompt | null — Subscribe to a {@link PromptRegistry} and re-`resolve` it whenever the player moves, returning the prompt to draw right now — or `null` when the player is out of range of every interactable. The registry notifies only on active-prompt *changes*, so this re-renders on transitions rather than every frame the hero moves. Feed it the player's `{ x, z }` position each frame; identical positions do no work.
|
|
1368
|
+
|
|
913
1369
|
## @jgengine/react/inventoryGrid
|
|
914
1370
|
|
|
915
1371
|
- `InventoryGrid` (function): function InventoryGrid({ inventoryId, columns, size = 44, gap = 6, itemIcon, onActivate, className, style, }: InventoryGridProps): React.JSX.Element — A drop-in inventory grid with drag/swap/stack-merge/split and full keyboard control, bound to `inventoryId`.
|
|
@@ -920,6 +1376,21 @@
|
|
|
920
1376
|
- `KeyHint` (function): function KeyHint({ children, className, style, }: { children: ReactNode; className?: string; style?: CSSProperties; }): React.JSX.Element | null — Wraps a keyboard/mouse control hint (a cap plus what it does). Renders nothing on coarse-pointer devices — a touchscreen has no keyboard, so the hint is noise and only fights the on-screen controls for space. The `data-jg-kbd-hint` marker is also hidden by an engine stylesheet as a hydration-safe backstop, so a hint stays hidden on touch even before this component's effect runs. Put the touch equivalent (a `TouchControls` dock, a tappable button) on the coarse branch instead.
|
|
921
1377
|
- `Keycap` (function): function Keycap({ children, className, style, }: { children: ReactNode; className?: string; style?: CSSProperties; }): React.JSX.Element — A single keyboard/mouse key rendered as a cap. Tagged `data-jg-kbd` so tooling can find it; on its own it stays visible (hiding a lone cap would strand its label). Wrap keys + their meaning in `KeyHint` to make the whole hint vanish on touch.
|
|
922
1378
|
|
|
1379
|
+
## @jgengine/react/keybindingMenu
|
|
1380
|
+
|
|
1381
|
+
- `KeybindingMenu` (function): function KeybindingMenu({ session, theme, title = "Controls", resetAllLabel = "Reset All", capturePrompt = "Press a key…", onChange, className, style, }: KeybindingMenuProps): ReactNode — A drop-in controls-settings surface for a {@link RebindSession}: one row per action showing its label and current key glyph. Clicking a row arms capture ("Press a key…") and a window `keydown` listener feeds the pressed `event.code` to `session.capture`; rows that collide with another action show a conflict badge; each row has a Reset button and the panel has a Reset-all button. Presentation only — all conflict/capture/reset logic lives in the core session, and action ids/labels are the game's free strings. Reskin via {@link KeybindingMenuTheme} or ambient HudTheme tokens. A game owns its overall settings layout; this is the reusable controls block it drops in.
|
|
1382
|
+
- `KeybindingMenuProps` (interface): interface KeybindingMenuProps — Props for {@link KeybindingMenu}.
|
|
1383
|
+
- `KeybindingMenuTheme` (interface): interface KeybindingMenuTheme — Reskin tokens for {@link KeybindingMenu}. All fall back to HudTheme `--jg-*` vars.
|
|
1384
|
+
- `useRebindSession` (function): function useRebindSession(session: RebindSession): RebindSession — Subscribe to a rebind session and re-render on every change (capture, reset, arm/disarm, restore). Returns the session unchanged for convenient inline use.
|
|
1385
|
+
|
|
1386
|
+
## @jgengine/react/killFeed
|
|
1387
|
+
|
|
1388
|
+
- `KillFeed` (function): function KillFeed({ ticker, kindStyles, theme, iconSize = 18, animate = true, zIndex = 40, className, style, }: KillFeedProps): ReactNode — A vertical event/kill-feed ticker: renders an {@link EventTicker}'s recent entries as a stack of rows, newest on top, each with its `fade` `0..1` mapped to opacity so entries dim and drop as they age out. Each row shows an optional per-kind (or per-entry) {@link GameIcon} and a per-kind accent color from `kindStyles`, styled with HudTheme tokens. Presentation only: all capping/timing lives in the core ticker, and the free-string `kind`/`text`/`icon` are never interpreted here — a game colors and icons each variant via `kindStyles`.
|
|
1389
|
+
- `KillFeedKindStyle` (interface): interface KillFeedKindStyle — Per-`kind` styling for a kill-feed row — accent color and an optional icon.
|
|
1390
|
+
- `KillFeedProps` (interface): interface KillFeedProps — Props for {@link KillFeed}.
|
|
1391
|
+
- `KillFeedTheme` (interface): interface KillFeedTheme — Reskin tokens for {@link KillFeed}.
|
|
1392
|
+
- `useEventTicker` (function): function useEventTicker(ticker: EventTicker, animate = true): EventTickerView[] — Subscribe to an event ticker and re-render it on an animation frame (unless the game already ticks it), returning the live entries newest-first with `fade` applied. Driving the frame loop is what makes entries visibly fade and drop as they age out.
|
|
1393
|
+
|
|
923
1394
|
## @jgengine/react/liveBind
|
|
924
1395
|
|
|
925
1396
|
- `LiveText` (function): function LiveText({ get, format, className, style, }: { get: () => number | string; format?: (value: number | string) => string; className?: string; style?: CSSProperties; }): React.JSX.Element — ⚠ undocumented
|
|
@@ -931,7 +1402,12 @@
|
|
|
931
1402
|
|
|
932
1403
|
- `Compass` (function): function Compass({ facingYaw, center, markers, width = 340, fov = (Math.PI * 2) / 3, kindStyles = DEFAULT_MARKER_KINDS, className, }: CompassProps): ReactNode — Horizontal compass strip centered on the player's facing direction, with the eight cardinals and optional marker pips from static views, an external source, or a native `MarkerSet`.
|
|
933
1404
|
- `CompassProps` (interface): interface CompassProps — ⚠ undocumented
|
|
1405
|
+
- `FullscreenMap` (function): function FullscreenMap({ open = true, bounds, contentWidth = 900, minScale = 0.5, maxScale = 8, title = "Map", onClose, onWorldClick, tool = "pan", onStrokeComplete, drawTone = "info", drawWidth = 3, children, overlayClassName, overlayStyle, ...surfaceProps }: FullscreenMapProps): ReactNode — Fullscreen pan/zoom world-map overlay — the enlarged "press M" map. Wheel to zoom (toward the cursor), drag to pan, and click to place (wire `onWorldClick` to a waypoint/annotation store). Switch `tool` to `"draw"` to freehand-draw strokes committed to `onStrokeComplete` (wire to `createAnnotationLayer`). Reuses {@link WorldMapSurface} for rendering, so terrain bake, fog, routes, zones, markers, and the player arrow all appear; a drag never fires `onWorldClick`. Compose a {@link MapLegend} or tool palette via `children`.
|
|
1406
|
+
- `FullscreenMapProps` (interface): interface FullscreenMapProps extends Omit<WorldMapSurfaceProps, "canvasWidth" | "canvasHeight" | "viewport" | "width" | "height" | "style"> — Props for {@link FullscreenMap}.
|
|
934
1407
|
- `MapBounds` (interface): interface MapBounds — ⚠ undocumented
|
|
1408
|
+
- `MapLegend` (function): function MapLegend({ kinds, labels, kindStyles = DEFAULT_MARKER_KINDS, title = "Legend", className, style, }: MapLegendProps): ReactNode — Marker-kind key for a map/minimap — glyph + color swatch per kind, labelled. Reads the same `kindStyles` the map renders with, so the legend can never drift from the pins.
|
|
1409
|
+
- `MapLegendProps` (interface): interface MapLegendProps — Props for {@link MapLegend}.
|
|
1410
|
+
- `MapViewport` (interface): interface MapViewport — Pan/zoom transform applied to a {@link WorldMapSurface}'s content group.
|
|
935
1411
|
- `Minimap` (function): function Minimap({ markers, center, worldRadius, fog, size = 176, facingYaw = 0, rotate = false, kindStyles = DEFAULT_MARKER_KINDS, background, mapBounds, routes, zones, cellStates, onWorldClick, className, style, title = "Map", children, }: MinimapProps): ReactNode — Framed circular minimap: optional baked terrain background, reveal-on-event fog overlay, categorized marker icons, and a facing arrow. Reads static marker views, an external marker source, or a native `MarkerSet`; supply your own `kindStyles` palette to reskin. Does not require `GameProvider`.
|
|
936
1412
|
- `MinimapChrome` (function): function MinimapChrome({ view, frame = false, frameColor = "rgba(148,163,184,0.4)", frameStrokeWidth = 1.5, cardinalLabel = "N", markers = [], markerColor = "#e2e8f0", markerRadius = 5, className, }: MinimapChromeProps): ReactNode — Headless minimap chrome — nests inside a game's own `<svg>`: an optional ring frame, and edge-clamped marker dots that draw as directional arrows when a marker carries a `heading` (the compass-arrow / player-blip layer ~8 games were re-drawing by hand over `projectToMinimap`/`clampToMinimapEdge`). Renders a bare `<g>` — no background, panel, or title; compose your own content layer (routes, zones, terrain) as sibling SVG nodes for full control of z-order, or call `MinimapChrome` twice (once for `frame`, again for `markers`) to sandwich custom content between the ring and the blips.
|
|
937
1413
|
- `MinimapChromeMarker` (interface): interface MinimapChromeMarker — One dot (or, with `heading`, a rotated arrow) drawn by `MinimapChrome`.
|
|
@@ -943,11 +1419,50 @@
|
|
|
943
1419
|
- `MinimapTrackPip` (interface): interface MinimapTrackPip — A point marker on the {@link MinimapTrack} rail at a 0..1 fraction (e.g. a gate, the exit, or the player).
|
|
944
1420
|
- `MinimapTrackProps` (interface): interface MinimapTrackProps — Props for {@link MinimapTrack}.
|
|
945
1421
|
- `MinimapTrackSpan` (interface): interface MinimapTrackSpan — A colored span across the {@link MinimapTrack} rail, given by 0..1 `start`/`end` fractions (e.g. from core `trackFraction`).
|
|
946
|
-
- `
|
|
1422
|
+
- `WaypointArrow` (function): function WaypointArrow({ relative, distance, label, formatDistance = (value) => `${Math.round(value)}m`, size = 44, color = "#f59e0b", className, style, }: WaypointArrowProps): ReactNode — On-screen guide arrow to the tracked waypoint — a HUD compass needle rotated by the facing-relative bearing, with an optional label and distance readout. Pair with `WaypointStore.guidance(playerXZ, facingYaw)`.
|
|
1423
|
+
- `WaypointArrowProps` (interface): interface WaypointArrowProps — Props for {@link WaypointArrow}.
|
|
1424
|
+
- `WorldMap` (function): function WorldMap({ markers, bounds, player, facingYaw = 0, fog, background, width = 520, height, kindStyles = DEFAULT_MARKER_KINDS, routes, zones, cellStates, onWorldClick, className, title = "World Map", onClose, }: WorldMapProps): ReactNode — Full-bounds top-down world map (the "press M" overlay): baked terrain background, reveal-on-event fog, all markers with labels, and the player. Rectangular linear projection over the supplied world `bounds`. Framed panel wrapper over {@link WorldMapSurface}.
|
|
947
1425
|
- `WorldMapProps` (interface): interface WorldMapProps — ⚠ undocumented
|
|
1426
|
+
- `WorldMapSurface` (function): function WorldMapSurface({ markers, bounds, player, facingYaw = 0, fog, background, width = 520, height, kindStyles = DEFAULT_MARKER_KINDS, routes, zones, cellStates, onWorldClick, canvasWidth, canvasHeight, viewport = IDENTITY_VIEWPORT, style, }: WorldMapSurfaceProps): ReactNode — The bare top-down map `<svg>` shared by {@link WorldMap} (framed panel) and {@link FullscreenMap} (pan/zoom overlay): baked terrain background, fog, map layers, markers with labels, and the player arrow, drawn under an optional viewport transform. Rectangular linear projection over the world `bounds`.
|
|
1427
|
+
- `WorldMapSurfaceProps` (interface): interface WorldMapSurfaceProps — Props for {@link WorldMapSurface}.
|
|
948
1428
|
- `useFog` (function): function useFog(fog: FogField): ReturnType<FogField["cells"]> — ⚠ undocumented
|
|
949
1429
|
- `useMarkers` (function): function useMarkers<TMeta = unknown>(markers: MarkerSet<TMeta>): readonly MapMarker<TMeta>[] — Subscribe to a native marker set or external marker source, or read a static marker array.
|
|
950
1430
|
|
|
1431
|
+
## @jgengine/react/menuRouter
|
|
1432
|
+
|
|
1433
|
+
- `MenuRouter` (interface): interface MenuRouter<Id extends string> — A menu screen stack: where you are, how you got there, and how to go back.
|
|
1434
|
+
- `MenuStackAction` (type): type MenuStackAction<Id extends string> = | { type: "open"; id: Id } | { type: "back" } | { type: "replace"; id: Id } | { type: "reset"; id?: Id } — A screen-stack transition. `reset` without an id collapses to the router's original root.
|
|
1435
|
+
- `menuStackReducer` (function): function menuStackReducer<Id extends string>(path: readonly Id[], action: MenuStackAction<Id>, root: Id): readonly Id[] — The pure screen-stack transition behind {@link useMenuRouter}. Exported so a game can drive the same navigation from its own store or a replayable command log instead of React state.
|
|
1436
|
+
- `useMenuRouter` (function): function useMenuRouter<Id extends string>(root: Id, options: { escapeToBack?: boolean } = {}): MenuRouter<Id> — The screen stack behind a game front-end: title → save select → settings → credits, and Escape back out. Every game menu needs this and none of it is game-specific, so it ships here rather than being re-derived per game. Holds no content and imposes no look — the game decides what each screen id renders.
|
|
1437
|
+
|
|
1438
|
+
## @jgengine/react/modals
|
|
1439
|
+
|
|
1440
|
+
- `ConfirmDialog` (function): function ConfirmDialog({ title, body, confirmLabel = "Confirm", cancelLabel = "Cancel", onConfirm, onCancel, danger = false, width = 360, className, style, }: ConfirmDialogProps): ReactNode — A generic two-button confirmation dialog — title, optional body, and Cancel / Confirm buttons over a `HudTheme`-token-driven {@link HudFrame}. Presentation-only: wire `onConfirm`/`onCancel` to a modal stack's `resolve` (typically inside a {@link ModalHost} render callback) and reskin via `HudTheme` tokens or `danger` for a destructive action. It interprets nothing — the game supplies the copy.
|
|
1441
|
+
- `ConfirmDialogProps` (interface): interface ConfirmDialogProps — Props for {@link ConfirmDialog}.
|
|
1442
|
+
- `ModalControls` (interface): interface ModalControls — Stack-bound controls handed to a {@link ModalHost} render callback.
|
|
1443
|
+
- `ModalHost` (function): function ModalHost({ stack, children, showBackdrop = true, backdrop, closeOnBackdrop = true, closeOnEsc = true, zIndexBase = 80, className, style, }: ModalHostProps): ReactNode — Full-screen modal host: watches a stack, renders only the topmost modal centered over a dimmed backdrop, and manages accessibility — the panel is a `role="dialog" aria-modal`, focus moves into it on open and is trapped with Tab/Shift+Tab cycling, Escape and (optionally) a backdrop click cancel the top modal, and focus returns to the previously focused element on close. It renders nothing when the stack is empty. Skin the panel and backdrop via `HudTheme` tokens.
|
|
1444
|
+
- `ModalHostProps` (interface): interface ModalHostProps — Props for {@link ModalHost}.
|
|
1445
|
+
- `ModalStackView` (interface): interface ModalStackView — React chrome over the headless modal stack (`@jgengine/core/ui/modalStack`) — the blocking-overlay layer a game raises over its scene: a pause menu, a "quit to menu?" confirm, a reward popup. {@link useModalStack} is the DATA/HOOK layer (subscribe + the active record), {@link ModalHost} renders the top modal with a backdrop, focus trap, and Esc-to-cancel, and {@link ConfirmDialog} / {@link PauseMenu} are ready-to-wire, HudTheme-token-driven building blocks. All unskinned and game-owned: the model never interprets a modal's `kind`, so a game switches on it to pick which of these (or its own) content to show, and reskins everything via `HudTheme` tokens and the frame.
|
|
1446
|
+
- `PauseMenu` (function): function PauseMenu({ title = "Paused", onResume, resumeLabel = "Resume", items = [], width = 300, className, style, }: PauseMenuProps): ReactNode — A reskinnable pause-menu building block: a primary Resume button plus a game-filled list of slot items (Settings, Save, Quit, …), stacked in a `HudTheme`-token-driven {@link HudFrame}. It ships the common shape every game's pause screen needs and nothing genre-specific — the game supplies the title, item labels/order, and destructive styling, and reskins with `HudTheme` tokens. Drop it into a {@link ModalHost} keyed on a `"pause"` modal, or render it standalone.
|
|
1447
|
+
- `PauseMenuItem` (interface): interface PauseMenuItem — One selectable row in a {@link PauseMenu}'s slot list (Settings, Save, Quit, …).
|
|
1448
|
+
- `PauseMenuProps` (interface): interface PauseMenuProps — Props for {@link PauseMenu}.
|
|
1449
|
+
- `useModalStack` (function): function useModalStack(stack: ModalStack): ModalStackView — Subscribe to a modal stack and re-render on every change, returning the active modal and depth.
|
|
1450
|
+
|
|
1451
|
+
## @jgengine/react/notifications
|
|
1452
|
+
|
|
1453
|
+
- `NotificationBell` (function): function NotificationBell({ store, onClick, icon = "🔔", className, style }: NotificationBellProps): ReactNode — Notification bell — an icon button with an unread-count badge, bound to a notification store. Toggle a {@link NotificationCenter} panel from its click.
|
|
1454
|
+
- `NotificationBellProps` (interface): interface NotificationBellProps — Props for {@link NotificationBell}.
|
|
1455
|
+
- `NotificationCenter` (function): function NotificationCenter({ store, title = "Notifications", emptyLabel = "You're all caught up.", onClose, formatTime, className, style, }: NotificationCenterProps): ReactNode — Notification center panel — the scrollable log toasts don't provide: newest notifications with a kind-colored marker, title/body, relative time, and an unread highlight; a header with the unread count, mark-all-read, and clear. Clicking an entry marks it read. Bind it to a `createNotificationCenter`.
|
|
1456
|
+
- `NotificationCenterProps` (interface): interface NotificationCenterProps — Props for {@link NotificationCenter}.
|
|
1457
|
+
- `useNotifications` (function): function useNotifications<TMeta = unknown>(store: NotificationStore<TMeta>): readonly NotificationEntry<TMeta>[] — Subscribe to a notification store's live list.
|
|
1458
|
+
|
|
1459
|
+
## @jgengine/react/objectiveBanner
|
|
1460
|
+
|
|
1461
|
+
- `ObjectiveBannerHost` (function): function ObjectiveBannerHost({ controller, theme, kindThemes, animate = true, dismissOnClick = false, zIndex = 50, className, style, }: ObjectiveBannerHostProps): ReactNode — A full-screen overlay that renders an {@link ObjectiveBannerController} as the classic transient centered title stamp — "WAVE 3", "VICTORY", "OBJECTIVE COMPLETE" — flying in, holding, and fading out. It subscribes to the model, drives `advance()` on an animation frame (unless the game ticks it), and maps the current banner's phase + progress to opacity/scale/translate. Reskin the base look with {@link ObjectiveBannerTheme} and color each variant via `kindThemes` keyed on the game-owned `kind`. Presentation only: all timing and queueing live in the core model, and `kind` is never interpreted here.
|
|
1462
|
+
- `ObjectiveBannerHostProps` (interface): interface ObjectiveBannerHostProps — Props for {@link ObjectiveBannerHost}.
|
|
1463
|
+
- `ObjectiveBannerTheme` (interface): interface ObjectiveBannerTheme — Reskin tokens for {@link ObjectiveBannerHost}. Per-`kind` overrides layer on top.
|
|
1464
|
+
- `useObjectiveBanner` (function): function useObjectiveBanner(controller: ObjectiveBannerController, animate = true): ObjectiveBannerView | null — Subscribe to a banner controller, drive its clock on an animation frame (unless the game already ticks it), and return the banner to draw right now — or `null` when idle. Re-renders every frame while a banner is animating.
|
|
1465
|
+
|
|
951
1466
|
## @jgengine/react/panels
|
|
952
1467
|
|
|
953
1468
|
- `PanelHost` (function): function PanelHost({ manager, render, panels, variation, shape, width, zIndexBase = 40, className, windowClassName, windowStyle, bodyStyle, }: { manager: PanelsManager; /** Content for a panel by id. Takes precedence over `panels`. */ render?: (id: string) => ReactNode; /** Static content map by pan… — Renders the open panels of a {@link usePanels} manager as absolutely-positioned, draggable, closable windows in z-order — the WoW window layer. Each window uses {@link HudFrame} chrome, is dragged by its title bar, raises focus on pointer-down, and gets its content from the `render` prop (or a `panels` map). Accessible: every window is a `role="dialog"` with an `aria-label` and a focusable close button; ESC-close is wired by the manager. Unskinned — art-direct via `HudTheme` tokens and the `variation`.
|
|
@@ -958,12 +1473,25 @@
|
|
|
958
1473
|
- `panelKeyAction` (function): function panelKeyAction(defs: readonly PanelDef[], state: PanelState, event: { code?: string; key?: string }): PanelKeyResult — Pure keybind resolver for a panel set: ESC resolves to `closeTop` when a closable window is open, and any other key routes through {@link panelByHotkey} (trying `code` then `key`) to a `toggle`. Returns the intent without touching the DOM, so it unit-tests headless and `usePanels` is a thin shell over it.
|
|
959
1474
|
- `usePanels` (function): function usePanels(defs: readonly PanelDef[], options?: UsePanelsOptions): PanelsManager — The DATA/HOOK layer: wrap the core panel model in state and install a window keybind listener — per-panel hotkeys toggle their window and ESC closes the topmost closable one. Hotkeys are ignored while the player is typing in an input/textarea/contenteditable. The listener is cleaned up on unmount and SSR-safe (armed in an effect). Feed the returned manager to {@link PanelHost}, or drive a bespoke window layout from it directly.
|
|
960
1475
|
|
|
1476
|
+
## @jgengine/react/photoMode
|
|
1477
|
+
|
|
1478
|
+
- `PhotoModeControls` (function): function PhotoModeControls({ store, onCapture, className, style }: PhotoModeControlsProps): ReactNode — Photo-mode toolbar — a hide/show-HUD toggle, a capture button, and an exit button, bound to a `createPhotoModeStore`. Presentation-only: the game wires `onCapture` to shell `captureCanvas`/`downloadImage` and reads `hideHud` to drop its gameplay HUD.
|
|
1479
|
+
- `PhotoModeControlsProps` (interface): interface PhotoModeControlsProps — Props for {@link PhotoModeControls}.
|
|
1480
|
+
- `usePhotoMode` (function): function usePhotoMode(store: PhotoModeStore): PhotoModeState — Subscribe to a photo-mode store's live state.
|
|
1481
|
+
|
|
961
1482
|
## @jgengine/react/preview
|
|
962
1483
|
|
|
963
1484
|
- `GamePreviewComponent` (type): type GamePreviewComponent = ComponentType<GamePreviewProps> — ⚠ undocumented
|
|
964
1485
|
- `GamePreviewProps` (type): type GamePreviewProps = { className?: string; } — ⚠ undocumented
|
|
965
1486
|
- `GamePreviewStates` (type): type GamePreviewStates = Record<string, GamePreviewComponent> — ⚠ undocumented
|
|
966
1487
|
|
|
1488
|
+
## @jgengine/react/previewFixtures
|
|
1489
|
+
|
|
1490
|
+
- `PREVIEW_FIXTURES` (const): const PREVIEW_FIXTURES: Record<string, PreviewFixture> — Registry of deterministic, engine-level preview fixtures — the *real* exported `@jgengine/react` components (`HudThemePreview`, `BarsPreview`, `IconsPreview`, …) that render identically every time from static values, so they can be screenshotted as regression evidence without booting a game.
|
|
1491
|
+
- `PreviewFixture` (interface): interface PreviewFixture — One entry in the engine preview-fixture registry: a deterministic, engine-level preview component keyed by a stable id.
|
|
1492
|
+
- `previewFixtureNames` (function): function previewFixtureNames(): string[] — Sorted list of registered fixture names, for discovery/listing.
|
|
1493
|
+
- `resolvePreviewFixture` (function): function resolvePreviewFixture(name: string): PreviewFixture | undefined — Resolve a fixture by name, or `undefined` when it is not registered.
|
|
1494
|
+
|
|
967
1495
|
## @jgengine/react/provider
|
|
968
1496
|
|
|
969
1497
|
- `GameContextBridge` (function): function GameContextBridge({ context, children, }: { context: GameContext | null; children?: ReactNode; }): React.JSX.Element — Re-provide a captured {@link GameContext} across a nested React reconciler boundary. The `<Canvas>` of `@react-three/fiber` renders its children in a *separate* React root, so a `GameProvider` in the outer tree does NOT reach inside it — hooks like `useGameContext` / `useEntityRenderCues` throw. The fix the shell already uses internally: capture the context outside the boundary (with {@link useOptionalGameContext}) and wrap the inner tree in `GameContextBridge`. A `null` context renders children unchanged, so the same code works in showcases with no running game. This is the seam behind `EntityPreview` — reach for it directly when building a bespoke nested canvas.
|
|
@@ -971,6 +1499,24 @@
|
|
|
971
1499
|
- `useGameContext` (function): function useGameContext(): GameContext — ⚠ undocumented
|
|
972
1500
|
- `useOptionalGameContext` (function): function useOptionalGameContext(): GameContext | null — The game context if a `GameProvider` is present, otherwise `null` — for chrome that may render outside a running game (showcases, previews).
|
|
973
1501
|
|
|
1502
|
+
## @jgengine/react/questTracker
|
|
1503
|
+
|
|
1504
|
+
- `QuestTracker` (function): function QuestTracker({ quests, title = "Quests", emptyLabel = "No active quests.", maxObjectives, accent = "var(--jg-accent, #facc15)", className, style, }: QuestTrackerProps): ReactNode — Quest / objective tracker HUD — a compact panel of active quests with a title and labelled, progress-barred objectives (checked + struck when complete). Presentation-only over `describeTrackedQuest(def, instance)` views, so it stays decoupled from the `QuestJournal` runtime.
|
|
1505
|
+
- `QuestTrackerProps` (interface): interface QuestTrackerProps — Props for {@link QuestTracker}.
|
|
1506
|
+
|
|
1507
|
+
## @jgengine/react/quickMenu
|
|
1508
|
+
|
|
1509
|
+
- `QuickMenu` (function): function QuickMenu({ items, layout = "list", onSelect, onClose, title, columns = 3, arc = { startAngle: Math.PI / 2, sweep: Math.PI }, radialSize = 300, accent = "var(--jg-accent, #38bdf8)", className, style, }: QuickMenuProps): ReactNode — Versatile quick menu that takes many forms — a `radial` wheel, a partial `arc`, a vertical `list`, or a `grid` — over one item model with icons, labels, hotkeys, count badges, cooldowns, section headers, and nested submenus (drill in / back). Radial and arc forms reuse {@link RadialMenu}; list and grid render sectioned rows/tiles. The game supplies content and skin.
|
|
1510
|
+
- `QuickMenuItem` (interface): interface QuickMenuItem extends RadialMenuOption — An entry on a {@link QuickMenu}: a leaf action, or (with `children`) a submenu.
|
|
1511
|
+
- `QuickMenuLayout` (type): type QuickMenuLayout = "radial" | "arc" | "list" | "grid" — The forms a {@link QuickMenu} can take.
|
|
1512
|
+
- `QuickMenuProps` (interface): interface QuickMenuProps — Props for {@link QuickMenu}.
|
|
1513
|
+
|
|
1514
|
+
## @jgengine/react/radialMenu
|
|
1515
|
+
|
|
1516
|
+
- `RadialMenu` (function): function RadialMenu({ options, open = true, onSelect, onClose, size = 300, innerRadius = 52, arc, highlightIndex, accent = "var(--jg-accent, #38bdf8)", className, style, }: RadialMenuProps): ReactNode — Radial / quick menu (weapon or emote wheel) — a ring or partial `arc` of selectable wedges the player points at with the mouse (or a stick). Pointer angle drives the highlight via core `radialIndexFromVector`; click/confirm fires `onSelect`, the neutral hub closes. Options carry optional hotkeys, count badges, cooldowns, and submenu markers. The game supplies icons/labels and skins it.
|
|
1517
|
+
- `RadialMenuOption` (interface): interface RadialMenuOption — One selectable entry on a radial/quick menu (weapon or emote wheel).
|
|
1518
|
+
- `RadialMenuProps` (interface): interface RadialMenuProps — Props for {@link RadialMenu}.
|
|
1519
|
+
|
|
974
1520
|
## @jgengine/react/rotateDevice
|
|
975
1521
|
|
|
976
1522
|
- `RotateDeviceScreen` (function): function RotateDeviceScreen({ title = "Turn your device", description, requiredOrientation = "landscape", accent = "var(--jg-accent, #8ea2ff)", icon, className, style, }: { /** Short headline. */ title?: string; /** One concise explanatory line. Defaults from `requiredOrientation`. */ description?: … — Full-viewport, non-dismissible rotate-device gate shown when a game requires an orientation the device isn't in.
|
|
@@ -980,6 +1526,21 @@
|
|
|
980
1526
|
- `SaveStoreView` (interface): interface SaveStoreView<T> — The reactive slice of a {@link SaveStore} returned by {@link useSaveStore} — the live value plus bound save actions, all re-rendering on change.
|
|
981
1527
|
- `useSaveStore` (function): function useSaveStore<T>(store: SaveStore<T>, options?: { load?: boolean }): SaveStoreView<T> — Bind a {@link SaveStore} to React: returns the live `value` and `status` and re-renders whenever either changes. By default it calls `load()` once on mount (pass `{ load: false }` to hydrate yourself). The same hook works for offline (localStorage) and cloud (Convex/DB) saves — only the store's backend differs.
|
|
982
1528
|
|
|
1529
|
+
## @jgengine/react/saveSlots
|
|
1530
|
+
|
|
1531
|
+
- `SaveSlotMenu` (function): function SaveSlotMenu({ model, onLoad, onNew, onDelete, onContinue, title = "Select Save", theme, now = Date.now, metaIcons, className, style, }: SaveSlotMenuProps): ReactNode — A drop-in save-select / profile menu that renders a {@link SaveSlots} index as a column of cards. A filled slot shows its name, the free-string `meta` the game supplied as chips, and a relative "saved" time, with Load and Delete actions; an empty slot shows a "New Game" affordance. A top-level Continue button targets the newest save (`model.mostRecent()`). This is a starting-point game-front-end building block — the game owns final art, wording, and layout; reskin it with {@link SaveSlotMenuTheme} or HudTheme CSS vars. Presentation only: all state lives in the core model, and `meta` keys are never interpreted.
|
|
1532
|
+
- `SaveSlotMenuProps` (interface): interface SaveSlotMenuProps — Props for {@link SaveSlotMenu}.
|
|
1533
|
+
- `SaveSlotMenuTheme` (interface): interface SaveSlotMenuTheme — Reskin tokens for {@link SaveSlotMenu}. All optional — each falls back to a HudTheme var then a neutral default.
|
|
1534
|
+
- `relativeSavedAt` (function): function relativeSavedAt(savedAt: number, nowMs = Date.now()): string — Turn a `savedAt` timestamp into a compact relative label ("just now", "4m ago", "2d ago"). Presentation-only helper — the model stores raw ms.
|
|
1535
|
+
- `useSaveSlots` (function): function useSaveSlots(model: SaveSlots): SaveSlotMeta[] — Subscribe to a {@link SaveSlots} index and re-render on any change (write, clear, rename, restore). Returns the live list of slots in menu order. Wire it into a save-select screen and mutate the model in event handlers — the menu re-renders itself.
|
|
1536
|
+
|
|
1537
|
+
## @jgengine/react/scoreboard
|
|
1538
|
+
|
|
1539
|
+
- `MedalToken` (type): type MedalToken = "gold" | "silver" | "bronze" — The medal tokens {@link medalFor} emits for the podium.
|
|
1540
|
+
- `Scoreboard` (function): function Scoreboard({ entries, rows, options, title, scoreLabel = "Score", nameFor, formatScore, medalIcon, theme, className, style, }: ScoreboardProps): ReactNode — A reskinnable ranked-score table for the {@link rankLeaderboard} selector: a rank column (medal icon/color for the top three via {@link medalFor}, otherwise the number), a name column, and a score column. The local player's row (`isLocal`) is washed and accented so "you" stands out. Feed it already-ranked `entries`, or raw `rows` plus `options` and it ranks them for you. All colors and spacing come from {@link ScoreboardTheme} / HudTheme `--jg-*` tokens — the component reads the model and never styles by game meaning.
|
|
1541
|
+
- `ScoreboardProps` (interface): interface ScoreboardProps — Props for {@link Scoreboard}. Pass either `entries` (already ranked) or `rows` + `options`.
|
|
1542
|
+
- `ScoreboardTheme` (interface): interface ScoreboardTheme — Reskin tokens for {@link Scoreboard}. Every color/spacing value reads a `--jg-*` token first.
|
|
1543
|
+
|
|
983
1544
|
## @jgengine/react/selectSnapshot
|
|
984
1545
|
|
|
985
1546
|
- `SelectCache` (type): type SelectCache<TSnapshot, TSelected> = { ready: boolean; snapshot: TSnapshot; value: TSelected; } — ⚠ undocumented
|
|
@@ -999,6 +1560,7 @@
|
|
|
999
1560
|
|
|
1000
1561
|
## @jgengine/react/settings
|
|
1001
1562
|
|
|
1563
|
+
- `SETTINGS_TRIGGER_CLASSNAME` (const): const SETTINGS_TRIGGER_CLASSNAME: "pointer-events-auto flex h-8 w-8 items-center justify-center rounded-md border border-[var(--jg-edge-bright)] bg-[var(--jg-surface)]/80 text-base text-[var(--jg-text-dim)] shadow-[0_1px_2px_rgba(0,0,0,0.6)] transition hover:bg-[var(--jg-surface-deep)] hover:text-[v… — Default HudTheme-token skin for {@link SettingsTrigger} — the 8×8 chrome button games re-authored seven times. Pass your own `className` only to override placement or brand chrome; the gear glyph already scales with `text-base` / `1em`.
|
|
1002
1564
|
- `SettingsActionView` (interface): interface SettingsActionView — A resolved game-state action — `run` is already bound to the game context and closes the menu.
|
|
1003
1565
|
- `SettingsCategoryView` (interface): interface SettingsCategoryView — A settings menu category with its rows and keybinds, ready to render.
|
|
1004
1566
|
- `SettingsController` (interface): interface SettingsController — The live settings controller — every category/row/keybind/action plus open-state. Render it any way you like or drive the engine menu.
|
|
@@ -1006,12 +1568,19 @@
|
|
|
1006
1568
|
- `SettingsKeybindRow` (interface): interface SettingsKeybindRow — One rebindable action row rendered in the controls settings category.
|
|
1007
1569
|
- `SettingsProvider` (function): function SettingsProvider({ store, children }: { store: SettingsStore; children: ReactNode }): React.JSX.Element — ⚠ undocumented
|
|
1008
1570
|
- `SettingsRow` (interface): interface SettingsRow — One editable setting rendered in a settings menu category.
|
|
1009
|
-
- `SettingsTrigger` (function): function SettingsTrigger({ className, children, label = "Settings", }: { className?: string; children?: ReactNode; label?: string; }): React.JSX.Element | null — Inline settings entry — drop it anywhere in your game's menu or HUD; it opens the themed settings menu. Headless: pass `className`
|
|
1571
|
+
- `SettingsTrigger` (function): function SettingsTrigger({ className = SETTINGS_TRIGGER_CLASSNAME, children, label = "Settings", }: { className?: string; children?: ReactNode; label?: string; }): React.JSX.Element | null — Inline settings entry — drop it anywhere in your game's menu or HUD; it opens the themed settings menu. Headless: pass `className` only when overriding the default HudTheme skin; pass `children` to replace the gear glyph. Renders nothing when the game has no settings to show, so it never leaves a dead button behind.
|
|
1010
1572
|
- `useHasSettings` (function): function useHasSettings(): boolean — True when the game has any setting or game-action to show — gate your own settings entry on it.
|
|
1011
1573
|
- `useSetting` (function): function useSetting<T extends SettingValue>(id: string, fallback: T): readonly [T, (value: SettingValue) => void] — Read + write one persisted setting; re-renders when the value changes anywhere.
|
|
1012
1574
|
- `useSettings` (function): function useSettings(): SettingsController — The engine settings controller for the current game — render your own settings UI from `categories`, or open the built-in menu with `open()`. Null-safe stub when mounted outside the shell.
|
|
1013
1575
|
- `useSettingsStore` (function): function useSettingsStore(): SettingsStore — The shared settings store, or a standalone one when no provider is mounted (game code read outside the shell).
|
|
1014
1576
|
|
|
1577
|
+
## @jgengine/react/shopGrid
|
|
1578
|
+
|
|
1579
|
+
- `ShopGrid` (function): function ShopGrid({ shop, wallet, onWalletChange, theme, currencyIcons, iconFor, showSell = false, walletCurrencies, title = "Shop", labelFor, minCardWidth = "140px", className, style, }: ShopGridProps): ReactNode — A drop-in vendor/shop grid: item cards (icon, name, price with a currency glyph, stock count or "∞") over a caller-owned wallet, plus a wallet balance readout. Each card's Buy button disables when the wallet cannot afford it (`shop.canAfford`) or the item is sold out; an optional Sell button appears for entries with a `sellPrice`. Buying/selling routes through the core shop model and hands the debited/credited wallet back via `onWalletChange` — the component never owns the wallet. Purely token-driven presentation (shared `--jg-*` HudTheme tokens, reskinnable via {@link ShopGridTheme}); `kind` and `currency` are free strings the game styles, never interpreted.
|
|
1580
|
+
- `ShopGridProps` (interface): interface ShopGridProps — Props for {@link ShopGrid}.
|
|
1581
|
+
- `ShopGridTheme` (interface): interface ShopGridTheme — Reskin tokens for {@link ShopGrid}. Falls back to shared `--jg-*` HudTheme tokens, then neutral defaults.
|
|
1582
|
+
- `useShopStock` (function): function useShopStock(shop: ShopStock): ShopStockEntry[] — Subscribe to a shop's stock and re-render whenever it changes (buy, sell, restock, price, add, remove, restore). Returns the current entry list — a detached snapshot safe to map over.
|
|
1583
|
+
|
|
1015
1584
|
## @jgengine/react/slots
|
|
1016
1585
|
|
|
1017
1586
|
- `ArmorSlots` (function): function ArmorSlots(props: SlotGridProps): React.JSX.Element — Armor piece slots.
|
|
@@ -1046,11 +1615,44 @@
|
|
|
1046
1615
|
- `StartScreen` (function): function StartScreen({ open = true, className, style, children, settings, settingsPlacement = "top-right", settingsClassName, settingsWrapperClassName, }: { open?: boolean; className?: string; style?: CSSProperties; children?: ReactNode; settings?: boolean | ReactNode; settingsPlacement?: StartScree… — Composable title/attract-screen scaffold: a full-bleed `data-jg-menu` overlay that positions and centers the game's own content, with an opt-in settings corner. It imposes no look — the game supplies the title, art, and buttons as children and styles the container through `className`/`style` (per the composable-chrome rule: a placement hook, not a mandated menu).
|
|
1047
1616
|
- `StartScreenCorner` (type): type StartScreenCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right" — Which corner of a `StartScreen` the opt-in settings slot is pinned to.
|
|
1048
1617
|
|
|
1618
|
+
## @jgengine/react/statusEffectBar
|
|
1619
|
+
|
|
1620
|
+
- `StatusEffectBar` (function): function StatusEffectBar({ effects, size = 44, gap = 8, iconFor, colorFor, schoolFor, labelFor, showTimer = true, ringWidth = 3, className, style, }: StatusEffectBarProps): ReactNode — A horizontal timeline of active status effects — one countdown-ring icon per effect. Presentation only and pure over its `effects` prop, so it renders straight off the status model's snapshot. `kind` is a free string the game styles (icon / color / label); the component never interprets buff-vs-debuff semantics. Ring, track, and frame read `HudTheme` tokens, so a theme change reskins the whole row.
|
|
1621
|
+
- `StatusEffectBarProps` (interface): interface StatusEffectBarProps — Props for {@link StatusEffectBar}.
|
|
1622
|
+
- `StatusIconResolver` (type): type StatusIconResolver = (kind: string) => GameIconName | ReactNode | null — `StatusEffectBar` (#status-effect-hud): a drop-in timeline HUD row that renders active buffs/debuffs as painted icons, each wrapped in a radial countdown ring and a stack-count badge, driven straight off the engine's existing status model (`StatusInstance` → `StatusEffectView`). A game passes its live effect views and gets a polished, reskinnable effect bar — no re-deriving ring math or timers. `kind` is a free string the game styles: the component never interprets buff-vs-debuff semantics, it only maps `kind` to an icon/color/label the game can fully override. Ring, track, and frame read `HudTheme` tokens (`--jg-accent`, `--jg-slot-*`), so a theme change reskins the whole row.
|
|
1623
|
+
|
|
1049
1624
|
## @jgengine/react/store
|
|
1050
1625
|
|
|
1051
1626
|
- `useKeyedStore` (function): function useKeyedStore<T>(handle: KeyedStoreHandle<T>, id: string): T — Subscribe a component to one owner's slot of a typed keyed-family store defined with `defineKeyedStore`. Returns the current value for `id` (or the definition's initial before any write for that id), re-rendering only when that owner's slot changes — the cast-free, boilerplate-free replacement for a hand-written `useGameStore((ctx) => ctx.game.store.get(`prefix:${id}`) as T)`.
|
|
1052
1627
|
- `useStore` (function): function useStore<T>(handle: StoreHandle<T>): T — Subscribe a component to a typed store slot defined with `defineStore`. Returns the current value (or the definition's initial before any write), re-rendering only when the slot changes — the cast-free, boilerplate-free replacement for a hand-written `useGameStore((ctx) => ctx.game.store.get(KEY) as T)`.
|
|
1053
1628
|
|
|
1629
|
+
## @jgengine/react/streetGeometryPreview
|
|
1630
|
+
|
|
1631
|
+
- `StreetGeometryPreview` (function): function StreetGeometryPreview({ className }: { className?: string }): React.JSX.Element — Deterministic close-up gallery of the shared road/junction mesh seam.
|
|
1632
|
+
|
|
1633
|
+
## @jgengine/react/talentTree
|
|
1634
|
+
|
|
1635
|
+
- `TalentIcon` (type): type TalentIcon = GameIconName | ReactNode | null — How a node id resolves to display art: a built-in {@link GameIconName}, any node, or `null` for the default.
|
|
1636
|
+
- `TalentTree` (function): function TalentTree<TStat extends string = string>({ view: viewProp, nodes, tree, onLearn, icon, label, branchLabel, title = "Talents", variation = "themed", nodeSize = 54, columnGap = 30, tierGap = 46, showPoints = true, className, style, }: TalentTreeProps<TStat>): ReactNode — Drop-in talent / skill-tree widget over the existing progression model (`@jgengine/core/game/talents` + its `talentTreeView` selector). The game passes its node definitions and a live `createTalentTree` instance; the widget lays nodes out by branch column and prerequisite-depth tier, draws SVG prerequisite edges, styles each node learned/available/locked/maxed, shows an icon + rank badge, and calls `onLearn(nodeId)` when the player clicks a node that is currently allocatable. All layout, edge-drawing, and eligibility come from the model/selector — the widget never re-derives topology. Unskinned and HudTheme-token driven; node ids/branches are opaque game data the game supplies icons and labels for.
|
|
1637
|
+
- `TalentTreeProps` (interface): interface TalentTreeProps<TStat extends string = string> — Props for {@link TalentTree}.
|
|
1638
|
+
|
|
1639
|
+
## @jgengine/react/timerReadout
|
|
1640
|
+
|
|
1641
|
+
- `TimerFormat` (type): type TimerFormat = "mm:ss" | "m:ss.d" | "ss.d" — Digital text format for a timer readout.
|
|
1642
|
+
- `TimerReadout` (function): function TimerReadout({ timer, id, source = "auto", format = "mm:ss", placeholder = "--:--", active = true, className, style, }: TimerReadoutProps): ReactNode — A live digital timer readout (mm:ss / m:ss.d) driven off a {@link TimerSet}. It re-reads every frame and formats remaining or elapsed time — a round clock, a respawn countdown, or an ability charge, all the same widget. HudTheme-skinned via `--jg-bar-text`; reskin with `style` or the theme tokens.
|
|
1643
|
+
- `TimerReadoutProps` (interface): interface TimerReadoutProps — Props for {@link TimerReadout}.
|
|
1644
|
+
- `TimerReadoutSource` (type): type TimerReadoutSource = "auto" | "remaining" | "elapsed" — Which value a readout leads with. `"auto"` follows the timer's direction — remaining for a countdown, elapsed for a countup charge.
|
|
1645
|
+
- `TimerRing` (function): function TimerRing({ timer, id, size = 72, thickness = 8, mode = "fill", color = "var(--jg-accent, #38bdf8)", trackColor = "var(--jg-bar-track, rgba(148,163,184,0.25))", children, active = true, className, style, }: TimerRingProps): ReactNode — A radial charge/cooldown ring driven off a {@link TimerSet}'s `progress01`. Re-reads every frame and sweeps an SVG arc as the timer advances — ability charge, cooldown wipe, respawn ring, capture progress, all the same widget. `mode` chooses filling vs. draining; center `children` can hold a readout. HudTheme-skinned via `--jg-accent` / `--jg-bar-track`.
|
|
1646
|
+
- `TimerRingProps` (interface): interface TimerRingProps — Props for {@link TimerRing}.
|
|
1647
|
+
- `formatTimerMs` (function): function formatTimerMs(ms: number, format: TimerFormat = "mm:ss"): string — Format a millisecond duration as digital timer text — `mm:ss` (default), `m:ss.d` (with tenths), or `ss.d` (seconds + tenths). Negative inputs clamp to zero. No genre meaning: the same helper serves a round clock, a respawn countdown, or an ability charge readout.
|
|
1648
|
+
- `useTimerRead` (function): function useTimerRead(timer: TimerSet, id: string, active = true): TimerRead | null — Subscribe to a single timer and re-read it every animation frame while mounted, so a HUD readout stays live without the game hand-rolling interval math. Reuses one read object (allocation-aware). Returns `null` for an unknown id. Pass `active={false}` to freeze the per-frame tick (e.g. an off-screen HUD).
|
|
1649
|
+
|
|
1650
|
+
## @jgengine/react/useDebouncedCommit
|
|
1651
|
+
|
|
1652
|
+
- `DebounceTimer` (interface): interface DebounceTimer — Injectable timer seam so the controller is testable with a manual clock.
|
|
1653
|
+
- `DebouncedCommit` (interface): interface DebouncedCommit<T> — Live-mirrored, trailing-debounced commit binding for a single control value.
|
|
1654
|
+
- `useDebouncedCommit` (function): function useDebouncedCommit<T>(value: T, commit: (value: T) => void, delayMs = 180): DebouncedCommit<T> — See {@link DebouncedCommit}. `commit` and `delayMs` may change between renders (kept in refs); the binding identity stays stable except when `value` (the local mirror) changes.
|
|
1655
|
+
|
|
1054
1656
|
## @jgengine/react/voice
|
|
1055
1657
|
|
|
1056
1658
|
- `MicToggle` (function): function MicToggle({ voice, className, mutedLabel, unmutedLabel, }: { voice: VoiceState; className?: string; mutedLabel?: ReactNode; unmutedLabel?: ReactNode; }): React.JSX.Element — ⚠ undocumented
|
|
@@ -1061,6 +1663,20 @@
|
|
|
1061
1663
|
- `VoiceState` (interface): interface VoiceState — ⚠ undocumented
|
|
1062
1664
|
- `useVoice` (function): function useVoice(options?: UseVoiceOptions): VoiceState — Mic capture + push-to-talk + channel roster over the VoiceTransport signaling seam. Transmission gates the captured tracks' `enabled` flag; the media plane that actually moves audio bytes (WebRTC/SFU) stays behind the transport, host-supplied. Call once per voice channel and hand the returned state to the voice components.
|
|
1063
1665
|
|
|
1666
|
+
## @jgengine/react/waveHud
|
|
1667
|
+
|
|
1668
|
+
- `WaveHud` (function): function WaveHud({ runner, theme, variation = "plate", width = 260, className, style }: WaveHudProps): ReactNode — A drop-in wave/spawn HUD panel over a {@link WaveRunner}: a big "WAVE N" label, a wave-progress bar (the shared {@link ExperienceBar}), and the live spawned / total, budget, and alert readouts — the visible face of "the brain behind WAVE 3". It subscribes to the runner and re-renders on change; the game drives the runner's clock. Reskin with {@link WaveHudTheme} and the shared HudTheme bar tokens. When the final wave finishes it shows a "WAVES CLEARED" state. Presentation only: the schedule, budget, and RNG live in the core model, and spawn `kind`s are never read.
|
|
1669
|
+
- `WaveHudProps` (interface): interface WaveHudProps — Props for {@link WaveHud}.
|
|
1670
|
+
- `WaveHudTheme` (interface): interface WaveHudTheme — Reskin tokens for {@link WaveHud}. All optional; each falls back to a sensible default.
|
|
1671
|
+
- `useWaveRunner` (function): function useWaveRunner(runner: WaveRunner): WaveView — Subscribe to a {@link WaveRunner} and re-render whenever it notifies (wave, budget, spawns, alert change). Returns the runner's pooled {@link WaveView}. The runner is driven by the game/demo (call `runner.update(dt)`), not by this hook.
|
|
1672
|
+
|
|
1673
|
+
## @jgengine/react/waypointMarkers
|
|
1674
|
+
|
|
1675
|
+
- `WaypointMarkerTheme` (interface): interface WaypointMarkerTheme — Reskin tokens for {@link WaypointMarkers}. Per-`kind` color layers on top via `kindColors`.
|
|
1676
|
+
- `WaypointMarkers` (function): function WaypointMarkers({ entries, project, viewport, distanceOf, distanceFormat, theme, kindColors, margin = 28, showPinLabels = true, className, style, }: WaypointMarkersProps): ReactNode — Off-screen objective / waypoint markers: an absolutely-positioned overlay that turns a set of world waypoints into on-screen pins and off-screen directional arrows. For each waypoint it calls the caller's `project` to get a screen point, then {@link layoutScreenMarker} to decide: an in-view target renders a pin (and optional label) at its projected spot; an off-screen or behind-camera target renders an arrow clamped to the viewport edge, rotated to point the way, with an optional distance label from `distanceOf`. Color comes from `theme` plus a per-`kind` `kindColors` map the game owns — the model never interprets `kind`. Presentation only: tracking, projection, and distance are all caller-supplied.
|
|
1677
|
+
- `WaypointMarkersProps` (interface): interface WaypointMarkersProps — Props for {@link WaypointMarkers}.
|
|
1678
|
+
- `useWaypoints` (function): function useWaypoints(source: WaypointTracker | readonly Waypoint[]): readonly Waypoint[] — Subscribe to a {@link WaypointTracker} and re-render on every change, returning its current waypoints. Pass a plain array instead and it is returned as-is (no subscription), so a game can drive the host from a tracker or from its own derived state.
|
|
1679
|
+
|
|
1064
1680
|
## @jgengine/shell/GamePhaseStamp
|
|
1065
1681
|
|
|
1066
1682
|
- `GamePhaseStamp` (function): function GamePhaseStamp(): null — ⚠ undocumented
|
|
@@ -1127,6 +1743,8 @@
|
|
|
1127
1743
|
- `CameraOccluder` (interface): interface CameraOccluder — Camera spring-arm occlusion filtering.
|
|
1128
1744
|
- `CameraShakeChannel` (interface): interface CameraShakeChannel — ⚠ undocumented
|
|
1129
1745
|
- `CameraShakeContext` (const): const CameraShakeContext: React.Context<CameraShakeChannel> — ⚠ undocumented
|
|
1746
|
+
- `ControllerCameraShake` (function): function ControllerCameraShake({ controller, priority = GAME_SIM_FRAME_PRIORITY, }: ControllerCameraShakeProps): ReactNode — The shell-side consumer of a core {@link CameraShakeController}: each frame it calls `controller.update(delta)` to bleed trauma, reads the pooled `controller.offset()`, and applies it additively to the active camera — a positional kick plus a pitch/yaw/roll rotation — so the view VISIBLY shakes on impacts. It runs after the camera rig (which re-poses the camera to its base every frame), so the shake composes with any rig without a manual save/restore and without fighting the built-in `shakeChannel`. Renders nothing.
|
|
1747
|
+
- `ControllerCameraShakeProps` (interface): interface ControllerCameraShakeProps — Props for {@link ControllerCameraShake}.
|
|
1130
1748
|
- `GAME_SIM_FRAME_PRIORITY` (const): const GAME_SIM_FRAME_PRIORITY: 0 — Run simulation/movement before orbit follow so poses are current.
|
|
1131
1749
|
- `GameCameraRig` (function): function GameCameraRig({ yawRef, pitchRef, config, onDragChange, pointerControls, panKeysEnabled, director, viewmodel, }: GameCameraRigProps): React.JSX.Element — ⚠ undocumented
|
|
1132
1750
|
- `GameCameraRigProps` (interface): interface GameCameraRigProps — ⚠ undocumented
|
|
@@ -1145,6 +1763,11 @@
|
|
|
1145
1763
|
- `readFirstPersonMuzzle` (function): function readFirstPersonMuzzle(target: THREE.Vector3): boolean — World position of the first-person weapon muzzle, or false when no viewmodel is mounted.
|
|
1146
1764
|
- `usePlayerFov` (function): function usePlayerFov(): PlayerFovState — ⚠ undocumented
|
|
1147
1765
|
|
|
1766
|
+
## @jgengine/shell/camera/ControllerCameraShake
|
|
1767
|
+
|
|
1768
|
+
- `ControllerCameraShake` (function): function ControllerCameraShake({ controller, priority = GAME_SIM_FRAME_PRIORITY, }: ControllerCameraShakeProps): ReactNode — The shell-side consumer of a core {@link CameraShakeController}: each frame it calls `controller.update(delta)` to bleed trauma, reads the pooled `controller.offset()`, and applies it additively to the active camera — a positional kick plus a pitch/yaw/roll rotation — so the view VISIBLY shakes on impacts. It runs after the camera rig (which re-poses the camera to its base every frame), so the shake composes with any rig without a manual save/restore and without fighting the built-in `shakeChannel`. Renders nothing.
|
|
1769
|
+
- `ControllerCameraShakeProps` (interface): interface ControllerCameraShakeProps — Props for {@link ControllerCameraShake}.
|
|
1770
|
+
|
|
1148
1771
|
## @jgengine/shell/camera/GameCameraRig
|
|
1149
1772
|
|
|
1150
1773
|
- `GameCameraRig` (function): function GameCameraRig({ yawRef, pitchRef, config, onDragChange, pointerControls, panKeysEnabled, director, viewmodel, }: GameCameraRigProps): React.JSX.Element — ⚠ undocumented
|
|
@@ -1346,7 +1969,7 @@
|
|
|
1346
1969
|
|
|
1347
1970
|
## @jgengine/shell/drivers/FrameDriver
|
|
1348
1971
|
|
|
1349
|
-
- `FrameDriver` (function): function FrameDriver({ ctx, playable, tracker, yawRef, pitchRef, primaryClickRef, pointerAxisRef, gateRef, onRuntimeError, multiplayer, serverIdRef, pointerService, pointerAim, pingCommand, poster, onPosterSettled, }: { ctx: GameContext; playable: PlayableGame; tracker: ActionStateTracker
|
|
1972
|
+
- `FrameDriver` (function): function FrameDriver({ ctx, playable, tracker, yawRef, pitchRef, primaryClickRef, pointerAxisRef, analogRef, gateRef, onRuntimeError, multiplayer, serverIdRef, pointerService, pointerAim, pingCommand, poster, onPosterSettled, }: { ctx: GameContext; playable: PlayableGame; tracker: ActionStateTracker… — ⚠ undocumented
|
|
1350
1973
|
- `POSTER_SETTLE_SECONDS` (const): const POSTER_SETTLE_SECONDS: 1.6 — ⚠ undocumented
|
|
1351
1974
|
|
|
1352
1975
|
## @jgengine/shell/drivers/HudOnlyDriver
|
|
@@ -1355,6 +1978,8 @@
|
|
|
1355
1978
|
|
|
1356
1979
|
## @jgengine/shell/environment
|
|
1357
1980
|
|
|
1981
|
+
- `DayNightSky` (function): function DayNightSky({ cycle, radius, hazeStrength, sunGlowStrength, lights = true, keyLightIntensity = 1.1, ambientIntensity = 0.6, }: DayNightSkyProps): React.JSX.Element — Binds a {@link DayNightCycle} to the engine's existing `SkyDome` shader and a pair of lights: each frame it reads `cycle.sample()` and writes the blended tint into the dome's top/horizon/sun uniforms while the sun's arc comes from the shared `daylightStateAt` geometry. This is the turnkey presentation seam — a game mounts this one component in its scene and gets a moving, color-graded day-night sky from the serializable model, with no hand-rolled per-frame lerp and no new renderer. The cycle's `phase`/color values are free-form and never interpreted here.
|
|
1982
|
+
- `DayNightSkyProps` (interface): interface DayNightSkyProps — Props for {@link DayNightSky}: the cycle to bind plus optional dome shape and light-strength knobs.
|
|
1358
1983
|
- `DaylightCycleConfig` (interface): interface DaylightCycleConfig — ⚠ undocumented
|
|
1359
1984
|
- `DaylightProps` (interface): interface DaylightProps — ⚠ undocumented
|
|
1360
1985
|
- `DaylightState` (interface): interface DaylightState — ⚠ undocumented
|
|
@@ -1369,6 +1994,8 @@
|
|
|
1369
1994
|
|
|
1370
1995
|
## @jgengine/shell/environment
|
|
1371
1996
|
|
|
1997
|
+
- `DayNightSky` (function): function DayNightSky({ cycle, radius, hazeStrength, sunGlowStrength, lights = true, keyLightIntensity = 1.1, ambientIntensity = 0.6, }: DayNightSkyProps): React.JSX.Element — Binds a {@link DayNightCycle} to the engine's existing `SkyDome` shader and a pair of lights: each frame it reads `cycle.sample()` and writes the blended tint into the dome's top/horizon/sun uniforms while the sun's arc comes from the shared `daylightStateAt` geometry. This is the turnkey presentation seam — a game mounts this one component in its scene and gets a moving, color-graded day-night sky from the serializable model, with no hand-rolled per-frame lerp and no new renderer. The cycle's `phase`/color values are free-form and never interpreted here.
|
|
1998
|
+
- `DayNightSkyProps` (interface): interface DayNightSkyProps — Props for {@link DayNightSky}: the cycle to bind plus optional dome shape and light-strength knobs.
|
|
1372
1999
|
- `DaylightCycleConfig` (interface): interface DaylightCycleConfig — ⚠ undocumented
|
|
1373
2000
|
- `DaylightProps` (interface): interface DaylightProps — ⚠ undocumented
|
|
1374
2001
|
- `DaylightState` (interface): interface DaylightState — ⚠ undocumented
|
|
@@ -1381,6 +2008,11 @@
|
|
|
1381
2008
|
- `TimeOfDayDaylightProps` (interface): interface TimeOfDayDaylightProps — ⚠ undocumented
|
|
1382
2009
|
- `VolumetricCloudsProps` (interface): interface VolumetricCloudsProps — Props for {@link VolumetricClouds} — fully-resolved cloud rules plus the shared sun direction.
|
|
1383
2010
|
|
|
2011
|
+
## @jgengine/shell/environment/DayNightSky
|
|
2012
|
+
|
|
2013
|
+
- `DayNightSky` (function): function DayNightSky({ cycle, radius, hazeStrength, sunGlowStrength, lights = true, keyLightIntensity = 1.1, ambientIntensity = 0.6, }: DayNightSkyProps): React.JSX.Element — Binds a {@link DayNightCycle} to the engine's existing `SkyDome` shader and a pair of lights: each frame it reads `cycle.sample()` and writes the blended tint into the dome's top/horizon/sun uniforms while the sun's arc comes from the shared `daylightStateAt` geometry. This is the turnkey presentation seam — a game mounts this one component in its scene and gets a moving, color-graded day-night sky from the serializable model, with no hand-rolled per-frame lerp and no new renderer. The cycle's `phase`/color values are free-form and never interpreted here.
|
|
2014
|
+
- `DayNightSkyProps` (interface): interface DayNightSkyProps — Props for {@link DayNightSky}: the cycle to bind plus optional dome shape and light-strength knobs.
|
|
2015
|
+
|
|
1384
2016
|
## @jgengine/shell/environment/Daylight
|
|
1385
2017
|
|
|
1386
2018
|
- `DaylightProps` (interface): interface DaylightProps — ⚠ undocumented
|
|
@@ -1400,7 +2032,9 @@
|
|
|
1400
2032
|
|
|
1401
2033
|
## @jgengine/shell/environment/RoadRibbons
|
|
1402
2034
|
|
|
1403
|
-
- `
|
|
2035
|
+
- `AuthoredRoadNetwork` (interface): interface AuthoredRoadNetwork — Trimmed ribbons for every road plus the welded surfaces that fill the crossings between them.
|
|
2036
|
+
- `JunctionSurface` (interface): interface JunctionSurface — One welded asphalt junction surface plus the color it should render in.
|
|
2037
|
+
- `RoadRibbons` (function): function RoadRibbons({ road, field, paths, }: { road: RoadEnvironmentDescriptor; field: TerrainField; paths: readonly (readonly RoadPoint[])[]; }): React.JSX.Element | null — Renders one `road()` descriptor from its trimmed centerline sub-paths (cut back at every junction by {@link buildAuthoredRoadNetwork}): an asphalt ribbon, a curb/edge strip along each border, an optional dashed centerline, and optional sidewalks. Because the sub-paths already stop at the junction boundary, every layer naturally ends there — no ribbon ploughs through the crossing and the dashed line no longer needs exclusion circles to skip intersections.
|
|
1404
2038
|
|
|
1405
2039
|
## @jgengine/shell/environment/VolumetricClouds
|
|
1406
2040
|
|
|
@@ -1490,7 +2124,12 @@
|
|
|
1490
2124
|
|
|
1491
2125
|
## @jgengine/shell/postfx/PostProcessing
|
|
1492
2126
|
|
|
1493
|
-
- `PostProcessing` (function): function PostProcessing({ config, quality = "high" }: { config: PostProcessingConfig; quality?: GraphicsQuality }): null — Mounts an `EffectComposer` inside the shell Canvas and takes over rendering (priority-1 `useFrame`, which disables R3F auto-render) to run the configured post chain: RenderPass → GTAO → UnrealBloom → OutputPass → Grade. Rendered only when `PlayableGame.postProcessing` is set, so games without it draw unchanged.
|
|
2127
|
+
- `PostProcessing` (function): function PostProcessing({ config, quality = "high" }: { config: PostProcessingConfig; quality?: GraphicsQuality }): null — Mounts an `EffectComposer` inside the shell Canvas and takes over rendering (priority-1 `useFrame`, which disables R3F auto-render) to run the configured post chain: RenderPass → GTAO → UnrealBloom → SMAA → OutputPass → Grade. Rendered only when `PlayableGame.postProcessing` is set, so games without it draw unchanged.
|
|
2128
|
+
|
|
2129
|
+
## @jgengine/shell/postfx/ScreenEffectsOverlay
|
|
2130
|
+
|
|
2131
|
+
- `ScreenEffectsOverlay` (function): function ScreenEffectsOverlay({ controller, blendMode = "normal", zIndex = 40, animate = true, }: ScreenEffectsOverlayProps): ReactNode — A DOM overlay that renders a {@link ScreenEffectsController} as full-screen color-grade layers over the game canvas — damage vignettes, heal flashes, a sustained low-health pulse — through the shell's postfx overlay layer, so a game gets screen feedback without hand-rolling shader or overlay timing. It subscribes to the model, drives `advance()` on an animation frame (unless the game ticks it), and paints one absolutely-positioned, pointer-transparent layer per active effect at its eased opacity. Presentation only: all timing and state live in the core model, and `kind` is never interpreted here.
|
|
2132
|
+
- `ScreenEffectsOverlayProps` (interface): interface ScreenEffectsOverlayProps — Reskin tokens for {@link ScreenEffectsOverlay}.
|
|
1494
2133
|
|
|
1495
2134
|
## @jgengine/shell/postfx/gradeShader
|
|
1496
2135
|
|
|
@@ -1562,6 +2201,19 @@
|
|
|
1562
2201
|
- `ModelPick` (type): type ModelPick = { model?: string; fallbackModel?: string; style?: Omit<ModelConfig, "url" | "dims">; } — Preferred + optional fallback catalog ids for a single entity/object slot. Soft-resolves through the catalog: when neither id is live (pack not pulled/ reindexed yet), the mapping is omitted and the shell keeps its primitive. Re-home later by fixing ids / pulling packs — no Kenney, no hard throws.
|
|
1563
2202
|
- `ModelResolveContext` (interface): interface ModelResolveContext — ⚠ undocumented
|
|
1564
2203
|
|
|
2204
|
+
## @jgengine/shell/render/sceneCapture
|
|
2205
|
+
|
|
2206
|
+
- `CaptureRenderer` (interface): interface CaptureRenderer — The bit of a WebGL renderer scene capture needs — its backing `<canvas>`.
|
|
2207
|
+
- `SceneCaptureBinding` (function): function SceneCaptureBinding({ bind }: { bind: (capture: () => string | null) => void }): null — In-`<Canvas>` binder that hands the scene-capture function out to HUD code living outside the reconciler (a photo-mode Capture button). Mount it inside the game's `WorldOverlay`; call `bind` receives a `() => string | null` that grabs the current frame. Renders nothing.
|
|
2208
|
+
- `captureCanvas` (function): function captureCanvas(gl: CaptureRenderer): string | null — Read the current frame to a PNG data URL. Requires the R3F `<Canvas>` to have been created with `gl={{ preserveDrawingBuffer: true }}` (the shell's game canvas already is); returns null if the backing canvas can't be read.
|
|
2209
|
+
- `downloadImage` (function): function downloadImage(dataUrl: string, filename = "screenshot.png"): void — Trigger a browser download of an image data URL (the photo-mode "save" action).
|
|
2210
|
+
|
|
2211
|
+
## @jgengine/shell/render/useDisposable
|
|
2212
|
+
|
|
2213
|
+
- `Disposable` (interface): interface Disposable — Anything exposing dispose() — three.js geometries, materials, textures, render targets.
|
|
2214
|
+
- `disposeAll` (function): function disposeAll(value: Disposable | readonly Disposable[]): void — Dispose a single resource or every resource in a tuple.
|
|
2215
|
+
- `useDisposable` (function): function useDisposable<T extends Disposable | readonly Disposable[]>(create: () => T, deps: DependencyList): T — Memoize a three.js resource (or tuple of resources) and dispose it when `deps` change or the component unmounts. Owns the useMemo + dispose-effect pair that otherwise repeats at every GPU-resource call site. The factory must return objects exposing `dispose()` (geometries, materials, textures, render targets).
|
|
2216
|
+
|
|
1565
2217
|
## @jgengine/shell/render/useEntityRenderCues
|
|
1566
2218
|
|
|
1567
2219
|
- `useEntityRenderCues` (function): function useEntityRenderCues(instanceId: string | undefined, tuning?: RenderCueTuning): MutableRefObject<EntityRenderCues> — Live motion + animation cues for one entity, read from a mutable ref inside your own `useFrame` — no re-render per frame, no diffing the parent group's position, no game-side module map for attack/hit timing. Backs both custom `renderEntity` rigs and a custom first-person viewmodel (#542): call it with `entity.id` / the local player's userId and drive bob/recoil/reload poses from `cuesRef.current` inside the calling component's own `useFrame`.
|
|
@@ -1662,6 +2314,11 @@
|
|
|
1662
2314
|
- `EMPTY_RESERVED` (const): const EMPTY_RESERVED: ReadonlySet<string> — No action names are reserved when no camera rig is active (hud/none presentation): games may bind `turnLeft`/`interact`/etc. as their own.
|
|
1663
2315
|
- `NO_ACTIONS` (const): const NO_ACTIONS: string[] — Empty action list — published while the orientation gate is up to suppress all held input without touching the tracker.
|
|
1664
2316
|
|
|
2317
|
+
## @jgengine/shell/shellMovement
|
|
2318
|
+
|
|
2319
|
+
- `DEFAULT_WALK_CODES` (const): const DEFAULT_WALK_CODES: { readonly moveForward: readonly ["KeyW"]; readonly moveBack: readonly ["KeyS"]; readonly moveLeft: readonly ["KeyA"]; readonly moveRight: readonly ["KeyD"]; readonly jump: readonly ["Space"]; } — Default keyboard codes for the shell walk controller (WASD + Space). Use as the base of `defineGame({ input: { ...DEFAULT_WALK_CODES, interact: ["KeyE"] } })` instead of re-typing the same five bindings in every game.
|
|
2320
|
+
- `SHELL_MOVEMENT_ACTIONS` (const): const SHELL_MOVEMENT_ACTIONS: readonly ["moveForward", "moveBack", "moveLeft", "moveRight", "jump"] — Movement action names the shell drives via the walk controller.
|
|
2321
|
+
|
|
1665
2322
|
## @jgengine/shell/structures
|
|
1666
2323
|
|
|
1667
2324
|
- `BuildingBlock` (function): function BuildingBlock({ part, palette }: BuildingBlockProps): React.JSX.Element — ⚠ undocumented
|
|
@@ -1761,6 +2418,7 @@
|
|
|
1761
2418
|
- `TerrainHeightSampler` (type): type TerrainHeightSampler = (x: number, z: number) => number — ⚠ undocumented
|
|
1762
2419
|
- `TerrainNormal` (type): type TerrainNormal = readonly [number, number, number] — A surface normal vector at a terrain sample point.
|
|
1763
2420
|
- `TerrainSeed` (type): type TerrainSeed = number | string — ⚠ undocumented
|
|
2421
|
+
- `TerrainSurfaceColorOptions` (interface): interface TerrainSurfaceColorOptions — Slope/noise surface shading laid over the height lerp so untextured ground reads like terrain instead of a smooth two-tone gradient. All knobs are optional with sane defaults; every field is a pure function of vertex position (+ `seed`), so the coloring is stable across rebuilds and tests.
|
|
1764
2422
|
- `TerrainVertexColorOptions` (interface): interface TerrainVertexColorOptions — ⚠ undocumented
|
|
1765
2423
|
- `displaceHeightfieldGeometry` (function): function displaceHeightfieldGeometry(geometry: THREE.BufferGeometry, sampleHeight: (x: number, z: number) => number, options: HeightfieldDisplaceOptions): void — Re-samples a `PlaneGeometry(width, depth, segments, segments).rotateX(-π/2)` heightfield mesh from a `sampleHeight` field in place: vertex Y, optional vertex color, grid central-difference normals, and an analytically maintained bounding sphere. With a dirty `region`, the work is O(region vertices) — heights/colors update inside the covering vertex window, normals inside the window plus a one-vertex ring — never a whole-mesh `computeVertexNormals`/`computeBoundingSphere` pass, which is what keeps per-frame brush stamps inside the editor's frame budget. The bounding sphere derives from the fixed plane extents plus a running height range kept on `geometry.userData`; partial passes only expand it, a full pass resets it exactly.
|
|
1766
2424
|
|
|
@@ -1798,6 +2456,7 @@
|
|
|
1798
2456
|
- `TerrainHeightSampler` (type): type TerrainHeightSampler = (x: number, z: number) => number — ⚠ undocumented
|
|
1799
2457
|
- `TerrainNormal` (type): type TerrainNormal = readonly [number, number, number] — A surface normal vector at a terrain sample point.
|
|
1800
2458
|
- `TerrainSeed` (type): type TerrainSeed = number | string — ⚠ undocumented
|
|
2459
|
+
- `TerrainSurfaceColorOptions` (interface): interface TerrainSurfaceColorOptions — Slope/noise surface shading laid over the height lerp so untextured ground reads like terrain instead of a smooth two-tone gradient. All knobs are optional with sane defaults; every field is a pure function of vertex position (+ `seed`), so the coloring is stable across rebuilds and tests.
|
|
1801
2460
|
- `TerrainVertexColorOptions` (interface): interface TerrainVertexColorOptions — ⚠ undocumented
|
|
1802
2461
|
- `displaceHeightfieldGeometry` (function): function displaceHeightfieldGeometry(geometry: THREE.BufferGeometry, sampleHeight: (x: number, z: number) => number, options: HeightfieldDisplaceOptions): void — Re-samples a `PlaneGeometry(width, depth, segments, segments).rotateX(-π/2)` heightfield mesh from a `sampleHeight` field in place: vertex Y, optional vertex color, grid central-difference normals, and an analytically maintained bounding sphere. With a dirty `region`, the work is O(region vertices) — heights/colors update inside the covering vertex window, normals inside the window plus a one-vertex ring — never a whole-mesh `computeVertexNormals`/`computeBoundingSphere` pass, which is what keeps per-frame brush stamps inside the editor's frame budget. The bounding sphere derives from the fixed plane extents plus a running height range kept on `geometry.userData`; partial passes only expand it, a full pass resets it exactly.
|
|
1803
2462
|
|
|
@@ -1844,7 +2503,7 @@
|
|
|
1844
2503
|
|
|
1845
2504
|
## @jgengine/shell/terrain/grassMaterial
|
|
1846
2505
|
|
|
1847
|
-
- `DEFAULT_GRASS_DISTANCE_FADE` (const): const DEFAULT_GRASS_DISTANCE_FADE: Required<GrassDistanceFadeOptions> — Default camera-distance fade band: tufts start thinning at
|
|
2506
|
+
- `DEFAULT_GRASS_DISTANCE_FADE` (const): const DEFAULT_GRASS_DISTANCE_FADE: Required<GrassDistanceFadeOptions> — Default camera-distance fade band: tufts start thinning at 55 m and are gone by 150 m so the meadow reads deep.
|
|
1848
2507
|
- `DEFAULT_GRASS_WIND` (const): const DEFAULT_GRASS_WIND: Required<GrassWindOptions> — ⚠ undocumented
|
|
1849
2508
|
- `GrassDistanceFadeOptions` (interface): interface GrassDistanceFadeOptions — Camera-distance fade band: tufts thin out between `start` and `end` meters, so the instance budget spends where the camera lives.
|
|
1850
2509
|
- `GrassMaterialHandle` (interface): interface GrassMaterialHandle — ⚠ undocumented
|
|
@@ -1881,6 +2540,7 @@
|
|
|
1881
2540
|
- `TerrainArea` (type): type TerrainArea = number | readonly [width: number, depth: number] — ⚠ undocumented
|
|
1882
2541
|
- `TerrainHeightSampler` (type): type TerrainHeightSampler = (x: number, z: number) => number — ⚠ undocumented
|
|
1883
2542
|
- `TerrainPaletteSampler` (type): type TerrainPaletteSampler = (x: number, z: number) => { low: string; high: string; waterline?: string } — Per-position palette override for multi-biome ground coloring — `createTerrainPaletteSampler` from `@jgengine/core/world/terrain` returns exactly this shape.
|
|
2543
|
+
- `TerrainSurfaceColorOptions` (interface): interface TerrainSurfaceColorOptions — Slope/noise surface shading laid over the height lerp so untextured ground reads like terrain instead of a smooth two-tone gradient. All knobs are optional with sane defaults; every field is a pure function of vertex position (+ `seed`), so the coloring is stable across rebuilds and tests.
|
|
1884
2544
|
- `TerrainVertexColorOptions` (interface): interface TerrainVertexColorOptions — ⚠ undocumented
|
|
1885
2545
|
|
|
1886
2546
|
## @jgengine/shell/touch/OrientationHint
|
|
@@ -1890,7 +2550,7 @@
|
|
|
1890
2550
|
## @jgengine/shell/touch/TouchControlsOverlay
|
|
1891
2551
|
|
|
1892
2552
|
- `TouchCodeSink` (interface): interface TouchCodeSink — ⚠ undocumented
|
|
1893
|
-
- `TouchControlsDock` (function): function TouchControlsDock({ scheme, sink, style, scale = 1, }: { scheme: TouchScheme; sink: TouchCodeSink; /** Player-selected skin; falls back to the scheme's game default. */ style?: TouchStyle; scale?: number;
|
|
2553
|
+
- `TouchControlsDock` (function): function TouchControlsDock({ scheme, sink, style, scale = 1, joystickVariant = "floating", }: { scheme: TouchScheme; sink: TouchCodeSink; /** Player-selected skin; falls back to the scheme's game default. */ style?: TouchStyle; scale?: number; /** Player-selected joystick behavior (Settings → Contro… — ⚠ undocumented
|
|
1894
2554
|
- `TouchPlaySurface` (function): function TouchPlaySurface({ scheme, sink, yawRef, pitchRef, maxPitch, onPrimaryTap, }: { scheme: TouchScheme; sink: TouchCodeSink; yawRef: MutableRefObject<number>; pitchRef: MutableRefObject<number>; maxPitch: number; onPrimaryTap: () => void; }): React.JSX.Element — ⚠ undocumented
|
|
1895
2555
|
- `primaryButtonOffsets` (function): function primaryButtonOffsets(count: number, scale = 1): { right: number; bottom: number }[] | null — Thumb-arc placement for primary buttons around the bottom-right corner: up to three on an inner ring, the rest on an outer ring. Null means too many buttons for an arc — the dock falls back to a wrapping grid.
|
|
1896
2556
|
- `touchDockClearance` (function): function touchDockClearance(scheme: TouchScheme | null, scale = 1): number — Vertical space (px, excluding device safe areas) that *bottom-docked* clusters occupy above the bottom edge. The shell publishes it as `--jg-hud-dock-clearance` so `HudCanvas` regions never collide with touch controls. Side rails and top clusters reserve their own rectangles through the layout registry instead of this scalar.
|
|
@@ -1899,6 +2559,17 @@
|
|
|
1899
2559
|
|
|
1900
2560
|
- `useShellMultiplayerSync` (function): function useShellMultiplayerSync(ctx: GameContext | null, multiplayer: ShellMultiplayer | null, playable: PlayableGame, serverIdRef: { current: string | null }, setRemotePlayers: Dispatch<SetStateAction<PresencePoseRow[]>>): void — Joins the multiplayer server for the live context and wires presence, feed relay, and chat sync until teardown.
|
|
1901
2561
|
|
|
2562
|
+
## @jgengine/shell/vfx/ParticleField
|
|
2563
|
+
|
|
2564
|
+
- `ParticleBlending` (type): type ParticleBlending = "additive" | "normal" — How particle fragments composite: `additive` for fire/sparks/magic glow, `normal` for smoke/dust.
|
|
2565
|
+
- `ParticleField` (function): function ParticleField({ system, advance = true, blending = "additive", scale = 300, depthWrite = false, }: ParticleFieldProps): ReactElement — Renders a core `ParticleSystem` as a GPU point cloud: one draw call, per-particle size / color / alpha via a soft-round shader, and a `drawRange` clamped to the live count so dead particles cost nothing. The simulation stays engine-side and genre-agnostic; this is purely how it reaches the screen. By default it advances the sim with the frame delta — pass `advance={false}` to drive it from your own fixed loop instead.
|
|
2566
|
+
- `ParticleFieldProps` (interface): interface ParticleFieldProps — Props for {@link ParticleField}.
|
|
2567
|
+
|
|
2568
|
+
## @jgengine/shell/vfx/WorldFloatingText
|
|
2569
|
+
|
|
2570
|
+
- `WorldFloatingText` (function): function WorldFloatingText({ field, advance = true, styleFor, fontSizePx, className, ...layout }: WorldFloatingTextProps): React.JSX.Element — R3F one-line drop-in for world-anchored floating text: mounts inside the scene, (optionally) advances a core {@link FloatingTextField} each frame, samples the live camera to project every live entry to the screen, and renders `@jgengine/react`'s {@link FloatingText} through a fullscreen `<Html>` overlay. This is the turnkey way an R3F game gets damage numbers / heal pops / XP gains from its own field without wiring projection by hand — the camera binding, viewport culling, and depth stacking come for free. Skin per `kind` with `styleFor`.
|
|
2571
|
+
- `WorldFloatingTextProps` (interface): interface WorldFloatingTextProps extends FloatingTextLayoutOptions — Props for {@link WorldFloatingText}.
|
|
2572
|
+
|
|
1902
2573
|
## @jgengine/shell/visibility/CullingProvider
|
|
1903
2574
|
|
|
1904
2575
|
- `CullingProvider` (function): function CullingProvider({ config, children }: { config: VisibilityConfig | undefined; children: ReactNode }): ReactNode — Drives automatic frustum + distance culling for every entity and placed object. It reads the live render camera each frame, updates the engine VisibilitySystem, and exposes a predicate the entity/object markers consult to toggle `group.visible` — objects fully outside the view (plus a conservative preload margin) are never submitted to the renderer, without unmounting them or touching gameplay. UI, sky, terrain, and environment live outside this subtree and are unaffected.
|
|
@@ -2096,6 +2767,13 @@
|
|
|
2096
2767
|
- `SpriteBatchInstance` (interface): interface SpriteBatchInstance — ⚠ undocumented
|
|
2097
2768
|
- `SpriteBatchProps` (interface): interface SpriteBatchProps — ⚠ undocumented
|
|
2098
2769
|
|
|
2770
|
+
## @jgengine/shell/world/WorldEntityFrames
|
|
2771
|
+
|
|
2772
|
+
- `WorldEntityFrames` (function): function WorldEntityFrames<E extends EntityFrameEntry>({ entries, renderFrame, tickMs = 0, className, anchorTransform, ...layout }: WorldEntityFramesProps<E>): React.JSX.Element — R3F convenience that mounts inside the scene, samples the live camera each frame (throttled by `tickMs`), and renders `@jgengine/react`'s {@link EntityFrames} through a fullscreen `<Html>` overlay. This is the one-line way an R3F game gets overhead enemy nameplates/health bars from its own entity array without a store: pass `entries` + a `renderFrame` that composes the shipped bars. The projection, viewport culling, and stacking come for free.
|
|
2773
|
+
- `WorldEntityFramesProps` (interface): interface WorldEntityFramesProps<E extends EntityFrameEntry> extends EntityFrameLayoutOptions — Props for {@link WorldEntityFrames}.
|
|
2774
|
+
- `projectWorldToScreen` (function): function projectWorldToScreen(scratch: THREE.Vector3, camera: THREE.Camera, worldPosition: readonly [number, number, number], width: number, height: number): EntityScreenProjection — Pure world→screen projection: NDC via `camera.project`, mapped to CSS pixels. `behind` is set when the point falls outside the near/far clip range (NDC z beyond [-1, 1]), which covers positions behind the camera. Exposed for tests and for callers wiring their own frame loop around a bare THREE camera.
|
|
2775
|
+
- `useWorldProjection` (function): function useWorldProjection(): ProjectEntity — Returns a {@link ProjectEntity} bound to the live R3F camera and canvas size — the world→screen half of the data-first entity-frame seam. Call the returned function with a world position to get a CSS-pixel screen point (or `null`/`behind` when the point is outside the frustum). Reads the camera fresh on every call, so sample it inside a frame loop. Games that already own their entities use this to feed `@jgengine/react`'s `EntityFrames` without mirroring state into a store.
|
|
2776
|
+
|
|
2099
2777
|
## @jgengine/shell/world/WorldHud
|
|
2100
2778
|
|
|
2101
2779
|
- `CombatCameraShake` (function): function CombatCameraShake(): null — ⚠ undocumented
|
|
@@ -2115,6 +2793,11 @@
|
|
|
2115
2793
|
|
|
2116
2794
|
- `WorldItems` (function): function WorldItems({ config }: { config?: WorldItemRenderConfig }): React.JSX.Element — Rarity→beam/color/label render binding + loot-filter overlay (#32/#33) for every dropped `worldItem`.
|
|
2117
2795
|
|
|
2796
|
+
## @jgengine/shell/world/WorldPings
|
|
2797
|
+
|
|
2798
|
+
- `WorldPings` (function): function WorldPings({ markers, kindStyles, pingsOnly = true, height = 2.4, showCallout = true, renderCallout, }: WorldPingsProps): ReactNode — World-space pings — the in-scene side of a ping/marker: a bobbing downward arrowhead pointing at the spot, a ground ring, and a billboarded callout, colored by marker kind and fading in/out over the marker's lifetime. Reads a `MarkerSet` (typically the one a `createPingSystem` writes to), a marker source, or a static array; mount through `PlayableGame.WorldOverlay`.
|
|
2799
|
+
- `WorldPingsProps` (interface): interface WorldPingsProps — Props for {@link WorldPings}.
|
|
2800
|
+
|
|
2118
2801
|
## @jgengine/shell/world/WorldScene
|
|
2119
2802
|
|
|
2120
2803
|
- `RemotePlayers` (function): function RemotePlayers({ rows }: { rows: PresencePoseRow[] }): React.JSX.Element — ⚠ undocumented
|
|
@@ -2130,6 +2813,12 @@
|
|
|
2130
2813
|
- `FloatTextInfo` (interface): interface FloatTextInfo — ⚠ undocumented
|
|
2131
2814
|
- `FloatTextStyle` (interface): interface FloatTextStyle — ⚠ undocumented
|
|
2132
2815
|
|
|
2816
|
+
## @jgengine/shell/world/pingPulse
|
|
2817
|
+
|
|
2818
|
+
- `PingOpacityInput` (interface): interface PingOpacityInput — Inputs to {@link pingOpacity}.
|
|
2819
|
+
- `pingBobOffset` (function): function pingBobOffset(elapsedSeconds: number, amplitude = 0.18, speedHz = 1.1): number — Vertical bob offset (world units) for a hovering ping arrow at `elapsedSeconds`.
|
|
2820
|
+
- `pingOpacity` (function): function pingOpacity(input: PingOpacityInput): number — Alpha for a world ping in `[0, 1]`: ramps up over `fadeInMs` after it appears and ramps back down over `fadeOutMs` before it expires. Pure math so the lifecycle can be unit-tested without an R3F canvas.
|
|
2821
|
+
|
|
2133
2822
|
## @jgengine/shell/world/worldBarSamples
|
|
2134
2823
|
|
|
2135
2824
|
- `NameplateSample` (interface): interface NameplateSample — One entity's projected nameplate: screen `x`/`y`, display `name`, health `percent` (or `null` when statless), and world `distance` from the player.
|