@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.
package/dist/avl/index.js CHANGED
@@ -10,7 +10,7 @@ import * as LucideIcons2 from 'lucide-react';
10
10
  import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, Bug, Send, ChevronUp, ChevronDown, Wrench, Tag, User, DollarSign, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { UISlotProvider, useUISlots, useTheme } from '@almadar/ui/context';
13
- import { evaluate, createMinimalContext } from '@almadar/evaluator';
13
+ import { evaluateGuard, evaluate, createMinimalContext } from '@almadar/evaluator';
14
14
  import { Link, Outlet, useLocation } from 'react-router-dom';
15
15
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
16
16
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
@@ -47,7 +47,7 @@ import { Canvas, useLoader, useFrame, useThree } from '@react-three/fiber';
47
47
  import { Billboard, Grid as Grid$1, OrbitControls } from '@react-three/drei';
48
48
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/patterns';
49
49
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
50
- import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, interpolateValue, createContextFromBindings } from '@almadar/runtime';
50
+ import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings } from '@almadar/runtime';
51
51
 
52
52
  var __defProp = Object.defineProperty;
53
53
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -12160,6 +12160,16 @@ var init_Skeleton = __esm({
12160
12160
  Skeleton.displayName = "Skeleton";
12161
12161
  }
12162
12162
  });
12163
+ function isKnownPattern(type) {
12164
+ return type in componentMapping;
12165
+ }
12166
+ var componentMapping;
12167
+ var init_pattern_resolver = __esm({
12168
+ "renderer/pattern-resolver.ts"() {
12169
+ createLogger("almadar:ui:pattern-resolver");
12170
+ componentMapping = {};
12171
+ }
12172
+ });
12163
12173
 
12164
12174
  // renderer/slot-definitions.ts
12165
12175
  function isPortalSlot(slot) {
@@ -12268,6 +12278,7 @@ var init_navigation = __esm({
12268
12278
  // renderer/index.ts
12269
12279
  var init_renderer = __esm({
12270
12280
  "renderer/index.ts"() {
12281
+ init_pattern_resolver();
12271
12282
  init_slot_definitions();
12272
12283
  }
12273
12284
  });
@@ -13971,7 +13982,7 @@ function recordTransition(trace) {
13971
13982
  ...trace,
13972
13983
  id: `t-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
13973
13984
  };
13974
- log4.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
13985
+ log5.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
13975
13986
  getState().transitions.push(entry);
13976
13987
  if (getState().transitions.length > MAX_TRANSITIONS) {
13977
13988
  getState().transitions.shift();
@@ -14070,7 +14081,7 @@ function getTraitSnapshots() {
14070
14081
  try {
14071
14082
  snapshots.push(getter());
14072
14083
  } catch (err) {
14073
- log4.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
14084
+ log5.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
14074
14085
  }
14075
14086
  }
14076
14087
  return snapshots;
@@ -14169,10 +14180,10 @@ function updateAssetStatus(url, status) {
14169
14180
  window.__orbitalVerification.assetStatus[url] = status;
14170
14181
  }
14171
14182
  }
14172
- var log4, MAX_TRANSITIONS;
14183
+ var log5, MAX_TRANSITIONS;
14173
14184
  var init_verificationRegistry = __esm({
14174
14185
  "lib/verificationRegistry.ts"() {
14175
- log4 = createLogger("almadar:bridge");
14186
+ log5 = createLogger("almadar:bridge");
14176
14187
  MAX_TRANSITIONS = 500;
14177
14188
  exposeOnWindow();
14178
14189
  }
@@ -14523,6 +14534,8 @@ function IsometricCanvas({
14523
14534
  showMinimap = true,
14524
14535
  enableCamera = true,
14525
14536
  unitScale = 1,
14537
+ spriteHeightRatio = 1.5,
14538
+ spriteMaxWidthRatio = 0.6,
14526
14539
  // Asset resolution
14527
14540
  getTerrainSprite,
14528
14541
  getFeatureSprite,
@@ -14913,8 +14926,8 @@ function IsometricCanvas({
14913
14926
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
14914
14927
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
14915
14928
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
14916
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
14917
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
14929
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
14930
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
14918
14931
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
14919
14932
  let drawH = unitDrawH;
14920
14933
  let drawW = unitDrawH * ar;
@@ -15298,6 +15311,8 @@ function BattleBoard({
15298
15311
  assetManifest: propAssetManifest,
15299
15312
  scale = 0.45,
15300
15313
  unitScale = 1,
15314
+ spriteHeightRatio = 1.5,
15315
+ spriteMaxWidthRatio = 0.6,
15301
15316
  header,
15302
15317
  sidebar,
15303
15318
  actions,
@@ -15588,7 +15603,9 @@ function BattleBoard({
15588
15603
  hasActiveEffects: hasActiveEffects2,
15589
15604
  effectSpriteUrls,
15590
15605
  resolveUnitFrame,
15591
- unitScale
15606
+ unitScale,
15607
+ spriteHeightRatio,
15608
+ spriteMaxWidthRatio
15592
15609
  }
15593
15610
  ),
15594
15611
  overlay && overlay(ctx)
@@ -16068,7 +16085,7 @@ function generateDiff(oldVal, newVal) {
16068
16085
  }
16069
16086
  return diff;
16070
16087
  }
16071
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log5, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
16088
+ var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
16072
16089
  var init_CodeBlock = __esm({
16073
16090
  "components/core/molecules/markdown/CodeBlock.tsx"() {
16074
16091
  init_cn();
@@ -16151,7 +16168,7 @@ var init_CodeBlock = __esm({
16151
16168
  "lolo-op-async": { color: ORB_COLORS.dark.async }
16152
16169
  };
16153
16170
  loloStyle = { ...dark, ...loloStyleOverrides };
16154
- log5 = createLogger("almadar:ui:markdown-code");
16171
+ log6 = createLogger("almadar:ui:markdown-code");
16155
16172
  CODE_LANGUAGES = [
16156
16173
  "text",
16157
16174
  "json",
@@ -16415,7 +16432,7 @@ var init_CodeBlock = __esm({
16415
16432
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
16416
16433
  setTimeout(() => setCopied(false), 2e3);
16417
16434
  } catch (err) {
16418
- log5.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
16435
+ log6.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
16419
16436
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
16420
16437
  }
16421
16438
  };
@@ -20296,14 +20313,14 @@ function useSafeEventBus2() {
20296
20313
  } };
20297
20314
  }
20298
20315
  }
20299
- var log6, lookStyles4, ButtonGroup;
20316
+ var log7, lookStyles4, ButtonGroup;
20300
20317
  var init_ButtonGroup = __esm({
20301
20318
  "components/core/molecules/ButtonGroup.tsx"() {
20302
20319
  "use client";
20303
20320
  init_cn();
20304
20321
  init_atoms2();
20305
20322
  init_useEventBus();
20306
- log6 = createLogger("almadar:ui:button-group");
20323
+ log7 = createLogger("almadar:ui:button-group");
20307
20324
  lookStyles4 = {
20308
20325
  "right-aligned-buttons": "",
20309
20326
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -20384,7 +20401,7 @@ var init_ButtonGroup = __esm({
20384
20401
  {
20385
20402
  variant: "ghost",
20386
20403
  onClick: () => {
20387
- log6.debug("Filter clicked", { field: filter.field });
20404
+ log7.debug("Filter clicked", { field: filter.field });
20388
20405
  },
20389
20406
  children: filter.label
20390
20407
  },
@@ -28046,9 +28063,9 @@ function debug(...args) {
28046
28063
  const [first, ...rest] = args;
28047
28064
  const message = typeof first === "string" ? first : "<debug>";
28048
28065
  if (rest.length === 0 && typeof first === "string") {
28049
- log7.debug(message);
28066
+ log8.debug(message);
28050
28067
  } else {
28051
- log7.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28068
+ log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28052
28069
  }
28053
28070
  }
28054
28071
  function debugGroup(label) {
@@ -28076,11 +28093,11 @@ function toLogMetaValue(v) {
28076
28093
  }
28077
28094
  return String(v);
28078
28095
  }
28079
- var NAMESPACE, log7;
28096
+ var NAMESPACE, log8;
28080
28097
  var init_debug = __esm({
28081
28098
  "lib/debug.ts"() {
28082
28099
  NAMESPACE = "almadar:ui:debug";
28083
- log7 = createLogger(NAMESPACE);
28100
+ log8 = createLogger(NAMESPACE);
28084
28101
  createLogger("almadar:ui:debug:input");
28085
28102
  createLogger("almadar:ui:debug:collision");
28086
28103
  createLogger("almadar:ui:debug:physics");
@@ -43962,11 +43979,11 @@ var init_Canvas3DErrorBoundary = __esm({
43962
43979
  "components/game/molecules/three/components/Canvas3DErrorBoundary.css"() {
43963
43980
  }
43964
43981
  });
43965
- var log8, Canvas3DErrorBoundary;
43982
+ var log9, Canvas3DErrorBoundary;
43966
43983
  var init_Canvas3DErrorBoundary2 = __esm({
43967
43984
  "components/game/molecules/three/components/Canvas3DErrorBoundary.tsx"() {
43968
43985
  init_Canvas3DErrorBoundary();
43969
- log8 = createLogger("almadar:ui:game:canvas3d:error-boundary");
43986
+ log9 = createLogger("almadar:ui:game:canvas3d:error-boundary");
43970
43987
  Canvas3DErrorBoundary = class extends Component {
43971
43988
  constructor(props) {
43972
43989
  super(props);
@@ -43994,8 +44011,8 @@ var init_Canvas3DErrorBoundary2 = __esm({
43994
44011
  componentDidCatch(error, errorInfo) {
43995
44012
  this.setState({ errorInfo });
43996
44013
  this.props.onError?.(error, errorInfo);
43997
- log8.error("Error caught", { error });
43998
- log8.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
44014
+ log9.error("Error caught", { error });
44015
+ log9.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
43999
44016
  }
44000
44017
  render() {
44001
44018
  if (this.state.hasError) {
@@ -44058,7 +44075,7 @@ function useGLTFModel(url, resourceBasePath) {
44058
44075
  setState({ model: null, isLoading: false, error: null });
44059
44076
  return;
44060
44077
  }
44061
- log9.debug("Loading", { url });
44078
+ log10.debug("Loading", { url });
44062
44079
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
44063
44080
  const assetRoot = resourceBasePath || detectAssetRoot2(url);
44064
44081
  const loader = new GLTFLoader$1();
@@ -44066,7 +44083,7 @@ function useGLTFModel(url, resourceBasePath) {
44066
44083
  loader.load(
44067
44084
  url,
44068
44085
  (gltf) => {
44069
- log9.debug("Loaded", { url });
44086
+ log10.debug("Loaded", { url });
44070
44087
  setState({
44071
44088
  model: gltf.scene,
44072
44089
  isLoading: false,
@@ -44075,7 +44092,7 @@ function useGLTFModel(url, resourceBasePath) {
44075
44092
  },
44076
44093
  void 0,
44077
44094
  (err) => {
44078
- log9.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
44095
+ log10.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
44079
44096
  setState({
44080
44097
  model: null,
44081
44098
  isLoading: false,
@@ -44191,11 +44208,11 @@ function ModelLoader({
44191
44208
  }
44192
44209
  );
44193
44210
  }
44194
- var log9;
44211
+ var log10;
44195
44212
  var init_ModelLoader = __esm({
44196
44213
  "components/game/molecules/three/components/ModelLoader.tsx"() {
44197
44214
  "use client";
44198
- log9 = createLogger("almadar:ui:game:model-loader");
44215
+ log10 = createLogger("almadar:ui:game:model-loader");
44199
44216
  }
44200
44217
  });
44201
44218
 
@@ -44321,6 +44338,8 @@ var init_GameCanvas3D2 = __esm({
44321
44338
  attackTargets = [],
44322
44339
  selectedTileIds = [],
44323
44340
  selectedUnitId = null,
44341
+ unitScale = 1,
44342
+ scale = 0.45,
44324
44343
  children
44325
44344
  }, ref) => {
44326
44345
  const containerRef = useRef(null);
@@ -44537,12 +44556,18 @@ var init_GameCanvas3D2 = __esm({
44537
44556
  },
44538
44557
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
44539
44558
  );
44559
+ const UNIT_BASE_MODEL_SCALE = 0.5;
44560
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
44561
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
44540
44562
  const DefaultUnitRenderer = useCallback(
44541
44563
  ({ unit, position }) => {
44542
44564
  const isSelected = selectedUnitId === unit.id;
44543
44565
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
44544
44566
  const hasAtlas = unitAtlasUrl(unit) !== null;
44545
44567
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
44568
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
44569
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
44570
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
44546
44571
  return /* @__PURE__ */ jsxs(
44547
44572
  "group",
44548
44573
  {
@@ -44560,7 +44585,8 @@ var init_GameCanvas3D2 = __esm({
44560
44585
  UnitSpriteBillboard,
44561
44586
  {
44562
44587
  sheetUrl: initialFrame.sheetUrl,
44563
- resolveFrame: () => resolveUnitFrame(unit.id)
44588
+ resolveFrame: () => resolveUnitFrame(unit.id),
44589
+ height: billboardHeight
44564
44590
  }
44565
44591
  ) })
44566
44592
  ) : unit.modelUrl ? (
@@ -44569,22 +44595,22 @@ var init_GameCanvas3D2 = __esm({
44569
44595
  ModelLoader,
44570
44596
  {
44571
44597
  url: unit.modelUrl,
44572
- scale: 0.5,
44598
+ scale: modelScale,
44573
44599
  fallbackGeometry: "box",
44574
44600
  castShadow: true
44575
44601
  }
44576
44602
  )
44577
44603
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
44578
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
44579
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
44604
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
44605
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
44580
44606
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44581
44607
  ] }),
44582
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
44583
- /* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
44608
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
44609
+ /* @__PURE__ */ jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
44584
44610
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44585
44611
  ] }),
44586
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
44587
- /* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
44612
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
44613
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
44588
44614
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44589
44615
  ] })
44590
44616
  ] }),
@@ -44617,7 +44643,7 @@ var init_GameCanvas3D2 = __esm({
44617
44643
  }
44618
44644
  );
44619
44645
  },
44620
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
44646
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
44621
44647
  );
44622
44648
  const DefaultFeatureRenderer = useCallback(
44623
44649
  ({
@@ -44760,33 +44786,35 @@ var init_GameCanvas3D2 = __esm({
44760
44786
  fadeStrength: 1
44761
44787
  }
44762
44788
  ),
44763
- tiles.map((tile, index) => {
44764
- const position = gridToWorld(
44765
- tile.x,
44766
- tile.z ?? tile.y ?? 0,
44767
- tile.elevation ?? 0
44768
- );
44769
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
44770
- return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44771
- }),
44772
- features.map((feature, index) => {
44773
- const position = gridToWorld(
44774
- feature.x,
44775
- feature.z ?? feature.y ?? 0,
44776
- (feature.elevation ?? 0) + 0.5
44777
- );
44778
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44779
- return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44780
- }),
44781
- units.map((unit) => {
44782
- const position = gridToWorld(
44783
- unit.x ?? 0,
44784
- unit.z ?? unit.y ?? 0,
44785
- (unit.elevation ?? 0) + 0.5
44786
- );
44787
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44788
- return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
44789
- }),
44789
+ /* @__PURE__ */ jsxs("group", { scale, children: [
44790
+ tiles.map((tile, index) => {
44791
+ const position = gridToWorld(
44792
+ tile.x,
44793
+ tile.z ?? tile.y ?? 0,
44794
+ tile.elevation ?? 0
44795
+ );
44796
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
44797
+ return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44798
+ }),
44799
+ features.map((feature, index) => {
44800
+ const position = gridToWorld(
44801
+ feature.x,
44802
+ feature.z ?? feature.y ?? 0,
44803
+ (feature.elevation ?? 0) + 0.5
44804
+ );
44805
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44806
+ return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44807
+ }),
44808
+ units.map((unit) => {
44809
+ const position = gridToWorld(
44810
+ unit.x ?? 0,
44811
+ unit.z ?? unit.y ?? 0,
44812
+ (unit.elevation ?? 0) + 0.5
44813
+ );
44814
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44815
+ return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
44816
+ })
44817
+ ] }),
44790
44818
  children,
44791
44819
  /* @__PURE__ */ jsx(
44792
44820
  OrbitControls,
@@ -44829,6 +44857,8 @@ function GameBoard3D({
44829
44857
  features = [],
44830
44858
  cameraMode = "perspective",
44831
44859
  backgroundColor = "#2a1a1a",
44860
+ unitScale = 1,
44861
+ scale = 0.45,
44832
44862
  tileClickEvent,
44833
44863
  unitClickEvent,
44834
44864
  attackEvent,
@@ -44929,6 +44959,8 @@ function GameBoard3D({
44929
44959
  selectedUnitId,
44930
44960
  validMoves,
44931
44961
  attackTargets,
44962
+ unitScale,
44963
+ scale,
44932
44964
  className: "game-board-3d__canvas w-full min-h-[85vh]"
44933
44965
  }
44934
44966
  ),
@@ -46914,6 +46946,8 @@ function RoguelikeBoard({
46914
46946
  assetManifest: propAssetManifest,
46915
46947
  scale = 0.45,
46916
46948
  unitScale = 1,
46949
+ spriteHeightRatio = 1.5,
46950
+ spriteMaxWidthRatio = 0.6,
46917
46951
  moveEvent,
46918
46952
  playAgainEvent,
46919
46953
  gameEndEvent,
@@ -47061,7 +47095,9 @@ function RoguelikeBoard({
47061
47095
  scale,
47062
47096
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
47063
47097
  assetManifest: propAssetManifest,
47064
- unitScale
47098
+ unitScale,
47099
+ spriteHeightRatio,
47100
+ spriteMaxWidthRatio
47065
47101
  }
47066
47102
  ) }),
47067
47103
  !isGameOver && /* @__PURE__ */ jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -48500,7 +48536,7 @@ function getAllEvents(traits2) {
48500
48536
  function EventDispatcherTab({ traits: traits2, schema }) {
48501
48537
  const eventBus = useEventBus();
48502
48538
  const { t } = useTranslate();
48503
- const [log15, setLog] = React90.useState([]);
48539
+ const [log16, setLog] = React90.useState([]);
48504
48540
  const prevStatesRef = React90.useRef(/* @__PURE__ */ new Map());
48505
48541
  React90.useEffect(() => {
48506
48542
  for (const trait of traits2) {
@@ -48564,9 +48600,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
48564
48600
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
48565
48601
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
48566
48602
  ] }),
48567
- log15.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48603
+ log16.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48568
48604
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
48569
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log15.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
48605
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log16.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
48570
48606
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
48571
48607
  " ",
48572
48608
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -51433,6 +51469,9 @@ function TowerDefenseBoard({
51433
51469
  waveActive: propWaveActive,
51434
51470
  towerCost = 25,
51435
51471
  scale = 0.45,
51472
+ unitScale = 1,
51473
+ spriteHeightRatio = 1.5,
51474
+ spriteMaxWidthRatio = 0.6,
51436
51475
  placeTowerEvent,
51437
51476
  startWaveEvent,
51438
51477
  playAgainEvent,
@@ -51540,7 +51579,10 @@ function TowerDefenseBoard({
51540
51579
  onTileClick: handleTileClick,
51541
51580
  onTileHover: (x, y) => setHoveredTile({ x, y }),
51542
51581
  onTileLeave: () => setHoveredTile(null),
51543
- scale
51582
+ scale,
51583
+ unitScale,
51584
+ spriteHeightRatio,
51585
+ spriteMaxWidthRatio
51544
51586
  }
51545
51587
  ),
51546
51588
  hoveredTile && canPlaceTower && validMoves.some((m) => m.x === hoveredTile.x && m.y === hoveredTile.y) && /* @__PURE__ */ 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__ */ jsx(Typography, { variant: "small", children: t("td.placeTower") ?? `Place tower (${towerCost} gold)` }) })
@@ -51876,6 +51918,8 @@ function WorldMapBoard({
51876
51918
  isLoading,
51877
51919
  scale = 0.4,
51878
51920
  unitScale = 2.5,
51921
+ spriteHeightRatio = 1.5,
51922
+ spriteMaxWidthRatio = 0.6,
51879
51923
  allowMoveAllHeroes = false,
51880
51924
  isInRange = defaultIsInRange,
51881
51925
  heroSelectEvent,
@@ -52113,6 +52157,8 @@ function WorldMapBoard({
52113
52157
  effectSpriteUrls,
52114
52158
  resolveUnitFrame,
52115
52159
  unitScale,
52160
+ spriteHeightRatio,
52161
+ spriteMaxWidthRatio,
52116
52162
  diamondTopY,
52117
52163
  enableCamera
52118
52164
  }
@@ -53431,7 +53477,7 @@ function isPatternConfig(value) {
53431
53477
  if (value instanceof Date) return false;
53432
53478
  if (typeof value === "function") return false;
53433
53479
  const record = value;
53434
- return "type" in record && typeof record.type === "string";
53480
+ return "type" in record && typeof record.type === "string" && isKnownPattern(record.type);
53435
53481
  }
53436
53482
  function isPlainConfigObject(value) {
53437
53483
  if (React90__default.isValidElement(value)) return false;
@@ -57343,7 +57389,7 @@ function convertObjectProps(props) {
57343
57389
  function convertFnFormLambdasInProps(props) {
57344
57390
  return convertObjectProps(props);
57345
57391
  }
57346
- var log10 = createLogger("almadar:ui:effects:client-handlers");
57392
+ var log11 = createLogger("almadar:ui:effects:client-handlers");
57347
57393
  function createClientEffectHandlers(options) {
57348
57394
  const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
57349
57395
  return {
@@ -57352,11 +57398,11 @@ function createClientEffectHandlers(options) {
57352
57398
  eventBus.emit(prefixedEvent, payload);
57353
57399
  },
57354
57400
  persist: async () => {
57355
- log10.warn("persist is server-side only, ignored on client");
57401
+ log11.warn("persist is server-side only, ignored on client");
57356
57402
  },
57357
57403
  set: (_entityId, field, value) => {
57358
57404
  if (!liveEntity) {
57359
- log10.warn("set is server-side only, ignored on client (no live entity)");
57405
+ log11.warn("set is server-side only, ignored on client (no live entity)");
57360
57406
  return;
57361
57407
  }
57362
57408
  liveEntity[field] = value;
@@ -57388,10 +57434,10 @@ function createClientEffectHandlers(options) {
57388
57434
  slotSetter.addPattern(slot, pattern, props);
57389
57435
  },
57390
57436
  navigate: navigate ?? ((path) => {
57391
- log10.warn("No navigate handler, ignoring", { path });
57437
+ log11.warn("No navigate handler, ignoring", { path });
57392
57438
  }),
57393
57439
  notify: notify ?? ((msg, type) => {
57394
- log10.debug("notify", { type, message: msg });
57440
+ log11.debug("notify", { type, message: msg });
57395
57441
  })
57396
57442
  };
57397
57443
  }
@@ -57623,7 +57669,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57623
57669
  };
57624
57670
  }, [traitBindings]);
57625
57671
  const executeTransitionEffects = useCallback(async (params) => {
57626
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log15 } = params;
57672
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log16 } = params;
57627
57673
  const traitName = binding.trait.name;
57628
57674
  const linkedEntity = binding.linkedEntity || "";
57629
57675
  const entityId = payload?.entityId;
@@ -57711,7 +57757,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57711
57757
  ...handlers,
57712
57758
  set: async (targetId, field, value) => {
57713
57759
  if (baseSet) await baseSet(targetId, field, value);
57714
- log15.debug("set:write", {
57760
+ log16.debug("set:write", {
57715
57761
  traitName,
57716
57762
  field,
57717
57763
  value: JSON.stringify(value),
@@ -57751,7 +57797,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57751
57797
  const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
57752
57798
  try {
57753
57799
  await executor.executeAll(effects);
57754
- log15.debug("effects:executed", () => ({
57800
+ log16.debug("effects:executed", () => ({
57755
57801
  traitName,
57756
57802
  transition: `${previousState}->${newState}`,
57757
57803
  event: flushEvent,
@@ -57761,7 +57807,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57761
57807
  slotsTouched: Array.from(pendingSlots.keys()).join(",")
57762
57808
  }));
57763
57809
  for (const [slot, patterns] of pendingSlots) {
57764
- log15.debug("flush:slot", {
57810
+ log16.debug("flush:slot", {
57765
57811
  traitName,
57766
57812
  slot,
57767
57813
  patternCount: patterns.length,
@@ -57776,7 +57822,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57776
57822
  });
57777
57823
  }
57778
57824
  } catch (error) {
57779
- log15.error("effects:error", {
57825
+ log16.error("effects:error", {
57780
57826
  traitName,
57781
57827
  transition: `${previousState}->${newState}`,
57782
57828
  event: flushEvent,
@@ -57799,7 +57845,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57799
57845
  if (binding.config) {
57800
57846
  guardCtx.config = binding.config;
57801
57847
  }
57802
- const passed = interpolateValue(tick.guard, createContextFromBindings(guardCtx));
57848
+ const passed = evaluateGuard(
57849
+ tick.guard,
57850
+ createContextFromBindings(guardCtx)
57851
+ );
57803
57852
  if (!passed) {
57804
57853
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
57805
57854
  return;
@@ -58768,7 +58817,7 @@ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
58768
58817
  init_navigation();
58769
58818
  init_verificationRegistry();
58770
58819
  var PERF_NAMESPACE = "almadar:perf:canvas";
58771
- var log12 = createLogger(PERF_NAMESPACE);
58820
+ var log13 = createLogger(PERF_NAMESPACE);
58772
58821
  var RING_SIZE = 50;
58773
58822
  var ring = [];
58774
58823
  var writeIdx = 0;
@@ -58819,7 +58868,7 @@ function perfEnd(name, startToken, detail) {
58819
58868
  }
58820
58869
  }
58821
58870
  push({ name, durationMs, ts: endTs, detail });
58822
- log12.debug(name, () => ({ durationMs, ...detail ?? {} }));
58871
+ log13.debug(name, () => ({ durationMs, ...detail ?? {} }));
58823
58872
  }
58824
58873
  var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
58825
58874
  if (!isEnabled()) return;
@@ -58829,7 +58878,7 @@ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, com
58829
58878
  ts: commitTime,
58830
58879
  detail: { baseDuration }
58831
58880
  });
58832
- log12.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
58881
+ log13.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
58833
58882
  };
58834
58883
 
58835
58884
  // runtime/prepareSchemaForPreview.ts
@@ -59472,7 +59521,7 @@ init_useEventBus();
59472
59521
  // components/avl/molecules/useCanvasDnd.tsx
59473
59522
  init_useEventBus();
59474
59523
  init_useAlmadarDndCollision();
59475
- var log13 = createLogger("almadar:ui:canvas-dnd");
59524
+ var log14 = createLogger("almadar:ui:canvas-dnd");
59476
59525
  function useCanvasDraggable({
59477
59526
  id,
59478
59527
  payload,
@@ -59511,7 +59560,7 @@ function defaultEmit(eventBus, drop) {
59511
59560
  if (payload.kind === "pattern") {
59512
59561
  const patternType = payload.data.type;
59513
59562
  if (typeof patternType !== "string") {
59514
- log13.warn("default-emit:pattern:missing-type");
59563
+ log14.warn("default-emit:pattern:missing-type");
59515
59564
  return;
59516
59565
  }
59517
59566
  const out = { patternType, containerNode: target.containerNode };
@@ -59520,23 +59569,23 @@ function defaultEmit(eventBus, drop) {
59520
59569
  out.index = resolved.index;
59521
59570
  }
59522
59571
  eventBus.emit("UI:PATTERN_DROP", out);
59523
- log13.info("default-emit:pattern", { patternType, level: target.level });
59572
+ log14.info("default-emit:pattern", { patternType, level: target.level });
59524
59573
  return;
59525
59574
  }
59526
59575
  if (payload.kind === "behavior") {
59527
59576
  const behaviorName = payload.data.name;
59528
59577
  if (typeof behaviorName !== "string") {
59529
- log13.warn("default-emit:behavior:missing-name");
59578
+ log14.warn("default-emit:behavior:missing-name");
59530
59579
  return;
59531
59580
  }
59532
59581
  eventBus.emit("UI:BEHAVIOR_DROP", {
59533
59582
  behaviorName,
59534
59583
  containerNode: target.containerNode
59535
59584
  });
59536
- log13.info("default-emit:behavior", { behaviorName, level: target.level });
59585
+ log14.info("default-emit:behavior", { behaviorName, level: target.level });
59537
59586
  return;
59538
59587
  }
59539
- log13.debug("default-emit:unhandled-kind", { kind: payload.kind });
59588
+ log14.debug("default-emit:unhandled-kind", { kind: payload.kind });
59540
59589
  }
59541
59590
  function CanvasDndProvider({
59542
59591
  children,
@@ -59552,9 +59601,9 @@ function CanvasDndProvider({
59552
59601
  if (payload) {
59553
59602
  setActivePayload(payload);
59554
59603
  eventBus.emit("UI:DRAG_START", { kind: payload.kind, data: payload.data });
59555
- log13.info("dragStart", { id: e.active.id, kind: payload.kind });
59604
+ log14.info("dragStart", { id: e.active.id, kind: payload.kind });
59556
59605
  } else {
59557
- log13.warn("dragStart:missing-payload", { id: e.active.id });
59606
+ log14.warn("dragStart:missing-payload", { id: e.active.id });
59558
59607
  }
59559
59608
  }, [eventBus]);
59560
59609
  const handleDragEnd = React90__default.useCallback((e) => {
@@ -59564,7 +59613,7 @@ function CanvasDndProvider({
59564
59613
  const overData = e.over?.data.current;
59565
59614
  const target = overData?.target;
59566
59615
  const accepts = overData?.accepts;
59567
- log13.info("dragEnd", {
59616
+ log14.info("dragEnd", {
59568
59617
  activeId: e.active.id,
59569
59618
  overId: e.over?.id,
59570
59619
  hasPayload: !!payload,
@@ -59576,7 +59625,7 @@ function CanvasDndProvider({
59576
59625
  }
59577
59626
  if (!payload || !target) return;
59578
59627
  if (accepts && !accepts.includes(payload.kind)) {
59579
- log13.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
59628
+ log14.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
59580
59629
  return;
59581
59630
  }
59582
59631
  const activator = e.activatorEvent;
@@ -59588,7 +59637,7 @@ function CanvasDndProvider({
59588
59637
  }, [eventBus, onDrop]);
59589
59638
  const handleDragCancel = React90__default.useCallback(() => {
59590
59639
  setActivePayload(null);
59591
- log13.info("dragCancel");
59640
+ log14.info("dragCancel");
59592
59641
  }, []);
59593
59642
  return /* @__PURE__ */ jsxs(
59594
59643
  DndContext,
@@ -61403,7 +61452,7 @@ init_AvlTransitionLane();
61403
61452
  init_AvlSwimLane();
61404
61453
  init_types();
61405
61454
  init_avl_elk_layout();
61406
- var log14 = createLogger("almadar:ui:avl:trait-scene");
61455
+ var log15 = createLogger("almadar:ui:avl:trait-scene");
61407
61456
  var SWIM_GUTTER2 = 120;
61408
61457
  var CENTER_W2 = 360;
61409
61458
  var AvlTraitScene = ({
@@ -61416,7 +61465,7 @@ var AvlTraitScene = ({
61416
61465
  const dataKey = useMemo(() => JSON.stringify(data), [data]);
61417
61466
  useEffect(() => {
61418
61467
  computeTraitLayout(data).then(setLayout).catch((error) => {
61419
- log14.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61468
+ log15.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61420
61469
  });
61421
61470
  }, [dataKey]);
61422
61471
  if (!layout) {