@almadar/ui 5.54.0 → 5.56.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.
@@ -8468,6 +8468,16 @@ var init_Skeleton = __esm({
8468
8468
  Skeleton.displayName = "Skeleton";
8469
8469
  }
8470
8470
  });
8471
+ function isKnownPattern(type) {
8472
+ return type in componentMapping;
8473
+ }
8474
+ var componentMapping;
8475
+ var init_pattern_resolver = __esm({
8476
+ "renderer/pattern-resolver.ts"() {
8477
+ logger.createLogger("almadar:ui:pattern-resolver");
8478
+ componentMapping = {};
8479
+ }
8480
+ });
8471
8481
 
8472
8482
  // renderer/slot-definitions.ts
8473
8483
  function isPortalSlot(slot) {
@@ -8576,6 +8586,7 @@ var init_navigation = __esm({
8576
8586
  // renderer/index.ts
8577
8587
  var init_renderer = __esm({
8578
8588
  "renderer/index.ts"() {
8589
+ init_pattern_resolver();
8579
8590
  init_slot_definitions();
8580
8591
  }
8581
8592
  });
@@ -10279,7 +10290,7 @@ function recordTransition(trace) {
10279
10290
  ...trace,
10280
10291
  id: `t-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
10281
10292
  };
10282
- log4.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
10293
+ log5.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
10283
10294
  getState().transitions.push(entry);
10284
10295
  if (getState().transitions.length > MAX_TRANSITIONS) {
10285
10296
  getState().transitions.shift();
@@ -10378,7 +10389,7 @@ function getTraitSnapshots() {
10378
10389
  try {
10379
10390
  snapshots.push(getter());
10380
10391
  } catch (err) {
10381
- log4.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
10392
+ log5.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
10382
10393
  }
10383
10394
  }
10384
10395
  return snapshots;
@@ -10477,10 +10488,10 @@ function updateAssetStatus(url, status) {
10477
10488
  window.__orbitalVerification.assetStatus[url] = status;
10478
10489
  }
10479
10490
  }
10480
- var log4, MAX_TRANSITIONS;
10491
+ var log5, MAX_TRANSITIONS;
10481
10492
  var init_verificationRegistry = __esm({
10482
10493
  "lib/verificationRegistry.ts"() {
10483
- log4 = logger.createLogger("almadar:bridge");
10494
+ log5 = logger.createLogger("almadar:bridge");
10484
10495
  MAX_TRANSITIONS = 500;
10485
10496
  exposeOnWindow();
10486
10497
  }
@@ -10831,6 +10842,8 @@ function IsometricCanvas({
10831
10842
  showMinimap = true,
10832
10843
  enableCamera = true,
10833
10844
  unitScale = 1,
10845
+ spriteHeightRatio = 1.5,
10846
+ spriteMaxWidthRatio = 0.6,
10834
10847
  // Asset resolution
10835
10848
  getTerrainSprite,
10836
10849
  getFeatureSprite,
@@ -11221,8 +11234,8 @@ function IsometricCanvas({
11221
11234
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
11222
11235
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11223
11236
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11224
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
11225
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
11237
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11238
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11226
11239
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
11227
11240
  let drawH = unitDrawH;
11228
11241
  let drawW = unitDrawH * ar;
@@ -11606,6 +11619,8 @@ function BattleBoard({
11606
11619
  assetManifest: propAssetManifest,
11607
11620
  scale = 0.45,
11608
11621
  unitScale = 1,
11622
+ spriteHeightRatio = 1.5,
11623
+ spriteMaxWidthRatio = 0.6,
11609
11624
  header,
11610
11625
  sidebar,
11611
11626
  actions,
@@ -11896,7 +11911,9 @@ function BattleBoard({
11896
11911
  hasActiveEffects: hasActiveEffects2,
11897
11912
  effectSpriteUrls,
11898
11913
  resolveUnitFrame,
11899
- unitScale
11914
+ unitScale,
11915
+ spriteHeightRatio,
11916
+ spriteMaxWidthRatio
11900
11917
  }
11901
11918
  ),
11902
11919
  overlay && overlay(ctx)
@@ -12774,7 +12791,7 @@ var init_avl_elk_layout = __esm({
12774
12791
  elk = new ELK__default.default();
12775
12792
  }
12776
12793
  });
12777
- var log5, SWIM_GUTTER, CENTER_W, BehaviorView;
12794
+ var log6, SWIM_GUTTER, CENTER_W, BehaviorView;
12778
12795
  var init_BehaviorView = __esm({
12779
12796
  "components/avl/molecules/BehaviorView.tsx"() {
12780
12797
  "use client";
@@ -12783,7 +12800,7 @@ var init_BehaviorView = __esm({
12783
12800
  init_AvlSwimLane();
12784
12801
  init_types();
12785
12802
  init_avl_elk_layout();
12786
- log5 = logger.createLogger("almadar:ui:avl:behavior-view");
12803
+ log6 = logger.createLogger("almadar:ui:avl:behavior-view");
12787
12804
  SWIM_GUTTER = 120;
12788
12805
  CENTER_W = 360;
12789
12806
  BehaviorView = ({ data }) => {
@@ -12794,7 +12811,7 @@ var init_BehaviorView = __esm({
12794
12811
  const dataKey = React81.useMemo(() => JSON.stringify(traitData), [traitData]);
12795
12812
  React81.useEffect(() => {
12796
12813
  if (!traitData) return;
12797
- computeTraitLayout(traitData).then(setLayout).catch((err) => log5.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
12814
+ computeTraitLayout(traitData).then(setLayout).catch((err) => log6.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
12798
12815
  }, [dataKey]);
12799
12816
  if (!traitData) {
12800
12817
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-[var(--color-border)] bg-[var(--color-card)] p-4 text-center text-[var(--color-muted-foreground)] text-sm", children: t("avl.noTraitData") });
@@ -13205,7 +13222,7 @@ function generateDiff(oldVal, newVal) {
13205
13222
  }
13206
13223
  return diff;
13207
13224
  }
13208
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
13225
+ var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
13209
13226
  var init_CodeBlock = __esm({
13210
13227
  "components/core/molecules/markdown/CodeBlock.tsx"() {
13211
13228
  init_cn();
@@ -13288,7 +13305,7 @@ var init_CodeBlock = __esm({
13288
13305
  "lolo-op-async": { color: syntax.ORB_COLORS.dark.async }
13289
13306
  };
13290
13307
  loloStyle = { ...dark__default.default, ...loloStyleOverrides };
13291
- log6 = logger.createLogger("almadar:ui:markdown-code");
13308
+ log7 = logger.createLogger("almadar:ui:markdown-code");
13292
13309
  CODE_LANGUAGES = [
13293
13310
  "text",
13294
13311
  "json",
@@ -13552,7 +13569,7 @@ var init_CodeBlock = __esm({
13552
13569
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
13553
13570
  setTimeout(() => setCopied(false), 2e3);
13554
13571
  } catch (err) {
13555
- log6.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
13572
+ log7.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
13556
13573
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
13557
13574
  }
13558
13575
  };
@@ -17433,14 +17450,14 @@ function useSafeEventBus2() {
17433
17450
  } };
17434
17451
  }
17435
17452
  }
17436
- var log7, lookStyles4, ButtonGroup;
17453
+ var log8, lookStyles4, ButtonGroup;
17437
17454
  var init_ButtonGroup = __esm({
17438
17455
  "components/core/molecules/ButtonGroup.tsx"() {
17439
17456
  "use client";
17440
17457
  init_cn();
17441
17458
  init_atoms2();
17442
17459
  init_useEventBus();
17443
- log7 = logger.createLogger("almadar:ui:button-group");
17460
+ log8 = logger.createLogger("almadar:ui:button-group");
17444
17461
  lookStyles4 = {
17445
17462
  "right-aligned-buttons": "",
17446
17463
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -17521,7 +17538,7 @@ var init_ButtonGroup = __esm({
17521
17538
  {
17522
17539
  variant: "ghost",
17523
17540
  onClick: () => {
17524
- log7.debug("Filter clicked", { field: filter.field });
17541
+ log8.debug("Filter clicked", { field: filter.field });
17525
17542
  },
17526
17543
  children: filter.label
17527
17544
  },
@@ -25183,9 +25200,9 @@ function debug(...args) {
25183
25200
  const [first, ...rest] = args;
25184
25201
  const message = typeof first === "string" ? first : "<debug>";
25185
25202
  if (rest.length === 0 && typeof first === "string") {
25186
- log8.debug(message);
25203
+ log9.debug(message);
25187
25204
  } else {
25188
- log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
25205
+ log9.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
25189
25206
  }
25190
25207
  }
25191
25208
  function debugGroup(label) {
@@ -25213,11 +25230,11 @@ function toLogMetaValue(v) {
25213
25230
  }
25214
25231
  return String(v);
25215
25232
  }
25216
- var NAMESPACE, log8;
25233
+ var NAMESPACE, log9;
25217
25234
  var init_debug = __esm({
25218
25235
  "lib/debug.ts"() {
25219
25236
  NAMESPACE = "almadar:ui:debug";
25220
- log8 = logger.createLogger(NAMESPACE);
25237
+ log9 = logger.createLogger(NAMESPACE);
25221
25238
  logger.createLogger("almadar:ui:debug:input");
25222
25239
  logger.createLogger("almadar:ui:debug:collision");
25223
25240
  logger.createLogger("almadar:ui:debug:physics");
@@ -41508,11 +41525,11 @@ var init_Canvas3DErrorBoundary = __esm({
41508
41525
  "components/game/molecules/three/components/Canvas3DErrorBoundary.css"() {
41509
41526
  }
41510
41527
  });
41511
- var log9, Canvas3DErrorBoundary;
41528
+ var log10, Canvas3DErrorBoundary;
41512
41529
  var init_Canvas3DErrorBoundary2 = __esm({
41513
41530
  "components/game/molecules/three/components/Canvas3DErrorBoundary.tsx"() {
41514
41531
  init_Canvas3DErrorBoundary();
41515
- log9 = logger.createLogger("almadar:ui:game:canvas3d:error-boundary");
41532
+ log10 = logger.createLogger("almadar:ui:game:canvas3d:error-boundary");
41516
41533
  Canvas3DErrorBoundary = class extends React81.Component {
41517
41534
  constructor(props) {
41518
41535
  super(props);
@@ -41540,8 +41557,8 @@ var init_Canvas3DErrorBoundary2 = __esm({
41540
41557
  componentDidCatch(error, errorInfo) {
41541
41558
  this.setState({ errorInfo });
41542
41559
  this.props.onError?.(error, errorInfo);
41543
- log9.error("Error caught", { error });
41544
- log9.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
41560
+ log10.error("Error caught", { error });
41561
+ log10.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
41545
41562
  }
41546
41563
  render() {
41547
41564
  if (this.state.hasError) {
@@ -41604,7 +41621,7 @@ function useGLTFModel(url, resourceBasePath) {
41604
41621
  setState({ model: null, isLoading: false, error: null });
41605
41622
  return;
41606
41623
  }
41607
- log10.debug("Loading", { url });
41624
+ log11.debug("Loading", { url });
41608
41625
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
41609
41626
  const assetRoot = resourceBasePath || detectAssetRoot2(url);
41610
41627
  const loader = new GLTFLoader.GLTFLoader();
@@ -41612,7 +41629,7 @@ function useGLTFModel(url, resourceBasePath) {
41612
41629
  loader.load(
41613
41630
  url,
41614
41631
  (gltf) => {
41615
- log10.debug("Loaded", { url });
41632
+ log11.debug("Loaded", { url });
41616
41633
  setState({
41617
41634
  model: gltf.scene,
41618
41635
  isLoading: false,
@@ -41621,7 +41638,7 @@ function useGLTFModel(url, resourceBasePath) {
41621
41638
  },
41622
41639
  void 0,
41623
41640
  (err) => {
41624
- log10.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
41641
+ log11.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
41625
41642
  setState({
41626
41643
  model: null,
41627
41644
  isLoading: false,
@@ -41737,11 +41754,11 @@ function ModelLoader({
41737
41754
  }
41738
41755
  );
41739
41756
  }
41740
- var log10;
41757
+ var log11;
41741
41758
  var init_ModelLoader = __esm({
41742
41759
  "components/game/molecules/three/components/ModelLoader.tsx"() {
41743
41760
  "use client";
41744
- log10 = logger.createLogger("almadar:ui:game:model-loader");
41761
+ log11 = logger.createLogger("almadar:ui:game:model-loader");
41745
41762
  }
41746
41763
  });
41747
41764
 
@@ -41867,6 +41884,8 @@ var init_GameCanvas3D2 = __esm({
41867
41884
  attackTargets = [],
41868
41885
  selectedTileIds = [],
41869
41886
  selectedUnitId = null,
41887
+ unitScale = 1,
41888
+ scale = 0.45,
41870
41889
  children
41871
41890
  }, ref) => {
41872
41891
  const containerRef = React81.useRef(null);
@@ -42083,12 +42102,18 @@ var init_GameCanvas3D2 = __esm({
42083
42102
  },
42084
42103
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
42085
42104
  );
42105
+ const UNIT_BASE_MODEL_SCALE = 0.5;
42106
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
42107
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
42086
42108
  const DefaultUnitRenderer = React81.useCallback(
42087
42109
  ({ unit, position }) => {
42088
42110
  const isSelected = selectedUnitId === unit.id;
42089
42111
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
42090
42112
  const hasAtlas = unitAtlasUrl(unit) !== null;
42091
42113
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
42114
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
42115
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
42116
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
42092
42117
  return /* @__PURE__ */ jsxRuntime.jsxs(
42093
42118
  "group",
42094
42119
  {
@@ -42106,7 +42131,8 @@ var init_GameCanvas3D2 = __esm({
42106
42131
  UnitSpriteBillboard,
42107
42132
  {
42108
42133
  sheetUrl: initialFrame.sheetUrl,
42109
- resolveFrame: () => resolveUnitFrame(unit.id)
42134
+ resolveFrame: () => resolveUnitFrame(unit.id),
42135
+ height: billboardHeight
42110
42136
  }
42111
42137
  ) })
42112
42138
  ) : unit.modelUrl ? (
@@ -42115,22 +42141,22 @@ var init_GameCanvas3D2 = __esm({
42115
42141
  ModelLoader,
42116
42142
  {
42117
42143
  url: unit.modelUrl,
42118
- scale: 0.5,
42144
+ scale: modelScale,
42119
42145
  fallbackGeometry: "box",
42120
42146
  castShadow: true
42121
42147
  }
42122
42148
  )
42123
42149
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
42124
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.3, 0], children: [
42125
- /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
42150
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
42151
+ /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
42126
42152
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42127
42153
  ] }),
42128
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.6, 0], children: [
42129
- /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
42154
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
42155
+ /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
42130
42156
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42131
42157
  ] }),
42132
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.9, 0], children: [
42133
- /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [0.12, 8, 8] }),
42158
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
42159
+ /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
42134
42160
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42135
42161
  ] })
42136
42162
  ] }),
@@ -42163,7 +42189,7 @@ var init_GameCanvas3D2 = __esm({
42163
42189
  }
42164
42190
  );
42165
42191
  },
42166
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
42192
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
42167
42193
  );
42168
42194
  const DefaultFeatureRenderer = React81.useCallback(
42169
42195
  ({
@@ -42306,33 +42332,35 @@ var init_GameCanvas3D2 = __esm({
42306
42332
  fadeStrength: 1
42307
42333
  }
42308
42334
  ),
42309
- tiles.map((tile, index) => {
42310
- const position = gridToWorld(
42311
- tile.x,
42312
- tile.z ?? tile.y ?? 0,
42313
- tile.elevation ?? 0
42314
- );
42315
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
42316
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42317
- }),
42318
- features.map((feature, index) => {
42319
- const position = gridToWorld(
42320
- feature.x,
42321
- feature.z ?? feature.y ?? 0,
42322
- (feature.elevation ?? 0) + 0.5
42323
- );
42324
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42325
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42326
- }),
42327
- units.map((unit) => {
42328
- const position = gridToWorld(
42329
- unit.x ?? 0,
42330
- unit.z ?? unit.y ?? 0,
42331
- (unit.elevation ?? 0) + 0.5
42332
- );
42333
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42334
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
42335
- }),
42335
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
42336
+ tiles.map((tile, index) => {
42337
+ const position = gridToWorld(
42338
+ tile.x,
42339
+ tile.z ?? tile.y ?? 0,
42340
+ tile.elevation ?? 0
42341
+ );
42342
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
42343
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42344
+ }),
42345
+ features.map((feature, index) => {
42346
+ const position = gridToWorld(
42347
+ feature.x,
42348
+ feature.z ?? feature.y ?? 0,
42349
+ (feature.elevation ?? 0) + 0.5
42350
+ );
42351
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42352
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42353
+ }),
42354
+ units.map((unit) => {
42355
+ const position = gridToWorld(
42356
+ unit.x ?? 0,
42357
+ unit.z ?? unit.y ?? 0,
42358
+ (unit.elevation ?? 0) + 0.5
42359
+ );
42360
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42361
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
42362
+ })
42363
+ ] }),
42336
42364
  children,
42337
42365
  /* @__PURE__ */ jsxRuntime.jsx(
42338
42366
  drei.OrbitControls,
@@ -42375,6 +42403,8 @@ function GameBoard3D({
42375
42403
  features = [],
42376
42404
  cameraMode = "perspective",
42377
42405
  backgroundColor = "#2a1a1a",
42406
+ unitScale = 1,
42407
+ scale = 0.45,
42378
42408
  tileClickEvent,
42379
42409
  unitClickEvent,
42380
42410
  attackEvent,
@@ -42475,6 +42505,8 @@ function GameBoard3D({
42475
42505
  selectedUnitId,
42476
42506
  validMoves,
42477
42507
  attackTargets,
42508
+ unitScale,
42509
+ scale,
42478
42510
  className: "game-board-3d__canvas w-full min-h-[85vh]"
42479
42511
  }
42480
42512
  ),
@@ -44460,6 +44492,8 @@ function RoguelikeBoard({
44460
44492
  assetManifest: propAssetManifest,
44461
44493
  scale = 0.45,
44462
44494
  unitScale = 1,
44495
+ spriteHeightRatio = 1.5,
44496
+ spriteMaxWidthRatio = 0.6,
44463
44497
  moveEvent,
44464
44498
  playAgainEvent,
44465
44499
  gameEndEvent,
@@ -44607,7 +44641,9 @@ function RoguelikeBoard({
44607
44641
  scale,
44608
44642
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
44609
44643
  assetManifest: propAssetManifest,
44610
- unitScale
44644
+ unitScale,
44645
+ spriteHeightRatio,
44646
+ spriteMaxWidthRatio
44611
44647
  }
44612
44648
  ) }),
44613
44649
  !isGameOver && /* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -46046,7 +46082,7 @@ function getAllEvents(traits2) {
46046
46082
  function EventDispatcherTab({ traits: traits2, schema }) {
46047
46083
  const eventBus = useEventBus();
46048
46084
  const { t } = hooks.useTranslate();
46049
- const [log14, setLog] = React81__namespace.useState([]);
46085
+ const [log15, setLog] = React81__namespace.useState([]);
46050
46086
  const prevStatesRef = React81__namespace.useRef(/* @__PURE__ */ new Map());
46051
46087
  React81__namespace.useEffect(() => {
46052
46088
  for (const trait of traits2) {
@@ -46110,9 +46146,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
46110
46146
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
46111
46147
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
46112
46148
  ] }),
46113
- log14.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
46149
+ log15.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
46114
46150
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
46115
- /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log14.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
46151
+ /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log15.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
46116
46152
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
46117
46153
  " ",
46118
46154
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -48979,6 +49015,9 @@ function TowerDefenseBoard({
48979
49015
  waveActive: propWaveActive,
48980
49016
  towerCost = 25,
48981
49017
  scale = 0.45,
49018
+ unitScale = 1,
49019
+ spriteHeightRatio = 1.5,
49020
+ spriteMaxWidthRatio = 0.6,
48982
49021
  placeTowerEvent,
48983
49022
  startWaveEvent,
48984
49023
  playAgainEvent,
@@ -49086,7 +49125,10 @@ function TowerDefenseBoard({
49086
49125
  onTileClick: handleTileClick,
49087
49126
  onTileHover: (x, y) => setHoveredTile({ x, y }),
49088
49127
  onTileLeave: () => setHoveredTile(null),
49089
- scale
49128
+ scale,
49129
+ unitScale,
49130
+ spriteHeightRatio,
49131
+ spriteMaxWidthRatio
49090
49132
  }
49091
49133
  ),
49092
49134
  hoveredTile && canPlaceTower && validMoves.some((m) => m.x === hoveredTile.x && m.y === hoveredTile.y) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-10 bg-background/80 rounded px-3 py-1 backdrop-blur-sm pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: t("td.placeTower") ?? `Place tower (${towerCost} gold)` }) })
@@ -49422,6 +49464,8 @@ function WorldMapBoard({
49422
49464
  isLoading,
49423
49465
  scale = 0.4,
49424
49466
  unitScale = 2.5,
49467
+ spriteHeightRatio = 1.5,
49468
+ spriteMaxWidthRatio = 0.6,
49425
49469
  allowMoveAllHeroes = false,
49426
49470
  isInRange = defaultIsInRange,
49427
49471
  heroSelectEvent,
@@ -49659,6 +49703,8 @@ function WorldMapBoard({
49659
49703
  effectSpriteUrls,
49660
49704
  resolveUnitFrame,
49661
49705
  unitScale,
49706
+ spriteHeightRatio,
49707
+ spriteMaxWidthRatio,
49662
49708
  diamondTopY,
49663
49709
  enableCamera
49664
49710
  }
@@ -50977,7 +51023,7 @@ function isPatternConfig(value) {
50977
51023
  if (value instanceof Date) return false;
50978
51024
  if (typeof value === "function") return false;
50979
51025
  const record = value;
50980
- return "type" in record && typeof record.type === "string";
51026
+ return "type" in record && typeof record.type === "string" && isKnownPattern(record.type);
50981
51027
  }
50982
51028
  function isPlainConfigObject(value) {
50983
51029
  if (React81__namespace.default.isValidElement(value)) return false;
@@ -51724,7 +51770,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51724
51770
  };
51725
51771
  }, [traitBindings]);
51726
51772
  const executeTransitionEffects = React81.useCallback(async (params) => {
51727
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log14 } = params;
51773
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log15 } = params;
51728
51774
  const traitName = binding.trait.name;
51729
51775
  const linkedEntity = binding.linkedEntity || "";
51730
51776
  const entityId = payload?.entityId;
@@ -51812,7 +51858,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51812
51858
  ...handlers,
51813
51859
  set: async (targetId, field, value) => {
51814
51860
  if (baseSet) await baseSet(targetId, field, value);
51815
- log14.debug("set:write", {
51861
+ log15.debug("set:write", {
51816
51862
  traitName,
51817
51863
  field,
51818
51864
  value: JSON.stringify(value),
@@ -51852,7 +51898,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51852
51898
  const executor = new runtime.EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
51853
51899
  try {
51854
51900
  await executor.executeAll(effects);
51855
- log14.debug("effects:executed", () => ({
51901
+ log15.debug("effects:executed", () => ({
51856
51902
  traitName,
51857
51903
  transition: `${previousState}->${newState}`,
51858
51904
  event: flushEvent,
@@ -51862,7 +51908,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51862
51908
  slotsTouched: Array.from(pendingSlots.keys()).join(",")
51863
51909
  }));
51864
51910
  for (const [slot, patterns] of pendingSlots) {
51865
- log14.debug("flush:slot", {
51911
+ log15.debug("flush:slot", {
51866
51912
  traitName,
51867
51913
  slot,
51868
51914
  patternCount: patterns.length,
@@ -51877,7 +51923,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51877
51923
  });
51878
51924
  }
51879
51925
  } catch (error) {
51880
- log14.error("effects:error", {
51926
+ log15.error("effects:error", {
51881
51927
  traitName,
51882
51928
  transition: `${previousState}->${newState}`,
51883
51929
  event: flushEvent,
@@ -51900,7 +51946,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51900
51946
  if (binding.config) {
51901
51947
  guardCtx.config = binding.config;
51902
51948
  }
51903
- const passed = runtime.interpolateValue(tick.guard, runtime.createContextFromBindings(guardCtx));
51949
+ const passed = evaluator.evaluateGuard(
51950
+ tick.guard,
51951
+ runtime.createContextFromBindings(guardCtx)
51952
+ );
51904
51953
  if (!passed) {
51905
51954
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
51906
51955
  return;
@@ -52349,7 +52398,7 @@ function clearSchemaCache() {
52349
52398
 
52350
52399
  // runtime/index.ts
52351
52400
  init_EntitySchemaContext();
52352
- var log11 = logger.createLogger("almadar:ui:trait-provider");
52401
+ var log12 = logger.createLogger("almadar:ui:trait-provider");
52353
52402
  var TraitContext = React81.createContext(null);
52354
52403
  function TraitProvider({
52355
52404
  traits: traitBindings,
@@ -52366,7 +52415,7 @@ function TraitProvider({
52366
52415
  currentState: stateName,
52367
52416
  availableEvents: trait.transitions.filter((t) => t.from === stateName).map((t) => t.event),
52368
52417
  dispatch: (eventKey, payload) => {
52369
- log11.debug("Dispatch", () => ({
52418
+ log12.debug("Dispatch", () => ({
52370
52419
  trait: trait.name,
52371
52420
  event: eventKey,
52372
52421
  payloadKeys: payload ? Object.keys(payload) : []
@@ -53116,7 +53165,7 @@ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
53116
53165
  init_navigation();
53117
53166
  init_verificationRegistry();
53118
53167
  var PERF_NAMESPACE = "almadar:perf:canvas";
53119
- var log13 = logger.createLogger(PERF_NAMESPACE);
53168
+ var log14 = logger.createLogger(PERF_NAMESPACE);
53120
53169
  var RING_SIZE = 50;
53121
53170
  var ring = [];
53122
53171
  var writeIdx = 0;
@@ -53171,7 +53220,7 @@ function perfEnd(name, startToken, detail) {
53171
53220
  }
53172
53221
  }
53173
53222
  push({ name, durationMs, ts: endTs, detail });
53174
- log13.debug(name, () => ({ durationMs, ...detail ?? {} }));
53223
+ log14.debug(name, () => ({ durationMs, ...detail ?? {} }));
53175
53224
  }
53176
53225
  function perfTime(name, fn, detail) {
53177
53226
  const t = perfStart(name);
@@ -53189,7 +53238,7 @@ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, com
53189
53238
  ts: commitTime,
53190
53239
  detail: { baseDuration }
53191
53240
  });
53192
- log13.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
53241
+ log14.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
53193
53242
  };
53194
53243
  function getPerfSnapshot() {
53195
53244
  if (ring.length < RING_SIZE) return ring.slice();