@almadar/ui 5.103.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.
Files changed (80) hide show
  1. package/dist/avl/index.cjs +168 -88
  2. package/dist/avl/index.css +3 -3
  3. package/dist/avl/index.js +168 -88
  4. package/dist/components/core/atoms/AtlasImage.d.ts +2 -2
  5. package/dist/components/core/atoms/FlipContainer.d.ts +1 -1
  6. package/dist/components/core/molecules/Card.d.ts +1 -1
  7. package/dist/components/core/molecules/Chart.d.ts +3 -3
  8. package/dist/components/core/molecules/DataGrid.d.ts +1 -1
  9. package/dist/components/core/molecules/DataList.d.ts +1 -1
  10. package/dist/components/core/molecules/DocPagination.d.ts +8 -1
  11. package/dist/components/core/molecules/DocSearch.d.ts +8 -1
  12. package/dist/components/core/molecules/FlipCard.d.ts +1 -1
  13. package/dist/components/core/molecules/LineChart.d.ts +3 -1
  14. package/dist/components/core/molecules/MapView.d.ts +18 -1
  15. package/dist/components/core/molecules/SortableList.d.ts +1 -1
  16. package/dist/components/core/molecules/TableView.d.ts +1 -1
  17. package/dist/components/core/organisms/DataTable.d.ts +7 -3
  18. package/dist/components/core/organisms/debug/RuntimeDebugger.d.ts +10 -1
  19. package/dist/components/core/organisms/debug/tabs/EntitiesTab.d.ts +2 -1
  20. package/dist/components/core/organisms/debug/tabs/EventDispatcherTab.d.ts +2 -1
  21. package/dist/components/core/organisms/debug/tabs/EventFlowTab.d.ts +6 -1
  22. package/dist/components/core/organisms/debug/tabs/GuardsPanel.d.ts +6 -1
  23. package/dist/components/core/organisms/debug/tabs/ServerBridgeTab.d.ts +12 -1
  24. package/dist/components/core/organisms/debug/tabs/TicksTab.d.ts +2 -1
  25. package/dist/components/core/organisms/debug/tabs/TraitsTab.d.ts +2 -1
  26. package/dist/components/core/organisms/debug/tabs/TransitionTimeline.d.ts +11 -1
  27. package/dist/components/core/organisms/debug/tabs/VerificationTab.d.ts +8 -1
  28. package/dist/components/game/2d/atoms/ActionButton.d.ts +2 -1
  29. package/dist/components/game/2d/atoms/ChoiceButton.d.ts +2 -1
  30. package/dist/components/game/2d/atoms/ComboCounter.d.ts +2 -1
  31. package/dist/components/game/2d/atoms/ControlButton.d.ts +2 -1
  32. package/dist/components/game/2d/atoms/DamageNumber.d.ts +2 -1
  33. package/dist/components/game/2d/atoms/DialogueBubble.d.ts +2 -1
  34. package/dist/components/game/2d/atoms/GameIcon.d.ts +2 -1
  35. package/dist/components/game/2d/atoms/HealthBar.d.ts +2 -1
  36. package/dist/components/game/2d/atoms/ItemSlot.d.ts +2 -1
  37. package/dist/components/game/2d/atoms/MiniMap.d.ts +2 -1
  38. package/dist/components/game/2d/atoms/ResourceCounter.d.ts +2 -1
  39. package/dist/components/game/2d/atoms/ScoreDisplay.d.ts +2 -1
  40. package/dist/components/game/2d/atoms/StatusEffect.d.ts +2 -1
  41. package/dist/components/game/2d/atoms/TimerDisplay.d.ts +2 -1
  42. package/dist/components/game/2d/atoms/TurnIndicator.d.ts +2 -1
  43. package/dist/components/game/2d/atoms/WaypointMarker.d.ts +2 -1
  44. package/dist/components/game/2d/molecules/Canvas2D.d.ts +6 -5
  45. package/dist/components/game/2d/molecules/GameHud.d.ts +2 -1
  46. package/dist/components/game/2d/molecules/GameMenu.d.ts +2 -1
  47. package/dist/components/game/2d/molecules/InventoryGrid.d.ts +2 -1
  48. package/dist/components/game/2d/molecules/ResourceBar.d.ts +2 -1
  49. package/dist/components/game/2d/molecules/SideCanvas2D.d.ts +36 -0
  50. package/dist/components/game/2d/molecules/StatBadge.d.ts +2 -1
  51. package/dist/components/game/3d/atoms/EventMarker3D.d.ts +17 -0
  52. package/dist/components/game/3d/atoms/SpriteBillboard3D.d.ts +18 -0
  53. package/dist/components/game/3d/index.cjs +539 -496
  54. package/dist/components/game/3d/index.js +367 -324
  55. package/dist/components/game/3d/molecules/FeatureMesh3D.d.ts +21 -0
  56. package/dist/components/game/3d/molecules/GameCamera3D.d.ts +35 -0
  57. package/dist/components/game/3d/molecules/Lighting3D.d.ts +10 -2
  58. package/dist/components/game/3d/molecules/SideScene3D.d.ts +31 -0
  59. package/dist/components/game/3d/molecules/TileMesh3D.d.ts +28 -0
  60. package/dist/components/game/3d/molecules/UnitMesh3D.d.ts +29 -0
  61. package/dist/components/game/shared/game3dTheme.d.ts +55 -0
  62. package/dist/components/game/shared/isometric.d.ts +38 -0
  63. package/dist/components/game/shared/isometricTypes.d.ts +4 -0
  64. package/dist/components/game/shared/lib/editorUtils.d.ts +8 -8
  65. package/dist/components/index.cjs +156 -83
  66. package/dist/components/index.css +3 -3
  67. package/dist/components/index.js +160 -87
  68. package/dist/hooks/useGitHub.d.ts +7 -7
  69. package/dist/marketing/index.cjs +2 -2
  70. package/dist/marketing/index.js +2 -2
  71. package/dist/providers/EventBusProvider.d.ts +1 -1
  72. package/dist/providers/SelectionProvider.d.ts +1 -1
  73. package/dist/providers/ServerBridge.d.ts +1 -1
  74. package/dist/providers/index.cjs +164 -84
  75. package/dist/providers/index.css +3 -3
  76. package/dist/providers/index.js +164 -84
  77. package/dist/runtime/index.cjs +164 -84
  78. package/dist/runtime/index.css +3 -3
  79. package/dist/runtime/index.js +164 -84
  80. package/package.json +10 -15
@@ -630,7 +630,7 @@ var init_AvlFieldType = __esm({
630
630
  }
631
631
  });
632
632
 
633
- // node_modules/clsx/dist/clsx.mjs
633
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
634
634
  function r(e) {
635
635
  var t, f3, n = "";
636
636
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -645,11 +645,11 @@ function clsx() {
645
645
  return n;
646
646
  }
647
647
  var init_clsx = __esm({
648
- "node_modules/clsx/dist/clsx.mjs"() {
648
+ "node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
649
649
  }
650
650
  });
651
651
 
652
- // node_modules/tailwind-merge/dist/bundle-mjs.mjs
652
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
653
653
  function twJoin() {
654
654
  let index = 0;
655
655
  let argument;
@@ -693,7 +693,7 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
693
693
  }
694
694
  var CLASS_PART_SEPARATOR, createClassGroupUtils, getGroupRecursive, arbitraryPropertyRegex, getGroupIdForArbitraryProperty, createClassMap, processClassesRecursively, getPart, isThemeGetter, getPrefixedClassGroupEntries, createLruCache, IMPORTANT_MODIFIER, createParseClassName, sortModifiers, createConfigUtils, SPLIT_CLASSES_REGEX, mergeClassList, toValue, fromTheme, arbitraryValueRegex, fractionRegex, stringLengths, tshirtUnitRegex, lengthUnitRegex, colorFunctionRegex, shadowRegex, imageRegex, isLength, isArbitraryLength, isNumber, isArbitraryNumber, isInteger, isPercent, isArbitraryValue, isTshirtSize, sizeLabels, isArbitrarySize, isArbitraryPosition, imageLabels, isArbitraryImage, isArbitraryShadow, isAny, getIsArbitraryValue, isLengthOnly, isNever, isShadow, isImage, getDefaultConfig, twMerge;
695
695
  var init_bundle_mjs = __esm({
696
- "node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
696
+ "node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
697
697
  CLASS_PART_SEPARATOR = "-";
698
698
  createClassGroupUtils = (config) => {
699
699
  const classMap = createClassMap(config);
@@ -11249,7 +11249,7 @@ function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric")
11249
11249
  const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
11250
11250
  return { x: Math.round(tileX), y: Math.round(tileY) };
11251
11251
  }
11252
- var TILE_WIDTH, TILE_HEIGHT, FLOOR_HEIGHT, DIAMOND_TOP_Y, FEATURE_COLORS;
11252
+ 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;
11253
11253
  var init_isometric = __esm({
11254
11254
  "components/game/shared/isometric.ts"() {
11255
11255
  TILE_WIDTH = 256;
@@ -11266,14 +11266,79 @@ var init_isometric = __esm({
11266
11266
  mountain: "#78716c",
11267
11267
  default: "#9ca3af"
11268
11268
  };
11269
+ TERRAIN_COLORS = {
11270
+ water: "#3b82f6",
11271
+ mountain: "#78716c",
11272
+ stone: "#9ca3af",
11273
+ default: "#4ade80"
11274
+ };
11275
+ TEAM_COLORS = {
11276
+ player: "#3b82f6",
11277
+ enemy: "#ef4444",
11278
+ neutral: "#6b7280",
11279
+ default: "#6b7280"
11280
+ };
11281
+ TEAM_SHADOW_COLORS = {
11282
+ player: "rgba(0,150,255,0.6)",
11283
+ default: "rgba(255,50,50,0.6)"
11284
+ };
11285
+ HIGHLIGHT_COLORS = {
11286
+ hover: "rgba(255,255,255,0.15)",
11287
+ validMove: "rgba(74,222,128,0.25)",
11288
+ attack: "rgba(239,68,68,0.35)"
11289
+ };
11290
+ SELECTION_RING_COLOR = "rgba(0,200,255,0.8)";
11291
+ GRID_STROKE_COLOR = "rgba(0,0,0,0.2)";
11292
+ BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
11293
+ MINIMAP_TERRAIN_COLORS = {
11294
+ water: "#3b82f6",
11295
+ mountain: "#78716c",
11296
+ default: "#4ade80"
11297
+ };
11298
+ MINIMAP_UNIT_COLORS = {
11299
+ player: "#60a5fa",
11300
+ enemy: "#f87171",
11301
+ neutral: "#9ca3af",
11302
+ default: "#9ca3af"
11303
+ };
11304
+ UNIT_LABEL_BG_COLORS = {
11305
+ player: "rgba(59,130,246,0.9)",
11306
+ enemy: "rgba(239,68,68,0.9)",
11307
+ neutral: "rgba(107,114,128,0.9)",
11308
+ default: "rgba(107,114,128,0.9)"
11309
+ };
11310
+ SIDE_PLATFORM_COLORS = {
11311
+ ground: "#4a7c59",
11312
+ platform: "#7c6b4a",
11313
+ hazard: "#c0392b",
11314
+ goal: "#f1c40f"
11315
+ };
11316
+ SIDE_PLAYER_COLOR = "#3498db";
11317
+ SIDE_PLAYER_EYE_COLOR = "#ffffff";
11318
+ SIDE_SKY_GRADIENT_TOP = "#1a1a2e";
11319
+ SIDE_SKY_GRADIENT_BOTTOM = "#16213e";
11320
+ SIDE_GRID_COLOR = "rgba(255, 255, 255, 0.03)";
11321
+ SIDE_FX_COLOR = "#ffe066";
11322
+ SIDE_PLATFORM_BEVEL_COLOR = "rgba(255,255,255,0.15)";
11323
+ SIDE_PLATFORM_SHADOW_COLOR = "rgba(0,0,0,0.3)";
11324
+ SIDE_HAZARD_STRIPE_COLOR = "#e74c3c";
11325
+ SIDE_GOAL_GLOW_COLOR = "rgba(241, 196, 15, 0.5)";
11326
+ DEFAULT_BG_COLOR = "#5c94fc";
11269
11327
  }
11270
11328
  });
11271
11329
 
11272
11330
  // components/game/shared/spriteSheetConstants.ts
11273
- var SHEET_COLUMNS;
11331
+ var SHEET_COLUMNS, SPRITE_SHEET_LAYOUT;
11274
11332
  var init_spriteSheetConstants = __esm({
11275
11333
  "components/game/shared/spriteSheetConstants.ts"() {
11276
11334
  SHEET_COLUMNS = 8;
11335
+ SPRITE_SHEET_LAYOUT = {
11336
+ idle: { row: 0, frames: 4, frameRate: 6, loop: true },
11337
+ walk: { row: 1, frames: 8, frameRate: 10, loop: true },
11338
+ attack: { row: 2, frames: 6, frameRate: 12, loop: false },
11339
+ hit: { row: 3, frames: 3, frameRate: 8, loop: false },
11340
+ death: { row: 4, frames: 6, frameRate: 8, loop: false }
11341
+ };
11277
11342
  }
11278
11343
  });
11279
11344
 
@@ -14003,7 +14068,10 @@ var init_useUnitSpriteAtlas = __esm({
14003
14068
  init_spriteAnimation();
14004
14069
  }
14005
14070
  });
14006
- function SideView({
14071
+ function normalizeBackdrop(bg) {
14072
+ return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
14073
+ }
14074
+ function SideCanvas2D({
14007
14075
  player,
14008
14076
  platforms,
14009
14077
  worldWidth,
@@ -14012,7 +14080,7 @@ function SideView({
14012
14080
  canvasHeight,
14013
14081
  follow,
14014
14082
  bgColor,
14015
- backgroundImage,
14083
+ backgroundImage: backgroundImageRaw,
14016
14084
  playerSprite,
14017
14085
  tileSprites,
14018
14086
  effects,
@@ -14020,27 +14088,22 @@ function SideView({
14020
14088
  keyUpMap,
14021
14089
  className
14022
14090
  }) {
14091
+ const backgroundImage = normalizeBackdrop(backgroundImageRaw);
14023
14092
  const canvasRef = React105.useRef(null);
14024
14093
  const eventBus = useEventBus();
14025
14094
  const keysRef = React105.useRef(/* @__PURE__ */ new Set());
14026
- const imageCache2 = React105.useRef(/* @__PURE__ */ new Map());
14027
- const [loadedImages, setLoadedImages] = React105.useState(/* @__PURE__ */ new Set());
14028
- const loadImage = React105.useCallback((url) => {
14029
- if (!url) return null;
14030
- const cached = imageCache2.current.get(url);
14031
- if (cached?.complete && cached.naturalWidth > 0) {
14032
- if (!loadedImages.has(url)) setLoadedImages((prev) => new Set(prev).add(url));
14033
- return cached;
14034
- }
14035
- if (!cached) {
14036
- const img = new Image();
14037
- img.crossOrigin = "anonymous";
14038
- img.src = url;
14039
- img.onload = () => setLoadedImages((prev) => new Set(prev).add(url));
14040
- imageCache2.current.set(url, img);
14095
+ const spriteUrls = React105.useMemo(() => {
14096
+ const urls = [];
14097
+ if (backgroundImage?.url) urls.push(backgroundImage.url);
14098
+ if (playerSprite?.url) urls.push(playerSprite.url);
14099
+ if (tileSprites) {
14100
+ for (const asset of Object.values(tileSprites)) {
14101
+ if (asset?.url) urls.push(asset.url);
14102
+ }
14041
14103
  }
14042
- return null;
14043
- }, [loadedImages]);
14104
+ return urls;
14105
+ }, [backgroundImage, playerSprite, tileSprites]);
14106
+ const { getImage } = useImageCache(spriteUrls);
14044
14107
  React105.useEffect(() => {
14045
14108
  if (typeof window === "undefined") return;
14046
14109
  const canvas = canvasRef.current;
@@ -14153,7 +14216,7 @@ function SideView({
14153
14216
  camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
14154
14217
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
14155
14218
  }
14156
- const bgImage = bgImg ? loadImage(bgImg.url) : null;
14219
+ const bgImage = bgImg ? getImage(bgImg.url) : void 0;
14157
14220
  const bgSrc = bgImage ? resolveAssetSource(bgImage, bgImg, NOOP) : null;
14158
14221
  if (bgSrc) {
14159
14222
  blit(ctx, bgSrc, 0, 0, cw, ch);
@@ -14164,12 +14227,12 @@ function SideView({
14164
14227
  ctx.fillRect(0, 0, cw, ch);
14165
14228
  } else {
14166
14229
  const grad = ctx.createLinearGradient(0, 0, 0, ch);
14167
- grad.addColorStop(0, SKY_GRADIENT_TOP);
14168
- grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
14230
+ grad.addColorStop(0, SIDE_SKY_GRADIENT_TOP);
14231
+ grad.addColorStop(1, SIDE_SKY_GRADIENT_BOTTOM);
14169
14232
  ctx.fillStyle = grad;
14170
14233
  ctx.fillRect(0, 0, cw, ch);
14171
14234
  }
14172
- ctx.strokeStyle = GRID_COLOR;
14235
+ ctx.strokeStyle = SIDE_GRID_COLOR;
14173
14236
  ctx.lineWidth = 1;
14174
14237
  const gridSize = 32;
14175
14238
  for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
@@ -14189,7 +14252,7 @@ function SideView({
14189
14252
  const platY = plat.y - camY;
14190
14253
  const platType = plat.type ?? "ground";
14191
14254
  const spriteAsset = tSprites?.[platType];
14192
- const tileImg = spriteAsset ? loadImage(spriteAsset.url) : null;
14255
+ const tileImg = spriteAsset ? getImage(spriteAsset.url) : void 0;
14193
14256
  const tileSrc = tileImg ? resolveAssetSource(tileImg, spriteAsset, NOOP) : null;
14194
14257
  if (tileSrc) {
14195
14258
  const originX = tileSrc.rect ? tileSrc.rect.sx : 0;
@@ -14204,15 +14267,15 @@ function SideView({
14204
14267
  ctx.drawImage(tileImg, originX, originY, srcW, tileH, platX + tx, platY, drawW, plat.height);
14205
14268
  }
14206
14269
  } else {
14207
- const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
14270
+ const color = SIDE_PLATFORM_COLORS[platType] ?? SIDE_PLATFORM_COLORS.ground;
14208
14271
  ctx.fillStyle = color;
14209
14272
  ctx.fillRect(platX, platY, plat.width, plat.height);
14210
- ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
14273
+ ctx.fillStyle = SIDE_PLATFORM_BEVEL_COLOR;
14211
14274
  ctx.fillRect(platX, platY, plat.width, 3);
14212
- ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
14275
+ ctx.fillStyle = SIDE_PLATFORM_SHADOW_COLOR;
14213
14276
  ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
14214
14277
  if (platType === "hazard") {
14215
- ctx.strokeStyle = "#e74c3c";
14278
+ ctx.strokeStyle = SIDE_HAZARD_STRIPE_COLOR;
14216
14279
  ctx.lineWidth = 2;
14217
14280
  for (let sx = platX; sx < platX + plat.width; sx += 12) {
14218
14281
  ctx.beginPath();
@@ -14222,7 +14285,7 @@ function SideView({
14222
14285
  }
14223
14286
  }
14224
14287
  if (platType === "goal") {
14225
- ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
14288
+ ctx.fillStyle = SIDE_GOAL_GLOW_COLOR;
14226
14289
  ctx.beginPath();
14227
14290
  ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
14228
14291
  ctx.fill();
@@ -14234,7 +14297,7 @@ function SideView({
14234
14297
  const ppx = px - camX;
14235
14298
  const ppy = py - camY;
14236
14299
  const facingRight = auth.facingRight ?? true;
14237
- const playerImg = pSprite ? loadImage(pSprite.url) : null;
14300
+ const playerImg = pSprite ? getImage(pSprite.url) : void 0;
14238
14301
  const playerSrc = playerImg ? resolveAssetSource(playerImg, pSprite, NOOP) : null;
14239
14302
  if (playerSrc) {
14240
14303
  ctx.save();
@@ -14247,7 +14310,7 @@ function SideView({
14247
14310
  }
14248
14311
  ctx.restore();
14249
14312
  } else {
14250
- ctx.fillStyle = PLAYER_COLOR;
14313
+ ctx.fillStyle = SIDE_PLAYER_COLOR;
14251
14314
  const radius = Math.min(pw, ph) * 0.25;
14252
14315
  ctx.beginPath();
14253
14316
  ctx.moveTo(ppx + radius, ppy);
@@ -14263,7 +14326,7 @@ function SideView({
14263
14326
  const eyeY = ppy + ph * 0.3;
14264
14327
  const eyeSize = 3;
14265
14328
  const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
14266
- ctx.fillStyle = PLAYER_EYE_COLOR;
14329
+ ctx.fillStyle = SIDE_PLAYER_EYE_COLOR;
14267
14330
  ctx.beginPath();
14268
14331
  ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
14269
14332
  ctx.fill();
@@ -14277,7 +14340,7 @@ function SideView({
14277
14340
  const alpha = Math.min(1, fx.ttl / 4);
14278
14341
  const prev = ctx.globalAlpha;
14279
14342
  ctx.globalAlpha = alpha;
14280
- ctx.fillStyle = "#ffe066";
14343
+ ctx.fillStyle = SIDE_FX_COLOR;
14281
14344
  ctx.beginPath();
14282
14345
  ctx.arc(fxScreenX, fxScreenY, 12, 0, Math.PI * 2);
14283
14346
  ctx.fill();
@@ -14285,7 +14348,7 @@ function SideView({
14285
14348
  }
14286
14349
  };
14287
14350
  return interp.startLoop(drawFrame);
14288
- }, [interp.startLoop, loadImage]);
14351
+ }, [interp.startLoop, getImage]);
14289
14352
  return /* @__PURE__ */ jsxRuntime.jsx(
14290
14353
  "canvas",
14291
14354
  {
@@ -14297,6 +14360,33 @@ function SideView({
14297
14360
  }
14298
14361
  );
14299
14362
  }
14363
+ var NOOP;
14364
+ var init_SideCanvas2D = __esm({
14365
+ "components/game/2d/molecules/SideCanvas2D.tsx"() {
14366
+ "use client";
14367
+ init_cn();
14368
+ init_useEventBus();
14369
+ init_useImageCache();
14370
+ init_atlasSlice();
14371
+ init_useRenderInterpolation();
14372
+ init_verificationRegistry();
14373
+ init_isometric();
14374
+ NOOP = () => {
14375
+ };
14376
+ SideCanvas2D.displayName = "SideCanvas2D";
14377
+ }
14378
+ });
14379
+ function normalizeBackdrop2(bg) {
14380
+ return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
14381
+ }
14382
+ function resolveTileFallbackColor(tile) {
14383
+ const override = tile.color;
14384
+ return override ?? TERRAIN_COLORS[tile.terrain ?? ""] ?? TERRAIN_COLORS.default;
14385
+ }
14386
+ function resolveUnitTeamColor(unit) {
14387
+ const override = unit.tint;
14388
+ return override ?? TEAM_COLORS[unit.team ?? ""] ?? TEAM_COLORS.default;
14389
+ }
14300
14390
  function Canvas2D({
14301
14391
  // Closed-circuit
14302
14392
  className,
@@ -14311,7 +14401,7 @@ function Canvas2D({
14311
14401
  effects: _effectsPropRaw = [],
14312
14402
  platforms,
14313
14403
  player,
14314
- backgroundImage,
14404
+ backgroundImage: backgroundImageRaw,
14315
14405
  // Interaction state
14316
14406
  selectedUnitId = null,
14317
14407
  validMoves = [],
@@ -14346,12 +14436,13 @@ function Canvas2D({
14346
14436
  // Side-view asset resolution
14347
14437
  playerSprite,
14348
14438
  tileSprites,
14349
- bgColor = "#5c94fc",
14439
+ bgColor = DEFAULT_BG_COLOR,
14350
14440
  worldWidth = 800,
14351
14441
  worldHeight = 400,
14352
14442
  // Remote asset loading
14353
14443
  assetManifest
14354
14444
  }) {
14445
+ const backgroundImage = normalizeBackdrop2(backgroundImageRaw);
14355
14446
  const isSide = projection === "side";
14356
14447
  const isFree = projection === "free";
14357
14448
  const flatLike = projection === "hex" || projection === "flat" || isFree;
@@ -14535,7 +14626,7 @@ function Canvas2D({
14535
14626
  return sortedTiles.map((t2) => ({
14536
14627
  x: t2.x,
14537
14628
  y: t2.y,
14538
- color: t2.terrain === "water" ? "#3b82f6" : t2.terrain === "mountain" ? "#78716c" : "#4ade80"
14629
+ color: MINIMAP_TERRAIN_COLORS[t2.terrain ?? ""] ?? MINIMAP_TERRAIN_COLORS.default
14539
14630
  }));
14540
14631
  }, [showMinimap, sortedTiles]);
14541
14632
  const miniMapUnits = React105.useMemo(() => {
@@ -14543,7 +14634,7 @@ function Canvas2D({
14543
14634
  return units.filter((u) => u.position).map((u) => ({
14544
14635
  x: u.position.x,
14545
14636
  y: u.position.y,
14546
- color: u.team === "player" ? "#60a5fa" : u.team === "enemy" ? "#f87171" : "#9ca3af",
14637
+ color: MINIMAP_UNIT_COLORS[u.team ?? ""] ?? MINIMAP_UNIT_COLORS.default,
14547
14638
  isPlayer: u.team === "player"
14548
14639
  }));
14549
14640
  }, [showMinimap, units]);
@@ -14580,7 +14671,7 @@ function Canvas2D({
14580
14671
  }
14581
14672
  }
14582
14673
  } else {
14583
- ctx.fillStyle = "#1a1a2e";
14674
+ ctx.fillStyle = BACKGROUND_FALLBACK_COLOR;
14584
14675
  ctx.fillRect(0, 0, viewportSize.width, viewportSize.height);
14585
14676
  }
14586
14677
  if (sortedTiles.length === 0 && units.length === 0 && features.length === 0) return;
@@ -14610,15 +14701,15 @@ function Canvas2D({
14610
14701
  } else if (img && img.naturalWidth === 0) {
14611
14702
  ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
14612
14703
  } else if (squareGrid) {
14613
- ctx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : tile.terrain === "stone" ? "#9ca3af" : "#4ade80";
14704
+ ctx.fillStyle = resolveTileFallbackColor(tile);
14614
14705
  ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
14615
- ctx.strokeStyle = "rgba(0,0,0,0.2)";
14706
+ ctx.strokeStyle = GRID_STROKE_COLOR;
14616
14707
  ctx.lineWidth = 1;
14617
14708
  ctx.strokeRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
14618
14709
  } else {
14619
14710
  const centerX = pos.x + scaledTileWidth / 2;
14620
14711
  const topY = pos.y + scaledDiamondTopY;
14621
- ctx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : tile.terrain === "stone" ? "#9ca3af" : "#4ade80";
14712
+ ctx.fillStyle = resolveTileFallbackColor(tile);
14622
14713
  ctx.beginPath();
14623
14714
  ctx.moveTo(centerX, topY);
14624
14715
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -14626,7 +14717,7 @@ function Canvas2D({
14626
14717
  ctx.lineTo(pos.x, topY + scaledFloorHeight / 2);
14627
14718
  ctx.closePath();
14628
14719
  ctx.fill();
14629
- ctx.strokeStyle = "rgba(0,0,0,0.2)";
14720
+ ctx.strokeStyle = GRID_STROKE_COLOR;
14630
14721
  ctx.lineWidth = 1;
14631
14722
  ctx.stroke();
14632
14723
  }
@@ -14647,11 +14738,11 @@ function Canvas2D({
14647
14738
  ctx.fill();
14648
14739
  };
14649
14740
  if (hoveredTile && hoveredTile.x === tile.x && hoveredTile.y === tile.y) {
14650
- drawHighlight("rgba(255, 255, 255, 0.15)");
14741
+ drawHighlight(HIGHLIGHT_COLORS.hover);
14651
14742
  }
14652
14743
  const tileKey = `${tile.x},${tile.y}`;
14653
- if (validMoveSet.has(tileKey)) drawHighlight("rgba(74, 222, 128, 0.25)");
14654
- if (attackTargetSet.has(tileKey)) drawHighlight("rgba(239, 68, 68, 0.35)");
14744
+ if (validMoveSet.has(tileKey)) drawHighlight(HIGHLIGHT_COLORS.validMove);
14745
+ if (attackTargetSet.has(tileKey)) drawHighlight(HIGHLIGHT_COLORS.attack);
14655
14746
  if (debug2) {
14656
14747
  const centerX = pos.x + scaledTileWidth / 2;
14657
14748
  const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
@@ -14725,9 +14816,9 @@ function Canvas2D({
14725
14816
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
14726
14817
  const unitIsSheet = unit.spriteSheet?.url !== void 0;
14727
14818
  const unitSrc = img && !unitIsSheet ? resolveAssetSource(img, unitAsset, bumpAtlas) : null;
14728
- const SHEET_ROWS = 5;
14729
14819
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
14730
- const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
14820
+ const sheetFrameH = img ? img.naturalHeight / LEGACY_SHEET_ROWS : 0;
14821
+ const legacyFrame = frameRect(0, 0, SHEET_COLUMNS, sheetFrameW, sheetFrameH);
14731
14822
  const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
14732
14823
  const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
14733
14824
  const ar = unitIsSheet ? sheetFrameW / (sheetFrameH || 1) : unitSrc ? unitSrc.aspect : frameW / (frameH || 1);
@@ -14745,17 +14836,16 @@ function Canvas2D({
14745
14836
  ctx.globalAlpha = 0.25;
14746
14837
  if (img) {
14747
14838
  if (unitIsSheet) {
14748
- ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
14839
+ ctx.drawImage(img, legacyFrame.sx, legacyFrame.sy, legacyFrame.sw, legacyFrame.sh, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
14749
14840
  } else if (unitSrc) {
14750
14841
  blit(ctx, unitSrc, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
14751
14842
  } else {
14752
14843
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
14753
14844
  }
14754
14845
  } else {
14755
- const color = unit.team === "player" ? "#3b82f6" : unit.team === "enemy" ? "#ef4444" : "#6b7280";
14756
14846
  ctx.beginPath();
14757
14847
  ctx.arc(ghostCenterX, ghostGroundY - 16 * scale, 20 * scale, 0, Math.PI * 2);
14758
- ctx.fillStyle = color;
14848
+ ctx.fillStyle = resolveUnitTeamColor(unit);
14759
14849
  ctx.fill();
14760
14850
  }
14761
14851
  ctx.restore();
@@ -14763,7 +14853,7 @@ function Canvas2D({
14763
14853
  if (isSelected) {
14764
14854
  ctx.beginPath();
14765
14855
  ctx.ellipse(centerX, groundY, drawW / 2 + 4 * scale, 12 * scale, 0, 0, Math.PI * 2);
14766
- ctx.strokeStyle = "rgba(0, 200, 255, 0.8)";
14856
+ ctx.strokeStyle = SELECTION_RING_COLOR;
14767
14857
  ctx.lineWidth = 3;
14768
14858
  ctx.stroke();
14769
14859
  }
@@ -14780,7 +14870,7 @@ function Canvas2D({
14780
14870
  const spriteY = groundY - fDrawH - (frame.applyBreathing ? breatheOffset : 0);
14781
14871
  ctx.save();
14782
14872
  if (unit.team) {
14783
- ctx.shadowColor = unit.team === "player" ? "rgba(0, 150, 255, 0.6)" : "rgba(255, 50, 50, 0.6)";
14873
+ ctx.shadowColor = TEAM_SHADOW_COLORS[unit.team] ?? TEAM_SHADOW_COLORS.default;
14784
14874
  ctx.shadowBlur = 12 * scale;
14785
14875
  }
14786
14876
  if (frame.flipX) {
@@ -14795,7 +14885,7 @@ function Canvas2D({
14795
14885
  const spriteY = groundY - drawH - breatheOffset;
14796
14886
  const drawUnit = (x) => {
14797
14887
  if (unitIsSheet) {
14798
- ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
14888
+ ctx.drawImage(img, legacyFrame.sx, legacyFrame.sy, legacyFrame.sw, legacyFrame.sh, x, spriteY, drawW, drawH);
14799
14889
  } else if (unitSrc) {
14800
14890
  blit(ctx, unitSrc, x, spriteY, drawW, drawH);
14801
14891
  } else {
@@ -14804,7 +14894,7 @@ function Canvas2D({
14804
14894
  };
14805
14895
  if (unit.team) {
14806
14896
  ctx.save();
14807
- ctx.shadowColor = unit.team === "player" ? "rgba(0, 150, 255, 0.6)" : "rgba(255, 50, 50, 0.6)";
14897
+ ctx.shadowColor = TEAM_SHADOW_COLORS[unit.team] ?? TEAM_SHADOW_COLORS.default;
14808
14898
  ctx.shadowBlur = 12 * scale;
14809
14899
  drawUnit(centerX - drawW / 2);
14810
14900
  ctx.restore();
@@ -14812,10 +14902,9 @@ function Canvas2D({
14812
14902
  drawUnit(centerX - drawW / 2);
14813
14903
  }
14814
14904
  } else {
14815
- const color = unit.team === "player" ? "#3b82f6" : unit.team === "enemy" ? "#ef4444" : "#6b7280";
14816
14905
  ctx.beginPath();
14817
14906
  ctx.arc(centerX, groundY - 20 * scale - breatheOffset, 20 * scale, 0, Math.PI * 2);
14818
- ctx.fillStyle = color;
14907
+ ctx.fillStyle = resolveUnitTeamColor(unit);
14819
14908
  ctx.fill();
14820
14909
  ctx.strokeStyle = "rgba(255,255,255,0.8)";
14821
14910
  ctx.lineWidth = 2;
@@ -15054,7 +15143,7 @@ function Canvas2D({
15054
15143
  }
15055
15144
  if (isSide) {
15056
15145
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { ref: containerRef, className: cn("relative overflow-hidden w-full h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
15057
- SideView,
15146
+ SideCanvas2D,
15058
15147
  {
15059
15148
  player,
15060
15149
  platforms: platforms && platforms.length ? platforms : DEFAULT_PLATFORMS,
@@ -15152,7 +15241,7 @@ function Canvas2D({
15152
15241
  {
15153
15242
  as: "span",
15154
15243
  className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
15155
- 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)" },
15244
+ style: { background: UNIT_LABEL_BG_COLORS[unit.team ?? ""] ?? UNIT_LABEL_BG_COLORS.default },
15156
15245
  children: unit.name
15157
15246
  }
15158
15247
  ),
@@ -15176,7 +15265,7 @@ function Canvas2D({
15176
15265
  }
15177
15266
  );
15178
15267
  }
15179
- var PLATFORM_COLORS, NOOP, PLAYER_COLOR, PLAYER_EYE_COLOR, SKY_GRADIENT_TOP, SKY_GRADIENT_BOTTOM, GRID_COLOR, DEFAULT_PLATFORMS;
15268
+ var LEGACY_SHEET_ROWS, DEFAULT_PLATFORMS;
15180
15269
  var init_Canvas2D = __esm({
15181
15270
  "components/game/2d/molecules/Canvas2D.tsx"() {
15182
15271
  "use client";
@@ -15198,19 +15287,9 @@ var init_Canvas2D = __esm({
15198
15287
  init_verificationRegistry();
15199
15288
  init_isometric();
15200
15289
  init_spriteSheetConstants();
15201
- PLATFORM_COLORS = {
15202
- ground: "#4a7c59",
15203
- platform: "#7c6b4a",
15204
- hazard: "#c0392b",
15205
- goal: "#f1c40f"
15206
- };
15207
- NOOP = () => {
15208
- };
15209
- PLAYER_COLOR = "#3498db";
15210
- PLAYER_EYE_COLOR = "#ffffff";
15211
- SKY_GRADIENT_TOP = "#1a1a2e";
15212
- SKY_GRADIENT_BOTTOM = "#16213e";
15213
- GRID_COLOR = "rgba(255, 255, 255, 0.03)";
15290
+ init_spriteAnimation();
15291
+ init_SideCanvas2D();
15292
+ LEGACY_SHEET_ROWS = Object.keys(SPRITE_SHEET_LAYOUT).length;
15214
15293
  DEFAULT_PLATFORMS = [
15215
15294
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
15216
15295
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -20335,9 +20414,9 @@ var init_BiologyCanvas = __esm({
20335
20414
  }
20336
20415
  });
20337
20416
 
20338
- // node_modules/katex/dist/katex.min.css
20417
+ // node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css
20339
20418
  var init_katex_min = __esm({
20340
- "node_modules/katex/dist/katex.min.css"() {
20419
+ "node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css"() {
20341
20420
  }
20342
20421
  });
20343
20422
  var Tabs;
@@ -32543,8 +32622,9 @@ var init_LineChart = __esm({
32543
32622
  const safeData = data ?? [];
32544
32623
  const sortedData = React105.useMemo(() => {
32545
32624
  if (safeData.length === 0) return [];
32625
+ if (!safeData.some((d) => d.date != null)) return [...safeData];
32546
32626
  return [...safeData].sort(
32547
- (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
32627
+ (a, b) => new Date(a.date ?? 0).getTime() - new Date(b.date ?? 0).getTime()
32548
32628
  );
32549
32629
  }, [safeData]);
32550
32630
  const points = React105.useMemo(() => {
@@ -33295,13 +33375,13 @@ var init_MapView = __esm({
33295
33375
  shadowSize: [41, 41]
33296
33376
  });
33297
33377
  L.Marker.prototype.options.icon = defaultIcon;
33298
- const { useEffect: useEffect71, useRef: useRef68, useCallback: useCallback104, useState: useState105 } = React105__namespace.default;
33378
+ const { useEffect: useEffect72, useRef: useRef69, useCallback: useCallback105, useState: useState105 } = React105__namespace.default;
33299
33379
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
33300
33380
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
33301
33381
  function MapUpdater({ centerLat, centerLng, zoom }) {
33302
33382
  const map = useMap();
33303
- const prevRef = useRef68({ centerLat, centerLng, zoom });
33304
- useEffect71(() => {
33383
+ const prevRef = useRef69({ centerLat, centerLng, zoom });
33384
+ useEffect72(() => {
33305
33385
  const prev = prevRef.current;
33306
33386
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
33307
33387
  map.setView([centerLat, centerLng], zoom);
@@ -33312,7 +33392,7 @@ var init_MapView = __esm({
33312
33392
  }
33313
33393
  function MapClickHandler({ onMapClick }) {
33314
33394
  const map = useMap();
33315
- useEffect71(() => {
33395
+ useEffect72(() => {
33316
33396
  if (!onMapClick) return;
33317
33397
  const handler = (e) => {
33318
33398
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -33341,7 +33421,7 @@ var init_MapView = __esm({
33341
33421
  }) {
33342
33422
  const eventBus = useEventBus2();
33343
33423
  const [clickedPosition, setClickedPosition] = useState105(null);
33344
- const handleMapClick = useCallback104((lat, lng) => {
33424
+ const handleMapClick = useCallback105((lat, lng) => {
33345
33425
  if (showClickedPin) {
33346
33426
  setClickedPosition({ lat, lng });
33347
33427
  }
@@ -33350,7 +33430,7 @@ var init_MapView = __esm({
33350
33430
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
33351
33431
  }
33352
33432
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
33353
- const handleMarkerClick = useCallback104((marker) => {
33433
+ const handleMarkerClick = useCallback105((marker) => {
33354
33434
  onMarkerClick?.(marker);
33355
33435
  if (markerClickEvent) {
33356
33436
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -1,4 +1,4 @@
1
- /* node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -214,11 +214,11 @@
214
214
  border-color: currentColor;
215
215
  }
216
216
  .katex .katex-version:after {
217
- content: "0.16.45";
217
+ content: "0.16.47";
218
218
  }
219
219
  .katex .katex-mathml {
220
- clip: rect(1px, 1px, 1px, 1px);
221
220
  border: 0;
221
+ clip-path: inset(50%);
222
222
  height: 1px;
223
223
  overflow: hidden;
224
224
  padding: 0;