@almadar/ui 5.64.0 → 5.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +241 -71
- package/dist/avl/index.d.cts +10 -2
- package/dist/avl/index.d.ts +1 -0
- package/dist/avl/index.js +244 -75
- package/dist/components/avl/derive-edit-focus.d.ts +8 -0
- package/dist/components/core/organisms/ChatBar.d.ts +31 -0
- package/dist/components/core/organisms/SubagentTracePanel.d.ts +50 -0
- package/dist/components/core/organisms/index.d.ts +3 -0
- package/dist/components/core/organisms/trace-edit-focus.d.ts +14 -0
- package/dist/components/game/atoms/ChoiceButton.d.ts +7 -1
- package/dist/components/game/molecules/HealthPanel.d.ts +3 -0
- package/dist/components/game/molecules/IsometricCanvas.d.ts +4 -1
- package/dist/components/game/molecules/PowerupSlots.d.ts +3 -0
- package/dist/components/game/molecules/TurnPanel.d.ts +3 -0
- package/dist/components/game/molecules/index.d.ts +1 -0
- package/dist/components/game/molecules/three/index.cjs +6 -6
- package/dist/components/game/molecules/three/index.js +6 -6
- package/dist/components/game/organisms/HexStrategyBoard.d.ts +37 -0
- package/dist/components/game/organisms/index.d.ts +2 -0
- package/dist/components/game/organisms/utils/isometric.d.ts +20 -7
- package/dist/components/index.cjs +1241 -53
- package/dist/components/index.js +1243 -60
- package/dist/hooks/index.cjs +94 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +95 -2
- package/dist/hooks/useAgentTrace.d.ts +85 -0
- package/dist/providers/index.cjs +210 -45
- package/dist/providers/index.js +213 -48
- package/dist/runtime/index.cjs +212 -47
- package/dist/runtime/index.js +215 -50
- package/package.json +2 -2
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EditFocus } from '@almadar/core';
|
|
2
|
+
/**
|
|
3
|
+
* Build an `EditFocus` from a clicked element's `data-orb-*` address (stamped by
|
|
4
|
+
* UISlotRenderer). The owning orbital is read from the DOM (`data-orb-orbital`,
|
|
5
|
+
* walking up via `closest` when the clicked node itself doesn't carry it); since
|
|
6
|
+
* `EditFocus.orbital` is required, returns `null` when it can't be resolved.
|
|
7
|
+
*/
|
|
8
|
+
export declare function deriveEditFocusFromElement(el: HTMLElement): EditFocus | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatBar Organism
|
|
3
|
+
*
|
|
4
|
+
* The always-visible bottom chat bar. A single-row input surface for talking
|
|
5
|
+
* to the agent: status icon, optional context badge, text input, and a
|
|
6
|
+
* status-driven action button (Send / Pause+Stop / Resume / Retry).
|
|
7
|
+
*
|
|
8
|
+
* The agent's activity stream lives in the dedicated Trace tab (see
|
|
9
|
+
* SubagentTracePanel). ChatBar emits generic EventBus events
|
|
10
|
+
* (`UI:CHAT_SEND`, `UI:ELEMENT_SELECTED`, plus the declarative `UI:*` actions
|
|
11
|
+
* the Button atom raises) — it owns no app-specific state.
|
|
12
|
+
*/
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import type { DisplayStateProps } from './types';
|
|
15
|
+
export type ChatBarStatus = 'idle' | 'running' | 'paused' | 'complete' | 'error';
|
|
16
|
+
export interface ChatBarProps extends DisplayStateProps {
|
|
17
|
+
/** Pipeline status */
|
|
18
|
+
status?: ChatBarStatus;
|
|
19
|
+
/** Currently active gate label, e.g. "Gate 2: State machines" */
|
|
20
|
+
activeGate?: string;
|
|
21
|
+
/** JEPA validity probability 0-1 */
|
|
22
|
+
jepaValidity?: number;
|
|
23
|
+
/** Input placeholder text */
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
/** Agent context description */
|
|
26
|
+
context?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function ChatBar({ status, activeGate, jepaValidity, placeholder, context, className, }: ChatBarProps): React.ReactElement;
|
|
29
|
+
export declare namespace ChatBar {
|
|
30
|
+
var displayName: string;
|
|
31
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubagentTracePanel — contextual side panel that surfaces subagent activity.
|
|
3
|
+
*
|
|
4
|
+
* Density adapts to disclosure level:
|
|
5
|
+
* - L1/L2 (builder/designer): compact mode — name + role badge + last message
|
|
6
|
+
* - L3/L4 (architect): full mode — rich per-subagent activity streams
|
|
7
|
+
*
|
|
8
|
+
* Atomic design: composes Box / VStack / HStack / Typography / Badge / Icon /
|
|
9
|
+
* Button / Modal / Accordion / CodeBlock / MarkdownContent from this package.
|
|
10
|
+
* It reads the agent-trace view-model from `@almadar/core` (Trace* types) and
|
|
11
|
+
* owns no transport — the consumer feeds it already-mapped view-model props.
|
|
12
|
+
*/
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import type { DisplayStateProps } from './types';
|
|
15
|
+
import type { TraceActivity, TraceSubagent, TraceChatMessage } from '@almadar/core';
|
|
16
|
+
/** Disclosure level driving panel density (builder=1 … architect=4). */
|
|
17
|
+
export type TraceDisclosureLevel = 1 | 2 | 3 | 4;
|
|
18
|
+
export interface SubagentTracePanelProps extends DisplayStateProps {
|
|
19
|
+
/** All known subagents from the runner. */
|
|
20
|
+
subagents: TraceSubagent[];
|
|
21
|
+
/** Current canvas focus orbital — only used by overlay mode. Tab mode ignores this. */
|
|
22
|
+
focusedOrbital?: string;
|
|
23
|
+
/** Drives density: 1-2 → compact, 3-4 → full activity embed (when mode='overlay'). */
|
|
24
|
+
disclosureLevel: TraceDisclosureLevel;
|
|
25
|
+
/** Whether the panel is visible. Typically auto-opens during generation in overlay mode. */
|
|
26
|
+
open: boolean;
|
|
27
|
+
/** Optional dismiss handler. */
|
|
28
|
+
onClose?: () => void;
|
|
29
|
+
/** Full coordinator activities (tool calls, results, messages, errors). */
|
|
30
|
+
coordinatorActivities?: TraceActivity[];
|
|
31
|
+
/**
|
|
32
|
+
* Canonical Coordinator conversation — same shape live and on reload. When
|
|
33
|
+
* present, takes precedence over `coordinatorActivities` for the Coordinator
|
|
34
|
+
* section.
|
|
35
|
+
*/
|
|
36
|
+
coordinatorMessages?: readonly TraceChatMessage[];
|
|
37
|
+
/**
|
|
38
|
+
* Rendering mode.
|
|
39
|
+
* - `'overlay'` (default): floating side panel positioned absolutely over the
|
|
40
|
+
* canvas. Density follows `disclosureLevel` (compact L1/L2, rich L3+). The
|
|
41
|
+
* `open` flag actually hides the panel when false.
|
|
42
|
+
* - `'tab'`: full-width content for a dedicated 'trace' supplemental tab.
|
|
43
|
+
* Always renders rich (regardless of disclosure level), always visible (the
|
|
44
|
+
* `open` flag is ignored), and includes an empty state when no subagents
|
|
45
|
+
* are present so users see the surface even before generation starts.
|
|
46
|
+
*/
|
|
47
|
+
mode?: 'overlay' | 'tab';
|
|
48
|
+
}
|
|
49
|
+
export declare const SubagentTracePanel: React.FC<SubagentTracePanelProps>;
|
|
50
|
+
export default SubagentTracePanel;
|
|
@@ -28,3 +28,6 @@ export { TeamOrganism, type TeamOrganismProps, } from "../../marketing/organisms
|
|
|
28
28
|
export { CaseStudyOrganism, type CaseStudyOrganismProps, } from "../../marketing/organisms/CaseStudyOrganism";
|
|
29
29
|
export { CodeRunnerPanel, type CodeRunnerPanelProps, type CodeSimulationOutput, } from './CodeRunnerPanel';
|
|
30
30
|
export { SegmentRenderer, type SegmentRendererProps, } from './SegmentRenderer';
|
|
31
|
+
export { ChatBar, type ChatBarProps, type ChatBarStatus } from './ChatBar';
|
|
32
|
+
export { ELEMENT_SELECTED_EVENT, parseEditFocus, } from './trace-edit-focus';
|
|
33
|
+
export { SubagentTracePanel, type SubagentTracePanelProps, type TraceDisclosureLevel, } from './SubagentTracePanel';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edit Focus — the contextual-edit selection contract for the trace chat bar.
|
|
3
|
+
*
|
|
4
|
+
* A canvas element-pick emits `UI:ELEMENT_SELECTED` on the EventBus carrying an
|
|
5
|
+
* `EditFocus`. This module names that event and narrows the bus payload back
|
|
6
|
+
* into a typed `EditFocus` for `ChatBar`'s focus chip. It depends only on
|
|
7
|
+
* `@almadar/core` types; the DOM→focus build lives at the emitting canvas
|
|
8
|
+
* (`avl/derive-edit-focus`), not here.
|
|
9
|
+
*/
|
|
10
|
+
import type { EditFocus, EventPayloadValue } from '@almadar/core';
|
|
11
|
+
/** The dedicated bus event a canvas element-pick emits. */
|
|
12
|
+
export declare const ELEMENT_SELECTED_EVENT = "UI:ELEMENT_SELECTED";
|
|
13
|
+
/** Narrow a `UI:ELEMENT_SELECTED` payload value back into an `EditFocus`. */
|
|
14
|
+
export declare function parseEditFocus(value: EventPayloadValue | undefined): EditFocus | null;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { type IconInput } from '../../core/atoms/Icon';
|
|
2
|
+
import type { AssetUrl } from '@almadar/core';
|
|
1
3
|
export interface ChoiceButtonProps {
|
|
2
4
|
/** Choice text content */
|
|
3
5
|
text: string;
|
|
4
6
|
/** Choice index number (displayed as prefix) */
|
|
5
7
|
index?: number;
|
|
8
|
+
/** Sprite image URL — takes precedence over icon when provided */
|
|
9
|
+
assetUrl?: AssetUrl;
|
|
10
|
+
/** Icon displayed before the text */
|
|
11
|
+
icon?: IconInput;
|
|
6
12
|
/** Whether the choice is disabled */
|
|
7
13
|
disabled?: boolean;
|
|
8
14
|
/** Whether the choice is currently selected */
|
|
@@ -12,7 +18,7 @@ export interface ChoiceButtonProps {
|
|
|
12
18
|
/** Additional CSS classes */
|
|
13
19
|
className?: string;
|
|
14
20
|
}
|
|
15
|
-
export declare function ChoiceButton({ text, index, disabled, selected, onClick, className, }: ChoiceButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function ChoiceButton({ text, index, assetUrl, icon, disabled, selected, onClick, className, }: ChoiceButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
16
22
|
export declare namespace ChoiceButton {
|
|
17
23
|
var displayName: string;
|
|
18
24
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { IconInput } from '../../core/atoms';
|
|
2
|
+
import type { AssetUrl } from '@almadar/core';
|
|
2
3
|
export interface HealthEffect {
|
|
3
4
|
icon: IconInput;
|
|
5
|
+
/** Sprite image URL — takes precedence over icon when provided */
|
|
6
|
+
assetUrl?: AssetUrl;
|
|
4
7
|
label?: string;
|
|
5
8
|
variant?: 'buff' | 'debuff' | 'neutral';
|
|
6
9
|
}
|
|
@@ -27,6 +27,7 @@ import * as React from 'react';
|
|
|
27
27
|
import type { AssetUrl, EventEmit } from '@almadar/core';
|
|
28
28
|
import type { IsometricTile, IsometricUnit, IsometricFeature } from '../organisms/types/isometric';
|
|
29
29
|
import type { ResolvedFrame } from '../organisms/types/spriteAnimation';
|
|
30
|
+
import type { TileLayout } from '../organisms/utils/isometric';
|
|
30
31
|
import type { UiError } from '../../core/atoms/types';
|
|
31
32
|
/** Event Contract:
|
|
32
33
|
* Emits: UI:TILE_CLICK
|
|
@@ -79,6 +80,8 @@ export interface IsometricCanvasProps {
|
|
|
79
80
|
}>;
|
|
80
81
|
/** Declarative event: emits UI:{tileLeaveEvent} with {} on tile leave */
|
|
81
82
|
tileLeaveEvent?: EventEmit<Record<string, never>>;
|
|
83
|
+
/** Tile layout projection: 'isometric' (default 2:1 diamond) or 'hex' (pointy-top offset rows) */
|
|
84
|
+
tileLayout?: TileLayout;
|
|
82
85
|
/** Render scale (0.4 = 40% zoom) */
|
|
83
86
|
scale?: number;
|
|
84
87
|
/** Show debug grid lines and coordinates */
|
|
@@ -129,7 +132,7 @@ export interface IsometricCanvasProps {
|
|
|
129
132
|
effects?: Record<string, string>;
|
|
130
133
|
};
|
|
131
134
|
}
|
|
132
|
-
export declare function IsometricCanvas({ className, isLoading, error, tiles: _tilesPropRaw, units: _unitsPropRaw, features: _featuresPropRaw, selectedUnitId, validMoves, attackTargets, hoveredTile, onTileClick, onUnitClick, onTileHover, onTileLeave, tileClickEvent, unitClickEvent, tileHoverEvent, tileLeaveEvent, scale, debug, backgroundImage, showMinimap, enableCamera, unitScale, spriteHeightRatio, spriteMaxWidthRatio, getTerrainSprite, getFeatureSprite, getUnitSprite, resolveUnitFrame, effectSpriteUrls, onDrawEffects, hasActiveEffects, diamondTopY: diamondTopYProp, assetBaseUrl, assetManifest, }: IsometricCanvasProps): React.JSX.Element;
|
|
135
|
+
export declare function IsometricCanvas({ className, isLoading, error, tiles: _tilesPropRaw, units: _unitsPropRaw, features: _featuresPropRaw, selectedUnitId, validMoves, attackTargets, hoveredTile, onTileClick, onUnitClick, onTileHover, onTileLeave, tileClickEvent, unitClickEvent, tileHoverEvent, tileLeaveEvent, tileLayout, scale, debug, backgroundImage, showMinimap, enableCamera, unitScale, spriteHeightRatio, spriteMaxWidthRatio, getTerrainSprite, getFeatureSprite, getUnitSprite, resolveUnitFrame, effectSpriteUrls, onDrawEffects, hasActiveEffects, diamondTopY: diamondTopYProp, assetBaseUrl, assetManifest, }: IsometricCanvasProps): React.JSX.Element;
|
|
133
136
|
export declare namespace IsometricCanvas {
|
|
134
137
|
var displayName: string;
|
|
135
138
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { IconInput } from '../../core/atoms';
|
|
2
|
+
import type { AssetUrl } from '@almadar/core';
|
|
2
3
|
export interface ActivePowerup {
|
|
3
4
|
/** Unique powerup ID */
|
|
4
5
|
id: string;
|
|
6
|
+
/** Sprite image URL — takes precedence over icon when provided */
|
|
7
|
+
assetUrl?: AssetUrl;
|
|
5
8
|
/** Icon component or emoji */
|
|
6
9
|
icon?: IconInput;
|
|
7
10
|
/** Powerup label */
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { IconInput } from '../../core/atoms';
|
|
2
|
+
import type { AssetUrl } from '@almadar/core';
|
|
2
3
|
export interface TurnPanelAction {
|
|
3
4
|
/** Action button label */
|
|
4
5
|
label: string;
|
|
6
|
+
/** Sprite image URL — takes precedence over icon when provided */
|
|
7
|
+
assetUrl?: AssetUrl;
|
|
5
8
|
/** Icon for the button */
|
|
6
9
|
icon?: IconInput;
|
|
7
10
|
/** Event name to emit when clicked */
|
|
@@ -28,4 +28,5 @@ export { GameMenu, type GameMenuProps, type MenuOption } from './GameMenu';
|
|
|
28
28
|
export { GameOverScreen, type GameOverScreenProps, type GameOverStat, type GameOverAction } from './GameOverScreen';
|
|
29
29
|
export { PlatformerCanvas, type PlatformerCanvasProps, type PlatformerPlatform, type PlatformerPlayer } from './PlatformerCanvas';
|
|
30
30
|
export { IsometricCanvas, type IsometricCanvasProps } from './IsometricCanvas';
|
|
31
|
+
export type { TileLayout } from '../organisms/utils/isometric';
|
|
31
32
|
export type { IsometricTile, IsometricUnit, IsometricFeature } from '../organisms/types/isometric';
|
|
@@ -2845,9 +2845,9 @@ var GameCanvas3D = React11.forwardRef(
|
|
|
2845
2845
|
const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
|
|
2846
2846
|
const hasAtlas = unitAtlasUrl(unit) !== null;
|
|
2847
2847
|
const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
|
|
2848
|
-
const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
|
|
2849
|
-
const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
|
|
2850
|
-
const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
|
|
2848
|
+
const modelScale = UNIT_BASE_MODEL_SCALE * unitScale * gridConfig.cellSize;
|
|
2849
|
+
const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale * gridConfig.cellSize;
|
|
2850
|
+
const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale * gridConfig.cellSize;
|
|
2851
2851
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2852
2852
|
"group",
|
|
2853
2853
|
{
|
|
@@ -2894,7 +2894,7 @@ var GameCanvas3D = React11.forwardRef(
|
|
|
2894
2894
|
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
|
|
2895
2895
|
] })
|
|
2896
2896
|
] }),
|
|
2897
|
-
unit.health !== void 0 && unit.maxHealth !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("group", { position: [0,
|
|
2897
|
+
unit.health !== void 0 && unit.maxHealth !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("group", { position: [0, billboardHeight, 0], children: [
|
|
2898
2898
|
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [-0.25, 0, 0], children: [
|
|
2899
2899
|
/* @__PURE__ */ jsxRuntime.jsx("planeGeometry", { args: [0.5, 0.05] }),
|
|
2900
2900
|
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color: 3355443 })
|
|
@@ -2923,7 +2923,7 @@ var GameCanvas3D = React11.forwardRef(
|
|
|
2923
2923
|
}
|
|
2924
2924
|
);
|
|
2925
2925
|
},
|
|
2926
|
-
[selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
|
|
2926
|
+
[selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale, gridConfig]
|
|
2927
2927
|
);
|
|
2928
2928
|
const DefaultFeatureRenderer = React11.useCallback(
|
|
2929
2929
|
({
|
|
@@ -3011,7 +3011,7 @@ var GameCanvas3D = React11.forwardRef(
|
|
|
3011
3011
|
{
|
|
3012
3012
|
ref: containerRef,
|
|
3013
3013
|
className: cn("game-canvas-3d relative w-full overflow-hidden", className),
|
|
3014
|
-
style: {
|
|
3014
|
+
style: { flex: "1 1 0", minHeight: "400px" },
|
|
3015
3015
|
"data-orientation": orientation,
|
|
3016
3016
|
"data-camera-mode": cameraMode,
|
|
3017
3017
|
"data-overlay": overlay,
|
|
@@ -2821,9 +2821,9 @@ var GameCanvas3D = forwardRef(
|
|
|
2821
2821
|
const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
|
|
2822
2822
|
const hasAtlas = unitAtlasUrl(unit) !== null;
|
|
2823
2823
|
const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
|
|
2824
|
-
const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
|
|
2825
|
-
const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
|
|
2826
|
-
const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
|
|
2824
|
+
const modelScale = UNIT_BASE_MODEL_SCALE * unitScale * gridConfig.cellSize;
|
|
2825
|
+
const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale * gridConfig.cellSize;
|
|
2826
|
+
const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale * gridConfig.cellSize;
|
|
2827
2827
|
return /* @__PURE__ */ jsxs(
|
|
2828
2828
|
"group",
|
|
2829
2829
|
{
|
|
@@ -2870,7 +2870,7 @@ var GameCanvas3D = forwardRef(
|
|
|
2870
2870
|
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
2871
2871
|
] })
|
|
2872
2872
|
] }),
|
|
2873
|
-
unit.health !== void 0 && unit.maxHealth !== void 0 && /* @__PURE__ */ jsxs("group", { position: [0,
|
|
2873
|
+
unit.health !== void 0 && unit.maxHealth !== void 0 && /* @__PURE__ */ jsxs("group", { position: [0, billboardHeight, 0], children: [
|
|
2874
2874
|
/* @__PURE__ */ jsxs("mesh", { position: [-0.25, 0, 0], children: [
|
|
2875
2875
|
/* @__PURE__ */ jsx("planeGeometry", { args: [0.5, 0.05] }),
|
|
2876
2876
|
/* @__PURE__ */ jsx("meshBasicMaterial", { color: 3355443 })
|
|
@@ -2899,7 +2899,7 @@ var GameCanvas3D = forwardRef(
|
|
|
2899
2899
|
}
|
|
2900
2900
|
);
|
|
2901
2901
|
},
|
|
2902
|
-
[selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
|
|
2902
|
+
[selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale, gridConfig]
|
|
2903
2903
|
);
|
|
2904
2904
|
const DefaultFeatureRenderer = useCallback(
|
|
2905
2905
|
({
|
|
@@ -2987,7 +2987,7 @@ var GameCanvas3D = forwardRef(
|
|
|
2987
2987
|
{
|
|
2988
2988
|
ref: containerRef,
|
|
2989
2989
|
className: cn("game-canvas-3d relative w-full overflow-hidden", className),
|
|
2990
|
-
style: {
|
|
2990
|
+
style: { flex: "1 1 0", minHeight: "400px" },
|
|
2991
2991
|
"data-orientation": orientation,
|
|
2992
2992
|
"data-camera-mode": cameraMode,
|
|
2993
2993
|
"data-overlay": overlay,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AssetUrl, EventEmit } from '@almadar/core';
|
|
3
|
+
import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
|
|
4
|
+
import type { DisplayStateProps } from '../../core/organisms/types';
|
|
5
|
+
import type { IsometricCanvasProps } from '../molecules/IsometricCanvas';
|
|
6
|
+
export interface HexStrategyBoardProps extends DisplayStateProps {
|
|
7
|
+
/** Hex grid tiles */
|
|
8
|
+
tiles?: IsometricTile[];
|
|
9
|
+
/** Units on the board */
|
|
10
|
+
units?: IsometricUnit[];
|
|
11
|
+
/** Features (resources, structures, etc.) on the board */
|
|
12
|
+
features?: IsometricFeature[];
|
|
13
|
+
/** Asset sprite manifest (same shape as IsometricCanvas.assetManifest) */
|
|
14
|
+
assetManifest?: IsometricCanvasProps['assetManifest'];
|
|
15
|
+
/** Base URL prepended to manifest sprite paths */
|
|
16
|
+
assetBaseUrl?: AssetUrl;
|
|
17
|
+
/** Render scale */
|
|
18
|
+
scale?: number;
|
|
19
|
+
/** Show minimap overlay */
|
|
20
|
+
showMinimap?: boolean;
|
|
21
|
+
/** Enable camera pan/zoom controls */
|
|
22
|
+
enableCamera?: boolean;
|
|
23
|
+
/** Declarative event: emits UI:{tileClickEvent} with { x, y } on tile click */
|
|
24
|
+
tileClickEvent?: EventEmit<{
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
}>;
|
|
28
|
+
/** Declarative event: emits UI:{unitClickEvent} with { unitId } on unit click */
|
|
29
|
+
unitClickEvent?: EventEmit<{
|
|
30
|
+
unitId: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
export declare function HexStrategyBoard({ tiles, units, features, assetManifest, assetBaseUrl, scale, showMinimap, enableCamera, tileClickEvent, unitClickEvent, isLoading, error, className, }: HexStrategyBoardProps): React.ReactElement;
|
|
34
|
+
export declare namespace HexStrategyBoard {
|
|
35
|
+
var displayName: string;
|
|
36
|
+
}
|
|
37
|
+
export default HexStrategyBoard;
|
|
@@ -18,6 +18,7 @@ export { useSpriteAnimations, type UseSpriteAnimationsResult, type UseSpriteAnim
|
|
|
18
18
|
export { usePhysics2D, type UsePhysics2DOptions, type UsePhysics2DReturn, } from './hooks/usePhysics2D';
|
|
19
19
|
export { PhysicsManager, type Physics2DState, type PhysicsBounds, type PhysicsConfig, } from './managers/PhysicsManager';
|
|
20
20
|
export { isoToScreen, screenToIso, TILE_WIDTH, TILE_HEIGHT, FLOOR_HEIGHT, DIAMOND_TOP_Y, FEATURE_COLORS, } from './utils/isometric';
|
|
21
|
+
export type { TileLayout } from './utils/isometric';
|
|
21
22
|
export { inferDirection, resolveSheetDirection, getCurrentFrame, resolveFrame, createUnitAnimationState, transitionAnimation, tickAnimationState, } from './utils/spriteAnimation';
|
|
22
23
|
export { SPRITE_SHEET_LAYOUT, SHEET_COLUMNS } from './utils/spriteSheetConstants';
|
|
23
24
|
export { BattleBoard, type BattleBoardProps, type BattlePhase, type BattleSlotContext, } from './BattleBoard';
|
|
@@ -33,6 +34,7 @@ export { CityBuilderBoard, type CityBuilderBoardProps, } from './CityBuilderBoar
|
|
|
33
34
|
export { GameBoard3D, type GameBoard3DProps, } from './GameBoard3D';
|
|
34
35
|
export { VisualNovelBoard, type VisualNovelBoardProps, type VisualNovelNode, type VisualNovelChoice, } from './VisualNovelBoard';
|
|
35
36
|
export { CardBattlerBoard, type CardBattlerBoardProps, type CardBattlerCard, } from './CardBattlerBoard';
|
|
37
|
+
export { HexStrategyBoard, type HexStrategyBoardProps, } from './HexStrategyBoard';
|
|
36
38
|
export { TraitStateViewer, type TraitStateViewerProps, type TraitStateMachineDefinition, type TraitTransition, } from './TraitStateViewer';
|
|
37
39
|
export { TraitSlot, type TraitSlotProps, type SlotItemData, } from './TraitSlot';
|
|
38
40
|
export { CollapsibleSection, EditorSlider, EditorSelect, EditorCheckbox, EditorTextInput, StatusBar, TerrainPalette, EditorToolbar, TERRAIN_COLORS, FEATURE_TYPES, type EditorMode, type CollapsibleSectionProps, type EditorSliderProps, type EditorSelectProps, type EditorCheckboxProps, type EditorTextInputProps, type StatusBarProps, type TerrainPaletteProps, type EditorToolbarProps, } from './editor';
|
|
@@ -27,20 +27,32 @@ export declare const DIAMOND_TOP_Y = 374;
|
|
|
27
27
|
* Feature type → fallback color mapping (when sprites not loaded).
|
|
28
28
|
*/
|
|
29
29
|
export declare const FEATURE_COLORS: Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Tile layout mode. 'isometric' = 2:1 diamond projection (default).
|
|
32
|
+
* 'hex' = pointy-top offset-row hex grid.
|
|
33
|
+
*
|
|
34
|
+
* Hex constants (at scale=1):
|
|
35
|
+
* w = TILE_WIDTH (256) — horizontal cell width
|
|
36
|
+
* h = FLOOR_HEIGHT (128) — vertical row stride (= w/2; hex row-to-row = h*0.75 = 96)
|
|
37
|
+
* Forward: screenX = col*w + (row&1)*(w/2) + baseOffsetX
|
|
38
|
+
* screenY = row * (h * 0.75)
|
|
39
|
+
* Inverse: row = round(screenY / (h*0.75)); col = round((screenX - (row&1)*(w/2) - baseOffsetX) / w)
|
|
40
|
+
*/
|
|
41
|
+
export type TileLayout = 'isometric' | 'hex';
|
|
30
42
|
/**
|
|
31
43
|
* Convert tile grid coordinates to screen pixel coordinates.
|
|
32
44
|
*
|
|
33
|
-
*
|
|
34
|
-
* -
|
|
35
|
-
* - Y increases to the lower-left
|
|
45
|
+
* For 'isometric' (default): 2:1 diamond projection.
|
|
46
|
+
* For 'hex': pointy-top offset-row projection (odd rows shifted right by w/2).
|
|
36
47
|
*
|
|
37
|
-
* @param tileX - Grid X coordinate
|
|
38
|
-
* @param tileY - Grid Y coordinate
|
|
48
|
+
* @param tileX - Grid X (col) coordinate
|
|
49
|
+
* @param tileY - Grid Y (row) coordinate
|
|
39
50
|
* @param scale - Render scale factor
|
|
40
51
|
* @param baseOffsetX - Horizontal offset to center the grid
|
|
52
|
+
* @param layout - Tile layout mode (default: 'isometric')
|
|
41
53
|
* @returns Screen position { x, y } of the tile's top-left corner
|
|
42
54
|
*/
|
|
43
|
-
export declare function isoToScreen(tileX: number, tileY: number, scale: number, baseOffsetX: number): {
|
|
55
|
+
export declare function isoToScreen(tileX: number, tileY: number, scale: number, baseOffsetX: number, layout?: TileLayout): {
|
|
44
56
|
x: number;
|
|
45
57
|
y: number;
|
|
46
58
|
};
|
|
@@ -53,9 +65,10 @@ export declare function isoToScreen(tileX: number, tileY: number, scale: number,
|
|
|
53
65
|
* @param screenY - Screen Y in pixels
|
|
54
66
|
* @param scale - Render scale factor
|
|
55
67
|
* @param baseOffsetX - Horizontal offset used in isoToScreen
|
|
68
|
+
* @param layout - Tile layout mode (default: 'isometric')
|
|
56
69
|
* @returns Snapped grid position { x, y }
|
|
57
70
|
*/
|
|
58
|
-
export declare function screenToIso(screenX: number, screenY: number, scale: number, baseOffsetX: number): {
|
|
71
|
+
export declare function screenToIso(screenX: number, screenY: number, scale: number, baseOffsetX: number, layout?: TileLayout): {
|
|
59
72
|
x: number;
|
|
60
73
|
y: number;
|
|
61
74
|
};
|