@almadar/ui 5.72.0 → 5.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/avl/index.cjs +402 -362
  2. package/dist/avl/index.js +402 -362
  3. package/dist/components/game/atoms/ActionButton.d.ts +3 -3
  4. package/dist/components/game/atoms/ChoiceButton.d.ts +3 -3
  5. package/dist/components/game/atoms/ComboCounter.d.ts +3 -3
  6. package/dist/components/game/atoms/ControlButton.d.ts +3 -3
  7. package/dist/components/game/atoms/DamageNumber.d.ts +3 -3
  8. package/dist/components/game/atoms/DialogueBubble.d.ts +3 -3
  9. package/dist/components/game/atoms/ItemSlot.d.ts +3 -3
  10. package/dist/components/game/atoms/ResourceCounter.d.ts +3 -3
  11. package/dist/components/game/atoms/ScoreDisplay.d.ts +3 -3
  12. package/dist/components/game/atoms/Sprite.d.ts +3 -20
  13. package/dist/components/game/atoms/StateIndicator.d.ts +2 -2
  14. package/dist/components/game/atoms/StatusEffect.d.ts +3 -3
  15. package/dist/components/game/atoms/TurnIndicator.d.ts +3 -3
  16. package/dist/components/game/atoms/WaypointMarker.d.ts +3 -3
  17. package/dist/components/game/molecules/CardHand.d.ts +2 -2
  18. package/dist/components/game/molecules/DialogueBox.d.ts +3 -3
  19. package/dist/components/game/molecules/EnemyPlate.d.ts +3 -3
  20. package/dist/components/game/molecules/GameCanvas2D.d.ts +3 -3
  21. package/dist/components/game/molecules/HealthPanel.d.ts +3 -3
  22. package/dist/components/game/molecules/IsometricCanvas.d.ts +8 -12
  23. package/dist/components/game/molecules/PowerupSlots.d.ts +3 -3
  24. package/dist/components/game/molecules/StatBadge.d.ts +5 -5
  25. package/dist/components/game/molecules/TurnPanel.d.ts +3 -3
  26. package/dist/components/game/molecules/three/index.cjs +51 -28
  27. package/dist/components/game/molecules/three/index.js +51 -28
  28. package/dist/components/game/molecules/useUnitSpriteAtlas.d.ts +3 -10
  29. package/dist/components/game/organisms/BattleBoard.d.ts +5 -6
  30. package/dist/components/game/organisms/CardBattlerBoard.d.ts +3 -4
  31. package/dist/components/game/organisms/CastleBoard.d.ts +5 -6
  32. package/dist/components/game/organisms/CityBuilderBoard.d.ts +6 -7
  33. package/dist/components/game/organisms/FishingBoard.d.ts +4 -6
  34. package/dist/components/game/organisms/PlatformerBoard.d.ts +5 -5
  35. package/dist/components/game/organisms/RoguelikeBoard.d.ts +4 -5
  36. package/dist/components/game/organisms/TopDownShooterBoard.d.ts +5 -6
  37. package/dist/components/game/organisms/TowerDefenseBoard.d.ts +5 -6
  38. package/dist/components/game/organisms/VisualNovelBoard.d.ts +4 -5
  39. package/dist/components/game/organisms/WorldMapBoard.d.ts +5 -6
  40. package/dist/components/game/organisms/types/effects.d.ts +7 -8
  41. package/dist/components/game/organisms/types/isometric.d.ts +8 -8
  42. package/dist/components/game/organisms/types/spriteAnimation.d.ts +3 -4
  43. package/dist/components/game/organisms/utils/makeAsset.d.ts +5 -0
  44. package/dist/components/game/templates/PlatformerTemplate.d.ts +5 -4
  45. package/dist/components/game/templates/game3dAssetManifest.d.ts +6 -8
  46. package/dist/components/index.cjs +417 -363
  47. package/dist/components/index.js +417 -363
  48. package/dist/providers/index.cjs +402 -362
  49. package/dist/providers/index.js +402 -362
  50. package/dist/runtime/index.cjs +402 -362
  51. package/dist/runtime/index.js +402 -362
  52. package/package.json +2 -2
@@ -1755,7 +1755,7 @@ function TileRenderer({
1755
1755
  children: /* @__PURE__ */ jsx(
1756
1756
  ModelLoader,
1757
1757
  {
1758
- url: tile.modelUrl,
1758
+ url: tile.modelUrl?.url,
1759
1759
  position,
1760
1760
  scale: cellSize * 0.9,
1761
1761
  fallbackGeometry: "box",
@@ -2157,7 +2157,7 @@ function FeatureModel({
2157
2157
  onHover
2158
2158
  }) {
2159
2159
  const groupRef = useRef(null);
2160
- const { model: loadedModel, isLoading } = useGLTFModel2(feature.assetUrl);
2160
+ const { model: loadedModel, isLoading } = useGLTFModel2(feature.assetUrl?.url);
2161
2161
  const model = useMemo(() => {
2162
2162
  if (!loadedModel) return null;
2163
2163
  const cloned = loadedModel.clone();
@@ -2292,12 +2292,7 @@ function frameRect(frame, row, columns, frameWidth, frameHeight) {
2292
2292
 
2293
2293
  // components/game/molecules/useUnitSpriteAtlas.ts
2294
2294
  function unitAtlasUrl(unit) {
2295
- if (unit.spriteSheet) return unit.spriteSheet;
2296
- const sprite = unit.sprite;
2297
- if (!sprite) return null;
2298
- const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
2299
- if (!match) return null;
2300
- return `${match[1]}.json`;
2295
+ return unit.spriteSheet?.url ?? null;
2301
2296
  }
2302
2297
  function resolveSheetUrl(atlasUrl, relativeSheetPath) {
2303
2298
  try {
@@ -2708,7 +2703,7 @@ var GameCanvas3D = forwardRef(
2708
2703
  children: /* @__PURE__ */ jsx(
2709
2704
  ModelLoader,
2710
2705
  {
2711
- url: tile.modelUrl,
2706
+ url: tile.modelUrl.url,
2712
2707
  scale: 0.95,
2713
2708
  fallbackGeometry: "box",
2714
2709
  castShadow: true,
@@ -2773,7 +2768,7 @@ var GameCanvas3D = forwardRef(
2773
2768
  /* @__PURE__ */ jsx(
2774
2769
  ModelLoader,
2775
2770
  {
2776
- url: unit.modelUrl,
2771
+ url: unit.modelUrl.url,
2777
2772
  scale: modelScale,
2778
2773
  fallbackGeometry: "box",
2779
2774
  castShadow: true
@@ -2833,7 +2828,7 @@ var GameCanvas3D = forwardRef(
2833
2828
  return /* @__PURE__ */ jsx(
2834
2829
  ModelLoader,
2835
2830
  {
2836
- url: feature.assetUrl,
2831
+ url: feature.assetUrl.url,
2837
2832
  position,
2838
2833
  scale: 0.5,
2839
2834
  rotation: [0, feature.rotation ?? 0, 0],
@@ -4201,7 +4196,18 @@ function GameBoard3D({
4201
4196
  const row = boardEntity(entity);
4202
4197
  const eventBus = useEventBus();
4203
4198
  const entityUnits = row ? rows(row.units) : [];
4204
- const units = entityUnits;
4199
+ const units = entityUnits.map((r) => ({
4200
+ id: str(r.id),
4201
+ x: num(r.x),
4202
+ y: num(r.y),
4203
+ z: num(r.z),
4204
+ faction: str(r.faction) || "neutral",
4205
+ team: str(r.team) || str(r.faction) || "neutral",
4206
+ unitType: r.unitType == null ? void 0 : str(r.unitType),
4207
+ name: r.name == null ? void 0 : str(r.name),
4208
+ health: r.health == null ? void 0 : num(r.health),
4209
+ maxHealth: r.maxHealth == null ? void 0 : num(r.maxHealth)
4210
+ }));
4205
4211
  const selectedUnitId = row ? str(row.selectedUnitId) || null : null;
4206
4212
  const phase = row ? str(row.phase) : "observation";
4207
4213
  const result = row ? str(row.result) : "none";
@@ -4593,16 +4599,31 @@ var Box = React11.forwardRef(
4593
4599
  );
4594
4600
  Box.displayName = "Box";
4595
4601
 
4596
- // components/game/templates/game3dAssetManifest.ts
4597
- function resolveManifestUrl(manifest, relative) {
4598
- if (relative == null) return void 0;
4599
- if (/^https?:\/\//.test(relative)) return relative;
4600
- const base = manifest?.baseUrl;
4601
- if (base == null) return relative;
4602
- const cleanBase = base.replace(/\/$/, "");
4603
- const cleanRel = relative.replace(/^\//, "");
4604
- return `${cleanBase}/${cleanRel}`;
4602
+ // components/game/organisms/utils/makeAsset.ts
4603
+ var ROLE_DEFAULTS = {
4604
+ tile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
4605
+ decoration: { dimension: "2d", animations: ["static"], aspect: "1:1" },
4606
+ effect: { dimension: "2d", animations: ["static"], aspect: "1:1" },
4607
+ item: { dimension: "2d", animations: ["static"], aspect: "5:7" },
4608
+ player: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
4609
+ enemy: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
4610
+ npc: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
4611
+ projectile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
4612
+ vehicle: { dimension: "2d", animations: ["idle", "walk"], aspect: "1:1" },
4613
+ ui: { dimension: "2d", animations: ["static"], aspect: "1:1" }
4614
+ };
4615
+ function makeAsset(url, role, overrides = {}) {
4616
+ const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
4617
+ return {
4618
+ url,
4619
+ role,
4620
+ category: url.split("/").pop()?.replace(/\.[^.]+$/, "") ?? role,
4621
+ ...defaults,
4622
+ ...overrides
4623
+ };
4605
4624
  }
4625
+
4626
+ // components/game/templates/game3dAssetManifest.ts
4606
4627
  function tileKind(type, passable) {
4607
4628
  if (passable === false) return "wall";
4608
4629
  if (type === "dirt" || type === "road") return "dirt";
@@ -4618,7 +4639,7 @@ function resolveTilesWithModels(layout, manifest) {
4618
4639
  z: t.z,
4619
4640
  type: t.type,
4620
4641
  passable: t.passable,
4621
- modelUrl: resolveManifestUrl(manifest, manifest?.models?.[kind])
4642
+ modelUrl: manifest?.models?.[kind]
4622
4643
  };
4623
4644
  });
4624
4645
  }
@@ -4627,7 +4648,7 @@ function resolvePropTiles(tiles, manifest) {
4627
4648
  const kind = tileKind(t.type ?? "", t.passable);
4628
4649
  return {
4629
4650
  ...t,
4630
- modelUrl: t.modelUrl ?? resolveManifestUrl(manifest, manifest?.models?.[kind])
4651
+ modelUrl: t.modelUrl ?? manifest?.models?.[kind]
4631
4652
  };
4632
4653
  });
4633
4654
  }
@@ -4638,7 +4659,8 @@ function resolveEntityTiles(entity, manifest) {
4638
4659
  const type = str(r.type) || str(r.terrain);
4639
4660
  const passable = r.passable !== false;
4640
4661
  const kind = tileKind(type, passable);
4641
- const explicitModel = r.modelUrl == null ? void 0 : str(r.modelUrl);
4662
+ const explicitModelUrl = r.modelUrl == null ? void 0 : str(r.modelUrl);
4663
+ const explicitModel = explicitModelUrl ? makeAsset(explicitModelUrl, "decoration", { dimension: "3d" }) : void 0;
4642
4664
  return {
4643
4665
  id: r.id == null ? void 0 : str(r.id),
4644
4666
  x: num(r.x),
@@ -4646,14 +4668,14 @@ function resolveEntityTiles(entity, manifest) {
4646
4668
  z: r.z == null ? void 0 : num(r.z),
4647
4669
  type,
4648
4670
  passable,
4649
- modelUrl: explicitModel ?? resolveManifestUrl(manifest, manifest?.models?.[kind])
4671
+ modelUrl: explicitModel ?? manifest?.models?.[kind]
4650
4672
  };
4651
4673
  });
4652
4674
  }
4653
4675
  function resolveFeaturesWithModels(features, manifest) {
4654
4676
  return features.map((f) => ({
4655
4677
  ...f,
4656
- assetUrl: f.assetUrl ?? resolveManifestUrl(manifest, manifest?.features?.[f.type])
4678
+ assetUrl: f.assetUrl ?? manifest?.features?.[f.type]
4657
4679
  }));
4658
4680
  }
4659
4681
  function resolveEntityFeatures(entity, manifest) {
@@ -4661,7 +4683,8 @@ function resolveEntityFeatures(entity, manifest) {
4661
4683
  if (!row) return [];
4662
4684
  return rows(row.features).map((r) => {
4663
4685
  const type = str(r.type);
4664
- const explicit = r.assetUrl == null ? void 0 : str(r.assetUrl);
4686
+ const explicitUrl = r.assetUrl == null ? void 0 : str(r.assetUrl);
4687
+ const explicit = explicitUrl ? makeAsset(explicitUrl, "decoration", { dimension: "3d" }) : void 0;
4665
4688
  return {
4666
4689
  id: r.id == null ? void 0 : str(r.id),
4667
4690
  x: num(r.x),
@@ -4669,7 +4692,7 @@ function resolveEntityFeatures(entity, manifest) {
4669
4692
  z: r.z == null ? void 0 : num(r.z),
4670
4693
  type,
4671
4694
  color: r.color == null ? void 0 : str(r.color),
4672
- assetUrl: explicit ?? resolveManifestUrl(manifest, manifest?.features?.[type])
4695
+ assetUrl: explicit ?? manifest?.features?.[type]
4673
4696
  };
4674
4697
  });
4675
4698
  }
@@ -1,19 +1,12 @@
1
- import type { AssetUrl } from '@almadar/core';
2
1
  import type { IsometricUnit } from '../organisms/types/isometric';
3
2
  import type { ResolvedFrame } from '../organisms/types/spriteAnimation';
4
3
  /**
5
4
  * Resolve the sprite-sheet atlas-JSON URL for a unit.
6
5
  *
7
- * An explicit `unit.spriteSheet` wins. Otherwise, when the unit's static
8
- * `sprite` points at a directional sheet PNG, derive its sibling atlas JSON by
9
- * the deterministic naming convention used in `shared/sprite-sheets/`:
10
- * the shared atlas drops the `-se` / `-sw` direction suffix and any `-vN`
11
- * variant suffix, then swaps `.png` → `.json`
12
- * (`amir-sprite-sheet-se.png` → `amir-sprite-sheet.json`).
13
- *
14
- * Returns null when no atlas can be resolved (the unit keeps its static draw).
6
+ * A unit has an atlas iff `unit.spriteSheet.url` is set (explicit metadata wins).
7
+ * No filename-pattern matching a unit without a `spriteSheet` Asset keeps its static draw.
15
8
  */
16
- export declare function unitAtlasUrl(unit: Pick<IsometricUnit, 'spriteSheet' | 'sprite'>): AssetUrl | null;
9
+ export declare function unitAtlasUrl(unit: Pick<IsometricUnit, 'spriteSheet'>): string | null;
17
10
  export interface UseUnitSpriteAtlasResult {
18
11
  /** Atlas-JSON URLs successfully loaded — feed these to no one; sheet PNGs are returned below. */
19
12
  sheetUrls: string[];
@@ -18,7 +18,7 @@
18
18
  * @packageDocumentation
19
19
  */
20
20
  import React from 'react';
21
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
21
+ import type { Asset, AssetUrl, EventEmit, EntityRow } from '@almadar/core';
22
22
  import type { DisplayStateProps } from '../../core/organisms/types';
23
23
  import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
24
24
  import type { ResolvedFrame } from './types/spriteAnimation';
@@ -48,11 +48,10 @@ export type BattleSlotContext = {
48
48
  };
49
49
  /** Asset manifest shape for BattleBoard. */
50
50
  type BattleAssetManifest = {
51
- baseUrl?: AssetUrl;
52
- terrains?: Record<string, AssetUrl>;
53
- units?: Record<string, AssetUrl>;
54
- features?: Record<string, AssetUrl>;
55
- effects?: Record<string, AssetUrl>;
51
+ terrains?: Record<string, Asset>;
52
+ units?: Record<string, Asset>;
53
+ features?: Record<string, Asset>;
54
+ effects?: Record<string, Asset>;
56
55
  };
57
56
  export interface BattleBoardProps extends DisplayStateProps {
58
57
  /** Entity (single board state) containing all board data */
@@ -1,10 +1,9 @@
1
1
  import React from 'react';
2
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
2
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
3
3
  import type { DisplayStateProps } from '../../core/organisms/types';
4
- /** Manifest of asset base-url + per-card sprite map (UI value DTO). */
4
+ /** Manifest of per-card sprite map (UI value DTO). */
5
5
  type CardBattlerAssetManifest = {
6
- baseUrl?: AssetUrl;
7
- cards?: Record<string, AssetUrl>;
6
+ cards?: Record<string, Asset>;
8
7
  };
9
8
  /** One card as carried on the entity / passed as a prop. */
10
9
  export interface CardBattlerCard {
@@ -13,14 +13,13 @@
13
13
  * @packageDocumentation
14
14
  */
15
15
  import React from 'react';
16
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
16
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
17
17
  import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
18
- /** Manifest of asset base-url + per-kind sprite maps (UI value DTO). */
18
+ /** Manifest of per-kind sprite maps (UI value DTO). */
19
19
  type CastleAssetManifest = {
20
- baseUrl?: AssetUrl;
21
- terrains?: Record<string, AssetUrl>;
22
- units?: Record<string, AssetUrl>;
23
- features?: Record<string, AssetUrl>;
20
+ terrains?: Record<string, Asset>;
21
+ units?: Record<string, Asset>;
22
+ features?: Record<string, Asset>;
24
23
  };
25
24
  /** Context exposed to render-prop slots */
26
25
  export type CastleSlotContext = {
@@ -1,18 +1,17 @@
1
1
  import React from 'react';
2
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
2
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
3
3
  import type { DisplayStateProps } from '../../core/organisms/types';
4
- /** Manifest of asset base-url + per-kind sprite maps (UI value DTO). */
4
+ /** Manifest of per-kind sprite maps (UI value DTO). */
5
5
  type CityBuilderAssetManifest = {
6
- baseUrl?: AssetUrl;
7
- terrains?: Record<string, AssetUrl>;
8
- units?: Record<string, AssetUrl>;
9
- features?: Record<string, AssetUrl>;
6
+ terrains?: Record<string, Asset>;
7
+ units?: Record<string, Asset>;
8
+ features?: Record<string, Asset>;
10
9
  };
11
10
  export interface CityBuilderTile {
12
11
  x: number;
13
12
  y: number;
14
13
  terrain?: string;
15
- terrainSprite?: AssetUrl;
14
+ terrainSprite?: Asset;
16
15
  passable?: boolean;
17
16
  }
18
17
  export interface CityBuilderBuilding {
@@ -1,11 +1,9 @@
1
1
  import React from 'react';
2
- import type { AssetUrl, EventEmit } from '@almadar/core';
2
+ import type { Asset, EventEmit } from '@almadar/core';
3
3
  import type { DisplayStateProps } from '../../core/organisms/types';
4
4
  export interface FishingBoardProps extends DisplayStateProps {
5
- /** Background image URL for the fishing scene */
6
- backgroundImage?: AssetUrl;
7
- /** Base URL prepended to asset paths */
8
- assetBaseUrl?: AssetUrl;
5
+ /** Background image asset for the fishing scene */
6
+ backgroundImage?: Asset;
9
7
  /** Render scale */
10
8
  scale?: number;
11
9
  /** Show minimap overlay */
@@ -26,7 +24,7 @@ export interface FishingBoardProps extends DisplayStateProps {
26
24
  unitId: string;
27
25
  }>;
28
26
  }
29
- export declare function FishingBoard({ backgroundImage, assetBaseUrl, scale, showMinimap, enableCamera, width, height, isLoading, error, className, }: FishingBoardProps): React.ReactElement;
27
+ export declare function FishingBoard({ backgroundImage, scale, showMinimap, enableCamera, width, height, isLoading, error, className, }: FishingBoardProps): React.ReactElement;
30
28
  export declare namespace FishingBoard {
31
29
  var displayName: string;
32
30
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
2
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
3
3
  import type { PlatformerPlatform, PlatformerPlayer } from '../molecules/PlatformerCanvas';
4
4
  export interface PlatformerBoardProps {
5
5
  /** Entity containing all board state (result, lives, score, level, player, platforms) */
@@ -21,10 +21,10 @@ export interface PlatformerBoardProps {
21
21
  worldHeight?: number;
22
22
  canvasWidth?: number;
23
23
  canvasHeight?: number;
24
- /** Player sprite URL */
25
- playerSprite?: AssetUrl;
26
- /** Map of platform type to tile sprite URL */
27
- tileSprites?: Record<string, AssetUrl>;
24
+ /** Player sprite */
25
+ playerSprite?: Asset;
26
+ /** Map of platform type to tile sprite */
27
+ tileSprites?: Record<string, Asset>;
28
28
  /** Canvas background color */
29
29
  bgColor?: string;
30
30
  /** Event names forwarded to PlatformerCanvas */
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
2
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
3
3
  import type { DisplayStateProps } from '../../core/organisms/types';
4
4
  import type { IsometricTile } from './types/isometric';
5
5
  type PlayerPos = {
@@ -20,10 +20,9 @@ type ItemRow = {
20
20
  kind: 'health_potion' | 'sword' | 'shield';
21
21
  };
22
22
  type RoguelikeAssetManifest = {
23
- baseUrl?: AssetUrl;
24
- terrains?: Record<string, AssetUrl>;
25
- units?: Record<string, AssetUrl>;
26
- features?: Record<string, AssetUrl>;
23
+ terrains?: Record<string, Asset>;
24
+ units?: Record<string, Asset>;
25
+ features?: Record<string, Asset>;
27
26
  };
28
27
  export interface RoguelikeBoardProps extends DisplayStateProps {
29
28
  entity?: EntityRow | readonly EntityRow[];
@@ -1,11 +1,10 @@
1
1
  import * as React from 'react';
2
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
3
- /** Asset base-url + per-kind sprite maps (organism owns asset choice; UI value DTO). */
2
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
3
+ /** Per-kind sprite maps (organism owns asset choice; UI value DTO). */
4
4
  type ShooterAssetManifest = {
5
- baseUrl?: AssetUrl;
6
- units?: Record<string, AssetUrl>;
7
- features?: Record<string, AssetUrl>;
8
- background?: AssetUrl;
5
+ units?: Record<string, Asset>;
6
+ features?: Record<string, Asset>;
7
+ background?: Asset;
9
8
  };
10
9
  export interface ShooterPlayer {
11
10
  x: number;
@@ -1,12 +1,11 @@
1
1
  import React from 'react';
2
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
2
+ import type { Asset, AssetUrl, EventEmit, EntityRow } from '@almadar/core';
3
3
  import type { DisplayStateProps } from '../../core/organisms/types';
4
- /** Manifest of asset base-url + per-kind sprite maps (UI value DTO). */
4
+ /** Manifest of per-kind sprite maps (UI value DTO). */
5
5
  type TowerDefenseAssetManifest = {
6
- baseUrl?: AssetUrl;
7
- terrains?: Record<string, AssetUrl>;
8
- units?: Record<string, AssetUrl>;
9
- features?: Record<string, AssetUrl>;
6
+ terrains?: Record<string, Asset>;
7
+ units?: Record<string, Asset>;
8
+ features?: Record<string, Asset>;
10
9
  };
11
10
  export interface TowerDefenseTile {
12
11
  x: number;
@@ -7,13 +7,12 @@
7
7
  * the `assetManifest` prop (organism owns asset choice — no hardcoded URLs).
8
8
  */
9
9
  import React from 'react';
10
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
10
+ import type { Asset, EventEmit, EntityRow } from '@almadar/core';
11
11
  import type { DisplayStateProps } from '../../core/organisms/types';
12
- /** Manifest of asset base-url + per-key scene + portrait maps (UI value DTO). */
12
+ /** Manifest of per-key scene + portrait maps (UI value DTO). */
13
13
  type VisualNovelAssetManifest = {
14
- baseUrl?: AssetUrl;
15
- backgrounds?: Record<string, AssetUrl>;
16
- portraits?: Record<string, AssetUrl>;
14
+ backgrounds?: Record<string, Asset>;
15
+ portraits?: Record<string, Asset>;
17
16
  };
18
17
  export interface VisualNovelChoice {
19
18
  label: string;
@@ -19,16 +19,15 @@
19
19
  * @packageDocumentation
20
20
  */
21
21
  import React from 'react';
22
- import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
22
+ import type { Asset, AssetUrl, EventEmit, EntityRow } from '@almadar/core';
23
23
  import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
24
24
  import type { ResolvedFrame } from './types/spriteAnimation';
25
25
  import type { UiError } from '../../core/atoms/types';
26
- /** Manifest of asset base-url + per-kind sprite maps (UI value DTO). */
26
+ /** Manifest of per-kind sprite maps (UI value DTO). */
27
27
  type WorldMapAssetManifest = {
28
- baseUrl?: AssetUrl;
29
- terrains?: Record<string, AssetUrl>;
30
- units?: Record<string, AssetUrl>;
31
- features?: Record<string, AssetUrl>;
28
+ terrains?: Record<string, Asset>;
29
+ units?: Record<string, Asset>;
30
+ features?: Record<string, Asset>;
32
31
  };
33
32
  /** Context exposed to render-prop slots. Hex / hero rows are `EntityRow`. */
34
33
  export type WorldMapSlotContext = {
@@ -1,4 +1,3 @@
1
- import type { AssetUrl } from '@almadar/core';
2
1
  /**
3
2
  * Canvas Effect Types
4
3
  *
@@ -12,7 +11,7 @@ import type { AssetUrl } from '@almadar/core';
12
11
  */
13
12
  export interface CanvasParticle {
14
13
  /** Sprite URL (white-on-transparent particle) */
15
- spriteUrl: AssetUrl;
14
+ spriteUrl: string;
16
15
  /** Current position in screen pixels */
17
16
  x: number;
18
17
  y: number;
@@ -51,7 +50,7 @@ export interface CanvasParticle {
51
50
  */
52
51
  export interface ParticleEmitterConfig {
53
52
  /** Array of sprite URLs to randomly pick from */
54
- spriteUrls: AssetUrl[];
53
+ spriteUrls: string[];
55
54
  /** Number of particles to spawn */
56
55
  count: number;
57
56
  /** Spawn origin in screen pixels */
@@ -96,7 +95,7 @@ export interface ParticleEmitterConfig {
96
95
  */
97
96
  export interface CanvasSequence {
98
97
  /** Ordered array of frame sprite URLs */
99
- frameUrls: AssetUrl[];
98
+ frameUrls: string[];
100
99
  /** Position in screen pixels (top-left of sprite) */
101
100
  x: number;
102
101
  y: number;
@@ -123,7 +122,7 @@ export interface CanvasSequence {
123
122
  * Configuration for spawning a frame sequence.
124
123
  */
125
124
  export interface SequenceConfig {
126
- frameUrls: AssetUrl[];
125
+ frameUrls: string[];
127
126
  originX: number;
128
127
  originY: number;
129
128
  frameDuration: number;
@@ -142,7 +141,7 @@ export interface SequenceConfig {
142
141
  */
143
142
  export interface CanvasOverlay {
144
143
  /** Sprite URL */
145
- spriteUrl: AssetUrl;
144
+ spriteUrl: string;
146
145
  /** Center position in screen pixels */
147
146
  x: number;
148
147
  y: number;
@@ -167,7 +166,7 @@ export interface CanvasOverlay {
167
166
  * Configuration for spawning an overlay.
168
167
  */
169
168
  export interface OverlayConfig {
170
- spriteUrl: AssetUrl;
169
+ spriteUrl: string;
171
170
  originX: number;
172
171
  originY: number;
173
172
  alpha?: number;
@@ -217,7 +216,7 @@ export interface CombatPreset {
217
216
  */
218
217
  export interface EffectAssetManifest {
219
218
  /** Base URL for all asset paths */
220
- baseUrl: AssetUrl;
219
+ baseUrl: string;
221
220
  /** Particle sprite groups (white-on-transparent, tinted at runtime) */
222
221
  particles?: {
223
222
  slash?: string[];
@@ -1,4 +1,4 @@
1
- import type { AssetUrl } from '@almadar/core';
1
+ import type { Asset } from '@almadar/core';
2
2
  import type { AnimationName } from './spriteAnimation';
3
3
  /**
4
4
  * Isometric Game Types
@@ -34,7 +34,7 @@ export interface IsometricTile {
34
34
  /** Tile type for visual rendering (3D) */
35
35
  type?: string;
36
36
  /** Direct sprite URL override (bypasses getTerrainSprite resolver) */
37
- terrainSprite?: AssetUrl;
37
+ terrainSprite?: Asset;
38
38
  /** Whether units can traverse this tile (default true) */
39
39
  passable?: boolean;
40
40
  /** Movement cost for pathfinding (default 1) */
@@ -44,7 +44,7 @@ export interface IsometricTile {
44
44
  /** Elevation offset for 3D rendering */
45
45
  elevation?: number;
46
46
  /** 3D model URL (GLB format) for GameCanvas3D — rendered via ModelLoader with box fallback */
47
- modelUrl?: AssetUrl;
47
+ modelUrl?: Asset;
48
48
  }
49
49
  /** A unit positioned on the isometric grid */
50
50
  export type IsometricUnit = {
@@ -62,13 +62,13 @@ export type IsometricUnit = {
62
62
  /** Grid z coordinate (3D format) */
63
63
  z?: number;
64
64
  /** Static sprite URL (used when no sprite sheet animation) */
65
- sprite?: AssetUrl;
65
+ sprite?: Asset;
66
66
  /** Sprite-sheet atlas JSON URL (e.g. `.../guardian-sprite-sheet.json`).
67
67
  * When set, the canvas loads the atlas and crops/animates a single frame
68
68
  * by animation state instead of drawing the whole sheet. */
69
- spriteSheet?: AssetUrl;
69
+ spriteSheet?: Asset;
70
70
  /** 3D model URL (GLB format) for GameCanvas3D — rendered via ModelLoader with box fallback */
71
- modelUrl?: AssetUrl;
71
+ modelUrl?: Asset;
72
72
  /** Unit archetype key for sprite resolution */
73
73
  unitType?: string;
74
74
  /** Hero identifier for sprite sheet lookup */
@@ -115,9 +115,9 @@ export type IsometricFeature = {
115
115
  /** Feature type key (e.g., 'goldMine', 'castle', 'portal') */
116
116
  type: string;
117
117
  /** Direct sprite URL override (bypasses getFeatureSprite resolver) */
118
- sprite?: AssetUrl;
118
+ sprite?: Asset;
119
119
  /** 3D model URL (GLB format) for GameCanvas3D */
120
- assetUrl?: AssetUrl;
120
+ assetUrl?: Asset;
121
121
  /** Color override for 3D rendering */
122
122
  color?: string;
123
123
  /** Elevation offset for 3D rendering */
@@ -1,4 +1,3 @@
1
- import type { AssetUrl } from '@almadar/core';
2
1
  /**
3
2
  * Sprite Sheet Animation Types
4
3
  *
@@ -27,7 +26,7 @@ export interface AnimationDef {
27
26
  /** A resolved frame ready to draw on canvas */
28
27
  export interface ResolvedFrame {
29
28
  /** URL of the sprite sheet image */
30
- sheetUrl: AssetUrl;
29
+ sheetUrl: string;
31
30
  /** Source X in the sheet (pixel offset) */
32
31
  sx: number;
33
32
  /** Source Y in the sheet (pixel offset) */
@@ -68,9 +67,9 @@ export interface SpriteFrameDims {
68
67
  /** Sheet URLs for both directions */
69
68
  export interface SpriteSheetUrls {
70
69
  /** Southeast-facing sheet URL */
71
- se: AssetUrl;
70
+ se: string;
72
71
  /** Southwest-facing sheet URL */
73
- sw: AssetUrl;
72
+ sw: string;
74
73
  }
75
74
  /**
76
75
  * Parsed sprite-sheet atlas JSON (e.g. `guardian-sprite-sheet.json`).
@@ -0,0 +1,5 @@
1
+ import type { Asset, EntityRole } from '@almadar/core';
2
+ /** Build an Asset from a url + the slot's role. Slot-fixed defaults by role. */
3
+ export declare function makeAsset(url: string, role: EntityRole, overrides?: Partial<Asset>): Asset;
4
+ /** Map a name→url record to name→Asset. */
5
+ export declare function makeAssetMap(record: Record<string, string>, role: EntityRole, overrides?: Partial<Asset>): Record<string, Asset>;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { Asset } from '@almadar/core';
2
3
  import type { TemplateProps } from '../../core/templates/types';
3
4
  import type { PlatformerBoardProps } from '../organisms/PlatformerBoard';
4
5
  export interface PlatformerTemplateProps extends TemplateProps {
@@ -10,10 +11,10 @@ export interface PlatformerTemplateProps extends TemplateProps {
10
11
  /** Canvas display size */
11
12
  canvasWidth?: number;
12
13
  canvasHeight?: number;
13
- /** Player sprite URL */
14
- playerSprite?: string;
15
- /** Map of platform type to tile sprite URL */
16
- tileSprites?: Record<string, string>;
14
+ /** Player sprite asset */
15
+ playerSprite?: Asset;
16
+ /** Map of platform type to tile sprite asset */
17
+ tileSprites?: Record<string, Asset>;
17
18
  /** Canvas background color */
18
19
  bgColor?: string;
19
20
  /** Forwarded to PlatformerBoard to emit GAME_END into the FSM */
@@ -9,16 +9,14 @@
9
9
  *
10
10
  * @packageDocumentation
11
11
  */
12
- import type { AssetUrl, EntityRow } from '@almadar/core';
12
+ import type { Asset, EntityRow } from '@almadar/core';
13
13
  import type { IsometricTile, IsometricFeature } from '../organisms/types/isometric';
14
- /** GLB model URLs for a 3D board, keyed by terrain "kind" and (optionally) feature type. */
14
+ /** GLB model assets for a 3D board, keyed by terrain "kind" and (optionally) feature type. */
15
15
  export interface Game3DAssetManifest {
16
- /** Base URL prepended to manifest-relative model paths (absolute paths pass through). */
17
- baseUrl?: AssetUrl;
18
- /** Floor model URLs by terrain kind ('wall' | 'dirt' | 'open'). */
19
- models?: Record<string, AssetUrl>;
20
- /** Feature/structure model URLs by feature type ('gold_mine', 'portal', …). */
21
- features?: Record<string, AssetUrl>;
16
+ /** Floor model assets by terrain kind ('wall' | 'dirt' | 'open'). */
17
+ models?: Record<string, Asset>;
18
+ /** Feature/structure model assets by feature type ('gold_mine', 'portal', ). */
19
+ features?: Record<string, Asset>;
22
20
  }
23
21
  /** Layout-only tile (no model URL): position + terrain kind. */
24
22
  export interface Tile3DLayout {