@almadar/ui 5.60.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");
@@ -38005,6 +37994,7 @@ var init_GraphCanvas = __esm({
38005
37994
  draggable = true,
38006
37995
  actions,
38007
37996
  onNodeClick,
37997
+ onNodeDoubleClick,
38008
37998
  nodeClickEvent,
38009
37999
  selectedNodeId,
38010
38000
  repulsion = 800,
@@ -38024,6 +38014,19 @@ var init_GraphCanvas = __esm({
38024
38014
  const [hoveredNode, setHoveredNode] = React82.useState(null);
38025
38015
  const nodesRef = React82.useRef([]);
38026
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
+ }, []);
38027
38030
  const interactionRef = React82.useRef({
38028
38031
  mode: "none",
38029
38032
  dragNodeId: null,
@@ -38036,10 +38039,8 @@ var init_GraphCanvas = __esm({
38036
38039
  const canvas = canvasRef.current;
38037
38040
  if (!canvas) return null;
38038
38041
  const rect = canvas.getBoundingClientRect();
38039
- const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;
38040
- const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;
38041
- const screenX = (e.clientX - rect.left) * scaleX;
38042
- const screenY = (e.clientY - rect.top) * scaleY;
38042
+ const screenX = e.clientX - rect.left;
38043
+ const screenY = e.clientY - rect.top;
38043
38044
  return {
38044
38045
  screenX,
38045
38046
  screenY,
@@ -38079,8 +38080,8 @@ var init_GraphCanvas = __esm({
38079
38080
  React82.useEffect(() => {
38080
38081
  const canvas = canvasRef.current;
38081
38082
  if (!canvas || propNodes.length === 0) return;
38082
- const w = canvas.width;
38083
- const h = canvas.height;
38083
+ const w = logicalW;
38084
+ const h = height;
38084
38085
  const simNodes = propNodes.map((n, idx) => {
38085
38086
  let x = n.x ?? 0;
38086
38087
  let y = n.y ?? 0;
@@ -38170,29 +38171,41 @@ var init_GraphCanvas = __esm({
38170
38171
  return () => {
38171
38172
  cancelAnimationFrame(animRef.current);
38172
38173
  };
38173
- }, [propNodes, propEdges, layout, repulsion, linkDistance]);
38174
+ }, [propNodes, propEdges, layout, repulsion, linkDistance, logicalW, height]);
38174
38175
  React82.useEffect(() => {
38175
38176
  const canvas = canvasRef.current;
38176
38177
  if (!canvas) return;
38177
38178
  const ctx = canvas.getContext("2d");
38178
38179
  if (!ctx) return;
38179
- const w = canvas.width;
38180
- const h = canvas.height;
38180
+ const w = logicalW;
38181
+ const h = height;
38181
38182
  const nodes = nodesRef.current;
38182
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);
38183
38186
  ctx.clearRect(0, 0, w, h);
38184
38187
  ctx.save();
38185
38188
  ctx.translate(offset.x, offset.y);
38186
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
+ }
38187
38198
  for (const edge of propEdges) {
38188
38199
  const source = nodes.find((n) => n.id === edge.source);
38189
38200
  const target = nodes.find((n) => n.id === edge.target);
38190
38201
  if (!source || !target) continue;
38202
+ const incident = !!hoveredNode && (edge.source === hoveredNode || edge.target === hoveredNode);
38203
+ ctx.globalAlpha = hoveredNode ? incident ? 1 : 0.12 : 1;
38191
38204
  ctx.beginPath();
38192
38205
  ctx.moveTo(source.x, source.y);
38193
38206
  ctx.lineTo(target.x, target.y);
38194
- ctx.strokeStyle = edge.color || "#88888866";
38195
- 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;
38196
38209
  ctx.stroke();
38197
38210
  if (edge.label && showLabels) {
38198
38211
  const mx = (source.x + target.x) / 2;
@@ -38203,11 +38216,13 @@ var init_GraphCanvas = __esm({
38203
38216
  ctx.fillText(edge.label, mx, my - 4);
38204
38217
  }
38205
38218
  }
38219
+ ctx.globalAlpha = 1;
38206
38220
  for (const node of nodes) {
38207
38221
  const size = node.size || 8;
38208
38222
  const color = resolveColor2(node.color || getGroupColor(node.group, groups), canvas);
38209
38223
  const isHovered = hoveredNode === node.id;
38210
38224
  const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
38225
+ ctx.globalAlpha = hoveredNode && !neighbors.has(node.id) ? 0.2 : 1;
38211
38226
  const radius = isSelected ? size + 4 : isHovered ? size + 2 : size;
38212
38227
  ctx.beginPath();
38213
38228
  ctx.arc(node.x, node.y, radius, 0, Math.PI * 2);
@@ -38327,6 +38342,15 @@ var init_GraphCanvas = __esm({
38327
38342
  interactionRef.current.dragNodeId = null;
38328
38343
  setHoveredNode(null);
38329
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
+ );
38330
38354
  if (isLoading) {
38331
38355
  return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
38332
38356
  }
@@ -38384,15 +38408,16 @@ var init_GraphCanvas = __esm({
38384
38408
  "canvas",
38385
38409
  {
38386
38410
  ref: canvasRef,
38387
- width: 800,
38388
- height,
38411
+ width: Math.round(logicalW * (typeof window !== "undefined" && window.devicePixelRatio || 1)),
38412
+ height: Math.round(height * (typeof window !== "undefined" && window.devicePixelRatio || 1)),
38389
38413
  className: "w-full cursor-grab active:cursor-grabbing",
38390
38414
  style: { height },
38391
38415
  onWheel: handleWheel,
38392
38416
  onMouseDown: handleMouseDown,
38393
38417
  onMouseMove: handleMouseMove,
38394
38418
  onMouseUp: handleMouseUp,
38395
- onMouseLeave: handleMouseLeave
38419
+ onMouseLeave: handleMouseLeave,
38420
+ onDoubleClick: handleDoubleClick
38396
38421
  }
38397
38422
  ) }),
38398
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: [
@@ -41986,11 +42011,11 @@ var init_Canvas3DErrorBoundary = __esm({
41986
42011
  "components/game/molecules/three/components/Canvas3DErrorBoundary.css"() {
41987
42012
  }
41988
42013
  });
41989
- var log11, Canvas3DErrorBoundary;
42014
+ var log10, Canvas3DErrorBoundary;
41990
42015
  var init_Canvas3DErrorBoundary2 = __esm({
41991
42016
  "components/game/molecules/three/components/Canvas3DErrorBoundary.tsx"() {
41992
42017
  init_Canvas3DErrorBoundary();
41993
- log11 = logger.createLogger("almadar:ui:game:canvas3d:error-boundary");
42018
+ log10 = logger.createLogger("almadar:ui:game:canvas3d:error-boundary");
41994
42019
  Canvas3DErrorBoundary = class extends React82.Component {
41995
42020
  constructor(props) {
41996
42021
  super(props);
@@ -42018,8 +42043,8 @@ var init_Canvas3DErrorBoundary2 = __esm({
42018
42043
  componentDidCatch(error, errorInfo) {
42019
42044
  this.setState({ errorInfo });
42020
42045
  this.props.onError?.(error, errorInfo);
42021
- log11.error("Error caught", { error });
42022
- log11.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
42046
+ log10.error("Error caught", { error });
42047
+ log10.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
42023
42048
  }
42024
42049
  render() {
42025
42050
  if (this.state.hasError) {
@@ -42082,7 +42107,7 @@ function useGLTFModel(url, resourceBasePath) {
42082
42107
  setState({ model: null, isLoading: false, error: null });
42083
42108
  return;
42084
42109
  }
42085
- log12.debug("Loading", { url });
42110
+ log11.debug("Loading", { url });
42086
42111
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
42087
42112
  const assetRoot = resourceBasePath || detectAssetRoot2(url);
42088
42113
  const loader = new GLTFLoader.GLTFLoader();
@@ -42090,7 +42115,7 @@ function useGLTFModel(url, resourceBasePath) {
42090
42115
  loader.load(
42091
42116
  url,
42092
42117
  (gltf) => {
42093
- log12.debug("Loaded", { url });
42118
+ log11.debug("Loaded", { url });
42094
42119
  setState({
42095
42120
  model: gltf.scene,
42096
42121
  isLoading: false,
@@ -42099,7 +42124,7 @@ function useGLTFModel(url, resourceBasePath) {
42099
42124
  },
42100
42125
  void 0,
42101
42126
  (err) => {
42102
- log12.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
42127
+ log11.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
42103
42128
  setState({
42104
42129
  model: null,
42105
42130
  isLoading: false,
@@ -42215,11 +42240,11 @@ function ModelLoader({
42215
42240
  }
42216
42241
  );
42217
42242
  }
42218
- var log12;
42243
+ var log11;
42219
42244
  var init_ModelLoader = __esm({
42220
42245
  "components/game/molecules/three/components/ModelLoader.tsx"() {
42221
42246
  "use client";
42222
- log12 = logger.createLogger("almadar:ui:game:model-loader");
42247
+ log11 = logger.createLogger("almadar:ui:game:model-loader");
42223
42248
  }
42224
42249
  });
42225
42250
 
@@ -42480,24 +42505,28 @@ var init_GameCanvas3D2 = __esm({
42480
42505
  const cameraConfig = React82.useMemo(() => {
42481
42506
  const size = Math.max(
42482
42507
  gridBounds.maxX - gridBounds.minX,
42483
- gridBounds.maxZ - gridBounds.minZ
42508
+ gridBounds.maxZ - gridBounds.minZ,
42509
+ 4
42510
+ // minimum framing distance so a tiny board isn't zoomed in
42484
42511
  );
42485
- 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;
42486
42515
  switch (cameraMode) {
42487
42516
  case "isometric":
42488
42517
  return {
42489
- position: [distance, distance * 0.8, distance],
42518
+ position: [cx + d, d * 0.8, cz + d],
42490
42519
  fov: 45
42491
42520
  };
42492
42521
  case "top-down":
42493
42522
  return {
42494
- position: [0, distance * 2, 0],
42523
+ position: [cx, d * 2, cz],
42495
42524
  fov: 45
42496
42525
  };
42497
42526
  case "perspective":
42498
42527
  default:
42499
42528
  return {
42500
- position: [distance, distance, distance],
42529
+ position: [cx + d, d, cz + d],
42501
42530
  fov: 45
42502
42531
  };
42503
42532
  }
@@ -42736,7 +42765,8 @@ var init_GameCanvas3D2 = __esm({
42736
42765
  "div",
42737
42766
  {
42738
42767
  ref: containerRef,
42739
- 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" },
42740
42770
  "data-orientation": orientation,
42741
42771
  "data-camera-mode": cameraMode,
42742
42772
  "data-overlay": overlay,
@@ -42751,7 +42781,7 @@ var init_GameCanvas3D2 = __esm({
42751
42781
  near: 0.1,
42752
42782
  far: 1e3
42753
42783
  },
42754
- style: { background: backgroundColor },
42784
+ style: { background: backgroundColor, height: "85vh", width: "100%" },
42755
42785
  onClick: (e) => {
42756
42786
  if (e.target === e.currentTarget) {
42757
42787
  eventHandlers.handleCanvasClick(e);
@@ -46534,7 +46564,7 @@ function getAllEvents(traits2) {
46534
46564
  function EventDispatcherTab({ traits: traits2, schema }) {
46535
46565
  const eventBus = useEventBus();
46536
46566
  const { t } = hooks.useTranslate();
46537
- const [log14, setLog] = React82__namespace.useState([]);
46567
+ const [log13, setLog] = React82__namespace.useState([]);
46538
46568
  const prevStatesRef = React82__namespace.useRef(/* @__PURE__ */ new Map());
46539
46569
  React82__namespace.useEffect(() => {
46540
46570
  for (const trait of traits2) {
@@ -46598,9 +46628,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
46598
46628
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
46599
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)) })
46600
46630
  ] }),
46601
- log14.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
46631
+ log13.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
46602
46632
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
46603
- /* @__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: [
46604
46634
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
46605
46635
  " ",
46606
46636
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -51615,7 +51645,7 @@ function isPatternConfig(value) {
51615
51645
  if (value instanceof Date) return false;
51616
51646
  if (typeof value === "function") return false;
51617
51647
  const record = value;
51618
- 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;
51619
51649
  }
51620
51650
  function isPlainConfigObject(value) {
51621
51651
  if (React82__namespace.default.isValidElement(value)) return false;
@@ -52209,7 +52239,7 @@ init_UISlotRenderer();
52209
52239
  // providers/VerificationProvider.tsx
52210
52240
  init_useEventBus();
52211
52241
  init_verificationRegistry();
52212
- var log13 = logger.createLogger("almadar:verify");
52242
+ var log12 = logger.createLogger("almadar:verify");
52213
52243
  var DISPATCH_SUFFIX = ":DISPATCH";
52214
52244
  var SUCCESS_SUFFIX = ":SUCCESS";
52215
52245
  var ERROR_SUFFIX = ":ERROR";
@@ -52256,7 +52286,7 @@ function VerificationProvider({
52256
52286
  const verificationProviderLifecycleListener = (evt) => {
52257
52287
  const parsed = parseLifecycleEvent(evt.type);
52258
52288
  if (!parsed) return;
52259
- 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 });
52260
52290
  const payload = evt.payload ?? {};
52261
52291
  if (parsed.kind === "dispatch") {
52262
52292
  const key = `${parsed.traitName}:${String(payload["event"] ?? "")}`;
@@ -52311,7 +52341,7 @@ function VerificationProvider({
52311
52341
  },
52312
52342
  timestamp: Date.now()
52313
52343
  });
52314
- 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 });
52315
52345
  } else if (parsed.kind === "error" && parsed.event) {
52316
52346
  const key = `${parsed.traitName}:${parsed.event}`;
52317
52347
  const pending = pendingRef.current.get(key);
@@ -52341,7 +52371,7 @@ function VerificationProvider({
52341
52371
  },
52342
52372
  timestamp: Date.now()
52343
52373
  });
52344
- 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 });
52345
52375
  }
52346
52376
  };
52347
52377
  Object.defineProperty(verificationProviderLifecycleListener, "name", {