@almadar/ui 5.59.0 → 5.61.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.
@@ -8426,16 +8426,6 @@ var init_Skeleton = __esm({
8426
8426
  Skeleton.displayName = "Skeleton";
8427
8427
  }
8428
8428
  });
8429
- function isKnownPattern(type) {
8430
- return type in componentMapping;
8431
- }
8432
- var componentMapping;
8433
- var init_pattern_resolver = __esm({
8434
- "renderer/pattern-resolver.ts"() {
8435
- logger.createLogger("almadar:ui:pattern-resolver");
8436
- componentMapping = {};
8437
- }
8438
- });
8439
8429
  function executeClientEffects(effects, config) {
8440
8430
  if (!effects || effects.length === 0) {
8441
8431
  return;
@@ -8444,7 +8434,7 @@ function executeClientEffects(effects, config) {
8444
8434
  try {
8445
8435
  executeEffect(effect, config);
8446
8436
  } catch (error) {
8447
- log4.error("Error executing effect", () => ({
8437
+ log3.error("Error executing effect", () => ({
8448
8438
  effect: JSON.stringify(effect),
8449
8439
  error: error instanceof Error ? error : String(error)
8450
8440
  }));
@@ -8476,7 +8466,7 @@ function executeEffect(effect, config) {
8476
8466
  break;
8477
8467
  }
8478
8468
  default:
8479
- log4.warn("Unknown effect type", { effectType: String(effectType) });
8469
+ log3.warn("Unknown effect type", { effectType: String(effectType) });
8480
8470
  }
8481
8471
  }
8482
8472
  function executeRenderUI(slot, patternConfig, config) {
@@ -8491,10 +8481,10 @@ function executeNotify(message, options, config) {
8491
8481
  function executeEmit(event, payload, config) {
8492
8482
  config.eventBus.emit(event, payload);
8493
8483
  }
8494
- var log4;
8484
+ var log3;
8495
8485
  var init_client_effect_executor = __esm({
8496
8486
  "renderer/client-effect-executor.ts"() {
8497
- log4 = logger.createLogger("almadar:ui:effects:client");
8487
+ log3 = logger.createLogger("almadar:ui:effects:client");
8498
8488
  }
8499
8489
  });
8500
8490
 
@@ -8655,12 +8645,12 @@ function useOfflineExecutor(options) {
8655
8645
  clearQueue
8656
8646
  };
8657
8647
  }
8658
- var log5, effectIdCounter, OfflineExecutor;
8648
+ var log4, effectIdCounter, OfflineExecutor;
8659
8649
  var init_offline_executor = __esm({
8660
8650
  "renderer/offline-executor.ts"() {
8661
8651
  "use client";
8662
8652
  init_client_effect_executor();
8663
- log5 = logger.createLogger("almadar:ui:effects:offline");
8653
+ log4 = logger.createLogger("almadar:ui:effects:offline");
8664
8654
  effectIdCounter = 0;
8665
8655
  OfflineExecutor = class {
8666
8656
  constructor(config) {
@@ -8714,7 +8704,7 @@ var init_offline_executor = __esm({
8714
8704
  this.state.syncQueue = JSON.parse(stored);
8715
8705
  }
8716
8706
  } catch (error) {
8717
- log5.warn("Failed to load sync queue", { error: error instanceof Error ? error : String(error) });
8707
+ log4.warn("Failed to load sync queue", { error: error instanceof Error ? error : String(error) });
8718
8708
  }
8719
8709
  }
8720
8710
  /**
@@ -8725,7 +8715,7 @@ var init_offline_executor = __esm({
8725
8715
  try {
8726
8716
  this.storage.setItem("orbital-offline-queue", JSON.stringify(this.state.syncQueue));
8727
8717
  } catch (error) {
8728
- log5.warn("Failed to save sync queue", { error: error instanceof Error ? error : String(error) });
8718
+ log4.warn("Failed to save sync queue", { error: error instanceof Error ? error : String(error) });
8729
8719
  }
8730
8720
  }
8731
8721
  /**
@@ -8795,7 +8785,7 @@ var init_offline_executor = __esm({
8795
8785
  this.queueForSync(type, { args, event, payload });
8796
8786
  break;
8797
8787
  default:
8798
- log5.warn("Unknown effect type", { type });
8788
+ log4.warn("Unknown effect type", { type });
8799
8789
  }
8800
8790
  }
8801
8791
  }
@@ -8900,7 +8890,6 @@ var init_offline_executor = __esm({
8900
8890
  // renderer/index.ts
8901
8891
  var init_renderer = __esm({
8902
8892
  "renderer/index.ts"() {
8903
- init_pattern_resolver();
8904
8893
  init_slot_definitions();
8905
8894
  }
8906
8895
  });
@@ -10604,7 +10593,7 @@ function recordTransition(trace) {
10604
10593
  ...trace,
10605
10594
  id: `t-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
10606
10595
  };
10607
- log6.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
10596
+ log5.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
10608
10597
  getState().transitions.push(entry);
10609
10598
  if (getState().transitions.length > MAX_TRANSITIONS) {
10610
10599
  getState().transitions.shift();
@@ -10673,7 +10662,7 @@ function getTraitSnapshots() {
10673
10662
  try {
10674
10663
  snapshots.push(getter());
10675
10664
  } catch (err) {
10676
- log6.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
10665
+ log5.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
10677
10666
  }
10678
10667
  }
10679
10668
  return snapshots;
@@ -10736,12 +10725,12 @@ function waitForTransition(event, timeoutMs = 1e4) {
10736
10725
  }
10737
10726
  function bindEventBus(eventBus) {
10738
10727
  if (typeof window === "undefined") return;
10739
- log6.info("bindEventBus", { hasOnAny: !!eventBus.onAny });
10728
+ log5.info("bindEventBus", { hasOnAny: !!eventBus.onAny });
10740
10729
  exposeOnWindow();
10741
10730
  if (window.__orbitalVerification) {
10742
10731
  window.__orbitalVerification.sendEvent = (event, payload, traitScope) => {
10743
10732
  const prefixed = event.startsWith("UI:") ? event : traitScope ? `UI:${traitScope}.${event}` : `UI:${event}`;
10744
- log6.debug("sendEvent", { event: prefixed, traitScope, payloadKeys: payload ? Object.keys(payload) : [] });
10733
+ log5.debug("sendEvent", { event: prefixed, traitScope, payloadKeys: payload ? Object.keys(payload) : [] });
10745
10734
  eventBus.emit(prefixed, payload);
10746
10735
  };
10747
10736
  const eventLog = [];
@@ -10790,10 +10779,10 @@ function updateAssetStatus(url, status) {
10790
10779
  window.__orbitalVerification.assetStatus[url] = status;
10791
10780
  }
10792
10781
  }
10793
- var log6, MAX_TRANSITIONS;
10782
+ var log5, MAX_TRANSITIONS;
10794
10783
  var init_verificationRegistry = __esm({
10795
10784
  "lib/verificationRegistry.ts"() {
10796
- log6 = logger.createLogger("almadar:bridge");
10785
+ log5 = logger.createLogger("almadar:bridge");
10797
10786
  MAX_TRANSITIONS = 500;
10798
10787
  exposeOnWindow();
10799
10788
  }
@@ -13122,7 +13111,7 @@ var init_avl_elk_layout = __esm({
13122
13111
  elk = new ELK__default.default();
13123
13112
  }
13124
13113
  });
13125
- var log7, SWIM_GUTTER, CENTER_W, BehaviorView;
13114
+ var log6, SWIM_GUTTER, CENTER_W, BehaviorView;
13126
13115
  var init_BehaviorView = __esm({
13127
13116
  "components/avl/molecules/BehaviorView.tsx"() {
13128
13117
  "use client";
@@ -13131,7 +13120,7 @@ var init_BehaviorView = __esm({
13131
13120
  init_AvlSwimLane();
13132
13121
  init_types();
13133
13122
  init_avl_elk_layout();
13134
- log7 = logger.createLogger("almadar:ui:avl:behavior-view");
13123
+ log6 = logger.createLogger("almadar:ui:avl:behavior-view");
13135
13124
  SWIM_GUTTER = 120;
13136
13125
  CENTER_W = 360;
13137
13126
  BehaviorView = ({ data }) => {
@@ -13142,7 +13131,7 @@ var init_BehaviorView = __esm({
13142
13131
  const dataKey = React82.useMemo(() => JSON.stringify(traitData), [traitData]);
13143
13132
  React82.useEffect(() => {
13144
13133
  if (!traitData) return;
13145
- computeTraitLayout(traitData).then(setLayout).catch((err) => log7.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
13134
+ computeTraitLayout(traitData).then(setLayout).catch((err) => log6.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
13146
13135
  }, [dataKey]);
13147
13136
  if (!traitData) {
13148
13137
  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") });
@@ -13553,7 +13542,7 @@ function generateDiff(oldVal, newVal) {
13553
13542
  }
13554
13543
  return diff;
13555
13544
  }
13556
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log8, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
13545
+ var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
13557
13546
  var init_CodeBlock = __esm({
13558
13547
  "components/core/molecules/markdown/CodeBlock.tsx"() {
13559
13548
  init_cn();
@@ -13636,7 +13625,7 @@ var init_CodeBlock = __esm({
13636
13625
  "lolo-op-async": { color: syntax.ORB_COLORS.dark.async }
13637
13626
  };
13638
13627
  loloStyle = { ...dark__default.default, ...loloStyleOverrides };
13639
- log8 = logger.createLogger("almadar:ui:markdown-code");
13628
+ log7 = logger.createLogger("almadar:ui:markdown-code");
13640
13629
  CODE_LANGUAGES = [
13641
13630
  "text",
13642
13631
  "json",
@@ -13900,7 +13889,7 @@ var init_CodeBlock = __esm({
13900
13889
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
13901
13890
  setTimeout(() => setCopied(false), 2e3);
13902
13891
  } catch (err) {
13903
- log8.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
13892
+ log7.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
13904
13893
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
13905
13894
  }
13906
13895
  };
@@ -17781,14 +17770,14 @@ function useSafeEventBus2() {
17781
17770
  } };
17782
17771
  }
17783
17772
  }
17784
- var log9, lookStyles4, ButtonGroup;
17773
+ var log8, lookStyles4, ButtonGroup;
17785
17774
  var init_ButtonGroup = __esm({
17786
17775
  "components/core/molecules/ButtonGroup.tsx"() {
17787
17776
  "use client";
17788
17777
  init_cn();
17789
17778
  init_atoms2();
17790
17779
  init_useEventBus();
17791
- log9 = logger.createLogger("almadar:ui:button-group");
17780
+ log8 = logger.createLogger("almadar:ui:button-group");
17792
17781
  lookStyles4 = {
17793
17782
  "right-aligned-buttons": "",
17794
17783
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -17869,7 +17858,7 @@ var init_ButtonGroup = __esm({
17869
17858
  {
17870
17859
  variant: "ghost",
17871
17860
  onClick: () => {
17872
- log9.debug("Filter clicked", { field: filter.field });
17861
+ log8.debug("Filter clicked", { field: filter.field });
17873
17862
  },
17874
17863
  children: filter.label
17875
17864
  },
@@ -25531,9 +25520,9 @@ function debug(...args) {
25531
25520
  const [first, ...rest] = args;
25532
25521
  const message = typeof first === "string" ? first : "<debug>";
25533
25522
  if (rest.length === 0 && typeof first === "string") {
25534
- log10.debug(message);
25523
+ log9.debug(message);
25535
25524
  } else {
25536
- log10.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
25525
+ log9.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
25537
25526
  }
25538
25527
  }
25539
25528
  function debugGroup(label) {
@@ -25561,11 +25550,11 @@ function toLogMetaValue(v) {
25561
25550
  }
25562
25551
  return String(v);
25563
25552
  }
25564
- var NAMESPACE, log10;
25553
+ var NAMESPACE, log9;
25565
25554
  var init_debug = __esm({
25566
25555
  "lib/debug.ts"() {
25567
25556
  NAMESPACE = "almadar:ui:debug";
25568
- log10 = logger.createLogger(NAMESPACE);
25557
+ log9 = logger.createLogger(NAMESPACE);
25569
25558
  logger.createLogger("almadar:ui:debug:input");
25570
25559
  logger.createLogger("almadar:ui:debug:collision");
25571
25560
  logger.createLogger("almadar:ui:debug:physics");
@@ -37970,6 +37959,12 @@ function getGroupColor(group, groups) {
37970
37959
  const idx = groups.indexOf(group);
37971
37960
  return GROUP_COLORS2[idx % GROUP_COLORS2.length];
37972
37961
  }
37962
+ function resolveColor2(color, el) {
37963
+ const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
37964
+ if (!m) return color;
37965
+ const resolved = getComputedStyle(el).getPropertyValue(m[1]).trim();
37966
+ return resolved || (m[2]?.trim() ?? "#888888");
37967
+ }
37973
37968
  var GROUP_COLORS2, GraphCanvas;
37974
37969
  var init_GraphCanvas = __esm({
37975
37970
  "components/core/molecules/GraphCanvas.tsx"() {
@@ -37999,6 +37994,7 @@ var init_GraphCanvas = __esm({
37999
37994
  draggable = true,
38000
37995
  actions,
38001
37996
  onNodeClick,
37997
+ onNodeDoubleClick,
38002
37998
  nodeClickEvent,
38003
37999
  selectedNodeId,
38004
38000
  repulsion = 800,
@@ -38018,6 +38014,19 @@ var init_GraphCanvas = __esm({
38018
38014
  const [hoveredNode, setHoveredNode] = React82.useState(null);
38019
38015
  const nodesRef = React82.useRef([]);
38020
38016
  const [, forceUpdate] = React82.useState(0);
38017
+ const [logicalW, setLogicalW] = React82.useState(800);
38018
+ React82.useEffect(() => {
38019
+ const canvas = canvasRef.current;
38020
+ if (!canvas || typeof ResizeObserver === "undefined") return;
38021
+ const measure = () => {
38022
+ const width = Math.round(canvas.clientWidth);
38023
+ if (width > 0) setLogicalW(width);
38024
+ };
38025
+ measure();
38026
+ const ro = new ResizeObserver(measure);
38027
+ ro.observe(canvas);
38028
+ return () => ro.disconnect();
38029
+ }, []);
38021
38030
  const interactionRef = React82.useRef({
38022
38031
  mode: "none",
38023
38032
  dragNodeId: null,
@@ -38071,8 +38080,8 @@ var init_GraphCanvas = __esm({
38071
38080
  React82.useEffect(() => {
38072
38081
  const canvas = canvasRef.current;
38073
38082
  if (!canvas || propNodes.length === 0) return;
38074
- const w = canvas.width;
38075
- const h = canvas.height;
38083
+ const w = logicalW;
38084
+ const h = height;
38076
38085
  const simNodes = propNodes.map((n, idx) => {
38077
38086
  let x = n.x ?? 0;
38078
38087
  let y = n.y ?? 0;
@@ -38162,28 +38171,41 @@ var init_GraphCanvas = __esm({
38162
38171
  return () => {
38163
38172
  cancelAnimationFrame(animRef.current);
38164
38173
  };
38165
- }, [propNodes, propEdges, layout, repulsion, linkDistance]);
38174
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, logicalW, height]);
38166
38175
  React82.useEffect(() => {
38167
38176
  const canvas = canvasRef.current;
38168
38177
  if (!canvas) return;
38169
38178
  const ctx = canvas.getContext("2d");
38170
38179
  if (!ctx) return;
38171
- const w = canvas.width;
38172
- const h = canvas.height;
38180
+ const w = logicalW;
38181
+ const h = height;
38173
38182
  const nodes = nodesRef.current;
38183
+ const accentColor = resolveColor2("var(--color-accent)", canvas);
38184
+ const dpr = typeof window !== "undefined" && window.devicePixelRatio || 1;
38185
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
38174
38186
  ctx.clearRect(0, 0, w, h);
38175
38187
  ctx.save();
38176
38188
  ctx.translate(offset.x, offset.y);
38177
38189
  ctx.scale(zoom, zoom);
38190
+ const neighbors = /* @__PURE__ */ new Set();
38191
+ if (hoveredNode) {
38192
+ neighbors.add(hoveredNode);
38193
+ for (const edge of propEdges) {
38194
+ if (edge.source === hoveredNode) neighbors.add(String(edge.target));
38195
+ else if (edge.target === hoveredNode) neighbors.add(String(edge.source));
38196
+ }
38197
+ }
38178
38198
  for (const edge of propEdges) {
38179
38199
  const source = nodes.find((n) => n.id === edge.source);
38180
38200
  const target = nodes.find((n) => n.id === edge.target);
38181
38201
  if (!source || !target) continue;
38202
+ const incident = !!hoveredNode && (edge.source === hoveredNode || edge.target === hoveredNode);
38203
+ ctx.globalAlpha = hoveredNode ? incident ? 1 : 0.12 : 1;
38182
38204
  ctx.beginPath();
38183
38205
  ctx.moveTo(source.x, source.y);
38184
38206
  ctx.lineTo(target.x, target.y);
38185
- ctx.strokeStyle = edge.color || "#88888866";
38186
- ctx.lineWidth = edge.weight ? Math.max(1, edge.weight) : 1;
38207
+ ctx.strokeStyle = incident ? accentColor : edge.color || "#88888866";
38208
+ ctx.lineWidth = incident ? 2 : edge.weight ? Math.max(1, edge.weight) : 1;
38187
38209
  ctx.stroke();
38188
38210
  if (edge.label && showLabels) {
38189
38211
  const mx = (source.x + target.x) / 2;
@@ -38194,18 +38216,20 @@ var init_GraphCanvas = __esm({
38194
38216
  ctx.fillText(edge.label, mx, my - 4);
38195
38217
  }
38196
38218
  }
38219
+ ctx.globalAlpha = 1;
38197
38220
  for (const node of nodes) {
38198
38221
  const size = node.size || 8;
38199
- const color = node.color || getGroupColor(node.group, groups);
38222
+ const color = resolveColor2(node.color || getGroupColor(node.group, groups), canvas);
38200
38223
  const isHovered = hoveredNode === node.id;
38201
38224
  const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
38225
+ ctx.globalAlpha = hoveredNode && !neighbors.has(node.id) ? 0.2 : 1;
38202
38226
  const radius = isSelected ? size + 4 : isHovered ? size + 2 : size;
38203
38227
  ctx.beginPath();
38204
38228
  ctx.arc(node.x, node.y, radius, 0, Math.PI * 2);
38205
38229
  ctx.fillStyle = color;
38206
38230
  ctx.fill();
38207
38231
  if (isSelected) {
38208
- ctx.strokeStyle = "var(--color-accent)";
38232
+ ctx.strokeStyle = accentColor;
38209
38233
  ctx.lineWidth = 3;
38210
38234
  } else {
38211
38235
  ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
@@ -38318,6 +38342,15 @@ var init_GraphCanvas = __esm({
38318
38342
  interactionRef.current.dragNodeId = null;
38319
38343
  setHoveredNode(null);
38320
38344
  }, []);
38345
+ const handleDoubleClick = React82.useCallback(
38346
+ (e) => {
38347
+ const coords = toCoords(e);
38348
+ if (!coords) return;
38349
+ const node = nodeAt(coords.graphX, coords.graphY);
38350
+ if (node) onNodeDoubleClick?.(node);
38351
+ },
38352
+ [toCoords, nodeAt, onNodeDoubleClick]
38353
+ );
38321
38354
  if (isLoading) {
38322
38355
  return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
38323
38356
  }
@@ -38375,15 +38408,16 @@ var init_GraphCanvas = __esm({
38375
38408
  "canvas",
38376
38409
  {
38377
38410
  ref: canvasRef,
38378
- width: 800,
38379
- height,
38411
+ width: Math.round(logicalW * (typeof window !== "undefined" && window.devicePixelRatio || 1)),
38412
+ height: Math.round(height * (typeof window !== "undefined" && window.devicePixelRatio || 1)),
38380
38413
  className: "w-full cursor-grab active:cursor-grabbing",
38381
38414
  style: { height },
38382
38415
  onWheel: handleWheel,
38383
38416
  onMouseDown: handleMouseDown,
38384
38417
  onMouseMove: handleMouseMove,
38385
38418
  onMouseUp: handleMouseUp,
38386
- onMouseLeave: handleMouseLeave
38419
+ onMouseLeave: handleMouseLeave,
38420
+ onDoubleClick: handleDoubleClick
38387
38421
  }
38388
38422
  ) }),
38389
38423
  groups.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", className: "px-4 py-2 border-t border-border", wrap: true, children: groups.map((group, idx) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
@@ -41977,11 +42011,11 @@ var init_Canvas3DErrorBoundary = __esm({
41977
42011
  "components/game/molecules/three/components/Canvas3DErrorBoundary.css"() {
41978
42012
  }
41979
42013
  });
41980
- var log11, Canvas3DErrorBoundary;
42014
+ var log10, Canvas3DErrorBoundary;
41981
42015
  var init_Canvas3DErrorBoundary2 = __esm({
41982
42016
  "components/game/molecules/three/components/Canvas3DErrorBoundary.tsx"() {
41983
42017
  init_Canvas3DErrorBoundary();
41984
- log11 = logger.createLogger("almadar:ui:game:canvas3d:error-boundary");
42018
+ log10 = logger.createLogger("almadar:ui:game:canvas3d:error-boundary");
41985
42019
  Canvas3DErrorBoundary = class extends React82.Component {
41986
42020
  constructor(props) {
41987
42021
  super(props);
@@ -42009,8 +42043,8 @@ var init_Canvas3DErrorBoundary2 = __esm({
42009
42043
  componentDidCatch(error, errorInfo) {
42010
42044
  this.setState({ errorInfo });
42011
42045
  this.props.onError?.(error, errorInfo);
42012
- log11.error("Error caught", { error });
42013
- log11.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
42046
+ log10.error("Error caught", { error });
42047
+ log10.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
42014
42048
  }
42015
42049
  render() {
42016
42050
  if (this.state.hasError) {
@@ -42073,7 +42107,7 @@ function useGLTFModel(url, resourceBasePath) {
42073
42107
  setState({ model: null, isLoading: false, error: null });
42074
42108
  return;
42075
42109
  }
42076
- log12.debug("Loading", { url });
42110
+ log11.debug("Loading", { url });
42077
42111
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
42078
42112
  const assetRoot = resourceBasePath || detectAssetRoot2(url);
42079
42113
  const loader = new GLTFLoader.GLTFLoader();
@@ -42081,7 +42115,7 @@ function useGLTFModel(url, resourceBasePath) {
42081
42115
  loader.load(
42082
42116
  url,
42083
42117
  (gltf) => {
42084
- log12.debug("Loaded", { url });
42118
+ log11.debug("Loaded", { url });
42085
42119
  setState({
42086
42120
  model: gltf.scene,
42087
42121
  isLoading: false,
@@ -42090,7 +42124,7 @@ function useGLTFModel(url, resourceBasePath) {
42090
42124
  },
42091
42125
  void 0,
42092
42126
  (err) => {
42093
- log12.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
42127
+ log11.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
42094
42128
  setState({
42095
42129
  model: null,
42096
42130
  isLoading: false,
@@ -42206,11 +42240,11 @@ function ModelLoader({
42206
42240
  }
42207
42241
  );
42208
42242
  }
42209
- var log12;
42243
+ var log11;
42210
42244
  var init_ModelLoader = __esm({
42211
42245
  "components/game/molecules/three/components/ModelLoader.tsx"() {
42212
42246
  "use client";
42213
- log12 = logger.createLogger("almadar:ui:game:model-loader");
42247
+ log11 = logger.createLogger("almadar:ui:game:model-loader");
42214
42248
  }
42215
42249
  });
42216
42250
 
@@ -42471,24 +42505,28 @@ var init_GameCanvas3D2 = __esm({
42471
42505
  const cameraConfig = React82.useMemo(() => {
42472
42506
  const size = Math.max(
42473
42507
  gridBounds.maxX - gridBounds.minX,
42474
- gridBounds.maxZ - gridBounds.minZ
42508
+ gridBounds.maxZ - gridBounds.minZ,
42509
+ 4
42510
+ // minimum framing distance so a tiny board isn't zoomed in
42475
42511
  );
42476
- const distance = size * 1.5;
42512
+ const cx = (gridBounds.minX + gridBounds.maxX) / 2;
42513
+ const cz = (gridBounds.minZ + gridBounds.maxZ) / 2;
42514
+ const d = size * 1.5;
42477
42515
  switch (cameraMode) {
42478
42516
  case "isometric":
42479
42517
  return {
42480
- position: [distance, distance * 0.8, distance],
42518
+ position: [cx + d, d * 0.8, cz + d],
42481
42519
  fov: 45
42482
42520
  };
42483
42521
  case "top-down":
42484
42522
  return {
42485
- position: [0, distance * 2, 0],
42523
+ position: [cx, d * 2, cz],
42486
42524
  fov: 45
42487
42525
  };
42488
42526
  case "perspective":
42489
42527
  default:
42490
42528
  return {
42491
- position: [distance, distance, distance],
42529
+ position: [cx + d, d, cz + d],
42492
42530
  fov: 45
42493
42531
  };
42494
42532
  }
@@ -42727,7 +42765,8 @@ var init_GameCanvas3D2 = __esm({
42727
42765
  "div",
42728
42766
  {
42729
42767
  ref: containerRef,
42730
- className: cn("game-canvas-3d relative w-full h-full min-h-[85vh] overflow-hidden", className),
42768
+ className: cn("game-canvas-3d relative w-full overflow-hidden", className),
42769
+ style: { minHeight: "85vh" },
42731
42770
  "data-orientation": orientation,
42732
42771
  "data-camera-mode": cameraMode,
42733
42772
  "data-overlay": overlay,
@@ -42742,7 +42781,7 @@ var init_GameCanvas3D2 = __esm({
42742
42781
  near: 0.1,
42743
42782
  far: 1e3
42744
42783
  },
42745
- style: { background: backgroundColor },
42784
+ style: { background: backgroundColor, height: "85vh", width: "100%" },
42746
42785
  onClick: (e) => {
42747
42786
  if (e.target === e.currentTarget) {
42748
42787
  eventHandlers.handleCanvasClick(e);
@@ -46525,7 +46564,7 @@ function getAllEvents(traits2) {
46525
46564
  function EventDispatcherTab({ traits: traits2, schema }) {
46526
46565
  const eventBus = useEventBus();
46527
46566
  const { t } = hooks.useTranslate();
46528
- const [log14, setLog] = React82__namespace.useState([]);
46567
+ const [log13, setLog] = React82__namespace.useState([]);
46529
46568
  const prevStatesRef = React82__namespace.useRef(/* @__PURE__ */ new Map());
46530
46569
  React82__namespace.useEffect(() => {
46531
46570
  for (const trait of traits2) {
@@ -46589,9 +46628,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
46589
46628
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
46590
46629
  /* @__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)) })
46591
46630
  ] }),
46592
- log14.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
46631
+ log13.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
46593
46632
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
46594
- /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log14.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
46633
+ /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log13.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
46595
46634
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
46596
46635
  " ",
46597
46636
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -51606,7 +51645,7 @@ function isPatternConfig(value) {
51606
51645
  if (value instanceof Date) return false;
51607
51646
  if (typeof value === "function") return false;
51608
51647
  const record = value;
51609
- return "type" in record && typeof record.type === "string" && isKnownPattern(record.type);
51648
+ return "type" in record && typeof record.type === "string" && patterns.getComponentForPattern(record.type) !== null;
51610
51649
  }
51611
51650
  function isPlainConfigObject(value) {
51612
51651
  if (React82__namespace.default.isValidElement(value)) return false;
@@ -52200,7 +52239,7 @@ init_UISlotRenderer();
52200
52239
  // providers/VerificationProvider.tsx
52201
52240
  init_useEventBus();
52202
52241
  init_verificationRegistry();
52203
- var log13 = logger.createLogger("almadar:verify");
52242
+ var log12 = logger.createLogger("almadar:verify");
52204
52243
  var DISPATCH_SUFFIX = ":DISPATCH";
52205
52244
  var SUCCESS_SUFFIX = ":SUCCESS";
52206
52245
  var ERROR_SUFFIX = ":ERROR";
@@ -52247,7 +52286,7 @@ function VerificationProvider({
52247
52286
  const verificationProviderLifecycleListener = (evt) => {
52248
52287
  const parsed = parseLifecycleEvent(evt.type);
52249
52288
  if (!parsed) return;
52250
- log13.debug("lifecycle:event", { kind: parsed.kind, traitName: parsed.traitName, event: parsed.event, type: evt.type });
52289
+ log12.debug("lifecycle:event", { kind: parsed.kind, traitName: parsed.traitName, event: parsed.event, type: evt.type });
52251
52290
  const payload = evt.payload ?? {};
52252
52291
  if (parsed.kind === "dispatch") {
52253
52292
  const key = `${parsed.traitName}:${String(payload["event"] ?? "")}`;
@@ -52302,7 +52341,7 @@ function VerificationProvider({
52302
52341
  },
52303
52342
  timestamp: Date.now()
52304
52343
  });
52305
- log13.debug("transition:success", { trait: parsed.traitName, event: parsed.event, from: pending?.from, to: newState, effectCount: effects.length });
52344
+ log12.debug("transition:success", { trait: parsed.traitName, event: parsed.event, from: pending?.from, to: newState, effectCount: effects.length });
52306
52345
  } else if (parsed.kind === "error" && parsed.event) {
52307
52346
  const key = `${parsed.traitName}:${parsed.event}`;
52308
52347
  const pending = pendingRef.current.get(key);
@@ -52332,7 +52371,7 @@ function VerificationProvider({
52332
52371
  },
52333
52372
  timestamp: Date.now()
52334
52373
  });
52335
- log13.warn("transition:error", { trait: parsed.traitName, event: parsed.event, from: fromState, error: errorMsg });
52374
+ log12.warn("transition:error", { trait: parsed.traitName, event: parsed.event, from: fromState, error: errorMsg });
52336
52375
  }
52337
52376
  };
52338
52377
  Object.defineProperty(verificationProviderLifecycleListener, "name", {