@almadar/ui 5.104.0 → 5.105.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.
@@ -16315,7 +16315,7 @@ function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric")
16315
16315
  const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
16316
16316
  return { x: Math.round(tileX), y: Math.round(tileY) };
16317
16317
  }
16318
- var TILE_WIDTH, TILE_HEIGHT, FLOOR_HEIGHT, DIAMOND_TOP_Y, FEATURE_COLORS;
16318
+ var TILE_WIDTH, TILE_HEIGHT, FLOOR_HEIGHT, DIAMOND_TOP_Y, FEATURE_COLORS, TERRAIN_COLORS, TEAM_COLORS, TEAM_SHADOW_COLORS, HIGHLIGHT_COLORS, SELECTION_RING_COLOR, GRID_STROKE_COLOR, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS, MINIMAP_UNIT_COLORS, UNIT_LABEL_BG_COLORS, SIDE_PLATFORM_COLORS, SIDE_PLAYER_COLOR, SIDE_PLAYER_EYE_COLOR, SIDE_SKY_GRADIENT_TOP, SIDE_SKY_GRADIENT_BOTTOM, SIDE_GRID_COLOR, SIDE_FX_COLOR, SIDE_PLATFORM_BEVEL_COLOR, SIDE_PLATFORM_SHADOW_COLOR, SIDE_HAZARD_STRIPE_COLOR, SIDE_GOAL_GLOW_COLOR, DEFAULT_BG_COLOR;
16319
16319
  var init_isometric = __esm({
16320
16320
  "components/game/shared/isometric.ts"() {
16321
16321
  TILE_WIDTH = 256;
@@ -16332,12 +16332,70 @@ var init_isometric = __esm({
16332
16332
  mountain: "#78716c",
16333
16333
  default: "#9ca3af"
16334
16334
  };
16335
+ TERRAIN_COLORS = {
16336
+ water: "#3b82f6",
16337
+ mountain: "#78716c",
16338
+ stone: "#9ca3af",
16339
+ default: "#4ade80"
16340
+ };
16341
+ TEAM_COLORS = {
16342
+ player: "#3b82f6",
16343
+ enemy: "#ef4444",
16344
+ neutral: "#6b7280",
16345
+ default: "#6b7280"
16346
+ };
16347
+ TEAM_SHADOW_COLORS = {
16348
+ player: "rgba(0,150,255,0.6)",
16349
+ default: "rgba(255,50,50,0.6)"
16350
+ };
16351
+ HIGHLIGHT_COLORS = {
16352
+ hover: "rgba(255,255,255,0.15)",
16353
+ validMove: "rgba(74,222,128,0.25)",
16354
+ attack: "rgba(239,68,68,0.35)"
16355
+ };
16356
+ SELECTION_RING_COLOR = "rgba(0,200,255,0.8)";
16357
+ GRID_STROKE_COLOR = "rgba(0,0,0,0.2)";
16358
+ BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
16359
+ MINIMAP_TERRAIN_COLORS = {
16360
+ water: "#3b82f6",
16361
+ mountain: "#78716c",
16362
+ default: "#4ade80"
16363
+ };
16364
+ MINIMAP_UNIT_COLORS = {
16365
+ player: "#60a5fa",
16366
+ enemy: "#f87171",
16367
+ neutral: "#9ca3af",
16368
+ default: "#9ca3af"
16369
+ };
16370
+ UNIT_LABEL_BG_COLORS = {
16371
+ player: "rgba(59,130,246,0.9)",
16372
+ enemy: "rgba(239,68,68,0.9)",
16373
+ neutral: "rgba(107,114,128,0.9)",
16374
+ default: "rgba(107,114,128,0.9)"
16375
+ };
16376
+ SIDE_PLATFORM_COLORS = {
16377
+ ground: "#4a7c59",
16378
+ platform: "#7c6b4a",
16379
+ hazard: "#c0392b",
16380
+ goal: "#f1c40f"
16381
+ };
16382
+ SIDE_PLAYER_COLOR = "#3498db";
16383
+ SIDE_PLAYER_EYE_COLOR = "#ffffff";
16384
+ SIDE_SKY_GRADIENT_TOP = "#1a1a2e";
16385
+ SIDE_SKY_GRADIENT_BOTTOM = "#16213e";
16386
+ SIDE_GRID_COLOR = "rgba(255, 255, 255, 0.03)";
16387
+ SIDE_FX_COLOR = "#ffe066";
16388
+ SIDE_PLATFORM_BEVEL_COLOR = "rgba(255,255,255,0.15)";
16389
+ SIDE_PLATFORM_SHADOW_COLOR = "rgba(0,0,0,0.3)";
16390
+ SIDE_HAZARD_STRIPE_COLOR = "#e74c3c";
16391
+ SIDE_GOAL_GLOW_COLOR = "rgba(241, 196, 15, 0.5)";
16392
+ DEFAULT_BG_COLOR = "#5c94fc";
16335
16393
  }
16336
16394
  });
16337
16395
  function normalizeBackdrop(bg) {
16338
16396
  return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
16339
16397
  }
16340
- function SideView({
16398
+ function SideCanvas2D({
16341
16399
  player,
16342
16400
  platforms,
16343
16401
  worldWidth,
@@ -16358,24 +16416,18 @@ function SideView({
16358
16416
  const canvasRef = useRef(null);
16359
16417
  const eventBus = useEventBus();
16360
16418
  const keysRef = useRef(/* @__PURE__ */ new Set());
16361
- const imageCache2 = useRef(/* @__PURE__ */ new Map());
16362
- const [loadedImages, setLoadedImages] = useState(/* @__PURE__ */ new Set());
16363
- const loadImage = useCallback((url) => {
16364
- if (!url) return null;
16365
- const cached = imageCache2.current.get(url);
16366
- if (cached?.complete && cached.naturalWidth > 0) {
16367
- if (!loadedImages.has(url)) setLoadedImages((prev) => new Set(prev).add(url));
16368
- return cached;
16369
- }
16370
- if (!cached) {
16371
- const img = new Image();
16372
- img.crossOrigin = "anonymous";
16373
- img.src = url;
16374
- img.onload = () => setLoadedImages((prev) => new Set(prev).add(url));
16375
- imageCache2.current.set(url, img);
16419
+ const spriteUrls = useMemo(() => {
16420
+ const urls = [];
16421
+ if (backgroundImage?.url) urls.push(backgroundImage.url);
16422
+ if (playerSprite?.url) urls.push(playerSprite.url);
16423
+ if (tileSprites) {
16424
+ for (const asset of Object.values(tileSprites)) {
16425
+ if (asset?.url) urls.push(asset.url);
16426
+ }
16376
16427
  }
16377
- return null;
16378
- }, [loadedImages]);
16428
+ return urls;
16429
+ }, [backgroundImage, playerSprite, tileSprites]);
16430
+ const { getImage } = useImageCache(spriteUrls);
16379
16431
  useEffect(() => {
16380
16432
  if (typeof window === "undefined") return;
16381
16433
  const canvas = canvasRef.current;
@@ -16488,7 +16540,7 @@ function SideView({
16488
16540
  camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
16489
16541
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
16490
16542
  }
16491
- const bgImage = bgImg ? loadImage(bgImg.url) : null;
16543
+ const bgImage = bgImg ? getImage(bgImg.url) : void 0;
16492
16544
  const bgSrc = bgImage ? resolveAssetSource(bgImage, bgImg, NOOP) : null;
16493
16545
  if (bgSrc) {
16494
16546
  blit(ctx, bgSrc, 0, 0, cw, ch);
@@ -16499,12 +16551,12 @@ function SideView({
16499
16551
  ctx.fillRect(0, 0, cw, ch);
16500
16552
  } else {
16501
16553
  const grad = ctx.createLinearGradient(0, 0, 0, ch);
16502
- grad.addColorStop(0, SKY_GRADIENT_TOP);
16503
- grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
16554
+ grad.addColorStop(0, SIDE_SKY_GRADIENT_TOP);
16555
+ grad.addColorStop(1, SIDE_SKY_GRADIENT_BOTTOM);
16504
16556
  ctx.fillStyle = grad;
16505
16557
  ctx.fillRect(0, 0, cw, ch);
16506
16558
  }
16507
- ctx.strokeStyle = GRID_COLOR;
16559
+ ctx.strokeStyle = SIDE_GRID_COLOR;
16508
16560
  ctx.lineWidth = 1;
16509
16561
  const gridSize = 32;
16510
16562
  for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
@@ -16524,7 +16576,7 @@ function SideView({
16524
16576
  const platY = plat.y - camY;
16525
16577
  const platType = plat.type ?? "ground";
16526
16578
  const spriteAsset = tSprites?.[platType];
16527
- const tileImg = spriteAsset ? loadImage(spriteAsset.url) : null;
16579
+ const tileImg = spriteAsset ? getImage(spriteAsset.url) : void 0;
16528
16580
  const tileSrc = tileImg ? resolveAssetSource(tileImg, spriteAsset, NOOP) : null;
16529
16581
  if (tileSrc) {
16530
16582
  const originX = tileSrc.rect ? tileSrc.rect.sx : 0;
@@ -16539,15 +16591,15 @@ function SideView({
16539
16591
  ctx.drawImage(tileImg, originX, originY, srcW, tileH, platX + tx, platY, drawW, plat.height);
16540
16592
  }
16541
16593
  } else {
16542
- const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
16594
+ const color = SIDE_PLATFORM_COLORS[platType] ?? SIDE_PLATFORM_COLORS.ground;
16543
16595
  ctx.fillStyle = color;
16544
16596
  ctx.fillRect(platX, platY, plat.width, plat.height);
16545
- ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
16597
+ ctx.fillStyle = SIDE_PLATFORM_BEVEL_COLOR;
16546
16598
  ctx.fillRect(platX, platY, plat.width, 3);
16547
- ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
16599
+ ctx.fillStyle = SIDE_PLATFORM_SHADOW_COLOR;
16548
16600
  ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
16549
16601
  if (platType === "hazard") {
16550
- ctx.strokeStyle = "#e74c3c";
16602
+ ctx.strokeStyle = SIDE_HAZARD_STRIPE_COLOR;
16551
16603
  ctx.lineWidth = 2;
16552
16604
  for (let sx = platX; sx < platX + plat.width; sx += 12) {
16553
16605
  ctx.beginPath();
@@ -16557,7 +16609,7 @@ function SideView({
16557
16609
  }
16558
16610
  }
16559
16611
  if (platType === "goal") {
16560
- ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
16612
+ ctx.fillStyle = SIDE_GOAL_GLOW_COLOR;
16561
16613
  ctx.beginPath();
16562
16614
  ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
16563
16615
  ctx.fill();
@@ -16569,7 +16621,7 @@ function SideView({
16569
16621
  const ppx = px - camX;
16570
16622
  const ppy = py - camY;
16571
16623
  const facingRight = auth.facingRight ?? true;
16572
- const playerImg = pSprite ? loadImage(pSprite.url) : null;
16624
+ const playerImg = pSprite ? getImage(pSprite.url) : void 0;
16573
16625
  const playerSrc = playerImg ? resolveAssetSource(playerImg, pSprite, NOOP) : null;
16574
16626
  if (playerSrc) {
16575
16627
  ctx.save();
@@ -16582,7 +16634,7 @@ function SideView({
16582
16634
  }
16583
16635
  ctx.restore();
16584
16636
  } else {
16585
- ctx.fillStyle = PLAYER_COLOR;
16637
+ ctx.fillStyle = SIDE_PLAYER_COLOR;
16586
16638
  const radius = Math.min(pw, ph) * 0.25;
16587
16639
  ctx.beginPath();
16588
16640
  ctx.moveTo(ppx + radius, ppy);
@@ -16598,7 +16650,7 @@ function SideView({
16598
16650
  const eyeY = ppy + ph * 0.3;
16599
16651
  const eyeSize = 3;
16600
16652
  const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
16601
- ctx.fillStyle = PLAYER_EYE_COLOR;
16653
+ ctx.fillStyle = SIDE_PLAYER_EYE_COLOR;
16602
16654
  ctx.beginPath();
16603
16655
  ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
16604
16656
  ctx.fill();
@@ -16612,7 +16664,7 @@ function SideView({
16612
16664
  const alpha = Math.min(1, fx.ttl / 4);
16613
16665
  const prev = ctx.globalAlpha;
16614
16666
  ctx.globalAlpha = alpha;
16615
- ctx.fillStyle = "#ffe066";
16667
+ ctx.fillStyle = SIDE_FX_COLOR;
16616
16668
  ctx.beginPath();
16617
16669
  ctx.arc(fxScreenX, fxScreenY, 12, 0, Math.PI * 2);
16618
16670
  ctx.fill();
@@ -16620,7 +16672,7 @@ function SideView({
16620
16672
  }
16621
16673
  };
16622
16674
  return interp.startLoop(drawFrame);
16623
- }, [interp.startLoop, loadImage]);
16675
+ }, [interp.startLoop, getImage]);
16624
16676
  return /* @__PURE__ */ jsx(
16625
16677
  "canvas",
16626
16678
  {
@@ -16632,6 +16684,33 @@ function SideView({
16632
16684
  }
16633
16685
  );
16634
16686
  }
16687
+ var NOOP;
16688
+ var init_SideCanvas2D = __esm({
16689
+ "components/game/2d/molecules/SideCanvas2D.tsx"() {
16690
+ "use client";
16691
+ init_cn();
16692
+ init_useEventBus();
16693
+ init_useImageCache();
16694
+ init_atlasSlice();
16695
+ init_useRenderInterpolation();
16696
+ init_verificationRegistry();
16697
+ init_isometric();
16698
+ NOOP = () => {
16699
+ };
16700
+ SideCanvas2D.displayName = "SideCanvas2D";
16701
+ }
16702
+ });
16703
+ function normalizeBackdrop2(bg) {
16704
+ return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
16705
+ }
16706
+ function resolveTileFallbackColor(tile) {
16707
+ const override = tile.color;
16708
+ return override ?? TERRAIN_COLORS[tile.terrain ?? ""] ?? TERRAIN_COLORS.default;
16709
+ }
16710
+ function resolveUnitTeamColor(unit) {
16711
+ const override = unit.tint;
16712
+ return override ?? TEAM_COLORS[unit.team ?? ""] ?? TEAM_COLORS.default;
16713
+ }
16635
16714
  function Canvas2D({
16636
16715
  // Closed-circuit
16637
16716
  className,
@@ -16681,13 +16760,13 @@ function Canvas2D({
16681
16760
  // Side-view asset resolution
16682
16761
  playerSprite,
16683
16762
  tileSprites,
16684
- bgColor = "#5c94fc",
16763
+ bgColor = DEFAULT_BG_COLOR,
16685
16764
  worldWidth = 800,
16686
16765
  worldHeight = 400,
16687
16766
  // Remote asset loading
16688
16767
  assetManifest
16689
16768
  }) {
16690
- const backgroundImage = normalizeBackdrop(backgroundImageRaw);
16769
+ const backgroundImage = normalizeBackdrop2(backgroundImageRaw);
16691
16770
  const isSide = projection === "side";
16692
16771
  const isFree = projection === "free";
16693
16772
  const flatLike = projection === "hex" || projection === "flat" || isFree;
@@ -16871,7 +16950,7 @@ function Canvas2D({
16871
16950
  return sortedTiles.map((t2) => ({
16872
16951
  x: t2.x,
16873
16952
  y: t2.y,
16874
- color: t2.terrain === "water" ? "#3b82f6" : t2.terrain === "mountain" ? "#78716c" : "#4ade80"
16953
+ color: MINIMAP_TERRAIN_COLORS[t2.terrain ?? ""] ?? MINIMAP_TERRAIN_COLORS.default
16875
16954
  }));
16876
16955
  }, [showMinimap, sortedTiles]);
16877
16956
  const miniMapUnits = useMemo(() => {
@@ -16879,7 +16958,7 @@ function Canvas2D({
16879
16958
  return units.filter((u) => u.position).map((u) => ({
16880
16959
  x: u.position.x,
16881
16960
  y: u.position.y,
16882
- color: u.team === "player" ? "#60a5fa" : u.team === "enemy" ? "#f87171" : "#9ca3af",
16961
+ color: MINIMAP_UNIT_COLORS[u.team ?? ""] ?? MINIMAP_UNIT_COLORS.default,
16883
16962
  isPlayer: u.team === "player"
16884
16963
  }));
16885
16964
  }, [showMinimap, units]);
@@ -16916,7 +16995,7 @@ function Canvas2D({
16916
16995
  }
16917
16996
  }
16918
16997
  } else {
16919
- ctx.fillStyle = "#1a1a2e";
16998
+ ctx.fillStyle = BACKGROUND_FALLBACK_COLOR;
16920
16999
  ctx.fillRect(0, 0, viewportSize.width, viewportSize.height);
16921
17000
  }
16922
17001
  if (sortedTiles.length === 0 && units.length === 0 && features.length === 0) return;
@@ -16946,15 +17025,15 @@ function Canvas2D({
16946
17025
  } else if (img && img.naturalWidth === 0) {
16947
17026
  ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
16948
17027
  } else if (squareGrid) {
16949
- ctx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : tile.terrain === "stone" ? "#9ca3af" : "#4ade80";
17028
+ ctx.fillStyle = resolveTileFallbackColor(tile);
16950
17029
  ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
16951
- ctx.strokeStyle = "rgba(0,0,0,0.2)";
17030
+ ctx.strokeStyle = GRID_STROKE_COLOR;
16952
17031
  ctx.lineWidth = 1;
16953
17032
  ctx.strokeRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
16954
17033
  } else {
16955
17034
  const centerX = pos.x + scaledTileWidth / 2;
16956
17035
  const topY = pos.y + scaledDiamondTopY;
16957
- ctx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : tile.terrain === "stone" ? "#9ca3af" : "#4ade80";
17036
+ ctx.fillStyle = resolveTileFallbackColor(tile);
16958
17037
  ctx.beginPath();
16959
17038
  ctx.moveTo(centerX, topY);
16960
17039
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -16962,7 +17041,7 @@ function Canvas2D({
16962
17041
  ctx.lineTo(pos.x, topY + scaledFloorHeight / 2);
16963
17042
  ctx.closePath();
16964
17043
  ctx.fill();
16965
- ctx.strokeStyle = "rgba(0,0,0,0.2)";
17044
+ ctx.strokeStyle = GRID_STROKE_COLOR;
16966
17045
  ctx.lineWidth = 1;
16967
17046
  ctx.stroke();
16968
17047
  }
@@ -16983,11 +17062,11 @@ function Canvas2D({
16983
17062
  ctx.fill();
16984
17063
  };
16985
17064
  if (hoveredTile && hoveredTile.x === tile.x && hoveredTile.y === tile.y) {
16986
- drawHighlight("rgba(255, 255, 255, 0.15)");
17065
+ drawHighlight(HIGHLIGHT_COLORS.hover);
16987
17066
  }
16988
17067
  const tileKey = `${tile.x},${tile.y}`;
16989
- if (validMoveSet.has(tileKey)) drawHighlight("rgba(74, 222, 128, 0.25)");
16990
- if (attackTargetSet.has(tileKey)) drawHighlight("rgba(239, 68, 68, 0.35)");
17068
+ if (validMoveSet.has(tileKey)) drawHighlight(HIGHLIGHT_COLORS.validMove);
17069
+ if (attackTargetSet.has(tileKey)) drawHighlight(HIGHLIGHT_COLORS.attack);
16991
17070
  if (debug2) {
16992
17071
  const centerX = pos.x + scaledTileWidth / 2;
16993
17072
  const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
@@ -17061,9 +17140,9 @@ function Canvas2D({
17061
17140
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
17062
17141
  const unitIsSheet = unit.spriteSheet?.url !== void 0;
17063
17142
  const unitSrc = img && !unitIsSheet ? resolveAssetSource(img, unitAsset, bumpAtlas) : null;
17064
- const SHEET_ROWS = 5;
17065
17143
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
17066
- const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
17144
+ const sheetFrameH = img ? img.naturalHeight / LEGACY_SHEET_ROWS : 0;
17145
+ const legacyFrame = frameRect(0, 0, SHEET_COLUMNS, sheetFrameW, sheetFrameH);
17067
17146
  const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
17068
17147
  const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
17069
17148
  const ar = unitIsSheet ? sheetFrameW / (sheetFrameH || 1) : unitSrc ? unitSrc.aspect : frameW / (frameH || 1);
@@ -17081,17 +17160,16 @@ function Canvas2D({
17081
17160
  ctx.globalAlpha = 0.25;
17082
17161
  if (img) {
17083
17162
  if (unitIsSheet) {
17084
- ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
17163
+ ctx.drawImage(img, legacyFrame.sx, legacyFrame.sy, legacyFrame.sw, legacyFrame.sh, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
17085
17164
  } else if (unitSrc) {
17086
17165
  blit(ctx, unitSrc, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
17087
17166
  } else {
17088
17167
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
17089
17168
  }
17090
17169
  } else {
17091
- const color = unit.team === "player" ? "#3b82f6" : unit.team === "enemy" ? "#ef4444" : "#6b7280";
17092
17170
  ctx.beginPath();
17093
17171
  ctx.arc(ghostCenterX, ghostGroundY - 16 * scale, 20 * scale, 0, Math.PI * 2);
17094
- ctx.fillStyle = color;
17172
+ ctx.fillStyle = resolveUnitTeamColor(unit);
17095
17173
  ctx.fill();
17096
17174
  }
17097
17175
  ctx.restore();
@@ -17099,7 +17177,7 @@ function Canvas2D({
17099
17177
  if (isSelected) {
17100
17178
  ctx.beginPath();
17101
17179
  ctx.ellipse(centerX, groundY, drawW / 2 + 4 * scale, 12 * scale, 0, 0, Math.PI * 2);
17102
- ctx.strokeStyle = "rgba(0, 200, 255, 0.8)";
17180
+ ctx.strokeStyle = SELECTION_RING_COLOR;
17103
17181
  ctx.lineWidth = 3;
17104
17182
  ctx.stroke();
17105
17183
  }
@@ -17116,7 +17194,7 @@ function Canvas2D({
17116
17194
  const spriteY = groundY - fDrawH - (frame.applyBreathing ? breatheOffset : 0);
17117
17195
  ctx.save();
17118
17196
  if (unit.team) {
17119
- ctx.shadowColor = unit.team === "player" ? "rgba(0, 150, 255, 0.6)" : "rgba(255, 50, 50, 0.6)";
17197
+ ctx.shadowColor = TEAM_SHADOW_COLORS[unit.team] ?? TEAM_SHADOW_COLORS.default;
17120
17198
  ctx.shadowBlur = 12 * scale;
17121
17199
  }
17122
17200
  if (frame.flipX) {
@@ -17131,7 +17209,7 @@ function Canvas2D({
17131
17209
  const spriteY = groundY - drawH - breatheOffset;
17132
17210
  const drawUnit = (x) => {
17133
17211
  if (unitIsSheet) {
17134
- ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
17212
+ ctx.drawImage(img, legacyFrame.sx, legacyFrame.sy, legacyFrame.sw, legacyFrame.sh, x, spriteY, drawW, drawH);
17135
17213
  } else if (unitSrc) {
17136
17214
  blit(ctx, unitSrc, x, spriteY, drawW, drawH);
17137
17215
  } else {
@@ -17140,7 +17218,7 @@ function Canvas2D({
17140
17218
  };
17141
17219
  if (unit.team) {
17142
17220
  ctx.save();
17143
- ctx.shadowColor = unit.team === "player" ? "rgba(0, 150, 255, 0.6)" : "rgba(255, 50, 50, 0.6)";
17221
+ ctx.shadowColor = TEAM_SHADOW_COLORS[unit.team] ?? TEAM_SHADOW_COLORS.default;
17144
17222
  ctx.shadowBlur = 12 * scale;
17145
17223
  drawUnit(centerX - drawW / 2);
17146
17224
  ctx.restore();
@@ -17148,10 +17226,9 @@ function Canvas2D({
17148
17226
  drawUnit(centerX - drawW / 2);
17149
17227
  }
17150
17228
  } else {
17151
- const color = unit.team === "player" ? "#3b82f6" : unit.team === "enemy" ? "#ef4444" : "#6b7280";
17152
17229
  ctx.beginPath();
17153
17230
  ctx.arc(centerX, groundY - 20 * scale - breatheOffset, 20 * scale, 0, Math.PI * 2);
17154
- ctx.fillStyle = color;
17231
+ ctx.fillStyle = resolveUnitTeamColor(unit);
17155
17232
  ctx.fill();
17156
17233
  ctx.strokeStyle = "rgba(255,255,255,0.8)";
17157
17234
  ctx.lineWidth = 2;
@@ -17390,7 +17467,7 @@ function Canvas2D({
17390
17467
  }
17391
17468
  if (isSide) {
17392
17469
  return /* @__PURE__ */ jsx(Box, { ref: containerRef, className: cn("relative overflow-hidden w-full h-full", className), children: /* @__PURE__ */ jsx(
17393
- SideView,
17470
+ SideCanvas2D,
17394
17471
  {
17395
17472
  player,
17396
17473
  platforms: platforms && platforms.length ? platforms : DEFAULT_PLATFORMS,
@@ -17488,7 +17565,7 @@ function Canvas2D({
17488
17565
  {
17489
17566
  as: "span",
17490
17567
  className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
17491
- style: { background: unit.team === "player" ? "rgba(59,130,246,0.9)" : unit.team === "enemy" ? "rgba(239,68,68,0.9)" : "rgba(107,114,128,0.9)" },
17568
+ style: { background: UNIT_LABEL_BG_COLORS[unit.team ?? ""] ?? UNIT_LABEL_BG_COLORS.default },
17492
17569
  children: unit.name
17493
17570
  }
17494
17571
  ),
@@ -17512,7 +17589,7 @@ function Canvas2D({
17512
17589
  }
17513
17590
  );
17514
17591
  }
17515
- var PLATFORM_COLORS, NOOP, PLAYER_COLOR, PLAYER_EYE_COLOR, SKY_GRADIENT_TOP, SKY_GRADIENT_BOTTOM, GRID_COLOR, DEFAULT_PLATFORMS;
17592
+ var LEGACY_SHEET_ROWS, DEFAULT_PLATFORMS;
17516
17593
  var init_Canvas2D = __esm({
17517
17594
  "components/game/2d/molecules/Canvas2D.tsx"() {
17518
17595
  "use client";
@@ -17534,19 +17611,9 @@ var init_Canvas2D = __esm({
17534
17611
  init_verificationRegistry();
17535
17612
  init_isometric();
17536
17613
  init_spriteSheetConstants();
17537
- PLATFORM_COLORS = {
17538
- ground: "#4a7c59",
17539
- platform: "#7c6b4a",
17540
- hazard: "#c0392b",
17541
- goal: "#f1c40f"
17542
- };
17543
- NOOP = () => {
17544
- };
17545
- PLAYER_COLOR = "#3498db";
17546
- PLAYER_EYE_COLOR = "#ffffff";
17547
- SKY_GRADIENT_TOP = "#1a1a2e";
17548
- SKY_GRADIENT_BOTTOM = "#16213e";
17549
- GRID_COLOR = "rgba(255, 255, 255, 0.03)";
17614
+ init_spriteAnimation();
17615
+ init_SideCanvas2D();
17616
+ LEGACY_SHEET_ROWS = Object.keys(SPRITE_SHEET_LAYOUT).length;
17550
17617
  DEFAULT_PLATFORMS = [
17551
17618
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
17552
17619
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -29354,7 +29421,7 @@ function TerrainPalette({ terrains, selectedTerrain, onSelect, className }) {
29354
29421
  {
29355
29422
  onClick: () => onSelect(terrain),
29356
29423
  className: `w-8 h-8 rounded cursor-pointer border-2 transition-all ${selectedTerrain === terrain ? "border-foreground scale-110 shadow-lg" : "border-muted hover:border-muted-foreground"}`,
29357
- style: { backgroundColor: TERRAIN_COLORS[terrain] || "var(--color-muted)" },
29424
+ style: { backgroundColor: TERRAIN_COLORS2[terrain] || "var(--color-muted)" },
29358
29425
  title: terrain
29359
29426
  },
29360
29427
  terrain
@@ -29373,7 +29440,7 @@ function EditorToolbar({ mode, onModeChange, className }) {
29373
29440
  m
29374
29441
  )) });
29375
29442
  }
29376
- var TERRAIN_COLORS, FEATURE_TYPES, MODE_LABELS;
29443
+ var TERRAIN_COLORS2, FEATURE_TYPES, MODE_LABELS;
29377
29444
  var init_editorUtils = __esm({
29378
29445
  "components/game/shared/lib/editorUtils.tsx"() {
29379
29446
  init_Box();
@@ -29382,7 +29449,7 @@ var init_editorUtils = __esm({
29382
29449
  init_Button();
29383
29450
  init_Badge();
29384
29451
  init_GameIcon();
29385
- TERRAIN_COLORS = {
29452
+ TERRAIN_COLORS2 = {
29386
29453
  grass: "#4a7c3f",
29387
29454
  dirt: "#8b6c42",
29388
29455
  stone: "#7a7a7a",
@@ -32168,13 +32235,13 @@ var init_MapView = __esm({
32168
32235
  shadowSize: [41, 41]
32169
32236
  });
32170
32237
  L.Marker.prototype.options.icon = defaultIcon;
32171
- const { useEffect: useEffect70, useRef: useRef66, useCallback: useCallback113, useState: useState108 } = React75__default;
32238
+ const { useEffect: useEffect71, useRef: useRef67, useCallback: useCallback114, useState: useState108 } = React75__default;
32172
32239
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
32173
32240
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
32174
32241
  function MapUpdater({ centerLat, centerLng, zoom }) {
32175
32242
  const map = useMap();
32176
- const prevRef = useRef66({ centerLat, centerLng, zoom });
32177
- useEffect70(() => {
32243
+ const prevRef = useRef67({ centerLat, centerLng, zoom });
32244
+ useEffect71(() => {
32178
32245
  const prev = prevRef.current;
32179
32246
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
32180
32247
  map.setView([centerLat, centerLng], zoom);
@@ -32185,7 +32252,7 @@ var init_MapView = __esm({
32185
32252
  }
32186
32253
  function MapClickHandler({ onMapClick }) {
32187
32254
  const map = useMap();
32188
- useEffect70(() => {
32255
+ useEffect71(() => {
32189
32256
  if (!onMapClick) return;
32190
32257
  const handler = (e) => {
32191
32258
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -32214,7 +32281,7 @@ var init_MapView = __esm({
32214
32281
  }) {
32215
32282
  const eventBus = useEventBus2();
32216
32283
  const [clickedPosition, setClickedPosition] = useState108(null);
32217
- const handleMapClick = useCallback113((lat, lng) => {
32284
+ const handleMapClick = useCallback114((lat, lng) => {
32218
32285
  if (showClickedPin) {
32219
32286
  setClickedPosition({ lat, lng });
32220
32287
  }
@@ -32223,7 +32290,7 @@ var init_MapView = __esm({
32223
32290
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
32224
32291
  }
32225
32292
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
32226
- const handleMarkerClick = useCallback113((marker) => {
32293
+ const handleMarkerClick = useCallback114((marker) => {
32227
32294
  onMarkerClick?.(marker);
32228
32295
  if (markerClickEvent) {
32229
32296
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -51918,4 +51985,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
51918
51985
  });
51919
51986
  }
51920
51987
 
51921
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EMPTY_EFFECT_STATE, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCard, GameHud, GameIcon, GameMenu, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateGraph, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, drawSprite, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSwipeGesture, useTapReveal, useTraitListens, useTranslate127 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
51988
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EMPTY_EFFECT_STATE, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCard, GameHud, GameIcon, GameMenu, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateGraph, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS2 as TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, drawSprite, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSwipeGesture, useTapReveal, useTraitListens, useTranslate127 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };