@almadar/ui 5.28.2 → 5.28.3

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.
@@ -11456,7 +11456,7 @@ var init_DamageNumber = __esm({
11456
11456
  function DialogueBubble({
11457
11457
  speaker,
11458
11458
  text,
11459
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/00_base_model.png",
11459
+ portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
11460
11460
  position = "bottom",
11461
11461
  className
11462
11462
  }) {
@@ -14066,7 +14066,7 @@ function IsometricCanvas({
14066
14066
  // Rendering options
14067
14067
  scale = 0.4,
14068
14068
  debug: debug2 = false,
14069
- backgroundImage,
14069
+ backgroundImage = "https://almadar-kflow-assets.web.app/shared/scenes/court.png",
14070
14070
  showMinimap = true,
14071
14071
  enableCamera = true,
14072
14072
  unitScale = 1,
@@ -14081,7 +14081,7 @@ function IsometricCanvas({
14081
14081
  // Tuning
14082
14082
  diamondTopY: diamondTopYProp,
14083
14083
  // Remote asset loading
14084
- assetBaseUrl,
14084
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/",
14085
14085
  assetManifest
14086
14086
  }) {
14087
14087
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
@@ -14840,6 +14840,10 @@ var init_boardEntity = __esm({
14840
14840
  });
14841
14841
  function BattleBoard({
14842
14842
  entity,
14843
+ tiles: propTiles,
14844
+ units: propUnits,
14845
+ features: propFeatures,
14846
+ assetManifest: propAssetManifest,
14843
14847
  scale = 0.45,
14844
14848
  unitScale = 1,
14845
14849
  header,
@@ -14865,11 +14869,11 @@ function BattleBoard({
14865
14869
  className
14866
14870
  }) {
14867
14871
  const board = boardEntity(entity) ?? {};
14868
- const tiles = Array.isArray(board.tiles) ? board.tiles : [];
14869
- const features = Array.isArray(board.features) ? board.features : [];
14872
+ const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
14873
+ const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
14870
14874
  const boardWidth = num(board.boardWidth, 8);
14871
14875
  const boardHeight = num(board.boardHeight, 6);
14872
- const assetManifest = board.assetManifest;
14876
+ const assetManifest = propAssetManifest ?? board.assetManifest;
14873
14877
  const backgroundImage = board.backgroundImage;
14874
14878
  const units = rows(board.units);
14875
14879
  const selectedUnitId = board.selectedUnitId ?? null;
@@ -14961,7 +14965,7 @@ function BattleBoard({
14961
14965
  }, 16);
14962
14966
  return () => clearInterval(interval);
14963
14967
  }, []);
14964
- const isoUnits = React88.useMemo(() => {
14968
+ const derivedIsoUnits = React88.useMemo(() => {
14965
14969
  return units.filter((u) => unitHealth(u) > 0).map((unit) => {
14966
14970
  const id = str(unit.id);
14967
14971
  const pos = movingPositions.get(id) ?? unitPosition(unit);
@@ -14985,6 +14989,7 @@ function BattleBoard({
14985
14989
  };
14986
14990
  });
14987
14991
  }, [units, movingPositions]);
14992
+ const isoUnits = propUnits ?? derivedIsoUnits;
14988
14993
  const maxY = Math.max(...tiles.map((t2) => t2.y), 0);
14989
14994
  const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
14990
14995
  const tileToScreen = React88.useCallback(
@@ -21359,16 +21364,21 @@ function EmojiEffect({
21359
21364
  }
21360
21365
  );
21361
21366
  }
21362
- function CanvasEffect(props) {
21367
+ function CanvasEffect({
21368
+ effectSpriteUrl = "https://almadar-kflow-assets.web.app/shared/effects/gas/gas00.png",
21369
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/effects/",
21370
+ ...props
21371
+ }) {
21363
21372
  const eventBus = useEventBus();
21364
- const { completeEvent, onComplete, ...rest } = props;
21373
+ const mergedProps = { effectSpriteUrl, assetBaseUrl, ...props };
21374
+ const { completeEvent, onComplete, ...rest } = mergedProps;
21365
21375
  const handleComplete = React88.useCallback(() => {
21366
21376
  if (completeEvent) eventBus.emit(`UI:${completeEvent}`, {});
21367
21377
  onComplete?.();
21368
21378
  }, [completeEvent, eventBus, onComplete]);
21369
21379
  const enhancedProps = { ...rest, onComplete: handleComplete };
21370
- if (props.assetManifest) {
21371
- return /* @__PURE__ */ jsxRuntime.jsx(CanvasEffectEngine, { ...enhancedProps, assetManifest: props.assetManifest });
21380
+ if (rest.assetManifest) {
21381
+ return /* @__PURE__ */ jsxRuntime.jsx(CanvasEffectEngine, { ...enhancedProps, assetManifest: rest.assetManifest });
21372
21382
  }
21373
21383
  return /* @__PURE__ */ jsxRuntime.jsx(EmojiEffect, { ...enhancedProps });
21374
21384
  }
@@ -22153,6 +22163,10 @@ var init_CaseStudyOrganism = __esm({
22153
22163
  });
22154
22164
  function CastleBoard({
22155
22165
  entity,
22166
+ tiles: propTiles,
22167
+ units: propUnits,
22168
+ features: propFeatures,
22169
+ assetManifest: propAssetManifest,
22156
22170
  scale = 0.45,
22157
22171
  header,
22158
22172
  sidePanel,
@@ -22168,10 +22182,10 @@ function CastleBoard({
22168
22182
  }) {
22169
22183
  const eventBus = useEventBus();
22170
22184
  const resolved = boardEntity(entity);
22171
- const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
22172
- const features = Array.isArray(resolved?.features) ? resolved.features : [];
22173
- const units = Array.isArray(resolved?.units) ? resolved.units : [];
22174
- const assetManifest = resolved?.assetManifest;
22185
+ const tiles = propTiles ?? (Array.isArray(resolved?.tiles) ? resolved.tiles : []);
22186
+ const features = propFeatures ?? (Array.isArray(resolved?.features) ? resolved.features : []);
22187
+ const units = propUnits ?? (Array.isArray(resolved?.units) ? resolved.units : []);
22188
+ const assetManifest = propAssetManifest ?? resolved?.assetManifest;
22175
22189
  const backgroundImage = resolved?.backgroundImage;
22176
22190
  const [hoveredTile, setHoveredTile] = React88.useState(null);
22177
22191
  const [selectedFeature, setSelectedFeature] = React88.useState(null);
@@ -22274,14 +22288,22 @@ var init_CastleBoard = __esm({
22274
22288
  function CastleTemplate({
22275
22289
  entity,
22276
22290
  scale = 0.45,
22291
+ tiles,
22292
+ units,
22293
+ features,
22294
+ assetManifest,
22277
22295
  className
22278
22296
  }) {
22279
22297
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
22280
- if (!resolved) return null;
22298
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
22281
22299
  return /* @__PURE__ */ jsxRuntime.jsx(
22282
22300
  CastleBoard,
22283
22301
  {
22284
22302
  entity: resolved,
22303
+ tiles,
22304
+ units,
22305
+ features,
22306
+ assetManifest,
22285
22307
  scale,
22286
22308
  featureClickEvent: "FEATURE_CLICK",
22287
22309
  unitClickEvent: "UNIT_CLICK",
@@ -28914,8 +28936,8 @@ function GameCanvas2D({
28914
28936
  tickEvent,
28915
28937
  drawEvent,
28916
28938
  fps = 60,
28917
- backgroundImage,
28918
- assetBaseUrl = "",
28939
+ backgroundImage = "https://almadar-kflow-assets.web.app/shared/scenes/resonators.jpeg",
28940
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/",
28919
28941
  className
28920
28942
  }) {
28921
28943
  const canvasRef = React88__namespace.useRef(null);
@@ -28979,6 +29001,9 @@ function GameCanvas2D({
28979
29001
  const bgImg = loadImage(backgroundImageRef.current);
28980
29002
  if (bgImg) {
28981
29003
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
29004
+ } else {
29005
+ ctx.fillStyle = "#0f1420";
29006
+ ctx.fillRect(0, 0, widthRef.current, heightRef.current);
28982
29007
  }
28983
29008
  }
28984
29009
  onDrawRef.current?.(ctx, frame);
@@ -30123,10 +30148,10 @@ function PlatformerCanvas({
30123
30148
  canvasHeight = 400,
30124
30149
  followCamera = true,
30125
30150
  bgColor,
30126
- playerSprite,
30151
+ playerSprite = "https://almadar-kflow-assets.web.app/shared/platformer/characters/platformChar_idle.png",
30127
30152
  tileSprites,
30128
- backgroundImage,
30129
- assetBaseUrl = "",
30153
+ backgroundImage = "https://almadar-kflow-assets.web.app/shared/scenes/court.png",
30154
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/platformer/",
30130
30155
  leftEvent = "MOVE_LEFT",
30131
30156
  rightEvent = "MOVE_RIGHT",
30132
30157
  jumpEvent = "JUMP",
@@ -48005,6 +48030,10 @@ function defaultIsInRange(from, to, range) {
48005
48030
  }
48006
48031
  function WorldMapBoard({
48007
48032
  entity,
48033
+ tiles: propTiles,
48034
+ units: propUnits,
48035
+ features: propFeatures,
48036
+ assetManifest: propAssetManifest,
48008
48037
  isLoading,
48009
48038
  scale = 0.4,
48010
48039
  unitScale = 2.5,
@@ -48033,16 +48062,16 @@ function WorldMapBoard({
48033
48062
  const resolved = boardEntity(entity);
48034
48063
  const hexes = rows(resolved?.hexes);
48035
48064
  const heroes = rows(resolved?.heroes);
48036
- const features = Array.isArray(resolved?.features) ? resolved.features : [];
48065
+ const features = propFeatures ?? (Array.isArray(resolved?.features) ? resolved.features : []);
48037
48066
  const selectedHeroId = resolved?.selectedHeroId ?? null;
48038
- const assetManifest = resolved?.assetManifest;
48067
+ const assetManifest = propAssetManifest ?? resolved?.assetManifest;
48039
48068
  const backgroundImage = resolved?.backgroundImage;
48040
48069
  const [hoveredTile, setHoveredTile] = React88.useState(null);
48041
48070
  const selectedHero = React88.useMemo(
48042
48071
  () => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
48043
48072
  [heroes, selectedHeroId]
48044
48073
  );
48045
- const tiles = React88.useMemo(
48074
+ const derivedTiles = React88.useMemo(
48046
48075
  () => hexes.map((hex) => ({
48047
48076
  x: num(hex.x),
48048
48077
  y: num(hex.y),
@@ -48051,8 +48080,9 @@ function WorldMapBoard({
48051
48080
  })),
48052
48081
  [hexes]
48053
48082
  );
48083
+ const tiles = propTiles ?? derivedTiles;
48054
48084
  const baseUnits = React88.useMemo(
48055
- () => heroes.map((hero) => ({
48085
+ () => propUnits ?? heroes.map((hero) => ({
48056
48086
  id: str(hero.id),
48057
48087
  position: heroPosition(hero),
48058
48088
  name: str(hero.name),
@@ -48061,7 +48091,7 @@ function WorldMapBoard({
48061
48091
  maxHealth: 100,
48062
48092
  sprite: hero.sprite == null ? void 0 : str(hero.sprite)
48063
48093
  })),
48064
- [heroes]
48094
+ [heroes, propUnits]
48065
48095
  );
48066
48096
  const MOVE_SPEED_MS_PER_TILE = 300;
48067
48097
  const movementAnimRef = React88.useRef(null);
@@ -48271,12 +48301,20 @@ function WorldMapTemplate({
48271
48301
  unitScale = 2.5,
48272
48302
  diamondTopY,
48273
48303
  allowMoveAllHeroes = false,
48304
+ tiles,
48305
+ units,
48306
+ features,
48307
+ assetManifest,
48274
48308
  className
48275
48309
  }) {
48276
48310
  return /* @__PURE__ */ jsxRuntime.jsx(
48277
48311
  WorldMapBoard,
48278
48312
  {
48279
48313
  entity,
48314
+ tiles,
48315
+ units,
48316
+ features,
48317
+ assetManifest,
48280
48318
  scale,
48281
48319
  unitScale,
48282
48320
  diamondTopY,
package/dist/avl/index.js CHANGED
@@ -11407,7 +11407,7 @@ var init_DamageNumber = __esm({
11407
11407
  function DialogueBubble({
11408
11408
  speaker,
11409
11409
  text,
11410
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/00_base_model.png",
11410
+ portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
11411
11411
  position = "bottom",
11412
11412
  className
11413
11413
  }) {
@@ -14017,7 +14017,7 @@ function IsometricCanvas({
14017
14017
  // Rendering options
14018
14018
  scale = 0.4,
14019
14019
  debug: debug2 = false,
14020
- backgroundImage,
14020
+ backgroundImage = "https://almadar-kflow-assets.web.app/shared/scenes/court.png",
14021
14021
  showMinimap = true,
14022
14022
  enableCamera = true,
14023
14023
  unitScale = 1,
@@ -14032,7 +14032,7 @@ function IsometricCanvas({
14032
14032
  // Tuning
14033
14033
  diamondTopY: diamondTopYProp,
14034
14034
  // Remote asset loading
14035
- assetBaseUrl,
14035
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/",
14036
14036
  assetManifest
14037
14037
  }) {
14038
14038
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
@@ -14791,6 +14791,10 @@ var init_boardEntity = __esm({
14791
14791
  });
14792
14792
  function BattleBoard({
14793
14793
  entity,
14794
+ tiles: propTiles,
14795
+ units: propUnits,
14796
+ features: propFeatures,
14797
+ assetManifest: propAssetManifest,
14794
14798
  scale = 0.45,
14795
14799
  unitScale = 1,
14796
14800
  header,
@@ -14816,11 +14820,11 @@ function BattleBoard({
14816
14820
  className
14817
14821
  }) {
14818
14822
  const board = boardEntity(entity) ?? {};
14819
- const tiles = Array.isArray(board.tiles) ? board.tiles : [];
14820
- const features = Array.isArray(board.features) ? board.features : [];
14823
+ const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
14824
+ const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
14821
14825
  const boardWidth = num(board.boardWidth, 8);
14822
14826
  const boardHeight = num(board.boardHeight, 6);
14823
- const assetManifest = board.assetManifest;
14827
+ const assetManifest = propAssetManifest ?? board.assetManifest;
14824
14828
  const backgroundImage = board.backgroundImage;
14825
14829
  const units = rows(board.units);
14826
14830
  const selectedUnitId = board.selectedUnitId ?? null;
@@ -14912,7 +14916,7 @@ function BattleBoard({
14912
14916
  }, 16);
14913
14917
  return () => clearInterval(interval);
14914
14918
  }, []);
14915
- const isoUnits = useMemo(() => {
14919
+ const derivedIsoUnits = useMemo(() => {
14916
14920
  return units.filter((u) => unitHealth(u) > 0).map((unit) => {
14917
14921
  const id = str(unit.id);
14918
14922
  const pos = movingPositions.get(id) ?? unitPosition(unit);
@@ -14936,6 +14940,7 @@ function BattleBoard({
14936
14940
  };
14937
14941
  });
14938
14942
  }, [units, movingPositions]);
14943
+ const isoUnits = propUnits ?? derivedIsoUnits;
14939
14944
  const maxY = Math.max(...tiles.map((t2) => t2.y), 0);
14940
14945
  const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
14941
14946
  const tileToScreen = useCallback(
@@ -21310,16 +21315,21 @@ function EmojiEffect({
21310
21315
  }
21311
21316
  );
21312
21317
  }
21313
- function CanvasEffect(props) {
21318
+ function CanvasEffect({
21319
+ effectSpriteUrl = "https://almadar-kflow-assets.web.app/shared/effects/gas/gas00.png",
21320
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/effects/",
21321
+ ...props
21322
+ }) {
21314
21323
  const eventBus = useEventBus();
21315
- const { completeEvent, onComplete, ...rest } = props;
21324
+ const mergedProps = { effectSpriteUrl, assetBaseUrl, ...props };
21325
+ const { completeEvent, onComplete, ...rest } = mergedProps;
21316
21326
  const handleComplete = useCallback(() => {
21317
21327
  if (completeEvent) eventBus.emit(`UI:${completeEvent}`, {});
21318
21328
  onComplete?.();
21319
21329
  }, [completeEvent, eventBus, onComplete]);
21320
21330
  const enhancedProps = { ...rest, onComplete: handleComplete };
21321
- if (props.assetManifest) {
21322
- return /* @__PURE__ */ jsx(CanvasEffectEngine, { ...enhancedProps, assetManifest: props.assetManifest });
21331
+ if (rest.assetManifest) {
21332
+ return /* @__PURE__ */ jsx(CanvasEffectEngine, { ...enhancedProps, assetManifest: rest.assetManifest });
21323
21333
  }
21324
21334
  return /* @__PURE__ */ jsx(EmojiEffect, { ...enhancedProps });
21325
21335
  }
@@ -22104,6 +22114,10 @@ var init_CaseStudyOrganism = __esm({
22104
22114
  });
22105
22115
  function CastleBoard({
22106
22116
  entity,
22117
+ tiles: propTiles,
22118
+ units: propUnits,
22119
+ features: propFeatures,
22120
+ assetManifest: propAssetManifest,
22107
22121
  scale = 0.45,
22108
22122
  header,
22109
22123
  sidePanel,
@@ -22119,10 +22133,10 @@ function CastleBoard({
22119
22133
  }) {
22120
22134
  const eventBus = useEventBus();
22121
22135
  const resolved = boardEntity(entity);
22122
- const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
22123
- const features = Array.isArray(resolved?.features) ? resolved.features : [];
22124
- const units = Array.isArray(resolved?.units) ? resolved.units : [];
22125
- const assetManifest = resolved?.assetManifest;
22136
+ const tiles = propTiles ?? (Array.isArray(resolved?.tiles) ? resolved.tiles : []);
22137
+ const features = propFeatures ?? (Array.isArray(resolved?.features) ? resolved.features : []);
22138
+ const units = propUnits ?? (Array.isArray(resolved?.units) ? resolved.units : []);
22139
+ const assetManifest = propAssetManifest ?? resolved?.assetManifest;
22126
22140
  const backgroundImage = resolved?.backgroundImage;
22127
22141
  const [hoveredTile, setHoveredTile] = useState(null);
22128
22142
  const [selectedFeature, setSelectedFeature] = useState(null);
@@ -22225,14 +22239,22 @@ var init_CastleBoard = __esm({
22225
22239
  function CastleTemplate({
22226
22240
  entity,
22227
22241
  scale = 0.45,
22242
+ tiles,
22243
+ units,
22244
+ features,
22245
+ assetManifest,
22228
22246
  className
22229
22247
  }) {
22230
22248
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
22231
- if (!resolved) return null;
22249
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
22232
22250
  return /* @__PURE__ */ jsx(
22233
22251
  CastleBoard,
22234
22252
  {
22235
22253
  entity: resolved,
22254
+ tiles,
22255
+ units,
22256
+ features,
22257
+ assetManifest,
22236
22258
  scale,
22237
22259
  featureClickEvent: "FEATURE_CLICK",
22238
22260
  unitClickEvent: "UNIT_CLICK",
@@ -28865,8 +28887,8 @@ function GameCanvas2D({
28865
28887
  tickEvent,
28866
28888
  drawEvent,
28867
28889
  fps = 60,
28868
- backgroundImage,
28869
- assetBaseUrl = "",
28890
+ backgroundImage = "https://almadar-kflow-assets.web.app/shared/scenes/resonators.jpeg",
28891
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/",
28870
28892
  className
28871
28893
  }) {
28872
28894
  const canvasRef = React88.useRef(null);
@@ -28930,6 +28952,9 @@ function GameCanvas2D({
28930
28952
  const bgImg = loadImage(backgroundImageRef.current);
28931
28953
  if (bgImg) {
28932
28954
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
28955
+ } else {
28956
+ ctx.fillStyle = "#0f1420";
28957
+ ctx.fillRect(0, 0, widthRef.current, heightRef.current);
28933
28958
  }
28934
28959
  }
28935
28960
  onDrawRef.current?.(ctx, frame);
@@ -30074,10 +30099,10 @@ function PlatformerCanvas({
30074
30099
  canvasHeight = 400,
30075
30100
  followCamera = true,
30076
30101
  bgColor,
30077
- playerSprite,
30102
+ playerSprite = "https://almadar-kflow-assets.web.app/shared/platformer/characters/platformChar_idle.png",
30078
30103
  tileSprites,
30079
- backgroundImage,
30080
- assetBaseUrl = "",
30104
+ backgroundImage = "https://almadar-kflow-assets.web.app/shared/scenes/court.png",
30105
+ assetBaseUrl = "https://almadar-kflow-assets.web.app/shared/platformer/",
30081
30106
  leftEvent = "MOVE_LEFT",
30082
30107
  rightEvent = "MOVE_RIGHT",
30083
30108
  jumpEvent = "JUMP",
@@ -47956,6 +47981,10 @@ function defaultIsInRange(from, to, range) {
47956
47981
  }
47957
47982
  function WorldMapBoard({
47958
47983
  entity,
47984
+ tiles: propTiles,
47985
+ units: propUnits,
47986
+ features: propFeatures,
47987
+ assetManifest: propAssetManifest,
47959
47988
  isLoading,
47960
47989
  scale = 0.4,
47961
47990
  unitScale = 2.5,
@@ -47984,16 +48013,16 @@ function WorldMapBoard({
47984
48013
  const resolved = boardEntity(entity);
47985
48014
  const hexes = rows(resolved?.hexes);
47986
48015
  const heroes = rows(resolved?.heroes);
47987
- const features = Array.isArray(resolved?.features) ? resolved.features : [];
48016
+ const features = propFeatures ?? (Array.isArray(resolved?.features) ? resolved.features : []);
47988
48017
  const selectedHeroId = resolved?.selectedHeroId ?? null;
47989
- const assetManifest = resolved?.assetManifest;
48018
+ const assetManifest = propAssetManifest ?? resolved?.assetManifest;
47990
48019
  const backgroundImage = resolved?.backgroundImage;
47991
48020
  const [hoveredTile, setHoveredTile] = useState(null);
47992
48021
  const selectedHero = useMemo(
47993
48022
  () => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
47994
48023
  [heroes, selectedHeroId]
47995
48024
  );
47996
- const tiles = useMemo(
48025
+ const derivedTiles = useMemo(
47997
48026
  () => hexes.map((hex) => ({
47998
48027
  x: num(hex.x),
47999
48028
  y: num(hex.y),
@@ -48002,8 +48031,9 @@ function WorldMapBoard({
48002
48031
  })),
48003
48032
  [hexes]
48004
48033
  );
48034
+ const tiles = propTiles ?? derivedTiles;
48005
48035
  const baseUnits = useMemo(
48006
- () => heroes.map((hero) => ({
48036
+ () => propUnits ?? heroes.map((hero) => ({
48007
48037
  id: str(hero.id),
48008
48038
  position: heroPosition(hero),
48009
48039
  name: str(hero.name),
@@ -48012,7 +48042,7 @@ function WorldMapBoard({
48012
48042
  maxHealth: 100,
48013
48043
  sprite: hero.sprite == null ? void 0 : str(hero.sprite)
48014
48044
  })),
48015
- [heroes]
48045
+ [heroes, propUnits]
48016
48046
  );
48017
48047
  const MOVE_SPEED_MS_PER_TILE = 300;
48018
48048
  const movementAnimRef = useRef(null);
@@ -48222,12 +48252,20 @@ function WorldMapTemplate({
48222
48252
  unitScale = 2.5,
48223
48253
  diamondTopY,
48224
48254
  allowMoveAllHeroes = false,
48255
+ tiles,
48256
+ units,
48257
+ features,
48258
+ assetManifest,
48225
48259
  className
48226
48260
  }) {
48227
48261
  return /* @__PURE__ */ jsx(
48228
48262
  WorldMapBoard,
48229
48263
  {
48230
48264
  entity,
48265
+ tiles,
48266
+ units,
48267
+ features,
48268
+ assetManifest,
48231
48269
  scale,
48232
48270
  unitScale,
48233
48271
  diamondTopY,
@@ -20,6 +20,7 @@
20
20
  import React from 'react';
21
21
  import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
22
22
  import type { DisplayStateProps } from '../../core/organisms/types';
23
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
23
24
  import type { ResolvedFrame } from './types/spriteAnimation';
24
25
  /** Battle phases an encounter walks through (UI value enum — not entity data). */
25
26
  export type BattlePhase = 'observation' | 'selection' | 'movement' | 'action' | 'enemy_turn' | 'game_over';
@@ -45,9 +46,25 @@ export type BattleSlotContext = {
45
46
  y: number;
46
47
  };
47
48
  };
49
+ /** Asset manifest shape for BattleBoard. */
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>;
56
+ };
48
57
  export interface BattleBoardProps extends DisplayStateProps {
49
58
  /** Entity (single board state) containing all board data */
50
59
  entity?: EntityRow | readonly EntityRow[];
60
+ /** Direct tile data — takes priority over entity-derived tiles. */
61
+ tiles?: IsometricTile[];
62
+ /** Direct unit data — takes priority over entity-derived units. */
63
+ units?: IsometricUnit[];
64
+ /** Direct feature data — takes priority over entity-derived features. */
65
+ features?: IsometricFeature[];
66
+ /** Direct asset manifest — takes priority over entity-derived manifest. */
67
+ assetManifest?: BattleAssetManifest;
51
68
  /** Canvas render scale */
52
69
  scale?: number;
53
70
  /** Unit draw-size multiplier */
@@ -104,7 +121,7 @@ export interface BattleBoardProps extends DisplayStateProps {
104
121
  }>;
105
122
  className?: string;
106
123
  }
107
- export declare function BattleBoard({ entity, scale, unitScale, header, sidebar, actions, overlay, gameOverOverlay, onAttack, onGameEnd, onUnitMove, calculateDamage, onDrawEffects, hasActiveEffects, effectSpriteUrls, resolveUnitFrame, tileClickEvent, unitClickEvent, endTurnEvent, cancelEvent, gameEndEvent, playAgainEvent, attackEvent, className, }: BattleBoardProps): React.JSX.Element;
124
+ export declare function BattleBoard({ entity, tiles: propTiles, units: propUnits, features: propFeatures, assetManifest: propAssetManifest, scale, unitScale, header, sidebar, actions, overlay, gameOverOverlay, onAttack, onGameEnd, onUnitMove, calculateDamage, onDrawEffects, hasActiveEffects, effectSpriteUrls, resolveUnitFrame, tileClickEvent, unitClickEvent, endTurnEvent, cancelEvent, gameEndEvent, playAgainEvent, attackEvent, className, }: BattleBoardProps): React.JSX.Element;
108
125
  export declare namespace BattleBoard {
109
126
  var displayName: string;
110
127
  }
@@ -63,7 +63,7 @@ export interface CanvasEffectProps {
63
63
  /** Canvas height (default 300) */
64
64
  height?: number;
65
65
  }
66
- export declare function CanvasEffect(props: CanvasEffectProps): React.JSX.Element | null;
66
+ export declare function CanvasEffect({ effectSpriteUrl, assetBaseUrl, ...props }: CanvasEffectProps): React.JSX.Element | null;
67
67
  export declare namespace CanvasEffect {
68
68
  var displayName: string;
69
69
  }
@@ -13,8 +13,15 @@
13
13
  * @packageDocumentation
14
14
  */
15
15
  import React from 'react';
16
- import type { EventEmit, EntityRow } from '@almadar/core';
17
- import type { IsometricUnit, IsometricFeature } from './types/isometric';
16
+ import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
17
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
18
+ /** Manifest of asset base-url + per-kind sprite maps (UI value DTO). */
19
+ type CastleAssetManifest = {
20
+ baseUrl?: AssetUrl;
21
+ terrains?: Record<string, AssetUrl>;
22
+ units?: Record<string, AssetUrl>;
23
+ features?: Record<string, AssetUrl>;
24
+ };
18
25
  /** Context exposed to render-prop slots */
19
26
  export type CastleSlotContext = {
20
27
  /** Currently hovered tile coordinates (null when not hovering) */
@@ -42,6 +49,14 @@ export interface CastleBoardProps {
42
49
  /** Castle board-state entity (single row or array). The board reads
43
50
  * `tiles` / `features` / `units` arrays plus an `assetManifest` off it. */
44
51
  entity?: EntityRow | readonly EntityRow[];
52
+ /** Direct tile data — takes priority over entity-derived tiles. */
53
+ tiles?: IsometricTile[];
54
+ /** Direct unit data — takes priority over entity-derived units. */
55
+ units?: IsometricUnit[];
56
+ /** Direct feature data — takes priority over entity-derived features. */
57
+ features?: IsometricFeature[];
58
+ /** Direct asset manifest — takes priority over entity-derived manifest. */
59
+ assetManifest?: CastleAssetManifest;
45
60
  /** Canvas render scale */
46
61
  scale?: number;
47
62
  /** Top bar / header */
@@ -76,7 +91,7 @@ export interface CastleBoardProps {
76
91
  }>;
77
92
  className?: string;
78
93
  }
79
- export declare function CastleBoard({ entity, scale, header, sidePanel, overlay, footer, onFeatureClick, onUnitClick, onTileClick, featureClickEvent, unitClickEvent, tileClickEvent, className, }: CastleBoardProps): React.JSX.Element;
94
+ export declare function CastleBoard({ entity, tiles: propTiles, units: propUnits, features: propFeatures, assetManifest: propAssetManifest, scale, header, sidePanel, overlay, footer, onFeatureClick, onUnitClick, onTileClick, featureClickEvent, unitClickEvent, tileClickEvent, className, }: CastleBoardProps): React.JSX.Element;
80
95
  export declare namespace CastleBoard {
81
96
  var displayName: string;
82
97
  }
@@ -20,8 +20,16 @@
20
20
  */
21
21
  import React from 'react';
22
22
  import type { AssetUrl, EventEmit, EntityRow } from '@almadar/core';
23
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
23
24
  import type { ResolvedFrame } from './types/spriteAnimation';
24
25
  import type { UiError } from '../../core/atoms/types';
26
+ /** Manifest of asset base-url + per-kind sprite maps (UI value DTO). */
27
+ type WorldMapAssetManifest = {
28
+ baseUrl?: AssetUrl;
29
+ terrains?: Record<string, AssetUrl>;
30
+ units?: Record<string, AssetUrl>;
31
+ features?: Record<string, AssetUrl>;
32
+ };
25
33
  /** Context exposed to render-prop slots. Hex / hero rows are `EntityRow`. */
26
34
  export type WorldMapSlotContext = {
27
35
  /** Currently hovered tile */
@@ -67,6 +75,14 @@ export interface WorldMapBoardProps {
67
75
  /** World-map board-state entity (single row or array). The board reads
68
76
  * `hexes` / `heroes` / `features` arrays + `selectedHeroId` off it. */
69
77
  entity?: EntityRow | readonly EntityRow[];
78
+ /** Direct tile data — takes priority over entity-derived tiles. */
79
+ tiles?: IsometricTile[];
80
+ /** Direct unit data — takes priority over entity-derived units. */
81
+ units?: IsometricUnit[];
82
+ /** Direct feature data — takes priority over entity-derived features. */
83
+ features?: IsometricFeature[];
84
+ /** Direct asset manifest — takes priority over entity-derived manifest. */
85
+ assetManifest?: WorldMapAssetManifest;
70
86
  /** Canvas render scale */
71
87
  scale?: number;
72
88
  /** Unit draw-size multiplier */
@@ -128,7 +144,7 @@ export interface WorldMapBoardProps {
128
144
  effectSpriteUrls?: AssetUrl[];
129
145
  resolveUnitFrame?: (unitId: string) => ResolvedFrame | null;
130
146
  }
131
- export declare function WorldMapBoard({ entity, isLoading, scale, unitScale, allowMoveAllHeroes, isInRange, heroSelectEvent, heroMoveEvent, battleEncounterEvent, featureEnterEvent, tileClickEvent, header, sidePanel, overlay, footer, onHeroSelect, onHeroMove, onBattleEncounter, onFeatureEnter, diamondTopY, enableCamera, effectSpriteUrls, resolveUnitFrame, className, }: WorldMapBoardProps): React.JSX.Element;
147
+ export declare function WorldMapBoard({ entity, tiles: propTiles, units: propUnits, features: propFeatures, assetManifest: propAssetManifest, isLoading, scale, unitScale, allowMoveAllHeroes, isInRange, heroSelectEvent, heroMoveEvent, battleEncounterEvent, featureEnterEvent, tileClickEvent, header, sidePanel, overlay, footer, onHeroSelect, onHeroMove, onBattleEncounter, onFeatureEnter, diamondTopY, enableCamera, effectSpriteUrls, resolveUnitFrame, className, }: WorldMapBoardProps): React.JSX.Element;
132
148
  export declare namespace WorldMapBoard {
133
149
  var displayName: string;
134
150
  }
@@ -10,12 +10,22 @@
10
10
  */
11
11
  import React from 'react';
12
12
  import type { TemplateProps } from '../../core/templates/types';
13
+ import type { CastleBoardProps } from '../organisms/CastleBoard';
14
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from '../organisms/types/isometric';
13
15
  export type { CastleSlotContext } from '../organisms/CastleBoard';
14
16
  export interface CastleTemplateProps extends TemplateProps {
15
17
  /** Canvas render scale */
16
18
  scale?: number;
19
+ /** Direct tile data — forwarded to CastleBoard; takes priority over entity. */
20
+ tiles?: IsometricTile[];
21
+ /** Direct unit data — forwarded to CastleBoard; takes priority over entity. */
22
+ units?: IsometricUnit[];
23
+ /** Direct feature data — forwarded to CastleBoard; takes priority over entity. */
24
+ features?: IsometricFeature[];
25
+ /** Direct asset manifest — forwarded to CastleBoard; takes priority over entity. */
26
+ assetManifest?: CastleBoardProps['assetManifest'];
17
27
  }
18
- export declare function CastleTemplate({ entity, scale, className, }: CastleTemplateProps): React.JSX.Element | null;
28
+ export declare function CastleTemplate({ entity, scale, tiles, units, features, assetManifest, className, }: CastleTemplateProps): React.JSX.Element | null;
19
29
  export declare namespace CastleTemplate {
20
30
  var displayName: string;
21
31
  }