@almadar/ui 6.5.0 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{EntityBindingContext-0Evn_LcT.d.cts → EntityBindingContext-Bn3ePJQC.d.cts} +1 -1
  2. package/dist/{EntityBindingContext-0Evn_LcT.d.ts → EntityBindingContext-Bn3ePJQC.d.ts} +1 -1
  3. package/dist/{GameAudioProvider-B48iXwz3.d.ts → GameAudioProvider-Ctceau1s.d.ts} +6 -18
  4. package/dist/{GameAudioProvider-CQAdPreB.d.cts → GameAudioProvider-Dk_Y3LN3.d.cts} +6 -18
  5. package/dist/avl/index.cjs +1216 -206
  6. package/dist/avl/index.js +1217 -207
  7. package/dist/{avl-schema-parser-dvJKXn-o.d.ts → avl-schema-parser-DncJLEn9.d.ts} +18 -0
  8. package/dist/{avl-schema-parser-Bt4NzAam.d.cts → avl-schema-parser-FQ1474v8.d.cts} +18 -0
  9. package/dist/{cn-DJSBBm5W.d.cts → cn-CCjFspAo.d.cts} +25 -1
  10. package/dist/{cn-BbhJq_nr.d.ts → cn-sgpqpN0U.d.ts} +25 -1
  11. package/dist/components/index.cjs +1025 -235
  12. package/dist/components/index.d.cts +176 -23
  13. package/dist/components/index.d.ts +176 -23
  14. package/dist/components/index.js +1023 -236
  15. package/dist/context/index.cjs +10 -13
  16. package/dist/context/index.js +10 -13
  17. package/dist/hooks/index.cjs +63 -13
  18. package/dist/hooks/index.d.cts +2 -2
  19. package/dist/hooks/index.d.ts +2 -2
  20. package/dist/hooks/index.js +64 -15
  21. package/dist/lib/drawable/three/index.cjs +126 -13
  22. package/dist/lib/drawable/three/index.d.cts +2 -2
  23. package/dist/lib/drawable/three/index.d.ts +2 -2
  24. package/dist/lib/drawable/three/index.js +127 -14
  25. package/dist/lib/index.cjs +180 -0
  26. package/dist/lib/index.d.cts +1 -1
  27. package/dist/lib/index.d.ts +1 -1
  28. package/dist/lib/index.js +178 -1
  29. package/dist/locales/index.cjs +6 -3
  30. package/dist/locales/index.js +6 -3
  31. package/dist/providers/index.cjs +922 -188
  32. package/dist/providers/index.d.cts +2 -2
  33. package/dist/providers/index.d.ts +2 -2
  34. package/dist/providers/index.js +922 -188
  35. package/dist/runtime/index.cjs +1505 -182
  36. package/dist/runtime/index.d.cts +78 -6
  37. package/dist/runtime/index.d.ts +78 -6
  38. package/dist/runtime/index.js +1504 -184
  39. package/dist/{useEventBus-CQWyAWpK.d.ts → useKeyboardRouter-D84cNWmA.d.ts} +31 -1
  40. package/dist/{useEventBus-Ckr4wqW3.d.cts → useKeyboardRouter-DQEE_9mq.d.cts} +31 -1
  41. package/locales/ar.json +2 -1
  42. package/locales/en.json +2 -1
  43. package/locales/sl.json +2 -1
  44. package/package.json +4 -4
  45. package/themes/comic.css +437 -0
  46. package/themes/index.css +1 -0
@@ -9922,14 +9922,15 @@ function drawArrowHead(ctx, x1, y1, x2, y2, size) {
9922
9922
  ctx.closePath();
9923
9923
  ctx.fill();
9924
9924
  }
9925
- function drawShape(ctx, shape, width, height, allShapes) {
9925
+ function drawShape(ctx, shape, width, height, allShapes, fontFamily) {
9926
9926
  ctx.save();
9927
9927
  const opacity = shape.opacity ?? 1;
9928
9928
  ctx.globalAlpha = opacity;
9929
9929
  const stroke = resolveColor2(shape.color, ctx, "#333333");
9930
9930
  const fill = shape.fill ? resolveColor2(shape.fill, ctx, "#cccccc") : void 0;
9931
9931
  ctx.lineWidth = shape.lineWidth ?? 2;
9932
- if (shape.dash) ctx.setLineDash([...DASH_PATTERNS[shape.dash]]);
9932
+ const dashPattern = shape.dash ? DASH_PATTERNS[shape.dash] : void 0;
9933
+ if (dashPattern) ctx.setLineDash([...dashPattern]);
9933
9934
  switch (shape.type) {
9934
9935
  case "grid": {
9935
9936
  const step = shape.step ?? 40;
@@ -10051,7 +10052,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
10051
10052
  case "text": {
10052
10053
  if (shape.x == null || shape.y == null || !shape.text) break;
10053
10054
  ctx.fillStyle = stroke;
10054
- ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
10055
+ ctx.font = `${shape.fontSize ?? 14}px ${shape.fontFamily ?? fontFamily ?? themeBodyFont(ctx.canvas)}`;
10055
10056
  ctx.textAlign = shape.align ?? "left";
10056
10057
  ctx.textBaseline = "middle";
10057
10058
  ctx.fillText(shape.text, shape.x, shape.y);
@@ -10093,7 +10094,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
10093
10094
  }
10094
10095
  ctx.restore();
10095
10096
  }
10096
- function readoutShapes(readouts, width) {
10097
+ function readoutShapes(readouts, width, fontFamily) {
10097
10098
  const out = [];
10098
10099
  const chipH = 18;
10099
10100
  const gap = 6;
@@ -10117,13 +10118,14 @@ function readoutShapes(readouts, width) {
10117
10118
  text,
10118
10119
  color: "#ffffff",
10119
10120
  fontSize: 10,
10120
- align: "center"
10121
+ align: "center",
10122
+ fontFamily
10121
10123
  });
10122
10124
  rightEdge = chipX - gap;
10123
10125
  }
10124
10126
  return out;
10125
10127
  }
10126
- function traceShapes(panel, k, width, height) {
10128
+ function traceShapes(panel, k, width, height, fontFamily) {
10127
10129
  const w = panel.width ?? Math.round(width * 0.32);
10128
10130
  const h = panel.height ?? Math.round(height * 0.28);
10129
10131
  const x = panel.x ?? width - w - 8;
@@ -10177,14 +10179,14 @@ function traceShapes(panel, k, width, height) {
10177
10179
  out.push({ type: "circle", x: last.x, y: last.y, radius: 2, color, fill: color });
10178
10180
  }
10179
10181
  if (series.label) {
10180
- out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9 });
10182
+ out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9, fontFamily });
10181
10183
  }
10182
10184
  });
10183
10185
  if (panel.yLabel) {
10184
- out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right" });
10186
+ out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
10185
10187
  }
10186
10188
  if (panel.xLabel) {
10187
- out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right" });
10189
+ out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
10188
10190
  }
10189
10191
  return out;
10190
10192
  }
@@ -10207,13 +10209,14 @@ var init_LearningCanvas = __esm({
10207
10209
  init_useEventBus();
10208
10210
  init_webPainter2d();
10209
10211
  init_paintDispatch();
10210
- DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
10212
+ DASH_PATTERNS = { solid: [], dashed: [6, 4], dotted: [2, 3] };
10211
10213
  TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
10212
10214
  exports.LearningCanvas = ({
10213
10215
  className,
10214
10216
  width = 600,
10215
10217
  height = 400,
10216
10218
  backgroundColor,
10219
+ fontFamily,
10217
10220
  shapes = [],
10218
10221
  drawables,
10219
10222
  projector,
@@ -10249,10 +10252,10 @@ var init_LearningCanvas = __esm({
10249
10252
  }, [shapes]);
10250
10253
  const derivedShapes = React79.useMemo(() => {
10251
10254
  if (!traces?.length && !readouts?.length) return shapes;
10252
- const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height));
10253
- const readoutOut = readouts?.length ? readoutShapes(readouts, width) : [];
10255
+ const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height, fontFamily));
10256
+ const readoutOut = readouts?.length ? readoutShapes(readouts, width, fontFamily) : [];
10254
10257
  return [...shapes, ...traceOut, ...readoutOut];
10255
- }, [shapes, traces, readouts, width, height]);
10258
+ }, [shapes, traces, readouts, width, height, fontFamily]);
10256
10259
  const draw = React79.useCallback(() => {
10257
10260
  const _perfT = ui.perfStart("learningcanvas:paint");
10258
10261
  const canvas = canvasRef.current;
@@ -10271,15 +10274,15 @@ var init_LearningCanvas = __esm({
10271
10274
  ctx.fillRect(0, 0, width, height);
10272
10275
  }
10273
10276
  for (const shape of derivedShapes) {
10274
- if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes);
10277
+ if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
10275
10278
  }
10276
10279
  for (const shape of derivedShapes) {
10277
- if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
10280
+ if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
10278
10281
  }
10279
10282
  if (drawables?.length && projector) {
10280
10283
  const painter = createWebPainter(ctx, invalidateRef.current);
10281
10284
  const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
10282
- const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: themeBodyFont(canvas) };
10285
+ const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: fontFamily || themeBodyFont(canvas) };
10283
10286
  for (const node of drawables) {
10284
10287
  paintDrawable(painter, node, dctx);
10285
10288
  }
@@ -13396,6 +13399,250 @@ var init_EmptyState = __esm({
13396
13399
  exports.EmptyState.displayName = "EmptyState";
13397
13400
  }
13398
13401
  });
13402
+
13403
+ // lib/editorMotions.ts
13404
+ function clamp(value, min, max) {
13405
+ return Math.max(min, Math.min(max, value));
13406
+ }
13407
+ function computeLines(text) {
13408
+ const lines = [];
13409
+ let start = 0;
13410
+ for (let i = 0; i <= text.length; i++) {
13411
+ if (i === text.length || text[i] === "\n") {
13412
+ lines.push({ start, end: i });
13413
+ start = i + 1;
13414
+ }
13415
+ }
13416
+ return lines;
13417
+ }
13418
+ function lineIndexAt(lines, pos) {
13419
+ for (let i = 0; i < lines.length; i++) {
13420
+ if (pos <= lines[i].end) return i;
13421
+ }
13422
+ return lines.length - 1;
13423
+ }
13424
+ function findWords(text) {
13425
+ const words = [];
13426
+ const re = /\w+|\S+/g;
13427
+ let m;
13428
+ while ((m = re.exec(text)) !== null) {
13429
+ words.push({ start: m.index, end: m.index + m[0].length });
13430
+ }
13431
+ return words;
13432
+ }
13433
+ function nextWordStart(text, pos) {
13434
+ for (const w of findWords(text)) {
13435
+ if (w.start > pos) return w.start;
13436
+ }
13437
+ return text.length;
13438
+ }
13439
+ function prevWordStart(text, pos) {
13440
+ let result = 0;
13441
+ for (const w of findWords(text)) {
13442
+ if (w.start < pos) result = w.start;
13443
+ else break;
13444
+ }
13445
+ return result;
13446
+ }
13447
+ function nextWordEnd(text, pos) {
13448
+ for (const w of findWords(text)) {
13449
+ const lastChar = w.end - 1;
13450
+ if (lastChar > pos) return lastChar;
13451
+ }
13452
+ return text.length > 0 ? text.length - 1 : 0;
13453
+ }
13454
+ function firstNonBlank(text, line) {
13455
+ let i = line.start;
13456
+ while (i < line.end && (text[i] === " " || text[i] === " ")) i++;
13457
+ return i;
13458
+ }
13459
+ function nextParagraphBoundary(lines, fromLineIdx, textLength) {
13460
+ for (let i = fromLineIdx + 1; i < lines.length; i++) {
13461
+ if (lines[i].start === lines[i].end) return lines[i].start;
13462
+ }
13463
+ return textLength;
13464
+ }
13465
+ function prevParagraphBoundary(lines, fromLineIdx) {
13466
+ for (let i = fromLineIdx - 1; i >= 0; i--) {
13467
+ if (lines[i].start === lines[i].end) return lines[i].start;
13468
+ }
13469
+ return 0;
13470
+ }
13471
+ function applyMotion(text, caret, motion, count) {
13472
+ const n = Math.max(1, count);
13473
+ const lines = computeLines(text);
13474
+ const lineIdx = lineIndexAt(lines, caret);
13475
+ const line = lines[lineIdx];
13476
+ switch (motion) {
13477
+ case "left":
13478
+ return clamp(caret - n, line.start, line.end);
13479
+ case "right":
13480
+ return clamp(caret + n, line.start, line.end);
13481
+ case "up": {
13482
+ const col = caret - line.start;
13483
+ const targetIdx = clamp(lineIdx - n, 0, lines.length - 1);
13484
+ const target = lines[targetIdx];
13485
+ return clamp(target.start + col, target.start, target.end);
13486
+ }
13487
+ case "down": {
13488
+ const col = caret - line.start;
13489
+ const targetIdx = clamp(lineIdx + n, 0, lines.length - 1);
13490
+ const target = lines[targetIdx];
13491
+ return clamp(target.start + col, target.start, target.end);
13492
+ }
13493
+ case "word-forward": {
13494
+ let pos = caret;
13495
+ for (let i = 0; i < n; i++) pos = nextWordStart(text, pos);
13496
+ return pos;
13497
+ }
13498
+ case "word-back": {
13499
+ let pos = caret;
13500
+ for (let i = 0; i < n; i++) pos = prevWordStart(text, pos);
13501
+ return pos;
13502
+ }
13503
+ case "word-end": {
13504
+ let pos = caret;
13505
+ for (let i = 0; i < n; i++) pos = nextWordEnd(text, pos);
13506
+ return pos;
13507
+ }
13508
+ case "line-start":
13509
+ return line.start;
13510
+ case "line-end":
13511
+ return line.end > line.start ? line.end - 1 : line.start;
13512
+ case "first-nonblank":
13513
+ return firstNonBlank(text, line);
13514
+ case "doc-start":
13515
+ return 0;
13516
+ case "doc-end":
13517
+ return text.length;
13518
+ case "paragraph-forward": {
13519
+ let pos = caret;
13520
+ for (let i = 0; i < n; i++) {
13521
+ pos = nextParagraphBoundary(lines, lineIndexAt(lines, pos), text.length);
13522
+ }
13523
+ return pos;
13524
+ }
13525
+ case "paragraph-back": {
13526
+ let pos = caret;
13527
+ for (let i = 0; i < n; i++) {
13528
+ pos = prevParagraphBoundary(lines, lineIndexAt(lines, pos));
13529
+ }
13530
+ return pos;
13531
+ }
13532
+ case "line":
13533
+ case "selection":
13534
+ return caret;
13535
+ default: {
13536
+ const _exhaustive = motion;
13537
+ return _exhaustive;
13538
+ }
13539
+ }
13540
+ }
13541
+ function motionRange(text, caret, motion, count, selection) {
13542
+ if (motion === "selection") {
13543
+ if (!selection) return [caret, caret];
13544
+ return [Math.min(selection[0], selection[1]), Math.max(selection[0], selection[1])];
13545
+ }
13546
+ const lines = computeLines(text);
13547
+ if (motion === "line") {
13548
+ const n = Math.max(1, count);
13549
+ const startIdx = lineIndexAt(lines, caret);
13550
+ const endIdx = clamp(startIdx + n - 1, 0, lines.length - 1);
13551
+ const start2 = lines[startIdx].start;
13552
+ const rawEnd = lines[endIdx].end;
13553
+ const end2 = rawEnd < text.length ? rawEnd + 1 : rawEnd;
13554
+ return [start2, end2];
13555
+ }
13556
+ const newCaret = applyMotion(text, caret, motion, count);
13557
+ let start = Math.min(caret, newCaret);
13558
+ let end = Math.max(caret, newCaret);
13559
+ if (motion === "word-end" || motion === "line-end") {
13560
+ end = Math.min(Math.max(start, newCaret) + 1, text.length);
13561
+ } else if (motion === "word-forward" && newCaret > caret) {
13562
+ const startLine = lineIndexAt(lines, caret);
13563
+ const endLine = lineIndexAt(lines, newCaret);
13564
+ if (endLine !== startLine) {
13565
+ end = lines[startLine].end;
13566
+ }
13567
+ }
13568
+ return [start, end];
13569
+ }
13570
+ function applyOperator(text, range, operator, register) {
13571
+ const start = clamp(range[0], 0, text.length);
13572
+ const end = clamp(range[1], start, text.length);
13573
+ const removed = text.slice(start, end);
13574
+ if (operator === "yank") {
13575
+ return { text, caret: start, register: removed };
13576
+ }
13577
+ return { text: text.slice(0, start) + text.slice(end), caret: start, register: removed };
13578
+ }
13579
+ var init_editorMotions = __esm({
13580
+ "lib/editorMotions.ts"() {
13581
+ }
13582
+ });
13583
+ function isMotionPayload(payload) {
13584
+ return !!payload && typeof payload.editorId === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
13585
+ }
13586
+ function isOperatePayload(payload) {
13587
+ return !!payload && typeof payload.editorId === "string" && typeof payload.operator === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
13588
+ }
13589
+ function isInsertTextPayload(payload) {
13590
+ return !!payload && typeof payload.editorId === "string" && typeof payload.text === "string";
13591
+ }
13592
+ function isSetModePayload(payload) {
13593
+ return !!payload && typeof payload.editorId === "string" && typeof payload.mode === "string" && typeof payload.caret === "string";
13594
+ }
13595
+ function useEditorCapabilities(args) {
13596
+ const [caretMode, setCaretMode] = React79.useState("bar");
13597
+ const registerRef = React79.useRef("");
13598
+ useEventListener(`UI:${args.events.onMotion}`, (evt) => {
13599
+ if (!args.editorId || !isMotionPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13600
+ const ta = args.textareaRef.current;
13601
+ if (!ta) return;
13602
+ const { motion, count } = evt.payload;
13603
+ const newCaret = applyMotion(ta.value, ta.selectionStart, motion, count);
13604
+ if (ta.selectionStart !== ta.selectionEnd) {
13605
+ ta.setSelectionRange(ta.selectionStart, newCaret);
13606
+ } else {
13607
+ ta.setSelectionRange(newCaret, newCaret);
13608
+ }
13609
+ });
13610
+ useEventListener(`UI:${args.events.onOperate}`, (evt) => {
13611
+ if (!args.editorId || !isOperatePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13612
+ const ta = args.textareaRef.current;
13613
+ if (!ta) return;
13614
+ const { operator, motion, count } = evt.payload;
13615
+ const selection = motion === "selection" ? [ta.selectionStart, ta.selectionEnd] : void 0;
13616
+ const range = motionRange(ta.value, ta.selectionStart, motion, count, selection);
13617
+ const result = applyOperator(ta.value, range, operator, registerRef.current);
13618
+ registerRef.current = result.register;
13619
+ if (operator === "yank") {
13620
+ ta.setSelectionRange(range[0], range[0]);
13621
+ } else {
13622
+ ta.setRangeText("", range[0], range[1], "end");
13623
+ }
13624
+ args.applyChange(ta.value);
13625
+ });
13626
+ useEventListener(`UI:${args.events.onInsertText}`, (evt) => {
13627
+ if (!args.editorId || !isInsertTextPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13628
+ const ta = args.textareaRef.current;
13629
+ if (!ta) return;
13630
+ ta.setRangeText(evt.payload.text, ta.selectionStart, ta.selectionEnd, "end");
13631
+ args.applyChange(ta.value);
13632
+ });
13633
+ useEventListener(`UI:${args.events.onSetMode}`, (evt) => {
13634
+ if (!args.editorId || !isSetModePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13635
+ setCaretMode(evt.payload.caret);
13636
+ });
13637
+ return { caretMode };
13638
+ }
13639
+ var init_useEditorCapabilities = __esm({
13640
+ "components/core/molecules/markdown/useEditorCapabilities.ts"() {
13641
+ "use client";
13642
+ init_useEventBus();
13643
+ init_editorMotions();
13644
+ }
13645
+ });
13399
13646
  function registerCodeLanguageLoader(loader) {
13400
13647
  codeLanguageLoader = loader;
13401
13648
  }
@@ -13484,7 +13731,36 @@ function useLanguageReady(language) {
13484
13731
  }, [language]);
13485
13732
  return ready;
13486
13733
  }
13487
- var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log5, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, HIGHLIGHT_CAPACITY_BYTES; exports.CodeBlock = void 0;
13734
+ function resolveHighlightStyle(lang) {
13735
+ if (lang === "orb") return orbStyle;
13736
+ if (lang === "lolo") return loloStyle;
13737
+ return dark__default.default;
13738
+ }
13739
+ function plainCodeColorOf(style) {
13740
+ return style['code[class*="language-"]']?.color ?? "#d4d4d4";
13741
+ }
13742
+ function buildLineProps(errorLines, extraClassName) {
13743
+ return (lineNumber) => {
13744
+ const base = {
13745
+ "data-line": String(lineNumber - 1),
13746
+ ...extraClassName ? { className: extraClassName } : {}
13747
+ };
13748
+ const severity = errorLines?.get(lineNumber);
13749
+ if (!severity) return base;
13750
+ return {
13751
+ ...base,
13752
+ style: {
13753
+ display: "block",
13754
+ backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
13755
+ // amber-400 @ 18%
13756
+ borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
13757
+ paddingLeft: "0.5rem",
13758
+ marginLeft: "-0.5rem"
13759
+ }
13760
+ };
13761
+ };
13762
+ }
13763
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log5, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, HIGHLIGHT_CAPACITY_BYTES, MONO_FONT_FAMILY, VIEWER_LINE_NUMBER_STYLE; exports.CodeBlock = void 0;
13488
13764
  var init_CodeBlock = __esm({
13489
13765
  "components/core/molecules/markdown/CodeBlock.tsx"() {
13490
13766
  init_cn();
@@ -13500,6 +13776,7 @@ var init_CodeBlock = __esm({
13500
13776
  init_Textarea();
13501
13777
  init_Icon();
13502
13778
  init_useEventBus();
13779
+ init_useEditorCapabilities();
13503
13780
  SyntaxHighlighter__default.default.registerLanguage("json", langJson__default.default);
13504
13781
  SyntaxHighlighter__default.default.registerLanguage("javascript", langJavascript__default.default);
13505
13782
  SyntaxHighlighter__default.default.registerLanguage("js", langJavascript__default.default);
@@ -13718,6 +13995,15 @@ var init_CodeBlock = __esm({
13718
13995
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
13719
13996
  HIDDEN_LINE_NUMBERS = { display: "none" };
13720
13997
  HIGHLIGHT_CAPACITY_BYTES = 512 * 1024;
13998
+ MONO_FONT_FAMILY = 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace';
13999
+ VIEWER_LINE_NUMBER_STYLE = {
14000
+ minWidth: "2.5em",
14001
+ paddingRight: "1rem",
14002
+ textAlign: "right",
14003
+ userSelect: "none",
14004
+ opacity: 0.5,
14005
+ fontVariantNumeric: "tabular-nums"
14006
+ };
13721
14007
  exports.CodeBlock = React79__namespace.default.memo(
13722
14008
  ({
13723
14009
  code: rawCode,
@@ -13742,15 +14028,39 @@ var init_CodeBlock = __esm({
13742
14028
  actions,
13743
14029
  isLoading = false,
13744
14030
  error,
13745
- showCopy
14031
+ showCopy,
14032
+ // editor capability surface — P1 wires these
14033
+ editorId,
14034
+ onEditorFocus = "EDITOR_FOCUS",
14035
+ onEditorBlur = "EDITOR_BLUR",
14036
+ onMotion = "MOTION",
14037
+ onOperate = "OPERATE",
14038
+ onInsertText = "INSERT_TEXT",
14039
+ onSetMode = "SET_MODE",
14040
+ motions = [
14041
+ "left",
14042
+ "right",
14043
+ "up",
14044
+ "down",
14045
+ "word-forward",
14046
+ "word-back",
14047
+ "word-end",
14048
+ "line-start",
14049
+ "line-end",
14050
+ "first-nonblank",
14051
+ "doc-start",
14052
+ "doc-end",
14053
+ "paragraph-forward",
14054
+ "paragraph-back",
14055
+ "line",
14056
+ "selection"
14057
+ ],
14058
+ operators = ["delete", "yank", "change"]
13746
14059
  }) => {
13747
14060
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
13748
- const isOrb = language === "orb";
13749
- const isLolo = language === "lolo";
13750
- const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark__default.default;
14061
+ const activeStyle = resolveHighlightStyle(language);
13751
14062
  const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
13752
- const plainCodeColor = activeStyle['code[class*="language-"]']?.color ?? "#d4d4d4";
13753
- const languageReady = useLanguageReady(language);
14063
+ const plainCodeColor = plainCodeColorOf(activeStyle);
13754
14064
  const eventBus = useEventBus();
13755
14065
  const { t } = hooks.useTranslate();
13756
14066
  const scrollRef = React79.useRef(null);
@@ -13762,6 +14072,9 @@ var init_CodeBlock = __esm({
13762
14072
  const activeFile = files?.[activeFileIndex];
13763
14073
  const activeCode = activeFile?.code ?? code;
13764
14074
  const activeLanguage = activeFile?.language ?? language;
14075
+ const languageReady = useLanguageReady(activeLanguage);
14076
+ const viewerStyle = resolveHighlightStyle(activeLanguage);
14077
+ const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
13765
14078
  const diffLines = React79.useMemo(() => {
13766
14079
  if (propDiff) return propDiff;
13767
14080
  if (mode === "diff" && oldValue !== void 0 && newValue !== void 0) {
@@ -13791,28 +14104,28 @@ var init_CodeBlock = __esm({
13791
14104
  ov.scrollLeft = ta.scrollLeft;
13792
14105
  }
13793
14106
  }, []);
13794
- const errorLineProps = React79.useMemo(() => {
13795
- if (!errorLines || errorLines.size === 0) {
13796
- return LINE_PROPS_FN;
13797
- }
13798
- return (lineNumber) => {
13799
- const severity = errorLines.get(lineNumber);
13800
- if (!severity) {
13801
- return { "data-line": String(lineNumber - 1) };
13802
- }
13803
- return {
13804
- "data-line": String(lineNumber - 1),
13805
- style: {
13806
- display: "block",
13807
- backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
13808
- // amber-400 @ 18%
13809
- borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
13810
- paddingLeft: "0.5rem",
13811
- marginLeft: "-0.5rem"
13812
- }
13813
- };
13814
- };
13815
- }, [errorLines]);
14107
+ const handleEditableChange = React79.useCallback((v) => {
14108
+ lastPropCodeRef.current = v;
14109
+ setEditableValue(v);
14110
+ onChange?.(v);
14111
+ }, [onChange]);
14112
+ const { caretMode } = useEditorCapabilities({
14113
+ editorId: editable ? editorId : void 0,
14114
+ textareaRef: editableTextareaRef,
14115
+ events: { onMotion, onOperate, onInsertText, onSetMode },
14116
+ applyChange: handleEditableChange
14117
+ });
14118
+ const [caretIndex, setCaretIndex] = React79.useState(0);
14119
+ const caretRowCol = React79.useMemo(() => {
14120
+ const before = editableValue.slice(0, Math.min(caretIndex, editableValue.length));
14121
+ const lines = before.split("\n");
14122
+ return { row: lines.length - 1, col: lines[lines.length - 1].length };
14123
+ }, [editableValue, caretIndex]);
14124
+ const errorLineProps = React79.useMemo(() => buildLineProps(errorLines), [errorLines]);
14125
+ const viewerLineProps = React79.useMemo(
14126
+ () => buildLineProps(errorLines, "px-4 py-0.5 hover:bg-muted/50"),
14127
+ [errorLines]
14128
+ );
13816
14129
  const isFoldable = foldableProp ?? true;
13817
14130
  const [collapsed, setCollapsed] = React79.useState(() => /* @__PURE__ */ new Set());
13818
14131
  const foldRegions = React79.useMemo(
@@ -13935,6 +14248,110 @@ var init_CodeBlock = __esm({
13935
14248
  ),
13936
14249
  [code, overCapacity, plainCodeColor, language, activeStyle, languageReady]
13937
14250
  );
14251
+ const viewerOverCapacity = activeCode.length > HIGHLIGHT_CAPACITY_BYTES;
14252
+ const viewerHighlightedElement = React79.useMemo(
14253
+ () => viewerOverCapacity ? /* @__PURE__ */ jsxRuntime.jsx(
14254
+ "div",
14255
+ {
14256
+ className: "px-4 py-0.5",
14257
+ style: {
14258
+ margin: 0,
14259
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14260
+ wordBreak: wrap ? "break-all" : "normal",
14261
+ color: viewerPlainCodeColor,
14262
+ fontFamily: MONO_FONT_FAMILY,
14263
+ fontSize: "12px",
14264
+ lineHeight: "1.6"
14265
+ },
14266
+ children: activeCode
14267
+ }
14268
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
14269
+ SyntaxHighlighter__default.default,
14270
+ {
14271
+ PreTag: "div",
14272
+ language: activeLanguage,
14273
+ style: viewerStyle,
14274
+ wrapLines: true,
14275
+ wrapLongLines: wrap,
14276
+ showLineNumbers,
14277
+ lineNumberStyle: VIEWER_LINE_NUMBER_STYLE,
14278
+ lineProps: viewerLineProps,
14279
+ customStyle: {
14280
+ backgroundColor: "transparent",
14281
+ borderRadius: 0,
14282
+ padding: "0.25rem 0",
14283
+ margin: 0,
14284
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14285
+ wordBreak: wrap ? "break-all" : "normal",
14286
+ fontFamily: MONO_FONT_FAMILY,
14287
+ fontSize: "12px",
14288
+ lineHeight: "1.6"
14289
+ },
14290
+ codeTagProps: { style: { fontFamily: MONO_FONT_FAMILY, fontSize: "12px", lineHeight: "1.6" } },
14291
+ children: activeCode
14292
+ }
14293
+ ),
14294
+ [activeCode, viewerOverCapacity, viewerPlainCodeColor, activeLanguage, viewerStyle, wrap, showLineNumbers, viewerLineProps, languageReady]
14295
+ );
14296
+ const diffOverCapacity = React79.useMemo(
14297
+ () => !!diffLines && diffLines.reduce((n, l) => n + l.content.length + 1, 0) > HIGHLIGHT_CAPACITY_BYTES,
14298
+ [diffLines]
14299
+ );
14300
+ const diffRowElements = React79.useMemo(() => {
14301
+ if (!diffLines) return null;
14302
+ return diffLines.map((line, idx) => {
14303
+ const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
14304
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
14305
+ showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx(
14306
+ exports.Typography,
14307
+ {
14308
+ variant: "caption",
14309
+ color: "secondary",
14310
+ className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
14311
+ children: line.lineNumber ?? ""
14312
+ }
14313
+ ),
14314
+ /* @__PURE__ */ jsxRuntime.jsxs(
14315
+ exports.Typography,
14316
+ {
14317
+ variant: "caption",
14318
+ className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
14319
+ children: [
14320
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
14321
+ diffOverCapacity ? line.content || " " : /* @__PURE__ */ jsxRuntime.jsx(
14322
+ SyntaxHighlighter__default.default,
14323
+ {
14324
+ PreTag: "span",
14325
+ CodeTag: "span",
14326
+ language: activeLanguage,
14327
+ style: viewerStyle,
14328
+ customStyle: {
14329
+ display: "inline",
14330
+ background: "transparent",
14331
+ padding: 0,
14332
+ margin: 0,
14333
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14334
+ wordBreak: wrap ? "break-all" : "normal",
14335
+ fontFamily: "inherit",
14336
+ fontSize: "inherit",
14337
+ lineHeight: "inherit"
14338
+ },
14339
+ codeTagProps: {
14340
+ style: {
14341
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14342
+ fontFamily: "inherit",
14343
+ fontSize: "inherit"
14344
+ }
14345
+ },
14346
+ children: line.content || " "
14347
+ }
14348
+ )
14349
+ ]
14350
+ }
14351
+ )
14352
+ ] }, idx);
14353
+ });
14354
+ }, [diffLines, showLineNumbers, wrap, diffOverCapacity, activeLanguage, viewerStyle, languageReady]);
13938
14355
  React79.useLayoutEffect(() => {
13939
14356
  const container = codeRef.current;
13940
14357
  if (!container) return;
@@ -14078,7 +14495,6 @@ var init_CodeBlock = __esm({
14078
14495
  label: file.label,
14079
14496
  content: null
14080
14497
  }));
14081
- const lines = activeCode.split("\n");
14082
14498
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
14083
14499
  tabItems && tabItems.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
14084
14500
  exports.Tabs,
@@ -14141,49 +14557,7 @@ var init_CodeBlock = __esm({
14141
14557
  ]
14142
14558
  }
14143
14559
  ),
14144
- /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffLines.map((line, idx) => {
14145
- const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
14146
- return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
14147
- showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx(
14148
- exports.Typography,
14149
- {
14150
- variant: "caption",
14151
- color: "secondary",
14152
- className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
14153
- children: line.lineNumber ?? ""
14154
- }
14155
- ),
14156
- /* @__PURE__ */ jsxRuntime.jsxs(
14157
- exports.Typography,
14158
- {
14159
- variant: "caption",
14160
- className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
14161
- children: [
14162
- /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
14163
- line.content
14164
- ]
14165
- }
14166
- )
14167
- ] }, idx);
14168
- }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: lines.map((line, idx) => /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "none", align: "start", className: "px-4 py-0.5 hover:bg-muted/50", children: [
14169
- showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx(
14170
- exports.Typography,
14171
- {
14172
- variant: "caption",
14173
- color: "secondary",
14174
- className: "w-8 text-right mr-4 select-none tabular-nums flex-shrink-0",
14175
- children: idx + 1
14176
- }
14177
- ),
14178
- /* @__PURE__ */ jsxRuntime.jsx(
14179
- exports.Typography,
14180
- {
14181
- variant: "caption",
14182
- className: cn("font-mono flex-1 min-w-0", wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
14183
- children: line || " "
14184
- }
14185
- )
14186
- ] }, idx)) }) })
14560
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
14187
14561
  ] }) });
14188
14562
  }
14189
14563
  const hasHeader = showLanguageBadge || effectiveCopy;
@@ -14270,13 +14644,11 @@ var init_CodeBlock = __esm({
14270
14644
  {
14271
14645
  ref: editableTextareaRef,
14272
14646
  defaultValue: code,
14273
- onChange: (e) => {
14274
- const v = e.target.value;
14275
- lastPropCodeRef.current = v;
14276
- setEditableValue(v);
14277
- onChange?.(v);
14278
- },
14647
+ onChange: (e) => handleEditableChange(e.target.value),
14279
14648
  onScroll: handleEditableScroll,
14649
+ onSelect: (e) => setCaretIndex(e.currentTarget.selectionStart),
14650
+ onFocus: editorId ? () => eventBus.emit(`UI:${onEditorFocus}`, { editorId }) : void 0,
14651
+ onBlur: editorId ? () => eventBus.emit(`UI:${onEditorBlur}`, { editorId }) : void 0,
14280
14652
  spellCheck: false,
14281
14653
  style: {
14282
14654
  position: "absolute",
@@ -14291,7 +14663,7 @@ var init_CodeBlock = __esm({
14291
14663
  resize: "none",
14292
14664
  backgroundColor: "transparent",
14293
14665
  color: "transparent",
14294
- caretColor: "#e6e6e6",
14666
+ caretColor: caretMode === "block" ? "transparent" : "#e6e6e6",
14295
14667
  WebkitTextFillColor: "transparent",
14296
14668
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
14297
14669
  fontSize: "13px",
@@ -14302,6 +14674,22 @@ var init_CodeBlock = __esm({
14302
14674
  }
14303
14675
  },
14304
14676
  editableTextareaKey
14677
+ ),
14678
+ caretMode !== "bar" && /* @__PURE__ */ jsxRuntime.jsx(
14679
+ "span",
14680
+ {
14681
+ "aria-hidden": true,
14682
+ style: {
14683
+ position: "absolute",
14684
+ top: `calc(1rem + ${caretRowCol.row * 19.5}px)`,
14685
+ left: `calc(1rem + ${caretRowCol.col}ch)`,
14686
+ width: "1ch",
14687
+ height: caretMode === "block" ? "19.5px" : "2px",
14688
+ backgroundColor: caretMode === "block" ? "rgba(230, 230, 230, 0.5)" : void 0,
14689
+ borderBottom: caretMode === "underline" ? "2px solid #e6e6e6" : void 0,
14690
+ pointerEvents: "none"
14691
+ }
14692
+ }
14305
14693
  )
14306
14694
  ]
14307
14695
  }
@@ -14329,55 +14717,175 @@ var init_CodeBlock = __esm({
14329
14717
  )
14330
14718
  ] });
14331
14719
  },
14332
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.showCopy === next.showCopy && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange && prev.errorLines === next.errorLines && prev.mode === next.mode && prev.title === next.title && prev.diff === next.diff && prev.files === next.files && prev.actions === next.actions && prev.isLoading === next.isLoading && prev.error === next.error
14720
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.showCopy === next.showCopy && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange && prev.errorLines === next.errorLines && prev.mode === next.mode && prev.title === next.title && prev.diff === next.diff && prev.files === next.files && prev.actions === next.actions && prev.isLoading === next.isLoading && prev.error === next.error && prev.editorId === next.editorId && prev.onEditorFocus === next.onEditorFocus && prev.onEditorBlur === next.onEditorBlur && prev.onMotion === next.onMotion && prev.onOperate === next.onOperate && prev.onInsertText === next.onInsertText && prev.onSetMode === next.onSetMode && prev.motions === next.motions && prev.operators === next.operators
14333
14721
  );
14334
14722
  exports.CodeBlock.displayName = "CodeBlock";
14335
14723
  }
14336
14724
  });
14725
+
14726
+ // components/core/molecules/markdown/mermaidSource.ts
14727
+ function isQuoted(label) {
14728
+ const trimmed = label.trim();
14729
+ return trimmed.length === 0 || trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1;
14730
+ }
14731
+ function quote(label) {
14732
+ return `"${label.replace(/"/g, "#quot;")}"`;
14733
+ }
14734
+ function isIdentifierChar(ch) {
14735
+ return /[A-Za-z0-9_\-.]/.test(ch);
14736
+ }
14737
+ function declaredType(code) {
14738
+ for (const line of code.split("\n")) {
14739
+ const trimmed = line.trim();
14740
+ if (trimmed.length === 0 || trimmed.startsWith("%%")) continue;
14741
+ return trimmed;
14742
+ }
14743
+ return "";
14744
+ }
14745
+ function isFlowchart(code) {
14746
+ return FLOWCHART_DIRECTIVE.test(declaredType(code));
14747
+ }
14748
+ function quoteNodeLabels(code) {
14749
+ let out = "";
14750
+ let i = 0;
14751
+ while (i < code.length) {
14752
+ const shape = NODE_SHAPES.find(([open2]) => code.startsWith(open2, i));
14753
+ const precededByIdentifier = i > 0 && isIdentifierChar(code[i - 1] ?? "");
14754
+ if (shape === void 0 || !precededByIdentifier) {
14755
+ out += code[i];
14756
+ i += 1;
14757
+ continue;
14758
+ }
14759
+ const [open, close] = shape;
14760
+ const contentStart = i + open.length;
14761
+ const closeAt = code.indexOf(close, contentStart);
14762
+ const newlineAt = code.indexOf("\n", contentStart);
14763
+ if (closeAt === -1 || newlineAt !== -1 && newlineAt < closeAt) {
14764
+ out += code[i];
14765
+ i += 1;
14766
+ continue;
14767
+ }
14768
+ const label = code.slice(contentStart, closeAt);
14769
+ out += open + (isQuoted(label) ? label : quote(label)) + close;
14770
+ i = closeAt + close.length;
14771
+ }
14772
+ return out;
14773
+ }
14774
+ function quoteEdgeLabels(code) {
14775
+ return code.split("\n").map((line) => {
14776
+ let out = "";
14777
+ let rest = line;
14778
+ for (; ; ) {
14779
+ const open = rest.indexOf("|");
14780
+ if (open === -1) break;
14781
+ const close = rest.indexOf("|", open + 1);
14782
+ if (close === -1) break;
14783
+ const label = rest.slice(open + 1, close);
14784
+ out += rest.slice(0, open + 1) + (isQuoted(label) ? label : quote(label)) + "|";
14785
+ rest = rest.slice(close + 1);
14786
+ }
14787
+ return out + rest;
14788
+ }).join("\n");
14789
+ }
14790
+ function quoteSubgraphTitles(code) {
14791
+ return code.split("\n").map((line) => {
14792
+ const match = /^(\s*subgraph\s+)(.+?)(\s*)$/.exec(line);
14793
+ if (match === null) return line;
14794
+ const [, prefix, title, trailing] = match;
14795
+ if (title === void 0 || prefix === void 0) return line;
14796
+ if (isQuoted(title) || title.includes("[")) return line;
14797
+ return prefix + quote(title) + (trailing ?? "");
14798
+ }).join("\n");
14799
+ }
14800
+ function mermaidRepairCandidates(code) {
14801
+ if (!isFlowchart(code)) return [];
14802
+ const nodes = quoteNodeLabels(code);
14803
+ const nodesAndEdges = quoteEdgeLabels(nodes);
14804
+ const all = quoteSubgraphTitles(nodesAndEdges);
14805
+ const ordered2 = [nodes, nodesAndEdges, all];
14806
+ const seen = /* @__PURE__ */ new Set([code]);
14807
+ const candidates = [];
14808
+ for (const candidate of ordered2) {
14809
+ if (seen.has(candidate)) continue;
14810
+ seen.add(candidate);
14811
+ candidates.push(candidate);
14812
+ }
14813
+ return candidates;
14814
+ }
14815
+ var NODE_SHAPES, FLOWCHART_DIRECTIVE;
14816
+ var init_mermaidSource = __esm({
14817
+ "components/core/molecules/markdown/mermaidSource.ts"() {
14818
+ NODE_SHAPES = [
14819
+ ["[[", "]]"],
14820
+ ["[(", ")]"],
14821
+ ["([", "])"],
14822
+ ["((", "))"],
14823
+ ["{{", "}}"],
14824
+ ["[", "]"],
14825
+ ["(", ")"],
14826
+ ["{", "}"]
14827
+ ];
14828
+ FLOWCHART_DIRECTIVE = /^(?:graph|flowchart)\b/;
14829
+ }
14830
+ });
14337
14831
  function loadMermaid() {
14338
14832
  mermaidModule ?? (mermaidModule = import('mermaid').then((m) => m.default));
14339
14833
  return mermaidModule;
14340
14834
  }
14341
- var mermaidModule, MermaidDiagram;
14835
+ var log6, mermaidModule, MermaidDiagram;
14342
14836
  var init_MermaidDiagram = __esm({
14343
14837
  "components/core/molecules/markdown/MermaidDiagram.tsx"() {
14344
14838
  init_Box();
14345
14839
  init_Typography();
14346
14840
  init_CodeBlock();
14841
+ init_mermaidSource();
14347
14842
  init_cn();
14843
+ log6 = logger.createLogger("almadar:ui:mermaid-diagram");
14348
14844
  mermaidModule = null;
14349
14845
  MermaidDiagram = React79__namespace.default.memo(
14350
14846
  ({ code, className }) => {
14351
14847
  const { resolvedMode } = context.useTheme();
14848
+ const { t } = hooks.useTranslate();
14352
14849
  const containerRef = React79.useRef(null);
14353
- const [error, setError] = React79.useState(null);
14850
+ const [unrenderable, setUnrenderable] = React79.useState(false);
14354
14851
  const reactId = React79.useId();
14355
14852
  React79.useEffect(() => {
14356
14853
  let active = true;
14357
14854
  void (async () => {
14358
- try {
14359
- const mermaid = await loadMermaid();
14360
- mermaid.initialize({
14361
- startOnLoad: false,
14362
- securityLevel: "strict",
14363
- theme: resolvedMode === "dark" ? "dark" : "default"
14364
- });
14365
- const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
14366
- const { svg } = await mermaid.render(domId, code);
14367
- if (!active || !containerRef.current) return;
14368
- containerRef.current.innerHTML = svg;
14369
- setError(null);
14370
- } catch (err) {
14371
- if (active) setError(err instanceof Error ? err.message : String(err));
14855
+ const mermaid = await loadMermaid();
14856
+ mermaid.initialize({
14857
+ startOnLoad: false,
14858
+ securityLevel: "strict",
14859
+ theme: resolvedMode === "dark" ? "dark" : "default"
14860
+ });
14861
+ const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
14862
+ let firstError = null;
14863
+ for (const [index, source] of [code, ...mermaidRepairCandidates(code)].entries()) {
14864
+ try {
14865
+ const { svg } = await mermaid.render(domId, source);
14866
+ if (!active) return;
14867
+ const container = containerRef.current;
14868
+ if (container === null) return;
14869
+ container.innerHTML = svg;
14870
+ container.dataset.mermaidRepaired = String(index > 0);
14871
+ setUnrenderable(false);
14872
+ if (index > 0) log6.debug("mermaid:repaired", { candidate: index });
14873
+ return;
14874
+ } catch (err) {
14875
+ firstError ?? (firstError = err instanceof Error ? err : new Error(String(err)));
14876
+ }
14372
14877
  }
14878
+ if (!active) return;
14879
+ log6.warn("mermaid:unrenderable", { error: firstError?.message ?? "", code });
14880
+ setUnrenderable(true);
14373
14881
  })();
14374
14882
  return () => {
14375
14883
  active = false;
14376
14884
  };
14377
14885
  }, [code, resolvedMode, reactId]);
14378
14886
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: cn("not-prose my-4", className), children: [
14379
- error !== null && /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "space-y-2 mb-2", children: [
14380
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-error whitespace-pre-wrap", children: error }),
14887
+ unrenderable && /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "space-y-2 mb-2", "data-testid": "mermaid-unrenderable", children: [
14888
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-muted-foreground", children: t("mermaid.unrenderable") }),
14381
14889
  /* @__PURE__ */ jsxRuntime.jsx(exports.CodeBlock, { code, language: "mermaid" })
14382
14890
  ] }),
14383
14891
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -14386,7 +14894,7 @@ var init_MermaidDiagram = __esm({
14386
14894
  ref: containerRef,
14387
14895
  "data-testid": "mermaid-diagram",
14388
14896
  className: "overflow-x-auto",
14389
- style: error !== null ? { display: "none" } : void 0
14897
+ style: unrenderable ? { display: "none" } : void 0
14390
14898
  }
14391
14899
  )
14392
14900
  ] });
@@ -17791,14 +18299,14 @@ function useSafeEventBus2() {
17791
18299
  } };
17792
18300
  }
17793
18301
  }
17794
- var log6, lookStyles4; exports.ButtonGroup = void 0;
18302
+ var log7, lookStyles4; exports.ButtonGroup = void 0;
17795
18303
  var init_ButtonGroup = __esm({
17796
18304
  "components/core/molecules/ButtonGroup.tsx"() {
17797
18305
  "use client";
17798
18306
  init_cn();
17799
18307
  init_atoms();
17800
18308
  init_useEventBus();
17801
- log6 = logger.createLogger("almadar:ui:button-group");
18309
+ log7 = logger.createLogger("almadar:ui:button-group");
17802
18310
  lookStyles4 = {
17803
18311
  "right-aligned-buttons": "",
17804
18312
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -17879,7 +18387,7 @@ var init_ButtonGroup = __esm({
17879
18387
  {
17880
18388
  variant: "ghost",
17881
18389
  onClick: () => {
17882
- log6.debug("Filter clicked", { field: filter.field });
18390
+ log7.debug("Filter clicked", { field: filter.field });
17883
18391
  },
17884
18392
  children: filter.label
17885
18393
  },
@@ -18897,7 +19405,7 @@ function collectDrawnItems(nodes) {
18897
19405
  for (const n of nodes) {
18898
19406
  switch (n.type) {
18899
19407
  case "draw-sprite":
18900
- if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height });
19408
+ if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotation });
18901
19409
  break;
18902
19410
  case "draw-shape":
18903
19411
  case "draw-text":
@@ -18907,7 +19415,7 @@ function collectDrawnItems(nodes) {
18907
19415
  break;
18908
19416
  case "draw-sprite-layer":
18909
19417
  for (const it of n.items) {
18910
- if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height });
19418
+ if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height, rotation: it.rotation });
18911
19419
  }
18912
19420
  break;
18913
19421
  case "draw-shape-layer":
@@ -18927,15 +19435,39 @@ function buildHitIndex(items) {
18927
19435
  }
18928
19436
  return m;
18929
19437
  }
19438
+ function withPreviewPosition(nodes, id, pos) {
19439
+ return nodes.map((n) => {
19440
+ if (n.type === "draw-sprite-layer" || n.type === "draw-shape-layer" || n.type === "draw-text-layer") {
19441
+ if (!n.items.some((it) => it.id === id)) return n;
19442
+ return { ...n, items: n.items.map((it) => it.id === id ? { ...it, position: pos } : it) };
19443
+ }
19444
+ if (n.type === "draw-group") {
19445
+ if (!Array.isArray(n.items)) return n;
19446
+ return { ...n, items: withPreviewPosition(n.items, id, pos) };
19447
+ }
19448
+ if (n.id === id && "position" in n) {
19449
+ return { ...n, position: pos };
19450
+ }
19451
+ return n;
19452
+ });
19453
+ }
18930
19454
  function hitTestSprites(items, projector, point) {
18931
19455
  for (let i = items.length - 1; i >= 0; i--) {
18932
19456
  const it = items[i];
18933
19457
  if (it.id === void 0) continue;
18934
19458
  const r = spriteRect(projector, { position: it.pos, anchor: it.anchor, width: it.width, height: it.height });
18935
- if (point.x >= r.x && point.x <= r.x + r.w && point.y >= r.y && point.y <= r.y + r.h) return it.id;
19459
+ const test = it.rotation ? rotatePoint(point, { x: r.x + r.w / 2, y: r.y + r.h / 2 }, -it.rotation) : point;
19460
+ if (test.x >= r.x && test.x <= r.x + r.w && test.y >= r.y && test.y <= r.y + r.h) return it.id;
18936
19461
  }
18937
19462
  return void 0;
18938
19463
  }
19464
+ function rotatePoint(p, center, radians) {
19465
+ const cos = Math.cos(radians);
19466
+ const sin = Math.sin(radians);
19467
+ const dx = p.x - center.x;
19468
+ const dy = p.y - center.y;
19469
+ return { x: center.x + dx * cos - dy * sin, y: center.y + dx * sin + dy * cos };
19470
+ }
18939
19471
  var init_hitTest = __esm({
18940
19472
  "lib/drawable/hitTest.ts"() {
18941
19473
  init_contract();
@@ -18944,6 +19476,41 @@ var init_hitTest = __esm({
18944
19476
  function normalizeBackdrop(bg) {
18945
19477
  return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
18946
19478
  }
19479
+ function selectionOverlayNodes(projector, item) {
19480
+ const r = spriteRect(projector, { position: item.pos, anchor: item.anchor, width: item.width, height: item.height });
19481
+ const tw = projector.tileWidth;
19482
+ const cellTopLeft = projector.anchorPoint(item.pos, "top-left");
19483
+ const offsetX = (r.x - cellTopLeft.x) / tw;
19484
+ const offsetY = (r.y - cellTopLeft.y) / tw;
19485
+ const width = r.w / tw;
19486
+ const height = r.h / tw;
19487
+ const handle = EDIT_HANDLE_SIZE_PX / tw;
19488
+ const ring = {
19489
+ type: "draw-shape",
19490
+ shape: "rect",
19491
+ position: item.pos,
19492
+ anchor: "top-left",
19493
+ offsetX,
19494
+ offsetY,
19495
+ width,
19496
+ height,
19497
+ stroke: EDIT_SELECTION_COLOR,
19498
+ strokeWidth: 2,
19499
+ fill: "none"
19500
+ };
19501
+ const handles = EDIT_SELECTION_CORNERS.map(([cx, cy]) => ({
19502
+ type: "draw-shape",
19503
+ shape: "rect",
19504
+ position: item.pos,
19505
+ anchor: "top-left",
19506
+ offsetX: offsetX + cx * width - handle / 2,
19507
+ offsetY: offsetY + cy * height - handle / 2,
19508
+ width: handle,
19509
+ height: handle,
19510
+ fill: EDIT_SELECTION_COLOR
19511
+ }));
19512
+ return [ring, ...handles];
19513
+ }
18947
19514
  function Canvas2D({
18948
19515
  className,
18949
19516
  isLoading = false,
@@ -18957,6 +19524,12 @@ function Canvas2D({
18957
19524
  tileLeaveEvent,
18958
19525
  keyMap,
18959
19526
  keyUpMap,
19527
+ editable = false,
19528
+ selectedId = null,
19529
+ onSelect,
19530
+ onMove,
19531
+ selectEvent,
19532
+ moveEvent,
18960
19533
  camera = "pan-zoom",
18961
19534
  scale = 0.4,
18962
19535
  tileWidth,
@@ -19214,10 +19787,22 @@ function Canvas2D({
19214
19787
  painter.scale(cam.zoom, cam.zoom);
19215
19788
  painter.translate(-viewportSize.width / 2 - cam.x, -viewportSize.height / 2 - cam.y);
19216
19789
  const dctx = { projector, time: timeMs, invalidate: bumpAtlas };
19217
- for (const node of drawables) paintDrawable(painter, node, dctx);
19790
+ let paintNodes = drawables;
19791
+ if (editable) {
19792
+ const drag = editDragRef.current;
19793
+ if (drag && drag.moved) {
19794
+ paintNodes = withPreviewPosition(paintNodes, drag.id, { x: drag.previewX, y: drag.previewY });
19795
+ }
19796
+ const selectedItem = selectedId != null ? drawnItems.find((it) => it.id === selectedId) : void 0;
19797
+ if (selectedItem) {
19798
+ const overlaySource = drag && drag.moved && drag.id === selectedId ? { ...selectedItem, pos: { x: drag.previewX, y: drag.previewY } } : selectedItem;
19799
+ paintNodes = [...paintNodes, ...selectionOverlayNodes(projector, overlaySource)];
19800
+ }
19801
+ }
19802
+ for (const node of paintNodes) paintDrawable(painter, node, dctx);
19218
19803
  painter.restore();
19219
- scheduleAnimation(drawables);
19220
- }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
19804
+ scheduleAnimation(paintNodes);
19805
+ }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance, editable, selectedId, drawnItems]);
19221
19806
  React79.useEffect(() => {
19222
19807
  drawTimeRef.current = draw;
19223
19808
  }, [draw]);
@@ -19262,23 +19847,83 @@ function Canvas2D({
19262
19847
  };
19263
19848
  }, [camera, followTarget, lerpToTarget, draw]);
19264
19849
  const singlePointerActiveRef = React79.useRef(false);
19850
+ const editDragRef = React79.useRef(null);
19851
+ const pointerToScene = React79.useCallback((clientX, clientY) => {
19852
+ const canvas = canvasRef.current;
19853
+ if (!canvas) return { x: 0, y: 0 };
19854
+ const world = screenToWorld(clientX, clientY, canvas, viewportSize);
19855
+ const adjustedX = world.x - scaledTileWidth / 2;
19856
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
19857
+ return unproject(adjustedX, adjustedY);
19858
+ }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject]);
19265
19859
  const handleCanvasPointerDown = React79.useCallback((e) => {
19266
19860
  singlePointerActiveRef.current = true;
19861
+ if (editable) {
19862
+ if (!canvasRef.current) return;
19863
+ const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
19864
+ const hitId = hitTestSprites(drawnItems, projector, world);
19865
+ if (hitId === void 0) return;
19866
+ const item = [...drawnItems].reverse().find((it) => it.id === hitId);
19867
+ if (!item) return;
19868
+ editDragRef.current = {
19869
+ id: hitId,
19870
+ pointerId: e.pointerId,
19871
+ startClientX: e.clientX,
19872
+ startClientY: e.clientY,
19873
+ startSceneX: item.pos.x,
19874
+ startSceneY: item.pos.y,
19875
+ moved: false,
19876
+ previewX: item.pos.x,
19877
+ previewY: item.pos.y
19878
+ };
19879
+ return;
19880
+ }
19267
19881
  if (enableCamera) handlePointerDown(e);
19268
- }, [enableCamera, handlePointerDown]);
19882
+ }, [editable, screenToWorld, viewportSize, drawnItems, projector, enableCamera, handlePointerDown]);
19269
19883
  const handleCanvasPointerMove = React79.useCallback((e) => {
19884
+ if (editable) {
19885
+ const drag = editDragRef.current;
19886
+ if (!drag || drag.pointerId !== e.pointerId) return;
19887
+ const dxPx = e.clientX - drag.startClientX;
19888
+ const dyPx = e.clientY - drag.startClientY;
19889
+ if (!drag.moved && Math.abs(dxPx) + Math.abs(dyPx) <= 5) return;
19890
+ drag.moved = true;
19891
+ const nowScene = pointerToScene(e.clientX, e.clientY);
19892
+ const startScene = pointerToScene(drag.startClientX, drag.startClientY);
19893
+ drag.previewX = drag.startSceneX + (nowScene.x - startScene.x);
19894
+ drag.previewY = drag.startSceneY + (nowScene.y - startScene.y);
19895
+ draw();
19896
+ return;
19897
+ }
19270
19898
  if (enableCamera) handlePointerMove(e, () => draw());
19271
- }, [enableCamera, handlePointerMove, draw]);
19899
+ }, [editable, pointerToScene, draw, enableCamera, handlePointerMove]);
19272
19900
  const handleCanvasHover = React79.useCallback((e) => {
19273
19901
  if (singlePointerActiveRef.current) return;
19274
19902
  if (!tileHoverEvent || !canvasRef.current) return;
19275
- const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
19276
- const adjustedX = world.x - scaledTileWidth / 2;
19277
- const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
19278
- const isoPos = unproject(adjustedX, adjustedY);
19903
+ const isoPos = pointerToScene(e.clientX, e.clientY);
19279
19904
  eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
19280
- }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, tileHoverEvent, eventBus]);
19905
+ }, [pointerToScene, tileHoverEvent, eventBus]);
19281
19906
  const handleCanvasPointerUp = React79.useCallback((e) => {
19907
+ if (editable) {
19908
+ singlePointerActiveRef.current = false;
19909
+ const drag = editDragRef.current;
19910
+ if (drag && drag.pointerId === e.pointerId) {
19911
+ editDragRef.current = null;
19912
+ if (drag.moved) {
19913
+ onMove?.(drag.id, drag.previewX, drag.previewY);
19914
+ if (moveEvent) eventBus.emit(`UI:${moveEvent}`, { id: drag.id, x: drag.previewX, y: drag.previewY });
19915
+ draw();
19916
+ return;
19917
+ }
19918
+ const next = selectedId === drag.id ? null : drag.id;
19919
+ onSelect?.(next);
19920
+ if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: next });
19921
+ return;
19922
+ }
19923
+ onSelect?.(null);
19924
+ if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: null });
19925
+ return;
19926
+ }
19282
19927
  singlePointerActiveRef.current = false;
19283
19928
  if (enableCamera) handlePointerUp();
19284
19929
  if (dragDistance() > 5) return;
@@ -19289,16 +19934,14 @@ function Canvas2D({
19289
19934
  eventBus.emit(`UI:${unitClickEvent}`, { unitId: spriteHit });
19290
19935
  return;
19291
19936
  }
19292
- const adjustedX = world.x - scaledTileWidth / 2;
19293
- const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
19294
- const isoPos = unproject(adjustedX, adjustedY);
19937
+ const isoPos = pointerToScene(e.clientX, e.clientY);
19295
19938
  const hitId = hitIndex.get(`${isoPos.x},${isoPos.y}`);
19296
19939
  if (hitId !== void 0 && unitClickEvent) {
19297
19940
  eventBus.emit(`UI:${unitClickEvent}`, { unitId: hitId });
19298
19941
  } else if (tileClickEvent) {
19299
19942
  eventBus.emit(`UI:${tileClickEvent}`, { x: isoPos.x, y: isoPos.y });
19300
19943
  }
19301
- }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, hitIndex, drawnItems, projector, tileClickEvent, unitClickEvent, eventBus]);
19944
+ }, [editable, selectedId, onMove, moveEvent, onSelect, selectEvent, eventBus, draw, enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, drawnItems, projector, tileClickEvent, unitClickEvent, hitIndex, pointerToScene]);
19302
19945
  const handleCanvasPointerLeave = React79.useCallback(() => {
19303
19946
  handleMouseLeave();
19304
19947
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
@@ -19317,7 +19960,7 @@ function Canvas2D({
19317
19960
  }, [enableCamera, handlePointerUp]);
19318
19961
  const gestureHandlers = useCanvasGestures({
19319
19962
  canvasRef,
19320
- enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent,
19963
+ enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent || editable,
19321
19964
  onPointerDown: handleCanvasPointerDown,
19322
19965
  onPointerMove: handleCanvasPointerMove,
19323
19966
  onPointerUp: handleCanvasPointerUp,
@@ -19449,7 +20092,7 @@ function Canvas2D({
19449
20092
  }
19450
20093
  ) });
19451
20094
  }
19452
- var canvas2DLog;
20095
+ var canvas2DLog, EDIT_SELECTION_COLOR, EDIT_HANDLE_SIZE_PX, EDIT_SELECTION_CORNERS;
19453
20096
  var init_Canvas2D = __esm({
19454
20097
  "components/game/molecules/Canvas2D.tsx"() {
19455
20098
  "use client";
@@ -19474,8 +20117,12 @@ var init_Canvas2D = __esm({
19474
20117
  init_DrawGroup();
19475
20118
  init_registry();
19476
20119
  init_hitTest();
20120
+ init_contract();
19477
20121
  init_isometric();
19478
20122
  canvas2DLog = logger.createLogger("almadar:ui:game-canvas");
20123
+ EDIT_SELECTION_COLOR = "#3b82f6";
20124
+ EDIT_HANDLE_SIZE_PX = 8;
20125
+ EDIT_SELECTION_CORNERS = [[0, 0], [1, 0], [0, 1], [1, 1]];
19479
20126
  Canvas2D.displayName = "Canvas2D";
19480
20127
  }
19481
20128
  });
@@ -19517,6 +20164,12 @@ function Canvas({
19517
20164
  featureClickEvent,
19518
20165
  keyMap,
19519
20166
  keyUpMap,
20167
+ editable,
20168
+ selectedId,
20169
+ onSelect,
20170
+ onMove,
20171
+ selectEvent,
20172
+ moveEvent,
19520
20173
  children
19521
20174
  }) {
19522
20175
  canvasLog.debug("Canvas render", { mode, drawablesCount: drawables?.length, projection, camera: camera ? JSON.stringify(camera) : void 0 });
@@ -19594,6 +20247,12 @@ function Canvas({
19594
20247
  tileLeaveEvent,
19595
20248
  keyMap,
19596
20249
  keyUpMap,
20250
+ editable,
20251
+ selectedId,
20252
+ onSelect,
20253
+ onMove,
20254
+ selectEvent,
20255
+ moveEvent,
19597
20256
  ...children !== void 0 ? { children } : {}
19598
20257
  }
19599
20258
  );
@@ -21976,6 +22635,12 @@ function commandMatches(command, query) {
21976
22635
  if (matchesQuery(query, command.label)) return true;
21977
22636
  return (command.keywords ?? []).some((keyword) => matchesQuery(query, keyword));
21978
22637
  }
22638
+ function dispatchCommandPaletteCommand(command, deps) {
22639
+ if (command.disabled) return;
22640
+ if (command.event) deps.emit(`UI:${command.event}`, { commandId: command.id });
22641
+ if (command.action) deps.emit(`UI:${command.action}`, command.actionPayload ?? {});
22642
+ deps.onSelect?.(command);
22643
+ }
21979
22644
  var UNGROUPED; exports.CommandPalette = void 0;
21980
22645
  var init_CommandPalette = __esm({
21981
22646
  "components/core/molecules/CommandPalette.tsx"() {
@@ -22030,9 +22695,7 @@ var init_CommandPalette = __esm({
22030
22695
  const handleSelect = React79.useCallback(
22031
22696
  (command) => {
22032
22697
  if (command.disabled) return;
22033
- if (command.event) eventBus.emit(`UI:${command.event}`, { commandId: command.id });
22034
- if (command.action) eventBus.emit(`UI:${command.action}`, command.actionPayload ?? {});
22035
- onSelect?.(command);
22698
+ dispatchCommandPaletteCommand(command, { emit: eventBus.emit, onSelect });
22036
22699
  handleClose();
22037
22700
  },
22038
22701
  [eventBus, onSelect, handleClose]
@@ -28252,9 +28915,9 @@ function debug(...args) {
28252
28915
  const [first, ...rest] = args;
28253
28916
  const message = typeof first === "string" ? first : "<debug>";
28254
28917
  if (rest.length === 0 && typeof first === "string") {
28255
- log7.debug(message);
28918
+ log8.debug(message);
28256
28919
  } else {
28257
- log7.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28920
+ log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28258
28921
  }
28259
28922
  }
28260
28923
  function debugGroup(label) {
@@ -28282,11 +28945,11 @@ function toLogMetaValue(v) {
28282
28945
  }
28283
28946
  return String(v);
28284
28947
  }
28285
- var NAMESPACE, log7;
28948
+ var NAMESPACE, log8;
28286
28949
  var init_debug = __esm({
28287
28950
  "lib/debug.ts"() {
28288
28951
  NAMESPACE = "almadar:ui:debug";
28289
- log7 = logger.createLogger(NAMESPACE);
28952
+ log8 = logger.createLogger(NAMESPACE);
28290
28953
  logger.createLogger("almadar:ui:debug:input");
28291
28954
  logger.createLogger("almadar:ui:debug:collision");
28292
28955
  logger.createLogger("almadar:ui:debug:physics");
@@ -30972,15 +31635,19 @@ function GameAudioToggle({
30972
31635
  size = "sm",
30973
31636
  className,
30974
31637
  onAsset,
30975
- offAsset
31638
+ offAsset,
31639
+ toggleEvent
30976
31640
  }) {
30977
31641
  const ctx = providers.useGameAudioContextOptional();
30978
31642
  const [localMuted, setLocalMuted] = React79.useState(false);
30979
31643
  const muted = ctx ? ctx.muted : localMuted;
30980
31644
  const setMuted = ctx ? ctx.setMuted : setLocalMuted;
31645
+ const eventBus = useEventBus();
30981
31646
  const handleToggle = React79.useCallback(() => {
30982
- setMuted(!muted);
30983
- }, [muted, setMuted]);
31647
+ const next = !muted;
31648
+ setMuted(next);
31649
+ if (toggleEvent) eventBus.emit(`UI:${toggleEvent}`, { muted: next });
31650
+ }, [muted, setMuted, toggleEvent, eventBus]);
30984
31651
  const activeAsset = muted ? offAsset : onAsset;
30985
31652
  return /* @__PURE__ */ jsxRuntime.jsx(
30986
31653
  exports.Button,
@@ -30999,6 +31666,7 @@ var init_GameAudioToggle = __esm({
30999
31666
  "use client";
31000
31667
  init_atoms();
31001
31668
  init_cn();
31669
+ init_useEventBus();
31002
31670
  init_GameIcon();
31003
31671
  GameAudioToggle.displayName = "GameAudioToggle";
31004
31672
  }
@@ -31270,6 +31938,47 @@ var init_useGameAudio = __esm({
31270
31938
  useGameAudio.displayName = "useGameAudio";
31271
31939
  }
31272
31940
  });
31941
+ function GameAudioCue({
31942
+ cue,
31943
+ cueSeq,
31944
+ music,
31945
+ muted,
31946
+ volume,
31947
+ manifest,
31948
+ baseUrl
31949
+ }) {
31950
+ const { play, playMusic, stopMusic, setMuted, setMasterVolume } = useGameAudio({
31951
+ manifest,
31952
+ baseUrl,
31953
+ initialMuted: muted,
31954
+ initialVolume: volume
31955
+ });
31956
+ const prevCueSeqRef = React79.useRef(cueSeq);
31957
+ React79.useEffect(() => {
31958
+ if (cue && cueSeq !== void 0 && cueSeq !== prevCueSeqRef.current) {
31959
+ play(cue);
31960
+ }
31961
+ prevCueSeqRef.current = cueSeq;
31962
+ }, [cue, cueSeq, play]);
31963
+ React79.useEffect(() => {
31964
+ if (music) playMusic(music);
31965
+ else stopMusic();
31966
+ }, [music, playMusic, stopMusic]);
31967
+ React79.useEffect(() => {
31968
+ if (muted !== void 0) setMuted(muted);
31969
+ }, [muted, setMuted]);
31970
+ React79.useEffect(() => {
31971
+ if (volume !== void 0) setMasterVolume(volume);
31972
+ }, [volume, setMasterVolume]);
31973
+ return null;
31974
+ }
31975
+ var init_GameAudioCue = __esm({
31976
+ "components/game/atoms/GameAudioCue.tsx"() {
31977
+ "use client";
31978
+ init_useGameAudio();
31979
+ GameAudioCue.displayName = "GameAudioCue";
31980
+ }
31981
+ });
31273
31982
  function isKnownState(s) {
31274
31983
  return s in DEFAULT_STATE_STYLES;
31275
31984
  }
@@ -32166,15 +32875,18 @@ var init_physicsPresets = __esm({
32166
32875
  ];
32167
32876
  }
32168
32877
  });
32169
- var GAME_FONTS; exports.GameShell = void 0;
32170
- var init_GameShell = __esm({
32171
- "components/game/templates/GameShell.tsx"() {
32172
- init_cn();
32173
- init_Box();
32174
- init_Card();
32175
- init_Typography();
32176
- init_AtlasImage();
32177
- GAME_FONTS = {
32878
+
32879
+ // lib/gameFonts.ts
32880
+ function resolveGameFontFamily(input) {
32881
+ if (!input) return void 0;
32882
+ const resolved = GAME_FONT_KEYS[input];
32883
+ if (resolved) return `'${resolved}', ui-sans-serif, system-ui, sans-serif`;
32884
+ return input;
32885
+ }
32886
+ var GAME_FONT_KEYS;
32887
+ var init_gameFonts = __esm({
32888
+ "lib/gameFonts.ts"() {
32889
+ GAME_FONT_KEYS = {
32178
32890
  fredoka: "Fredoka",
32179
32891
  future: "Kenney Future",
32180
32892
  "future-narrow": "Kenney Future Narrow",
@@ -32182,6 +32894,17 @@ var init_GameShell = __esm({
32182
32894
  blocks: "Kenney Blocks",
32183
32895
  mini: "Kenney Mini"
32184
32896
  };
32897
+ }
32898
+ });
32899
+ exports.GameShell = void 0;
32900
+ var init_GameShell = __esm({
32901
+ "components/game/templates/GameShell.tsx"() {
32902
+ init_cn();
32903
+ init_gameFonts();
32904
+ init_Box();
32905
+ init_Card();
32906
+ init_Typography();
32907
+ init_AtlasImage();
32185
32908
  exports.GameShell = ({
32186
32909
  appName = "Game",
32187
32910
  hud,
@@ -32195,7 +32918,7 @@ var init_GameShell = __esm({
32195
32918
  fontFamily,
32196
32919
  "data-theme": dataTheme
32197
32920
  }) => {
32198
- const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
32921
+ const displayFont = resolveGameFontFamily(fontFamily);
32199
32922
  return /* @__PURE__ */ jsxRuntime.jsxs(
32200
32923
  exports.Box,
32201
32924
  {
@@ -32214,7 +32937,7 @@ var init_GameShell = __esm({
32214
32937
  // passed — an always-on inline stamp would shadow the orbital's
32215
32938
  // inline-theme font-family-display token (inline style beats the
32216
32939
  // theme provider's vars for the whole shell subtree).
32217
- ...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
32940
+ ...displayFont ? { "--font-family-display": displayFont } : {}
32218
32941
  },
32219
32942
  children: [
32220
32943
  backgroundAsset && /* @__PURE__ */ jsxRuntime.jsx(
@@ -32347,6 +33070,7 @@ var init_molecules = __esm({
32347
33070
  init_Canvas();
32348
33071
  init_useUnitSpriteAtlas();
32349
33072
  init_GameAudioToggle();
33073
+ init_GameAudioCue();
32350
33074
  init_useGameAudio();
32351
33075
  init_useCamera();
32352
33076
  init_TraitStateViewer();
@@ -32375,6 +33099,7 @@ var init_MathCanvas = __esm({
32375
33099
  init_perf();
32376
33100
  init_atoms();
32377
33101
  init_Stack();
33102
+ init_gameFonts();
32378
33103
  init_LearningCanvas();
32379
33104
  exports.MathCanvas = ({
32380
33105
  className,
@@ -32394,6 +33119,7 @@ var init_MathCanvas = __esm({
32394
33119
  showTickLabels = false,
32395
33120
  tickLabelFontSize = 10,
32396
33121
  labelFontSize = 12,
33122
+ fontFamily: fontFamilyProp,
32397
33123
  showCurveLabels = false,
32398
33124
  curves = [],
32399
33125
  points = [],
@@ -32416,6 +33142,7 @@ var init_MathCanvas = __esm({
32416
33142
  error
32417
33143
  }) => {
32418
33144
  const eventBus = useEventBus();
33145
+ const fontFamily = resolveGameFontFamily(fontFamilyProp);
32419
33146
  const keyMapKey = keyMap ? JSON.stringify(keyMap) : null;
32420
33147
  const keyUpMapKey = keyUpMap ? JSON.stringify(keyUpMap) : null;
32421
33148
  const stableKeyMap = React79.useMemo(() => keyMap, [keyMapKey]);
@@ -32465,18 +33192,18 @@ var init_MathCanvas = __esm({
32465
33192
  let kx = 0;
32466
33193
  for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep, kx++) {
32467
33194
  if (kx % labelEveryX === 0 && x !== 0) {
32468
- out.push({ type: "text", x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
33195
+ out.push({ type: "text", fontFamily, x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
32469
33196
  }
32470
33197
  }
32471
33198
  const labelEveryY = Math.max(1, Math.ceil((yMax - yMin) / gridStep / Math.floor(plotH / 28)));
32472
33199
  let ky = 0;
32473
33200
  for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep, ky++) {
32474
33201
  if (ky % labelEveryY === 0 && y !== 0) {
32475
- out.push({ type: "text", x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
33202
+ out.push({ type: "text", fontFamily, x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
32476
33203
  }
32477
33204
  }
32478
33205
  if (xMin <= 0 && xMax >= 0 && yMin <= 0 && yMax >= 0) {
32479
- out.push({ type: "text", x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
33206
+ out.push({ type: "text", fontFamily, x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
32480
33207
  }
32481
33208
  }
32482
33209
  for (const region of regions) {
@@ -32503,6 +33230,7 @@ var init_MathCanvas = __esm({
32503
33230
  const mid = Math.floor(region.samples.length / 2);
32504
33231
  out.push({
32505
33232
  type: "text",
33233
+ fontFamily,
32506
33234
  x: mapX((first.x + last.x) / 2),
32507
33235
  y: (mapY(region.samples[mid].y) + mapY(baseline)) / 2,
32508
33236
  text: region.label,
@@ -32539,14 +33267,14 @@ var init_MathCanvas = __esm({
32539
33267
  const px = mapX(guide.at);
32540
33268
  out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color, dash });
32541
33269
  if (guide.label) {
32542
- out.push({ type: "text", x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
33270
+ out.push({ type: "text", fontFamily, x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
32543
33271
  }
32544
33272
  } else {
32545
33273
  if (guide.at < yMin || guide.at > yMax) continue;
32546
33274
  const py = mapY(guide.at);
32547
33275
  out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color, dash });
32548
33276
  if (guide.label) {
32549
- out.push({ type: "text", x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
33277
+ out.push({ type: "text", fontFamily, x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
32550
33278
  }
32551
33279
  }
32552
33280
  }
@@ -32585,6 +33313,7 @@ var init_MathCanvas = __esm({
32585
33313
  if (showCurveLabels && curve.label && lastInRange) {
32586
33314
  out.push({
32587
33315
  type: "text",
33316
+ fontFamily,
32588
33317
  x: mapX(lastInRange.x) + 6,
32589
33318
  y: mapY(lastInRange.y) - 6,
32590
33319
  text: curve.label,
@@ -32622,6 +33351,7 @@ var init_MathCanvas = __esm({
32622
33351
  if (hop.label) {
32623
33352
  out.push({
32624
33353
  type: "text",
33354
+ fontFamily,
32625
33355
  x: (x1 + x2) / 2,
32626
33356
  y: xAxisY - peak - 8,
32627
33357
  text: hop.label,
@@ -32649,6 +33379,7 @@ var init_MathCanvas = __esm({
32649
33379
  const rad = mid * Math.PI / 180;
32650
33380
  out.push({
32651
33381
  type: "text",
33382
+ fontFamily,
32652
33383
  x: mapX(angle.x + 1.35 * radius * Math.cos(rad)),
32653
33384
  y: mapY(angle.y + 1.35 * radius * Math.sin(rad)),
32654
33385
  text: angle.label,
@@ -32670,7 +33401,7 @@ var init_MathCanvas = __esm({
32670
33401
  fill: isOpen ? "#ffffff" : p.color ?? "#dc2626"
32671
33402
  });
32672
33403
  if (p.label) {
32673
- out.push({ type: "text", x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
33404
+ out.push({ type: "text", fontFamily, x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
32674
33405
  }
32675
33406
  }
32676
33407
  for (const v of vectors) {
@@ -32681,7 +33412,7 @@ var init_MathCanvas = __esm({
32681
33412
  const y2 = mapY(v.y + v.vy);
32682
33413
  out.push({ type: "arrow", x1, y1, x2, y2, color: v.color ?? "#7c3aed", lineWidth: 2 });
32683
33414
  if (v.label) {
32684
- out.push({ type: "text", x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
33415
+ out.push({ type: "text", fontFamily, x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
32685
33416
  }
32686
33417
  }
32687
33418
  out.push(...shapes);
@@ -32702,6 +33433,7 @@ var init_MathCanvas = __esm({
32702
33433
  showTickLabels,
32703
33434
  tickLabelFontSize,
32704
33435
  labelFontSize,
33436
+ fontFamily,
32705
33437
  showCurveLabels,
32706
33438
  curves,
32707
33439
  points,
@@ -32757,6 +33489,7 @@ var init_MathCanvas = __esm({
32757
33489
  width,
32758
33490
  height,
32759
33491
  backgroundColor,
33492
+ fontFamily,
32760
33493
  shapes: derivedShapes,
32761
33494
  drawables,
32762
33495
  projector,
@@ -33989,13 +34722,13 @@ var init_MapView = __esm({
33989
34722
  shadowSize: [41, 41]
33990
34723
  });
33991
34724
  L.Marker.prototype.options.icon = defaultIcon;
33992
- const { useEffect: useEffect70, useRef: useRef67, useCallback: useCallback109, useState: useState109 } = React79__namespace.default;
34725
+ const { useEffect: useEffect72, useRef: useRef70, useCallback: useCallback109, useState: useState110 } = React79__namespace.default;
33993
34726
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
33994
34727
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
33995
34728
  function MapUpdater({ centerLat, centerLng, zoom }) {
33996
34729
  const map = useMap();
33997
- const prevRef = useRef67({ centerLat, centerLng, zoom });
33998
- useEffect70(() => {
34730
+ const prevRef = useRef70({ centerLat, centerLng, zoom });
34731
+ useEffect72(() => {
33999
34732
  const prev = prevRef.current;
34000
34733
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
34001
34734
  map.setView([centerLat, centerLng], zoom);
@@ -34006,7 +34739,7 @@ var init_MapView = __esm({
34006
34739
  }
34007
34740
  function MapClickHandler({ onMapClick }) {
34008
34741
  const map = useMap();
34009
- useEffect70(() => {
34742
+ useEffect72(() => {
34010
34743
  if (!onMapClick) return;
34011
34744
  const handler = (e) => {
34012
34745
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -34034,7 +34767,7 @@ var init_MapView = __esm({
34034
34767
  showAttribution = true
34035
34768
  }) {
34036
34769
  const eventBus = useEventBus2();
34037
- const [clickedPosition, setClickedPosition] = useState109(null);
34770
+ const [clickedPosition, setClickedPosition] = useState110(null);
34038
34771
  const handleMapClick = useCallback109((lat, lng) => {
34039
34772
  if (showClickedPin) {
34040
34773
  setClickedPosition({ lat, lng });
@@ -48972,7 +49705,7 @@ function getAllEvents(traits2) {
48972
49705
  function EventDispatcherTab({ traits: traits2, schema }) {
48973
49706
  const eventBus = useEventBus();
48974
49707
  const { t } = hooks.useTranslate();
48975
- const [log19, setLog] = React79__namespace.useState([]);
49708
+ const [log20, setLog] = React79__namespace.useState([]);
48976
49709
  const prevStatesRef = React79__namespace.useRef(/* @__PURE__ */ new Map());
48977
49710
  React79__namespace.useEffect(() => {
48978
49711
  for (const trait of traits2) {
@@ -49036,9 +49769,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
49036
49769
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.otherEvents") }),
49037
49770
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
49038
49771
  ] }),
49039
- log19.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
49772
+ log20.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
49040
49773
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.recentTransitions") }),
49041
- /* @__PURE__ */ jsxRuntime.jsx(exports.Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "font-mono text-xs", children: [
49774
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Stack, { gap: "xs", children: log20.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "font-mono text-xs", children: [
49042
49775
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary", children: entry.traitName }),
49043
49776
  " ",
49044
49777
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: entry.from }),
@@ -51229,6 +51962,7 @@ var init_component_registry_generated = __esm({
51229
51962
  init_FormSection();
51230
51963
  init_FormSectionHeader();
51231
51964
  init_FxOverlay();
51965
+ init_GameAudioCue();
51232
51966
  init_GameAudioToggle();
51233
51967
  init_GameHud();
51234
51968
  init_GameIcon();
@@ -51506,6 +52240,7 @@ var init_component_registry_generated = __esm({
51506
52240
  "FormLayout": exports.FormLayout,
51507
52241
  "FormSectionHeader": exports.FormSectionHeader,
51508
52242
  "FxOverlay": exports.FxOverlay,
52243
+ "GameAudioCue": GameAudioCue,
51509
52244
  "GameAudioToggle": GameAudioToggle,
51510
52245
  "GameHud": GameHud,
51511
52246
  "GameIcon": GameIcon,
@@ -52992,7 +53727,7 @@ init_AboutPageTemplate();
52992
53727
 
52993
53728
  // components/index.ts
52994
53729
  init_cn();
52995
- var log8 = logger.createLogger("almadar:ui:orbital-history");
53730
+ var log9 = logger.createLogger("almadar:ui:orbital-history");
52996
53731
  function useOrbitalHistory(options) {
52997
53732
  const { appId, authToken, userId, onHistoryChange, onRevertSuccess } = options;
52998
53733
  const getHeaders = React79.useCallback(() => {
@@ -53054,7 +53789,7 @@ function useOrbitalHistory(options) {
53054
53789
  setCurrentVersion(mergedTimeline[0].version);
53055
53790
  }
53056
53791
  } catch (err) {
53057
- log8.error("Failed to load history", { error: err instanceof Error ? err : String(err) });
53792
+ log9.error("Failed to load history", { error: err instanceof Error ? err : String(err) });
53058
53793
  setError(err instanceof Error ? err.message : "Failed to load history");
53059
53794
  } finally {
53060
53795
  setIsLoading(false);
@@ -53087,7 +53822,7 @@ function useOrbitalHistory(options) {
53087
53822
  error: data.error || "Unknown error during revert"
53088
53823
  };
53089
53824
  } catch (err) {
53090
- log8.error("Failed to revert", { error: err instanceof Error ? err : String(err) });
53825
+ log9.error("Failed to revert", { error: err instanceof Error ? err : String(err) });
53091
53826
  return {
53092
53827
  success: false,
53093
53828
  error: err instanceof Error ? err.message : "Failed to revert"
@@ -53111,7 +53846,7 @@ function useOrbitalHistory(options) {
53111
53846
  refresh
53112
53847
  };
53113
53848
  }
53114
- var log9 = logger.createLogger("almadar:ui:filesystem");
53849
+ var log10 = logger.createLogger("almadar:ui:filesystem");
53115
53850
  function useFileSystem() {
53116
53851
  const [status, setStatus] = React79.useState("idle");
53117
53852
  const [error, setError] = React79.useState(null);
@@ -53126,7 +53861,7 @@ function useFileSystem() {
53126
53861
  setError(null);
53127
53862
  setIsLoading(true);
53128
53863
  try {
53129
- log9.debug("Booting WebContainer");
53864
+ log10.debug("Booting WebContainer");
53130
53865
  await new Promise((resolve) => setTimeout(resolve, 100));
53131
53866
  setStatus("ready");
53132
53867
  } catch (err) {
@@ -53187,7 +53922,7 @@ function useFileSystem() {
53187
53922
  setFiles(newTree);
53188
53923
  setStatus("running");
53189
53924
  } catch (err) {
53190
- log9.error("Failed to mount files", { error: err instanceof Error ? err : String(err) });
53925
+ log10.error("Failed to mount files", { error: err instanceof Error ? err : String(err) });
53191
53926
  } finally {
53192
53927
  setIsLoading(false);
53193
53928
  }
@@ -53228,7 +53963,7 @@ function useFileSystem() {
53228
53963
  const path = contentArg !== void 0 ? pathOrContent : selectedPath;
53229
53964
  const content = contentArg !== void 0 ? contentArg : pathOrContent;
53230
53965
  if (!path) {
53231
- log9.warn("updateContent called without path and no file selected");
53966
+ log10.warn("updateContent called without path and no file selected");
53232
53967
  return;
53233
53968
  }
53234
53969
  setFileContents((prev) => {
@@ -53244,14 +53979,14 @@ function useFileSystem() {
53244
53979
  setSelectedFile((prev) => prev ? { ...prev, content, isDirty: true } : null);
53245
53980
  }, []);
53246
53981
  const refreshTree = React79.useCallback(async () => {
53247
- log9.debug("Refreshing tree");
53982
+ log10.debug("Refreshing tree");
53248
53983
  }, []);
53249
53984
  const runCommand = React79.useCallback(async (command) => {
53250
- log9.debug("Running command", { command });
53985
+ log10.debug("Running command", { command });
53251
53986
  return { exitCode: 0, output: "" };
53252
53987
  }, []);
53253
53988
  const startDevServer = React79.useCallback(async () => {
53254
- log9.debug("Starting dev server");
53989
+ log10.debug("Starting dev server");
53255
53990
  setPreviewUrl("http://localhost:5173");
53256
53991
  }, []);
53257
53992
  return {
@@ -53274,7 +54009,7 @@ function useFileSystem() {
53274
54009
  startDevServer
53275
54010
  };
53276
54011
  }
53277
- var log10 = logger.createLogger("almadar:ui:extensions");
54012
+ var log11 = logger.createLogger("almadar:ui:extensions");
53278
54013
  var defaultManifest = {
53279
54014
  languages: {
53280
54015
  typescript: { extensions: [".ts", ".tsx"], icon: "ts", color: "#3178c6" },
@@ -53293,7 +54028,7 @@ function useExtensions(options) {
53293
54028
  const [isLoading, setIsLoading] = React79.useState(false);
53294
54029
  const [error, setError] = React79.useState(null);
53295
54030
  const loadExtension = React79.useCallback(async (extensionId) => {
53296
- log10.debug("Loading extension", { extensionId });
54031
+ log11.debug("Loading extension", { extensionId });
53297
54032
  }, []);
53298
54033
  const loadExtensions = React79.useCallback(async () => {
53299
54034
  setIsLoading(true);
@@ -53365,7 +54100,7 @@ function useExtensions(options) {
53365
54100
  getExtensionForFile
53366
54101
  };
53367
54102
  }
53368
- var log11 = logger.createLogger("almadar:ui:file-editor");
54103
+ var log12 = logger.createLogger("almadar:ui:file-editor");
53369
54104
  function useFileEditor(options) {
53370
54105
  const { extensions, fileSystem, onSchemaUpdate } = options;
53371
54106
  const [openFiles, setOpenFiles] = React79.useState([]);
@@ -53390,7 +54125,7 @@ function useFileEditor(options) {
53390
54125
  setOpenFiles((prev) => [...prev, newFile]);
53391
54126
  setActiveFilePath(path);
53392
54127
  } catch (err) {
53393
- log11.error("Failed to open file", { error: err instanceof Error ? err : String(err) });
54128
+ log12.error("Failed to open file", { error: err instanceof Error ? err : String(err) });
53394
54129
  }
53395
54130
  }, [openFiles, fileSystem, extensions]);
53396
54131
  const closeFile = React79.useCallback((path) => {
@@ -53451,7 +54186,7 @@ function useFileEditor(options) {
53451
54186
  }
53452
54187
  }
53453
54188
  } catch (err) {
53454
- log11.error("Failed to save file", { error: err instanceof Error ? err : String(err) });
54189
+ log12.error("Failed to save file", { error: err instanceof Error ? err : String(err) });
53455
54190
  } finally {
53456
54191
  setIsSaving(false);
53457
54192
  }
@@ -53480,7 +54215,7 @@ function useFileEditor(options) {
53480
54215
  saveAllFiles
53481
54216
  };
53482
54217
  }
53483
- var log12 = logger.createLogger("almadar:ui:compile");
54218
+ var log13 = logger.createLogger("almadar:ui:compile");
53484
54219
  function useCompile() {
53485
54220
  const [isCompiling, setIsCompiling] = React79.useState(false);
53486
54221
  const [stage, setStage] = React79.useState("idle");
@@ -53491,7 +54226,7 @@ function useCompile() {
53491
54226
  setStage("compiling");
53492
54227
  setError(null);
53493
54228
  try {
53494
- log12.debug("Compiling schema", { name: schema.name });
54229
+ log13.debug("Compiling schema", { name: schema.name });
53495
54230
  const result = {
53496
54231
  success: true,
53497
54232
  files: []
@@ -53517,7 +54252,7 @@ function useCompile() {
53517
54252
  compileSchema
53518
54253
  };
53519
54254
  }
53520
- var log13 = logger.createLogger("almadar:ui:preview");
54255
+ var log14 = logger.createLogger("almadar:ui:preview");
53521
54256
  function usePreview(options) {
53522
54257
  const [previewUrl, setPreviewUrl] = React79.useState(null);
53523
54258
  const [isLoading, setIsLoading] = React79.useState(!!options?.appId);
@@ -53551,17 +54286,17 @@ function usePreview(options) {
53551
54286
  setIsLoading(false);
53552
54287
  return;
53553
54288
  }
53554
- log13.debug("Setting up preview for app", { appId });
54289
+ log14.debug("Setting up preview for app", { appId });
53555
54290
  setPreviewUrl(`/api/orbitals/${appId}`);
53556
54291
  setIsLoading(false);
53557
54292
  }, [options?.appId]);
53558
54293
  const startPreview = React79.useCallback(async () => {
53559
- log13.debug("startPreview called");
54294
+ log14.debug("startPreview called");
53560
54295
  }, []);
53561
54296
  const stopPreview = React79.useCallback(async () => {
53562
54297
  setIsLoading(true);
53563
54298
  try {
53564
- log13.debug("Stopping preview server");
54299
+ log14.debug("Stopping preview server");
53565
54300
  setPreviewUrl(null);
53566
54301
  setApp(null);
53567
54302
  } finally {
@@ -53570,15 +54305,15 @@ function usePreview(options) {
53570
54305
  }, []);
53571
54306
  const refresh = React79.useCallback(async () => {
53572
54307
  if (!previewUrl) return;
53573
- log13.debug("Refreshing preview");
54308
+ log14.debug("Refreshing preview");
53574
54309
  setPreviewUrl(`${previewUrl.split("?")[0]}?t=${Date.now()}`);
53575
54310
  }, [previewUrl]);
53576
54311
  const handleRefresh = React79.useCallback(async () => {
53577
- log13.debug("Handle refresh");
54312
+ log14.debug("Handle refresh");
53578
54313
  await refresh();
53579
54314
  }, [refresh]);
53580
54315
  const handleReset = React79.useCallback(async () => {
53581
- log13.debug("Resetting preview");
54316
+ log14.debug("Resetting preview");
53582
54317
  setError(null);
53583
54318
  setLoadError(null);
53584
54319
  setErrorToast(null);
@@ -53612,7 +54347,7 @@ function usePreview(options) {
53612
54347
  dismissErrorToast
53613
54348
  };
53614
54349
  }
53615
- var log14 = logger.createLogger("almadar:ui:agent-chat");
54350
+ var log15 = logger.createLogger("almadar:ui:agent-chat");
53616
54351
  function useAgentChat(options) {
53617
54352
  const [messages, setMessages] = React79.useState([]);
53618
54353
  const [status, setStatus] = React79.useState("idle");
@@ -53635,7 +54370,7 @@ function useAgentChat(options) {
53635
54370
  timestamp: Date.now()
53636
54371
  };
53637
54372
  setMessages((prev) => [...prev, userMessage]);
53638
- log14.debug("Sending message", { content });
54373
+ log15.debug("Sending message", { content });
53639
54374
  const assistantMessage = {
53640
54375
  id: (Date.now() + 1).toString(),
53641
54376
  role: "assistant",
@@ -53658,7 +54393,7 @@ function useAgentChat(options) {
53658
54393
  setError(null);
53659
54394
  const skillName = Array.isArray(skill) ? skill[0] : skill;
53660
54395
  try {
53661
- log14.debug("Starting generation", () => ({ skillName, prompt, genOptions: JSON.stringify(genOptions) }));
54396
+ log15.debug("Starting generation", () => ({ skillName, prompt, genOptions: JSON.stringify(genOptions) }));
53662
54397
  await new Promise((resolve) => setTimeout(resolve, 100));
53663
54398
  setStatus("complete");
53664
54399
  options?.onComplete?.();
@@ -53670,10 +54405,10 @@ function useAgentChat(options) {
53670
54405
  }
53671
54406
  }, [options]);
53672
54407
  const continueConversation = React79.useCallback(async (message) => {
53673
- log14.debug("Continue conversation", { message: Array.isArray(message) ? message : [message] });
54408
+ log15.debug("Continue conversation", { message: Array.isArray(message) ? message : [message] });
53674
54409
  }, []);
53675
54410
  const resumeWithDecision = React79.useCallback(async (decisions) => {
53676
- log14.debug("Resume with decision", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
54411
+ log15.debug("Resume with decision", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
53677
54412
  setInterrupt(null);
53678
54413
  }, []);
53679
54414
  const cancel = React79.useCallback(() => {
@@ -53710,7 +54445,7 @@ function useAgentChat(options) {
53710
54445
  clearHistory
53711
54446
  };
53712
54447
  }
53713
- var log15 = logger.createLogger("almadar:ui:validation");
54448
+ var log16 = logger.createLogger("almadar:ui:validation");
53714
54449
  function useValidation() {
53715
54450
  const [result, setResult] = React79.useState(null);
53716
54451
  const [isValidating, setIsValidating] = React79.useState(false);
@@ -53724,7 +54459,7 @@ function useValidation() {
53724
54459
  setStage("validating");
53725
54460
  setProgressMessage("Validating schema...");
53726
54461
  try {
53727
- log15.debug("Validating app", { appId });
54462
+ log16.debug("Validating app", { appId });
53728
54463
  const validationResult = {
53729
54464
  valid: true,
53730
54465
  errors: [],
@@ -53777,7 +54512,7 @@ function useValidation() {
53777
54512
  reset
53778
54513
  };
53779
54514
  }
53780
- var log16 = logger.createLogger("almadar:ui:deep-agent");
54515
+ var log17 = logger.createLogger("almadar:ui:deep-agent");
53781
54516
  function useDeepAgentGeneration() {
53782
54517
  const [requests, setRequests] = React79.useState([]);
53783
54518
  const [currentRequest, setCurrentRequest] = React79.useState(null);
@@ -53801,7 +54536,7 @@ function useDeepAgentGeneration() {
53801
54536
  setCurrentRequest(request);
53802
54537
  setRequests((prev) => [...prev, request]);
53803
54538
  try {
53804
- log16.debug("Generating from prompt", { prompt });
54539
+ log17.debug("Generating from prompt", { prompt });
53805
54540
  await new Promise((resolve) => setTimeout(resolve, 100));
53806
54541
  request.status = "completed";
53807
54542
  setCurrentRequest(request);
@@ -53821,7 +54556,7 @@ function useDeepAgentGeneration() {
53821
54556
  }
53822
54557
  }, []);
53823
54558
  const startGeneration = React79.useCallback(async (skill, prompt, _options) => {
53824
- log16.debug("Starting generation with skill", { skill });
54559
+ log17.debug("Starting generation with skill", { skill });
53825
54560
  await generate(prompt);
53826
54561
  }, [generate]);
53827
54562
  const cancelGeneration = React79.useCallback(() => {
@@ -53843,7 +54578,7 @@ function useDeepAgentGeneration() {
53843
54578
  setIsComplete(false);
53844
54579
  }, []);
53845
54580
  const submitInterruptDecisions = React79.useCallback((decisions) => {
53846
- log16.debug("Submitting interrupt decisions", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
54581
+ log17.debug("Submitting interrupt decisions", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
53847
54582
  setInterrupt(null);
53848
54583
  }, []);
53849
54584
  return {
@@ -53865,6 +54600,66 @@ function useDeepAgentGeneration() {
53865
54600
 
53866
54601
  // hooks/index.ts
53867
54602
  init_useEventBus();
54603
+
54604
+ // hooks/useKeyboardRouter.ts
54605
+ init_useEventBus();
54606
+ function useKeyboardRouter(options) {
54607
+ const {
54608
+ captureTable,
54609
+ editorFocusEvent = "EDITOR_FOCUS",
54610
+ editorBlurEvent = "EDITOR_BLUR",
54611
+ keyEvent = "KEY",
54612
+ enabled = true
54613
+ } = options;
54614
+ const eventBus = useEventBus();
54615
+ const captureTableRef = React79.useRef(captureTable);
54616
+ captureTableRef.current = captureTable;
54617
+ const focusedEditorIdRef = React79.useRef(null);
54618
+ React79.useEffect(() => {
54619
+ const unsubFocus = eventBus.on(`UI:${editorFocusEvent}`, (event) => {
54620
+ const editorId = event.payload?.editorId;
54621
+ if (typeof editorId === "string") {
54622
+ focusedEditorIdRef.current = editorId;
54623
+ }
54624
+ });
54625
+ const unsubBlur = eventBus.on(`UI:${editorBlurEvent}`, (event) => {
54626
+ const editorId = event.payload?.editorId;
54627
+ if (typeof editorId === "string" && focusedEditorIdRef.current === editorId) {
54628
+ focusedEditorIdRef.current = null;
54629
+ }
54630
+ });
54631
+ return () => {
54632
+ unsubFocus();
54633
+ unsubBlur();
54634
+ };
54635
+ }, [eventBus, editorFocusEvent, editorBlurEvent]);
54636
+ React79.useEffect(() => {
54637
+ if (!enabled) return;
54638
+ const handleKeyDown = (event) => {
54639
+ if (event.isComposing) return;
54640
+ const target = focusedEditorIdRef.current ?? "shell";
54641
+ const entry = captureTableRef.current[target];
54642
+ const captured = entry !== void 0 && (entry.mode === "any" || entry.keys.has(event.key));
54643
+ if (captured) {
54644
+ event.preventDefault();
54645
+ }
54646
+ eventBus.emit(`UI:${keyEvent}`, {
54647
+ editorId: target,
54648
+ key: event.key,
54649
+ code: event.code,
54650
+ ctrl: event.ctrlKey,
54651
+ alt: event.altKey,
54652
+ shift: event.shiftKey,
54653
+ meta: event.metaKey,
54654
+ repeat: event.repeat
54655
+ });
54656
+ };
54657
+ window.addEventListener("keydown", handleKeyDown, { capture: true });
54658
+ return () => {
54659
+ window.removeEventListener("keydown", handleKeyDown, { capture: true });
54660
+ };
54661
+ }, [eventBus, enabled, keyEvent]);
54662
+ }
53868
54663
  function expressionEqual(a, b) {
53869
54664
  if (Object.is(a, b)) return true;
53870
54665
  if (Array.isArray(a) && Array.isArray(b)) {
@@ -53947,21 +54742,12 @@ function reconcileSlotProps(prev, next) {
53947
54742
  }
53948
54743
 
53949
54744
  // hooks/useUISlots.ts
53950
- var log17 = logger.createLogger("almadar:ui:ui-slots");
54745
+ var log18 = logger.createLogger("almadar:ui:ui-slots");
53951
54746
  var DEFAULT_SOURCE_KEY = "__default__";
53952
54747
  var MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
53953
- var ALL_SLOTS2 = [
53954
- "main",
53955
- "sidebar",
53956
- "modal",
53957
- "drawer",
53958
- "overlay",
53959
- "center",
53960
- "toast",
53961
- "hud-top",
53962
- "hud-bottom",
53963
- "floating"
53964
- ];
54748
+ var ALL_SLOTS2 = core.UI_SLOTS.filter(
54749
+ (slot) => !slot.includes(".") && slot !== "hud" && slot !== "screen"
54750
+ );
53965
54751
  var DEFAULT_SLOTS = ALL_SLOTS2.reduce(
53966
54752
  (acc, slot) => {
53967
54753
  acc[slot] = null;
@@ -54024,7 +54810,7 @@ function useUISlotManager() {
54024
54810
  try {
54025
54811
  callback(slot, content);
54026
54812
  } catch (error) {
54027
- log17.error("Subscriber error", { error: error instanceof Error ? error : String(error) });
54813
+ log18.error("Subscriber error", { error: error instanceof Error ? error : String(error) });
54028
54814
  }
54029
54815
  });
54030
54816
  }, []);
@@ -54036,7 +54822,7 @@ function useUISlotManager() {
54036
54822
  try {
54037
54823
  callback(content);
54038
54824
  } catch (error) {
54039
- log17.error("Trait subscriber error", { traitName, error: error instanceof Error ? error : String(error) });
54825
+ log18.error("Trait subscriber error", { traitName, error: error instanceof Error ? error : String(error) });
54040
54826
  }
54041
54827
  });
54042
54828
  },
@@ -54093,7 +54879,7 @@ function useUISlotManager() {
54093
54879
  const slotSources = prev[config.target] ?? {};
54094
54880
  const existing = slotSources[sourceKey];
54095
54881
  if (existing && existing.priority > content.priority) {
54096
- log17.warn("Slot already has higher priority content", {
54882
+ log18.warn("Slot already has higher priority content", {
54097
54883
  slot: config.target,
54098
54884
  sourceKey,
54099
54885
  existingPriority: existing.priority,
@@ -54104,7 +54890,7 @@ function useUISlotManager() {
54104
54890
  if (existing && existing.priority === content.priority && existing.pattern === content.pattern && existing.animation === content.animation && existing.transitionEvent === content.transitionEvent && existing.fromState === content.fromState && existing.entity === content.entity && existing.nodeId === content.nodeId && existing.autoDismissAt === void 0 && content.autoDismissAt === void 0 && existing.onDismiss === void 0 === (content.onDismiss === void 0)) {
54105
54891
  const reconciled = reconcileSlotProps(existing.props, content.props);
54106
54892
  if (reconciled.equal) {
54107
- log17.debug("slot:flush-bail", { slot: config.target, sourceKey, pattern: content.pattern });
54893
+ log18.debug("slot:flush-bail", { slot: config.target, sourceKey, pattern: content.pattern });
54108
54894
  return prev;
54109
54895
  }
54110
54896
  content.props = reconciled.value;
@@ -54116,7 +54902,7 @@ function useUISlotManager() {
54116
54902
  const nextAll = { ...prev, [config.target]: nextSources };
54117
54903
  const priorWriters = Object.keys(slotSources);
54118
54904
  if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
54119
- log17.warn("slot:contention", {
54905
+ log18.warn("slot:contention", {
54120
54906
  slot: config.target,
54121
54907
  writers: [priorWriters[0], sourceKey],
54122
54908
  patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
@@ -54126,7 +54912,7 @@ function useUISlotManager() {
54126
54912
  indexTraitRender(content.sourceTrait, content);
54127
54913
  notifyTraitSubscribers(content.sourceTrait, content);
54128
54914
  }
54129
- log17.info("slot:written", {
54915
+ log18.info("slot:written", {
54130
54916
  slot: config.target,
54131
54917
  sourceKey,
54132
54918
  sourceTrait: content.sourceTrait,
@@ -54171,7 +54957,7 @@ function useUISlotManager() {
54171
54957
  setSources((prev) => {
54172
54958
  const slotSources = prev[slot];
54173
54959
  if (!slotSources || !(sourceKey in slotSources)) {
54174
- log17.debug("slot:clear-noop", { slot, sourceTrait, reason: !slotSources ? "no-slot" : "no-source" });
54960
+ log18.debug("slot:clear-noop", { slot, sourceTrait, reason: !slotSources ? "no-slot" : "no-source" });
54175
54961
  return prev;
54176
54962
  }
54177
54963
  const content = slotSources[sourceKey];
@@ -54187,7 +54973,7 @@ function useUISlotManager() {
54187
54973
  }
54188
54974
  const nextSources = { ...slotSources };
54189
54975
  delete nextSources[sourceKey];
54190
- log17.info("slot:cleared", { slot, sourceTrait, lastPatternType: content.pattern });
54976
+ log18.info("slot:cleared", { slot, sourceTrait, lastPatternType: content.pattern });
54191
54977
  notifySubscribers(slot, aggregateSlot(nextSources));
54192
54978
  return { ...prev, [slot]: nextSources };
54193
54979
  });
@@ -54363,7 +55149,7 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
54363
55149
  };
54364
55150
  }, [eventBus, dispatch, stableListens]);
54365
55151
  }
54366
- var log18 = logger.createLogger("almadar:ui:shared-entity-store");
55152
+ var log19 = logger.createLogger("almadar:ui:shared-entity-store");
54367
55153
  var EMPTY_ENTITY_STATE = {};
54368
55154
  function createSharedEntityStore() {
54369
55155
  const states = /* @__PURE__ */ new Map();
@@ -54393,7 +55179,7 @@ function createSharedEntityStore() {
54393
55179
  try {
54394
55180
  callback();
54395
55181
  } catch (error) {
54396
- log18.error("Shared entity subscriber error", {
55182
+ log19.error("Shared entity subscriber error", {
54397
55183
  entityId,
54398
55184
  error: error instanceof Error ? error : String(error)
54399
55185
  });
@@ -54999,7 +55785,8 @@ var en_default = {
54999
55785
  "richTextEditor.image": "Insert image",
55000
55786
  "richTextEditor.imagePrompt": "Image URL",
55001
55787
  "richTextEditor.placeholder": "Start writing\u2026",
55002
- "form.imageUrlFallback": "\u2026or paste an image address"
55788
+ "form.imageUrlFallback": "\u2026or paste an image address",
55789
+ "mermaid.unrenderable": "This diagram could not be displayed. Its source is shown below."
55003
55790
  };
55004
55791
 
55005
55792
  // hooks/useTranslate.ts
@@ -55020,7 +55807,7 @@ var I18nContext = React79.createContext({
55020
55807
  });
55021
55808
  I18nContext.displayName = "I18nContext";
55022
55809
  var I18nProvider = I18nContext.Provider;
55023
- function useTranslate116() {
55810
+ function useTranslate117() {
55024
55811
  return React79.useContext(I18nContext);
55025
55812
  }
55026
55813
  function createTranslate(messages) {
@@ -55251,6 +56038,7 @@ exports.EditorSelect = EditorSelect;
55251
56038
  exports.EditorSlider = EditorSlider;
55252
56039
  exports.EditorTextInput = EditorTextInput;
55253
56040
  exports.EditorToolbar = EditorToolbar;
56041
+ exports.GameAudioCue = GameAudioCue;
55254
56042
  exports.GameAudioToggle = GameAudioToggle;
55255
56043
  exports.GameHud = GameHud;
55256
56044
  exports.GameIcon = GameIcon;
@@ -55295,6 +56083,7 @@ exports.createSharedEntityStore = createSharedEntityStore;
55295
56083
  exports.createTranslate = createTranslate;
55296
56084
  exports.createUnitAnimationState = createUnitAnimationState;
55297
56085
  exports.cylinderBetween = cylinderBetween;
56086
+ exports.dispatchCommandPaletteCommand = dispatchCommandPaletteCommand;
55298
56087
  exports.get3DClickPayload = get3DClickPayload;
55299
56088
  exports.getCurrentFrame = getCurrentFrame;
55300
56089
  exports.getTileDimensions = getTileDimensions;
@@ -55360,6 +56149,7 @@ exports.useGitHubRepos = useGitHubRepos;
55360
56149
  exports.useGitHubStatus = useGitHubStatus;
55361
56150
  exports.useImageCache = useImageCache;
55362
56151
  exports.useInfiniteScroll = useInfiniteScroll;
56152
+ exports.useKeyboardRouter = useKeyboardRouter;
55363
56153
  exports.useLongPress = useLongPress;
55364
56154
  exports.useMediaQuery = useMediaQuery;
55365
56155
  exports.useOrbitalHistory = useOrbitalHistory;
@@ -55374,7 +56164,7 @@ exports.useSharedEntityStoreContext = useSharedEntityStoreContext;
55374
56164
  exports.useSwipeGesture = useSwipeGesture;
55375
56165
  exports.useTapReveal = useTapReveal;
55376
56166
  exports.useTraitListens = useTraitListens;
55377
- exports.useTranslate = useTranslate116;
56167
+ exports.useTranslate = useTranslate117;
55378
56168
  exports.useUIEvents = useUIEvents;
55379
56169
  exports.useUISlotManager = useUISlotManager;
55380
56170
  exports.useUnitSpriteAtlas = useUnitSpriteAtlas;