@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
@@ -12,7 +12,7 @@ import { useTranslate } from '@almadar/ui/hooks';
12
12
  import { useUISlots, useTheme } from '@almadar/ui/context';
13
13
  import { evaluate, createMinimalContext } from '@almadar/evaluator';
14
14
  import { createContextFromBindings, interpolateValue } from '@almadar/runtime';
15
- import { mergeEntityFrame, isFileValue, isInlineTrait, isSecretConfigType, isRenderBindingMarker } from '@almadar/core';
15
+ import { UI_SLOTS, mergeEntityFrame, isFileValue, isInlineTrait, isSecretConfigType, isRenderBindingMarker } from '@almadar/core';
16
16
  import { createPortal } from 'react-dom';
17
17
  import { wrapCallbackForEvent, perfStart, perfEnd } from '@almadar/runtime/ui';
18
18
  import { Link, Outlet, useLocation } from 'react-router-dom';
@@ -9847,14 +9847,15 @@ function drawArrowHead(ctx, x1, y1, x2, y2, size) {
9847
9847
  ctx.closePath();
9848
9848
  ctx.fill();
9849
9849
  }
9850
- function drawShape(ctx, shape, width, height, allShapes) {
9850
+ function drawShape(ctx, shape, width, height, allShapes, fontFamily) {
9851
9851
  ctx.save();
9852
9852
  const opacity = shape.opacity ?? 1;
9853
9853
  ctx.globalAlpha = opacity;
9854
9854
  const stroke = resolveColor2(shape.color, ctx, "#333333");
9855
9855
  const fill = shape.fill ? resolveColor2(shape.fill, ctx, "#cccccc") : void 0;
9856
9856
  ctx.lineWidth = shape.lineWidth ?? 2;
9857
- if (shape.dash) ctx.setLineDash([...DASH_PATTERNS[shape.dash]]);
9857
+ const dashPattern = shape.dash ? DASH_PATTERNS[shape.dash] : void 0;
9858
+ if (dashPattern) ctx.setLineDash([...dashPattern]);
9858
9859
  switch (shape.type) {
9859
9860
  case "grid": {
9860
9861
  const step = shape.step ?? 40;
@@ -9976,7 +9977,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
9976
9977
  case "text": {
9977
9978
  if (shape.x == null || shape.y == null || !shape.text) break;
9978
9979
  ctx.fillStyle = stroke;
9979
- ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
9980
+ ctx.font = `${shape.fontSize ?? 14}px ${shape.fontFamily ?? fontFamily ?? themeBodyFont(ctx.canvas)}`;
9980
9981
  ctx.textAlign = shape.align ?? "left";
9981
9982
  ctx.textBaseline = "middle";
9982
9983
  ctx.fillText(shape.text, shape.x, shape.y);
@@ -10018,7 +10019,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
10018
10019
  }
10019
10020
  ctx.restore();
10020
10021
  }
10021
- function readoutShapes(readouts, width) {
10022
+ function readoutShapes(readouts, width, fontFamily) {
10022
10023
  const out = [];
10023
10024
  const chipH = 18;
10024
10025
  const gap = 6;
@@ -10042,13 +10043,14 @@ function readoutShapes(readouts, width) {
10042
10043
  text,
10043
10044
  color: "#ffffff",
10044
10045
  fontSize: 10,
10045
- align: "center"
10046
+ align: "center",
10047
+ fontFamily
10046
10048
  });
10047
10049
  rightEdge = chipX - gap;
10048
10050
  }
10049
10051
  return out;
10050
10052
  }
10051
- function traceShapes(panel, k, width, height) {
10053
+ function traceShapes(panel, k, width, height, fontFamily) {
10052
10054
  const w = panel.width ?? Math.round(width * 0.32);
10053
10055
  const h = panel.height ?? Math.round(height * 0.28);
10054
10056
  const x = panel.x ?? width - w - 8;
@@ -10102,14 +10104,14 @@ function traceShapes(panel, k, width, height) {
10102
10104
  out.push({ type: "circle", x: last.x, y: last.y, radius: 2, color, fill: color });
10103
10105
  }
10104
10106
  if (series.label) {
10105
- out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9 });
10107
+ out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9, fontFamily });
10106
10108
  }
10107
10109
  });
10108
10110
  if (panel.yLabel) {
10109
- out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right" });
10111
+ out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
10110
10112
  }
10111
10113
  if (panel.xLabel) {
10112
- out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right" });
10114
+ out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
10113
10115
  }
10114
10116
  return out;
10115
10117
  }
@@ -10132,13 +10134,14 @@ var init_LearningCanvas = __esm({
10132
10134
  init_useEventBus();
10133
10135
  init_webPainter2d();
10134
10136
  init_paintDispatch();
10135
- DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
10137
+ DASH_PATTERNS = { solid: [], dashed: [6, 4], dotted: [2, 3] };
10136
10138
  TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
10137
10139
  LearningCanvas = ({
10138
10140
  className,
10139
10141
  width = 600,
10140
10142
  height = 400,
10141
10143
  backgroundColor,
10144
+ fontFamily,
10142
10145
  shapes = [],
10143
10146
  drawables,
10144
10147
  projector,
@@ -10174,10 +10177,10 @@ var init_LearningCanvas = __esm({
10174
10177
  }, [shapes]);
10175
10178
  const derivedShapes = useMemo(() => {
10176
10179
  if (!traces?.length && !readouts?.length) return shapes;
10177
- const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height));
10178
- const readoutOut = readouts?.length ? readoutShapes(readouts, width) : [];
10180
+ const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height, fontFamily));
10181
+ const readoutOut = readouts?.length ? readoutShapes(readouts, width, fontFamily) : [];
10179
10182
  return [...shapes, ...traceOut, ...readoutOut];
10180
- }, [shapes, traces, readouts, width, height]);
10183
+ }, [shapes, traces, readouts, width, height, fontFamily]);
10181
10184
  const draw = useCallback(() => {
10182
10185
  const _perfT = perfStart("learningcanvas:paint");
10183
10186
  const canvas = canvasRef.current;
@@ -10196,15 +10199,15 @@ var init_LearningCanvas = __esm({
10196
10199
  ctx.fillRect(0, 0, width, height);
10197
10200
  }
10198
10201
  for (const shape of derivedShapes) {
10199
- if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes);
10202
+ if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
10200
10203
  }
10201
10204
  for (const shape of derivedShapes) {
10202
- if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
10205
+ if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
10203
10206
  }
10204
10207
  if (drawables?.length && projector) {
10205
10208
  const painter = createWebPainter(ctx, invalidateRef.current);
10206
10209
  const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
10207
- const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: themeBodyFont(canvas) };
10210
+ const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: fontFamily || themeBodyFont(canvas) };
10208
10211
  for (const node of drawables) {
10209
10212
  paintDrawable(painter, node, dctx);
10210
10213
  }
@@ -13321,6 +13324,250 @@ var init_EmptyState = __esm({
13321
13324
  EmptyState.displayName = "EmptyState";
13322
13325
  }
13323
13326
  });
13327
+
13328
+ // lib/editorMotions.ts
13329
+ function clamp(value, min, max) {
13330
+ return Math.max(min, Math.min(max, value));
13331
+ }
13332
+ function computeLines(text) {
13333
+ const lines = [];
13334
+ let start = 0;
13335
+ for (let i = 0; i <= text.length; i++) {
13336
+ if (i === text.length || text[i] === "\n") {
13337
+ lines.push({ start, end: i });
13338
+ start = i + 1;
13339
+ }
13340
+ }
13341
+ return lines;
13342
+ }
13343
+ function lineIndexAt(lines, pos) {
13344
+ for (let i = 0; i < lines.length; i++) {
13345
+ if (pos <= lines[i].end) return i;
13346
+ }
13347
+ return lines.length - 1;
13348
+ }
13349
+ function findWords(text) {
13350
+ const words = [];
13351
+ const re = /\w+|\S+/g;
13352
+ let m;
13353
+ while ((m = re.exec(text)) !== null) {
13354
+ words.push({ start: m.index, end: m.index + m[0].length });
13355
+ }
13356
+ return words;
13357
+ }
13358
+ function nextWordStart(text, pos) {
13359
+ for (const w of findWords(text)) {
13360
+ if (w.start > pos) return w.start;
13361
+ }
13362
+ return text.length;
13363
+ }
13364
+ function prevWordStart(text, pos) {
13365
+ let result = 0;
13366
+ for (const w of findWords(text)) {
13367
+ if (w.start < pos) result = w.start;
13368
+ else break;
13369
+ }
13370
+ return result;
13371
+ }
13372
+ function nextWordEnd(text, pos) {
13373
+ for (const w of findWords(text)) {
13374
+ const lastChar = w.end - 1;
13375
+ if (lastChar > pos) return lastChar;
13376
+ }
13377
+ return text.length > 0 ? text.length - 1 : 0;
13378
+ }
13379
+ function firstNonBlank(text, line) {
13380
+ let i = line.start;
13381
+ while (i < line.end && (text[i] === " " || text[i] === " ")) i++;
13382
+ return i;
13383
+ }
13384
+ function nextParagraphBoundary(lines, fromLineIdx, textLength) {
13385
+ for (let i = fromLineIdx + 1; i < lines.length; i++) {
13386
+ if (lines[i].start === lines[i].end) return lines[i].start;
13387
+ }
13388
+ return textLength;
13389
+ }
13390
+ function prevParagraphBoundary(lines, fromLineIdx) {
13391
+ for (let i = fromLineIdx - 1; i >= 0; i--) {
13392
+ if (lines[i].start === lines[i].end) return lines[i].start;
13393
+ }
13394
+ return 0;
13395
+ }
13396
+ function applyMotion(text, caret, motion, count) {
13397
+ const n = Math.max(1, count);
13398
+ const lines = computeLines(text);
13399
+ const lineIdx = lineIndexAt(lines, caret);
13400
+ const line = lines[lineIdx];
13401
+ switch (motion) {
13402
+ case "left":
13403
+ return clamp(caret - n, line.start, line.end);
13404
+ case "right":
13405
+ return clamp(caret + n, line.start, line.end);
13406
+ case "up": {
13407
+ const col = caret - line.start;
13408
+ const targetIdx = clamp(lineIdx - n, 0, lines.length - 1);
13409
+ const target = lines[targetIdx];
13410
+ return clamp(target.start + col, target.start, target.end);
13411
+ }
13412
+ case "down": {
13413
+ const col = caret - line.start;
13414
+ const targetIdx = clamp(lineIdx + n, 0, lines.length - 1);
13415
+ const target = lines[targetIdx];
13416
+ return clamp(target.start + col, target.start, target.end);
13417
+ }
13418
+ case "word-forward": {
13419
+ let pos = caret;
13420
+ for (let i = 0; i < n; i++) pos = nextWordStart(text, pos);
13421
+ return pos;
13422
+ }
13423
+ case "word-back": {
13424
+ let pos = caret;
13425
+ for (let i = 0; i < n; i++) pos = prevWordStart(text, pos);
13426
+ return pos;
13427
+ }
13428
+ case "word-end": {
13429
+ let pos = caret;
13430
+ for (let i = 0; i < n; i++) pos = nextWordEnd(text, pos);
13431
+ return pos;
13432
+ }
13433
+ case "line-start":
13434
+ return line.start;
13435
+ case "line-end":
13436
+ return line.end > line.start ? line.end - 1 : line.start;
13437
+ case "first-nonblank":
13438
+ return firstNonBlank(text, line);
13439
+ case "doc-start":
13440
+ return 0;
13441
+ case "doc-end":
13442
+ return text.length;
13443
+ case "paragraph-forward": {
13444
+ let pos = caret;
13445
+ for (let i = 0; i < n; i++) {
13446
+ pos = nextParagraphBoundary(lines, lineIndexAt(lines, pos), text.length);
13447
+ }
13448
+ return pos;
13449
+ }
13450
+ case "paragraph-back": {
13451
+ let pos = caret;
13452
+ for (let i = 0; i < n; i++) {
13453
+ pos = prevParagraphBoundary(lines, lineIndexAt(lines, pos));
13454
+ }
13455
+ return pos;
13456
+ }
13457
+ case "line":
13458
+ case "selection":
13459
+ return caret;
13460
+ default: {
13461
+ const _exhaustive = motion;
13462
+ return _exhaustive;
13463
+ }
13464
+ }
13465
+ }
13466
+ function motionRange(text, caret, motion, count, selection) {
13467
+ if (motion === "selection") {
13468
+ if (!selection) return [caret, caret];
13469
+ return [Math.min(selection[0], selection[1]), Math.max(selection[0], selection[1])];
13470
+ }
13471
+ const lines = computeLines(text);
13472
+ if (motion === "line") {
13473
+ const n = Math.max(1, count);
13474
+ const startIdx = lineIndexAt(lines, caret);
13475
+ const endIdx = clamp(startIdx + n - 1, 0, lines.length - 1);
13476
+ const start2 = lines[startIdx].start;
13477
+ const rawEnd = lines[endIdx].end;
13478
+ const end2 = rawEnd < text.length ? rawEnd + 1 : rawEnd;
13479
+ return [start2, end2];
13480
+ }
13481
+ const newCaret = applyMotion(text, caret, motion, count);
13482
+ let start = Math.min(caret, newCaret);
13483
+ let end = Math.max(caret, newCaret);
13484
+ if (motion === "word-end" || motion === "line-end") {
13485
+ end = Math.min(Math.max(start, newCaret) + 1, text.length);
13486
+ } else if (motion === "word-forward" && newCaret > caret) {
13487
+ const startLine = lineIndexAt(lines, caret);
13488
+ const endLine = lineIndexAt(lines, newCaret);
13489
+ if (endLine !== startLine) {
13490
+ end = lines[startLine].end;
13491
+ }
13492
+ }
13493
+ return [start, end];
13494
+ }
13495
+ function applyOperator(text, range, operator, register) {
13496
+ const start = clamp(range[0], 0, text.length);
13497
+ const end = clamp(range[1], start, text.length);
13498
+ const removed = text.slice(start, end);
13499
+ if (operator === "yank") {
13500
+ return { text, caret: start, register: removed };
13501
+ }
13502
+ return { text: text.slice(0, start) + text.slice(end), caret: start, register: removed };
13503
+ }
13504
+ var init_editorMotions = __esm({
13505
+ "lib/editorMotions.ts"() {
13506
+ }
13507
+ });
13508
+ function isMotionPayload(payload) {
13509
+ return !!payload && typeof payload.editorId === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
13510
+ }
13511
+ function isOperatePayload(payload) {
13512
+ return !!payload && typeof payload.editorId === "string" && typeof payload.operator === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
13513
+ }
13514
+ function isInsertTextPayload(payload) {
13515
+ return !!payload && typeof payload.editorId === "string" && typeof payload.text === "string";
13516
+ }
13517
+ function isSetModePayload(payload) {
13518
+ return !!payload && typeof payload.editorId === "string" && typeof payload.mode === "string" && typeof payload.caret === "string";
13519
+ }
13520
+ function useEditorCapabilities(args) {
13521
+ const [caretMode, setCaretMode] = useState("bar");
13522
+ const registerRef = useRef("");
13523
+ useEventListener(`UI:${args.events.onMotion}`, (evt) => {
13524
+ if (!args.editorId || !isMotionPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13525
+ const ta = args.textareaRef.current;
13526
+ if (!ta) return;
13527
+ const { motion, count } = evt.payload;
13528
+ const newCaret = applyMotion(ta.value, ta.selectionStart, motion, count);
13529
+ if (ta.selectionStart !== ta.selectionEnd) {
13530
+ ta.setSelectionRange(ta.selectionStart, newCaret);
13531
+ } else {
13532
+ ta.setSelectionRange(newCaret, newCaret);
13533
+ }
13534
+ });
13535
+ useEventListener(`UI:${args.events.onOperate}`, (evt) => {
13536
+ if (!args.editorId || !isOperatePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13537
+ const ta = args.textareaRef.current;
13538
+ if (!ta) return;
13539
+ const { operator, motion, count } = evt.payload;
13540
+ const selection = motion === "selection" ? [ta.selectionStart, ta.selectionEnd] : void 0;
13541
+ const range = motionRange(ta.value, ta.selectionStart, motion, count, selection);
13542
+ const result = applyOperator(ta.value, range, operator, registerRef.current);
13543
+ registerRef.current = result.register;
13544
+ if (operator === "yank") {
13545
+ ta.setSelectionRange(range[0], range[0]);
13546
+ } else {
13547
+ ta.setRangeText("", range[0], range[1], "end");
13548
+ }
13549
+ args.applyChange(ta.value);
13550
+ });
13551
+ useEventListener(`UI:${args.events.onInsertText}`, (evt) => {
13552
+ if (!args.editorId || !isInsertTextPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13553
+ const ta = args.textareaRef.current;
13554
+ if (!ta) return;
13555
+ ta.setRangeText(evt.payload.text, ta.selectionStart, ta.selectionEnd, "end");
13556
+ args.applyChange(ta.value);
13557
+ });
13558
+ useEventListener(`UI:${args.events.onSetMode}`, (evt) => {
13559
+ if (!args.editorId || !isSetModePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
13560
+ setCaretMode(evt.payload.caret);
13561
+ });
13562
+ return { caretMode };
13563
+ }
13564
+ var init_useEditorCapabilities = __esm({
13565
+ "components/core/molecules/markdown/useEditorCapabilities.ts"() {
13566
+ "use client";
13567
+ init_useEventBus();
13568
+ init_editorMotions();
13569
+ }
13570
+ });
13324
13571
  function registerCodeLanguageLoader(loader) {
13325
13572
  codeLanguageLoader = loader;
13326
13573
  }
@@ -13409,7 +13656,36 @@ function useLanguageReady(language) {
13409
13656
  }, [language]);
13410
13657
  return ready;
13411
13658
  }
13412
- 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, CodeBlock;
13659
+ function resolveHighlightStyle(lang) {
13660
+ if (lang === "orb") return orbStyle;
13661
+ if (lang === "lolo") return loloStyle;
13662
+ return dark;
13663
+ }
13664
+ function plainCodeColorOf(style) {
13665
+ return style['code[class*="language-"]']?.color ?? "#d4d4d4";
13666
+ }
13667
+ function buildLineProps(errorLines, extraClassName) {
13668
+ return (lineNumber) => {
13669
+ const base = {
13670
+ "data-line": String(lineNumber - 1),
13671
+ ...extraClassName ? { className: extraClassName } : {}
13672
+ };
13673
+ const severity = errorLines?.get(lineNumber);
13674
+ if (!severity) return base;
13675
+ return {
13676
+ ...base,
13677
+ style: {
13678
+ display: "block",
13679
+ backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
13680
+ // amber-400 @ 18%
13681
+ borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
13682
+ paddingLeft: "0.5rem",
13683
+ marginLeft: "-0.5rem"
13684
+ }
13685
+ };
13686
+ };
13687
+ }
13688
+ 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, CodeBlock;
13413
13689
  var init_CodeBlock = __esm({
13414
13690
  "components/core/molecules/markdown/CodeBlock.tsx"() {
13415
13691
  init_cn();
@@ -13425,6 +13701,7 @@ var init_CodeBlock = __esm({
13425
13701
  init_Textarea();
13426
13702
  init_Icon();
13427
13703
  init_useEventBus();
13704
+ init_useEditorCapabilities();
13428
13705
  SyntaxHighlighter.registerLanguage("json", langJson);
13429
13706
  SyntaxHighlighter.registerLanguage("javascript", langJavascript);
13430
13707
  SyntaxHighlighter.registerLanguage("js", langJavascript);
@@ -13643,6 +13920,15 @@ var init_CodeBlock = __esm({
13643
13920
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
13644
13921
  HIDDEN_LINE_NUMBERS = { display: "none" };
13645
13922
  HIGHLIGHT_CAPACITY_BYTES = 512 * 1024;
13923
+ MONO_FONT_FAMILY = 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace';
13924
+ VIEWER_LINE_NUMBER_STYLE = {
13925
+ minWidth: "2.5em",
13926
+ paddingRight: "1rem",
13927
+ textAlign: "right",
13928
+ userSelect: "none",
13929
+ opacity: 0.5,
13930
+ fontVariantNumeric: "tabular-nums"
13931
+ };
13646
13932
  CodeBlock = React79__default.memo(
13647
13933
  ({
13648
13934
  code: rawCode,
@@ -13667,15 +13953,39 @@ var init_CodeBlock = __esm({
13667
13953
  actions,
13668
13954
  isLoading = false,
13669
13955
  error,
13670
- showCopy
13956
+ showCopy,
13957
+ // editor capability surface — P1 wires these
13958
+ editorId,
13959
+ onEditorFocus = "EDITOR_FOCUS",
13960
+ onEditorBlur = "EDITOR_BLUR",
13961
+ onMotion = "MOTION",
13962
+ onOperate = "OPERATE",
13963
+ onInsertText = "INSERT_TEXT",
13964
+ onSetMode = "SET_MODE",
13965
+ motions = [
13966
+ "left",
13967
+ "right",
13968
+ "up",
13969
+ "down",
13970
+ "word-forward",
13971
+ "word-back",
13972
+ "word-end",
13973
+ "line-start",
13974
+ "line-end",
13975
+ "first-nonblank",
13976
+ "doc-start",
13977
+ "doc-end",
13978
+ "paragraph-forward",
13979
+ "paragraph-back",
13980
+ "line",
13981
+ "selection"
13982
+ ],
13983
+ operators = ["delete", "yank", "change"]
13671
13984
  }) => {
13672
13985
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
13673
- const isOrb = language === "orb";
13674
- const isLolo = language === "lolo";
13675
- const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark;
13986
+ const activeStyle = resolveHighlightStyle(language);
13676
13987
  const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
13677
- const plainCodeColor = activeStyle['code[class*="language-"]']?.color ?? "#d4d4d4";
13678
- const languageReady = useLanguageReady(language);
13988
+ const plainCodeColor = plainCodeColorOf(activeStyle);
13679
13989
  const eventBus = useEventBus();
13680
13990
  const { t } = useTranslate();
13681
13991
  const scrollRef = useRef(null);
@@ -13687,6 +13997,9 @@ var init_CodeBlock = __esm({
13687
13997
  const activeFile = files?.[activeFileIndex];
13688
13998
  const activeCode = activeFile?.code ?? code;
13689
13999
  const activeLanguage = activeFile?.language ?? language;
14000
+ const languageReady = useLanguageReady(activeLanguage);
14001
+ const viewerStyle = resolveHighlightStyle(activeLanguage);
14002
+ const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
13690
14003
  const diffLines = useMemo(() => {
13691
14004
  if (propDiff) return propDiff;
13692
14005
  if (mode === "diff" && oldValue !== void 0 && newValue !== void 0) {
@@ -13716,28 +14029,28 @@ var init_CodeBlock = __esm({
13716
14029
  ov.scrollLeft = ta.scrollLeft;
13717
14030
  }
13718
14031
  }, []);
13719
- const errorLineProps = useMemo(() => {
13720
- if (!errorLines || errorLines.size === 0) {
13721
- return LINE_PROPS_FN;
13722
- }
13723
- return (lineNumber) => {
13724
- const severity = errorLines.get(lineNumber);
13725
- if (!severity) {
13726
- return { "data-line": String(lineNumber - 1) };
13727
- }
13728
- return {
13729
- "data-line": String(lineNumber - 1),
13730
- style: {
13731
- display: "block",
13732
- backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
13733
- // amber-400 @ 18%
13734
- borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
13735
- paddingLeft: "0.5rem",
13736
- marginLeft: "-0.5rem"
13737
- }
13738
- };
13739
- };
13740
- }, [errorLines]);
14032
+ const handleEditableChange = useCallback((v) => {
14033
+ lastPropCodeRef.current = v;
14034
+ setEditableValue(v);
14035
+ onChange?.(v);
14036
+ }, [onChange]);
14037
+ const { caretMode } = useEditorCapabilities({
14038
+ editorId: editable ? editorId : void 0,
14039
+ textareaRef: editableTextareaRef,
14040
+ events: { onMotion, onOperate, onInsertText, onSetMode },
14041
+ applyChange: handleEditableChange
14042
+ });
14043
+ const [caretIndex, setCaretIndex] = useState(0);
14044
+ const caretRowCol = useMemo(() => {
14045
+ const before = editableValue.slice(0, Math.min(caretIndex, editableValue.length));
14046
+ const lines = before.split("\n");
14047
+ return { row: lines.length - 1, col: lines[lines.length - 1].length };
14048
+ }, [editableValue, caretIndex]);
14049
+ const errorLineProps = useMemo(() => buildLineProps(errorLines), [errorLines]);
14050
+ const viewerLineProps = useMemo(
14051
+ () => buildLineProps(errorLines, "px-4 py-0.5 hover:bg-muted/50"),
14052
+ [errorLines]
14053
+ );
13741
14054
  const isFoldable = foldableProp ?? true;
13742
14055
  const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
13743
14056
  const foldRegions = useMemo(
@@ -13860,6 +14173,110 @@ var init_CodeBlock = __esm({
13860
14173
  ),
13861
14174
  [code, overCapacity, plainCodeColor, language, activeStyle, languageReady]
13862
14175
  );
14176
+ const viewerOverCapacity = activeCode.length > HIGHLIGHT_CAPACITY_BYTES;
14177
+ const viewerHighlightedElement = useMemo(
14178
+ () => viewerOverCapacity ? /* @__PURE__ */ jsx(
14179
+ "div",
14180
+ {
14181
+ className: "px-4 py-0.5",
14182
+ style: {
14183
+ margin: 0,
14184
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14185
+ wordBreak: wrap ? "break-all" : "normal",
14186
+ color: viewerPlainCodeColor,
14187
+ fontFamily: MONO_FONT_FAMILY,
14188
+ fontSize: "12px",
14189
+ lineHeight: "1.6"
14190
+ },
14191
+ children: activeCode
14192
+ }
14193
+ ) : /* @__PURE__ */ jsx(
14194
+ SyntaxHighlighter,
14195
+ {
14196
+ PreTag: "div",
14197
+ language: activeLanguage,
14198
+ style: viewerStyle,
14199
+ wrapLines: true,
14200
+ wrapLongLines: wrap,
14201
+ showLineNumbers,
14202
+ lineNumberStyle: VIEWER_LINE_NUMBER_STYLE,
14203
+ lineProps: viewerLineProps,
14204
+ customStyle: {
14205
+ backgroundColor: "transparent",
14206
+ borderRadius: 0,
14207
+ padding: "0.25rem 0",
14208
+ margin: 0,
14209
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14210
+ wordBreak: wrap ? "break-all" : "normal",
14211
+ fontFamily: MONO_FONT_FAMILY,
14212
+ fontSize: "12px",
14213
+ lineHeight: "1.6"
14214
+ },
14215
+ codeTagProps: { style: { fontFamily: MONO_FONT_FAMILY, fontSize: "12px", lineHeight: "1.6" } },
14216
+ children: activeCode
14217
+ }
14218
+ ),
14219
+ [activeCode, viewerOverCapacity, viewerPlainCodeColor, activeLanguage, viewerStyle, wrap, showLineNumbers, viewerLineProps, languageReady]
14220
+ );
14221
+ const diffOverCapacity = useMemo(
14222
+ () => !!diffLines && diffLines.reduce((n, l) => n + l.content.length + 1, 0) > HIGHLIGHT_CAPACITY_BYTES,
14223
+ [diffLines]
14224
+ );
14225
+ const diffRowElements = useMemo(() => {
14226
+ if (!diffLines) return null;
14227
+ return diffLines.map((line, idx) => {
14228
+ const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
14229
+ return /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
14230
+ showLineNumbers && /* @__PURE__ */ jsx(
14231
+ Typography,
14232
+ {
14233
+ variant: "caption",
14234
+ color: "secondary",
14235
+ className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
14236
+ children: line.lineNumber ?? ""
14237
+ }
14238
+ ),
14239
+ /* @__PURE__ */ jsxs(
14240
+ Typography,
14241
+ {
14242
+ variant: "caption",
14243
+ className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
14244
+ children: [
14245
+ /* @__PURE__ */ jsx(Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
14246
+ diffOverCapacity ? line.content || " " : /* @__PURE__ */ jsx(
14247
+ SyntaxHighlighter,
14248
+ {
14249
+ PreTag: "span",
14250
+ CodeTag: "span",
14251
+ language: activeLanguage,
14252
+ style: viewerStyle,
14253
+ customStyle: {
14254
+ display: "inline",
14255
+ background: "transparent",
14256
+ padding: 0,
14257
+ margin: 0,
14258
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14259
+ wordBreak: wrap ? "break-all" : "normal",
14260
+ fontFamily: "inherit",
14261
+ fontSize: "inherit",
14262
+ lineHeight: "inherit"
14263
+ },
14264
+ codeTagProps: {
14265
+ style: {
14266
+ whiteSpace: wrap ? "pre-wrap" : "pre",
14267
+ fontFamily: "inherit",
14268
+ fontSize: "inherit"
14269
+ }
14270
+ },
14271
+ children: line.content || " "
14272
+ }
14273
+ )
14274
+ ]
14275
+ }
14276
+ )
14277
+ ] }, idx);
14278
+ });
14279
+ }, [diffLines, showLineNumbers, wrap, diffOverCapacity, activeLanguage, viewerStyle, languageReady]);
13863
14280
  useLayoutEffect(() => {
13864
14281
  const container = codeRef.current;
13865
14282
  if (!container) return;
@@ -14003,7 +14420,6 @@ var init_CodeBlock = __esm({
14003
14420
  label: file.label,
14004
14421
  content: null
14005
14422
  }));
14006
- const lines = activeCode.split("\n");
14007
14423
  return /* @__PURE__ */ jsx(Card, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
14008
14424
  tabItems && tabItems.length > 1 && /* @__PURE__ */ jsx(Box, { className: "border-b border-border", children: /* @__PURE__ */ jsx(
14009
14425
  Tabs,
@@ -14066,49 +14482,7 @@ var init_CodeBlock = __esm({
14066
14482
  ]
14067
14483
  }
14068
14484
  ),
14069
- /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffLines.map((line, idx) => {
14070
- const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
14071
- return /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
14072
- showLineNumbers && /* @__PURE__ */ jsx(
14073
- Typography,
14074
- {
14075
- variant: "caption",
14076
- color: "secondary",
14077
- className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
14078
- children: line.lineNumber ?? ""
14079
- }
14080
- ),
14081
- /* @__PURE__ */ jsxs(
14082
- Typography,
14083
- {
14084
- variant: "caption",
14085
- className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
14086
- children: [
14087
- /* @__PURE__ */ jsx(Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
14088
- line.content
14089
- ]
14090
- }
14091
- )
14092
- ] }, idx);
14093
- }) }) : /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: lines.map((line, idx) => /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: "px-4 py-0.5 hover:bg-muted/50", children: [
14094
- showLineNumbers && /* @__PURE__ */ jsx(
14095
- Typography,
14096
- {
14097
- variant: "caption",
14098
- color: "secondary",
14099
- className: "w-8 text-right mr-4 select-none tabular-nums flex-shrink-0",
14100
- children: idx + 1
14101
- }
14102
- ),
14103
- /* @__PURE__ */ jsx(
14104
- Typography,
14105
- {
14106
- variant: "caption",
14107
- className: cn("font-mono flex-1 min-w-0", wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
14108
- children: line || " "
14109
- }
14110
- )
14111
- ] }, idx)) }) })
14485
+ /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
14112
14486
  ] }) });
14113
14487
  }
14114
14488
  const hasHeader = showLanguageBadge || effectiveCopy;
@@ -14195,13 +14569,11 @@ var init_CodeBlock = __esm({
14195
14569
  {
14196
14570
  ref: editableTextareaRef,
14197
14571
  defaultValue: code,
14198
- onChange: (e) => {
14199
- const v = e.target.value;
14200
- lastPropCodeRef.current = v;
14201
- setEditableValue(v);
14202
- onChange?.(v);
14203
- },
14572
+ onChange: (e) => handleEditableChange(e.target.value),
14204
14573
  onScroll: handleEditableScroll,
14574
+ onSelect: (e) => setCaretIndex(e.currentTarget.selectionStart),
14575
+ onFocus: editorId ? () => eventBus.emit(`UI:${onEditorFocus}`, { editorId }) : void 0,
14576
+ onBlur: editorId ? () => eventBus.emit(`UI:${onEditorBlur}`, { editorId }) : void 0,
14205
14577
  spellCheck: false,
14206
14578
  style: {
14207
14579
  position: "absolute",
@@ -14216,7 +14588,7 @@ var init_CodeBlock = __esm({
14216
14588
  resize: "none",
14217
14589
  backgroundColor: "transparent",
14218
14590
  color: "transparent",
14219
- caretColor: "#e6e6e6",
14591
+ caretColor: caretMode === "block" ? "transparent" : "#e6e6e6",
14220
14592
  WebkitTextFillColor: "transparent",
14221
14593
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
14222
14594
  fontSize: "13px",
@@ -14227,6 +14599,22 @@ var init_CodeBlock = __esm({
14227
14599
  }
14228
14600
  },
14229
14601
  editableTextareaKey
14602
+ ),
14603
+ caretMode !== "bar" && /* @__PURE__ */ jsx(
14604
+ "span",
14605
+ {
14606
+ "aria-hidden": true,
14607
+ style: {
14608
+ position: "absolute",
14609
+ top: `calc(1rem + ${caretRowCol.row * 19.5}px)`,
14610
+ left: `calc(1rem + ${caretRowCol.col}ch)`,
14611
+ width: "1ch",
14612
+ height: caretMode === "block" ? "19.5px" : "2px",
14613
+ backgroundColor: caretMode === "block" ? "rgba(230, 230, 230, 0.5)" : void 0,
14614
+ borderBottom: caretMode === "underline" ? "2px solid #e6e6e6" : void 0,
14615
+ pointerEvents: "none"
14616
+ }
14617
+ }
14230
14618
  )
14231
14619
  ]
14232
14620
  }
@@ -14254,55 +14642,175 @@ var init_CodeBlock = __esm({
14254
14642
  )
14255
14643
  ] });
14256
14644
  },
14257
- (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
14645
+ (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
14258
14646
  );
14259
14647
  CodeBlock.displayName = "CodeBlock";
14260
14648
  }
14261
14649
  });
14650
+
14651
+ // components/core/molecules/markdown/mermaidSource.ts
14652
+ function isQuoted(label) {
14653
+ const trimmed = label.trim();
14654
+ return trimmed.length === 0 || trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1;
14655
+ }
14656
+ function quote(label) {
14657
+ return `"${label.replace(/"/g, "#quot;")}"`;
14658
+ }
14659
+ function isIdentifierChar(ch) {
14660
+ return /[A-Za-z0-9_\-.]/.test(ch);
14661
+ }
14662
+ function declaredType(code) {
14663
+ for (const line of code.split("\n")) {
14664
+ const trimmed = line.trim();
14665
+ if (trimmed.length === 0 || trimmed.startsWith("%%")) continue;
14666
+ return trimmed;
14667
+ }
14668
+ return "";
14669
+ }
14670
+ function isFlowchart(code) {
14671
+ return FLOWCHART_DIRECTIVE.test(declaredType(code));
14672
+ }
14673
+ function quoteNodeLabels(code) {
14674
+ let out = "";
14675
+ let i = 0;
14676
+ while (i < code.length) {
14677
+ const shape = NODE_SHAPES.find(([open2]) => code.startsWith(open2, i));
14678
+ const precededByIdentifier = i > 0 && isIdentifierChar(code[i - 1] ?? "");
14679
+ if (shape === void 0 || !precededByIdentifier) {
14680
+ out += code[i];
14681
+ i += 1;
14682
+ continue;
14683
+ }
14684
+ const [open, close] = shape;
14685
+ const contentStart = i + open.length;
14686
+ const closeAt = code.indexOf(close, contentStart);
14687
+ const newlineAt = code.indexOf("\n", contentStart);
14688
+ if (closeAt === -1 || newlineAt !== -1 && newlineAt < closeAt) {
14689
+ out += code[i];
14690
+ i += 1;
14691
+ continue;
14692
+ }
14693
+ const label = code.slice(contentStart, closeAt);
14694
+ out += open + (isQuoted(label) ? label : quote(label)) + close;
14695
+ i = closeAt + close.length;
14696
+ }
14697
+ return out;
14698
+ }
14699
+ function quoteEdgeLabels(code) {
14700
+ return code.split("\n").map((line) => {
14701
+ let out = "";
14702
+ let rest = line;
14703
+ for (; ; ) {
14704
+ const open = rest.indexOf("|");
14705
+ if (open === -1) break;
14706
+ const close = rest.indexOf("|", open + 1);
14707
+ if (close === -1) break;
14708
+ const label = rest.slice(open + 1, close);
14709
+ out += rest.slice(0, open + 1) + (isQuoted(label) ? label : quote(label)) + "|";
14710
+ rest = rest.slice(close + 1);
14711
+ }
14712
+ return out + rest;
14713
+ }).join("\n");
14714
+ }
14715
+ function quoteSubgraphTitles(code) {
14716
+ return code.split("\n").map((line) => {
14717
+ const match = /^(\s*subgraph\s+)(.+?)(\s*)$/.exec(line);
14718
+ if (match === null) return line;
14719
+ const [, prefix, title, trailing] = match;
14720
+ if (title === void 0 || prefix === void 0) return line;
14721
+ if (isQuoted(title) || title.includes("[")) return line;
14722
+ return prefix + quote(title) + (trailing ?? "");
14723
+ }).join("\n");
14724
+ }
14725
+ function mermaidRepairCandidates(code) {
14726
+ if (!isFlowchart(code)) return [];
14727
+ const nodes = quoteNodeLabels(code);
14728
+ const nodesAndEdges = quoteEdgeLabels(nodes);
14729
+ const all = quoteSubgraphTitles(nodesAndEdges);
14730
+ const ordered2 = [nodes, nodesAndEdges, all];
14731
+ const seen = /* @__PURE__ */ new Set([code]);
14732
+ const candidates = [];
14733
+ for (const candidate of ordered2) {
14734
+ if (seen.has(candidate)) continue;
14735
+ seen.add(candidate);
14736
+ candidates.push(candidate);
14737
+ }
14738
+ return candidates;
14739
+ }
14740
+ var NODE_SHAPES, FLOWCHART_DIRECTIVE;
14741
+ var init_mermaidSource = __esm({
14742
+ "components/core/molecules/markdown/mermaidSource.ts"() {
14743
+ NODE_SHAPES = [
14744
+ ["[[", "]]"],
14745
+ ["[(", ")]"],
14746
+ ["([", "])"],
14747
+ ["((", "))"],
14748
+ ["{{", "}}"],
14749
+ ["[", "]"],
14750
+ ["(", ")"],
14751
+ ["{", "}"]
14752
+ ];
14753
+ FLOWCHART_DIRECTIVE = /^(?:graph|flowchart)\b/;
14754
+ }
14755
+ });
14262
14756
  function loadMermaid() {
14263
14757
  mermaidModule ?? (mermaidModule = import('mermaid').then((m) => m.default));
14264
14758
  return mermaidModule;
14265
14759
  }
14266
- var mermaidModule, MermaidDiagram;
14760
+ var log6, mermaidModule, MermaidDiagram;
14267
14761
  var init_MermaidDiagram = __esm({
14268
14762
  "components/core/molecules/markdown/MermaidDiagram.tsx"() {
14269
14763
  init_Box();
14270
14764
  init_Typography();
14271
14765
  init_CodeBlock();
14766
+ init_mermaidSource();
14272
14767
  init_cn();
14768
+ log6 = createLogger("almadar:ui:mermaid-diagram");
14273
14769
  mermaidModule = null;
14274
14770
  MermaidDiagram = React79__default.memo(
14275
14771
  ({ code, className }) => {
14276
14772
  const { resolvedMode } = useTheme();
14773
+ const { t } = useTranslate();
14277
14774
  const containerRef = useRef(null);
14278
- const [error, setError] = useState(null);
14775
+ const [unrenderable, setUnrenderable] = useState(false);
14279
14776
  const reactId = useId();
14280
14777
  useEffect(() => {
14281
14778
  let active = true;
14282
14779
  void (async () => {
14283
- try {
14284
- const mermaid = await loadMermaid();
14285
- mermaid.initialize({
14286
- startOnLoad: false,
14287
- securityLevel: "strict",
14288
- theme: resolvedMode === "dark" ? "dark" : "default"
14289
- });
14290
- const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
14291
- const { svg } = await mermaid.render(domId, code);
14292
- if (!active || !containerRef.current) return;
14293
- containerRef.current.innerHTML = svg;
14294
- setError(null);
14295
- } catch (err) {
14296
- if (active) setError(err instanceof Error ? err.message : String(err));
14780
+ const mermaid = await loadMermaid();
14781
+ mermaid.initialize({
14782
+ startOnLoad: false,
14783
+ securityLevel: "strict",
14784
+ theme: resolvedMode === "dark" ? "dark" : "default"
14785
+ });
14786
+ const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
14787
+ let firstError = null;
14788
+ for (const [index, source] of [code, ...mermaidRepairCandidates(code)].entries()) {
14789
+ try {
14790
+ const { svg } = await mermaid.render(domId, source);
14791
+ if (!active) return;
14792
+ const container = containerRef.current;
14793
+ if (container === null) return;
14794
+ container.innerHTML = svg;
14795
+ container.dataset.mermaidRepaired = String(index > 0);
14796
+ setUnrenderable(false);
14797
+ if (index > 0) log6.debug("mermaid:repaired", { candidate: index });
14798
+ return;
14799
+ } catch (err) {
14800
+ firstError ?? (firstError = err instanceof Error ? err : new Error(String(err)));
14801
+ }
14297
14802
  }
14803
+ if (!active) return;
14804
+ log6.warn("mermaid:unrenderable", { error: firstError?.message ?? "", code });
14805
+ setUnrenderable(true);
14298
14806
  })();
14299
14807
  return () => {
14300
14808
  active = false;
14301
14809
  };
14302
14810
  }, [code, resolvedMode, reactId]);
14303
14811
  return /* @__PURE__ */ jsxs(Box, { className: cn("not-prose my-4", className), children: [
14304
- error !== null && /* @__PURE__ */ jsxs(Box, { className: "space-y-2 mb-2", children: [
14305
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-error whitespace-pre-wrap", children: error }),
14812
+ unrenderable && /* @__PURE__ */ jsxs(Box, { className: "space-y-2 mb-2", "data-testid": "mermaid-unrenderable", children: [
14813
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("mermaid.unrenderable") }),
14306
14814
  /* @__PURE__ */ jsx(CodeBlock, { code, language: "mermaid" })
14307
14815
  ] }),
14308
14816
  /* @__PURE__ */ jsx(
@@ -14311,7 +14819,7 @@ var init_MermaidDiagram = __esm({
14311
14819
  ref: containerRef,
14312
14820
  "data-testid": "mermaid-diagram",
14313
14821
  className: "overflow-x-auto",
14314
- style: error !== null ? { display: "none" } : void 0
14822
+ style: unrenderable ? { display: "none" } : void 0
14315
14823
  }
14316
14824
  )
14317
14825
  ] });
@@ -17716,14 +18224,14 @@ function useSafeEventBus2() {
17716
18224
  } };
17717
18225
  }
17718
18226
  }
17719
- var log6, lookStyles4, ButtonGroup;
18227
+ var log7, lookStyles4, ButtonGroup;
17720
18228
  var init_ButtonGroup = __esm({
17721
18229
  "components/core/molecules/ButtonGroup.tsx"() {
17722
18230
  "use client";
17723
18231
  init_cn();
17724
18232
  init_atoms();
17725
18233
  init_useEventBus();
17726
- log6 = createLogger("almadar:ui:button-group");
18234
+ log7 = createLogger("almadar:ui:button-group");
17727
18235
  lookStyles4 = {
17728
18236
  "right-aligned-buttons": "",
17729
18237
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -17804,7 +18312,7 @@ var init_ButtonGroup = __esm({
17804
18312
  {
17805
18313
  variant: "ghost",
17806
18314
  onClick: () => {
17807
- log6.debug("Filter clicked", { field: filter.field });
18315
+ log7.debug("Filter clicked", { field: filter.field });
17808
18316
  },
17809
18317
  children: filter.label
17810
18318
  },
@@ -18822,7 +19330,7 @@ function collectDrawnItems(nodes) {
18822
19330
  for (const n of nodes) {
18823
19331
  switch (n.type) {
18824
19332
  case "draw-sprite":
18825
- if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height });
19333
+ if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotation });
18826
19334
  break;
18827
19335
  case "draw-shape":
18828
19336
  case "draw-text":
@@ -18832,7 +19340,7 @@ function collectDrawnItems(nodes) {
18832
19340
  break;
18833
19341
  case "draw-sprite-layer":
18834
19342
  for (const it of n.items) {
18835
- if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height });
19343
+ if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height, rotation: it.rotation });
18836
19344
  }
18837
19345
  break;
18838
19346
  case "draw-shape-layer":
@@ -18852,15 +19360,39 @@ function buildHitIndex(items) {
18852
19360
  }
18853
19361
  return m;
18854
19362
  }
19363
+ function withPreviewPosition(nodes, id, pos) {
19364
+ return nodes.map((n) => {
19365
+ if (n.type === "draw-sprite-layer" || n.type === "draw-shape-layer" || n.type === "draw-text-layer") {
19366
+ if (!n.items.some((it) => it.id === id)) return n;
19367
+ return { ...n, items: n.items.map((it) => it.id === id ? { ...it, position: pos } : it) };
19368
+ }
19369
+ if (n.type === "draw-group") {
19370
+ if (!Array.isArray(n.items)) return n;
19371
+ return { ...n, items: withPreviewPosition(n.items, id, pos) };
19372
+ }
19373
+ if (n.id === id && "position" in n) {
19374
+ return { ...n, position: pos };
19375
+ }
19376
+ return n;
19377
+ });
19378
+ }
18855
19379
  function hitTestSprites(items, projector, point) {
18856
19380
  for (let i = items.length - 1; i >= 0; i--) {
18857
19381
  const it = items[i];
18858
19382
  if (it.id === void 0) continue;
18859
19383
  const r = spriteRect(projector, { position: it.pos, anchor: it.anchor, width: it.width, height: it.height });
18860
- if (point.x >= r.x && point.x <= r.x + r.w && point.y >= r.y && point.y <= r.y + r.h) return it.id;
19384
+ const test = it.rotation ? rotatePoint(point, { x: r.x + r.w / 2, y: r.y + r.h / 2 }, -it.rotation) : point;
19385
+ if (test.x >= r.x && test.x <= r.x + r.w && test.y >= r.y && test.y <= r.y + r.h) return it.id;
18861
19386
  }
18862
19387
  return void 0;
18863
19388
  }
19389
+ function rotatePoint(p, center, radians) {
19390
+ const cos = Math.cos(radians);
19391
+ const sin = Math.sin(radians);
19392
+ const dx = p.x - center.x;
19393
+ const dy = p.y - center.y;
19394
+ return { x: center.x + dx * cos - dy * sin, y: center.y + dx * sin + dy * cos };
19395
+ }
18864
19396
  var init_hitTest = __esm({
18865
19397
  "lib/drawable/hitTest.ts"() {
18866
19398
  init_contract();
@@ -18869,6 +19401,41 @@ var init_hitTest = __esm({
18869
19401
  function normalizeBackdrop(bg) {
18870
19402
  return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
18871
19403
  }
19404
+ function selectionOverlayNodes(projector, item) {
19405
+ const r = spriteRect(projector, { position: item.pos, anchor: item.anchor, width: item.width, height: item.height });
19406
+ const tw = projector.tileWidth;
19407
+ const cellTopLeft = projector.anchorPoint(item.pos, "top-left");
19408
+ const offsetX = (r.x - cellTopLeft.x) / tw;
19409
+ const offsetY = (r.y - cellTopLeft.y) / tw;
19410
+ const width = r.w / tw;
19411
+ const height = r.h / tw;
19412
+ const handle = EDIT_HANDLE_SIZE_PX / tw;
19413
+ const ring = {
19414
+ type: "draw-shape",
19415
+ shape: "rect",
19416
+ position: item.pos,
19417
+ anchor: "top-left",
19418
+ offsetX,
19419
+ offsetY,
19420
+ width,
19421
+ height,
19422
+ stroke: EDIT_SELECTION_COLOR,
19423
+ strokeWidth: 2,
19424
+ fill: "none"
19425
+ };
19426
+ const handles = EDIT_SELECTION_CORNERS.map(([cx, cy]) => ({
19427
+ type: "draw-shape",
19428
+ shape: "rect",
19429
+ position: item.pos,
19430
+ anchor: "top-left",
19431
+ offsetX: offsetX + cx * width - handle / 2,
19432
+ offsetY: offsetY + cy * height - handle / 2,
19433
+ width: handle,
19434
+ height: handle,
19435
+ fill: EDIT_SELECTION_COLOR
19436
+ }));
19437
+ return [ring, ...handles];
19438
+ }
18872
19439
  function Canvas2D({
18873
19440
  className,
18874
19441
  isLoading = false,
@@ -18882,6 +19449,12 @@ function Canvas2D({
18882
19449
  tileLeaveEvent,
18883
19450
  keyMap,
18884
19451
  keyUpMap,
19452
+ editable = false,
19453
+ selectedId = null,
19454
+ onSelect,
19455
+ onMove,
19456
+ selectEvent,
19457
+ moveEvent,
18885
19458
  camera = "pan-zoom",
18886
19459
  scale = 0.4,
18887
19460
  tileWidth,
@@ -19139,10 +19712,22 @@ function Canvas2D({
19139
19712
  painter.scale(cam.zoom, cam.zoom);
19140
19713
  painter.translate(-viewportSize.width / 2 - cam.x, -viewportSize.height / 2 - cam.y);
19141
19714
  const dctx = { projector, time: timeMs, invalidate: bumpAtlas };
19142
- for (const node of drawables) paintDrawable(painter, node, dctx);
19715
+ let paintNodes = drawables;
19716
+ if (editable) {
19717
+ const drag = editDragRef.current;
19718
+ if (drag && drag.moved) {
19719
+ paintNodes = withPreviewPosition(paintNodes, drag.id, { x: drag.previewX, y: drag.previewY });
19720
+ }
19721
+ const selectedItem = selectedId != null ? drawnItems.find((it) => it.id === selectedId) : void 0;
19722
+ if (selectedItem) {
19723
+ const overlaySource = drag && drag.moved && drag.id === selectedId ? { ...selectedItem, pos: { x: drag.previewX, y: drag.previewY } } : selectedItem;
19724
+ paintNodes = [...paintNodes, ...selectionOverlayNodes(projector, overlaySource)];
19725
+ }
19726
+ }
19727
+ for (const node of paintNodes) paintDrawable(painter, node, dctx);
19143
19728
  painter.restore();
19144
- scheduleAnimation(drawables);
19145
- }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
19729
+ scheduleAnimation(paintNodes);
19730
+ }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance, editable, selectedId, drawnItems]);
19146
19731
  useEffect(() => {
19147
19732
  drawTimeRef.current = draw;
19148
19733
  }, [draw]);
@@ -19187,23 +19772,83 @@ function Canvas2D({
19187
19772
  };
19188
19773
  }, [camera, followTarget, lerpToTarget, draw]);
19189
19774
  const singlePointerActiveRef = useRef(false);
19775
+ const editDragRef = useRef(null);
19776
+ const pointerToScene = useCallback((clientX, clientY) => {
19777
+ const canvas = canvasRef.current;
19778
+ if (!canvas) return { x: 0, y: 0 };
19779
+ const world = screenToWorld(clientX, clientY, canvas, viewportSize);
19780
+ const adjustedX = world.x - scaledTileWidth / 2;
19781
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
19782
+ return unproject(adjustedX, adjustedY);
19783
+ }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject]);
19190
19784
  const handleCanvasPointerDown = useCallback((e) => {
19191
19785
  singlePointerActiveRef.current = true;
19786
+ if (editable) {
19787
+ if (!canvasRef.current) return;
19788
+ const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
19789
+ const hitId = hitTestSprites(drawnItems, projector, world);
19790
+ if (hitId === void 0) return;
19791
+ const item = [...drawnItems].reverse().find((it) => it.id === hitId);
19792
+ if (!item) return;
19793
+ editDragRef.current = {
19794
+ id: hitId,
19795
+ pointerId: e.pointerId,
19796
+ startClientX: e.clientX,
19797
+ startClientY: e.clientY,
19798
+ startSceneX: item.pos.x,
19799
+ startSceneY: item.pos.y,
19800
+ moved: false,
19801
+ previewX: item.pos.x,
19802
+ previewY: item.pos.y
19803
+ };
19804
+ return;
19805
+ }
19192
19806
  if (enableCamera) handlePointerDown(e);
19193
- }, [enableCamera, handlePointerDown]);
19807
+ }, [editable, screenToWorld, viewportSize, drawnItems, projector, enableCamera, handlePointerDown]);
19194
19808
  const handleCanvasPointerMove = useCallback((e) => {
19809
+ if (editable) {
19810
+ const drag = editDragRef.current;
19811
+ if (!drag || drag.pointerId !== e.pointerId) return;
19812
+ const dxPx = e.clientX - drag.startClientX;
19813
+ const dyPx = e.clientY - drag.startClientY;
19814
+ if (!drag.moved && Math.abs(dxPx) + Math.abs(dyPx) <= 5) return;
19815
+ drag.moved = true;
19816
+ const nowScene = pointerToScene(e.clientX, e.clientY);
19817
+ const startScene = pointerToScene(drag.startClientX, drag.startClientY);
19818
+ drag.previewX = drag.startSceneX + (nowScene.x - startScene.x);
19819
+ drag.previewY = drag.startSceneY + (nowScene.y - startScene.y);
19820
+ draw();
19821
+ return;
19822
+ }
19195
19823
  if (enableCamera) handlePointerMove(e, () => draw());
19196
- }, [enableCamera, handlePointerMove, draw]);
19824
+ }, [editable, pointerToScene, draw, enableCamera, handlePointerMove]);
19197
19825
  const handleCanvasHover = useCallback((e) => {
19198
19826
  if (singlePointerActiveRef.current) return;
19199
19827
  if (!tileHoverEvent || !canvasRef.current) return;
19200
- const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
19201
- const adjustedX = world.x - scaledTileWidth / 2;
19202
- const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
19203
- const isoPos = unproject(adjustedX, adjustedY);
19828
+ const isoPos = pointerToScene(e.clientX, e.clientY);
19204
19829
  eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
19205
- }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, tileHoverEvent, eventBus]);
19830
+ }, [pointerToScene, tileHoverEvent, eventBus]);
19206
19831
  const handleCanvasPointerUp = useCallback((e) => {
19832
+ if (editable) {
19833
+ singlePointerActiveRef.current = false;
19834
+ const drag = editDragRef.current;
19835
+ if (drag && drag.pointerId === e.pointerId) {
19836
+ editDragRef.current = null;
19837
+ if (drag.moved) {
19838
+ onMove?.(drag.id, drag.previewX, drag.previewY);
19839
+ if (moveEvent) eventBus.emit(`UI:${moveEvent}`, { id: drag.id, x: drag.previewX, y: drag.previewY });
19840
+ draw();
19841
+ return;
19842
+ }
19843
+ const next = selectedId === drag.id ? null : drag.id;
19844
+ onSelect?.(next);
19845
+ if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: next });
19846
+ return;
19847
+ }
19848
+ onSelect?.(null);
19849
+ if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: null });
19850
+ return;
19851
+ }
19207
19852
  singlePointerActiveRef.current = false;
19208
19853
  if (enableCamera) handlePointerUp();
19209
19854
  if (dragDistance() > 5) return;
@@ -19214,16 +19859,14 @@ function Canvas2D({
19214
19859
  eventBus.emit(`UI:${unitClickEvent}`, { unitId: spriteHit });
19215
19860
  return;
19216
19861
  }
19217
- const adjustedX = world.x - scaledTileWidth / 2;
19218
- const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
19219
- const isoPos = unproject(adjustedX, adjustedY);
19862
+ const isoPos = pointerToScene(e.clientX, e.clientY);
19220
19863
  const hitId = hitIndex.get(`${isoPos.x},${isoPos.y}`);
19221
19864
  if (hitId !== void 0 && unitClickEvent) {
19222
19865
  eventBus.emit(`UI:${unitClickEvent}`, { unitId: hitId });
19223
19866
  } else if (tileClickEvent) {
19224
19867
  eventBus.emit(`UI:${tileClickEvent}`, { x: isoPos.x, y: isoPos.y });
19225
19868
  }
19226
- }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, hitIndex, drawnItems, projector, tileClickEvent, unitClickEvent, eventBus]);
19869
+ }, [editable, selectedId, onMove, moveEvent, onSelect, selectEvent, eventBus, draw, enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, drawnItems, projector, tileClickEvent, unitClickEvent, hitIndex, pointerToScene]);
19227
19870
  const handleCanvasPointerLeave = useCallback(() => {
19228
19871
  handleMouseLeave();
19229
19872
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
@@ -19242,7 +19885,7 @@ function Canvas2D({
19242
19885
  }, [enableCamera, handlePointerUp]);
19243
19886
  const gestureHandlers = useCanvasGestures({
19244
19887
  canvasRef,
19245
- enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent,
19888
+ enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent || editable,
19246
19889
  onPointerDown: handleCanvasPointerDown,
19247
19890
  onPointerMove: handleCanvasPointerMove,
19248
19891
  onPointerUp: handleCanvasPointerUp,
@@ -19374,7 +20017,7 @@ function Canvas2D({
19374
20017
  }
19375
20018
  ) });
19376
20019
  }
19377
- var canvas2DLog;
20020
+ var canvas2DLog, EDIT_SELECTION_COLOR, EDIT_HANDLE_SIZE_PX, EDIT_SELECTION_CORNERS;
19378
20021
  var init_Canvas2D = __esm({
19379
20022
  "components/game/molecules/Canvas2D.tsx"() {
19380
20023
  "use client";
@@ -19399,8 +20042,12 @@ var init_Canvas2D = __esm({
19399
20042
  init_DrawGroup();
19400
20043
  init_registry();
19401
20044
  init_hitTest();
20045
+ init_contract();
19402
20046
  init_isometric();
19403
20047
  canvas2DLog = createLogger("almadar:ui:game-canvas");
20048
+ EDIT_SELECTION_COLOR = "#3b82f6";
20049
+ EDIT_HANDLE_SIZE_PX = 8;
20050
+ EDIT_SELECTION_CORNERS = [[0, 0], [1, 0], [0, 1], [1, 1]];
19404
20051
  Canvas2D.displayName = "Canvas2D";
19405
20052
  }
19406
20053
  });
@@ -19442,6 +20089,12 @@ function Canvas({
19442
20089
  featureClickEvent,
19443
20090
  keyMap,
19444
20091
  keyUpMap,
20092
+ editable,
20093
+ selectedId,
20094
+ onSelect,
20095
+ onMove,
20096
+ selectEvent,
20097
+ moveEvent,
19445
20098
  children
19446
20099
  }) {
19447
20100
  canvasLog.debug("Canvas render", { mode, drawablesCount: drawables?.length, projection, camera: camera ? JSON.stringify(camera) : void 0 });
@@ -19519,6 +20172,12 @@ function Canvas({
19519
20172
  tileLeaveEvent,
19520
20173
  keyMap,
19521
20174
  keyUpMap,
20175
+ editable,
20176
+ selectedId,
20177
+ onSelect,
20178
+ onMove,
20179
+ selectEvent,
20180
+ moveEvent,
19522
20181
  ...children !== void 0 ? { children } : {}
19523
20182
  }
19524
20183
  );
@@ -21901,6 +22560,12 @@ function commandMatches(command, query) {
21901
22560
  if (matchesQuery(query, command.label)) return true;
21902
22561
  return (command.keywords ?? []).some((keyword) => matchesQuery(query, keyword));
21903
22562
  }
22563
+ function dispatchCommandPaletteCommand(command, deps) {
22564
+ if (command.disabled) return;
22565
+ if (command.event) deps.emit(`UI:${command.event}`, { commandId: command.id });
22566
+ if (command.action) deps.emit(`UI:${command.action}`, command.actionPayload ?? {});
22567
+ deps.onSelect?.(command);
22568
+ }
21904
22569
  var UNGROUPED, CommandPalette;
21905
22570
  var init_CommandPalette = __esm({
21906
22571
  "components/core/molecules/CommandPalette.tsx"() {
@@ -21955,9 +22620,7 @@ var init_CommandPalette = __esm({
21955
22620
  const handleSelect = useCallback(
21956
22621
  (command) => {
21957
22622
  if (command.disabled) return;
21958
- if (command.event) eventBus.emit(`UI:${command.event}`, { commandId: command.id });
21959
- if (command.action) eventBus.emit(`UI:${command.action}`, command.actionPayload ?? {});
21960
- onSelect?.(command);
22623
+ dispatchCommandPaletteCommand(command, { emit: eventBus.emit, onSelect });
21961
22624
  handleClose();
21962
22625
  },
21963
22626
  [eventBus, onSelect, handleClose]
@@ -28177,9 +28840,9 @@ function debug(...args) {
28177
28840
  const [first, ...rest] = args;
28178
28841
  const message = typeof first === "string" ? first : "<debug>";
28179
28842
  if (rest.length === 0 && typeof first === "string") {
28180
- log7.debug(message);
28843
+ log8.debug(message);
28181
28844
  } else {
28182
- log7.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28845
+ log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28183
28846
  }
28184
28847
  }
28185
28848
  function debugGroup(label) {
@@ -28207,11 +28870,11 @@ function toLogMetaValue(v) {
28207
28870
  }
28208
28871
  return String(v);
28209
28872
  }
28210
- var NAMESPACE, log7;
28873
+ var NAMESPACE, log8;
28211
28874
  var init_debug = __esm({
28212
28875
  "lib/debug.ts"() {
28213
28876
  NAMESPACE = "almadar:ui:debug";
28214
- log7 = createLogger(NAMESPACE);
28877
+ log8 = createLogger(NAMESPACE);
28215
28878
  createLogger("almadar:ui:debug:input");
28216
28879
  createLogger("almadar:ui:debug:collision");
28217
28880
  createLogger("almadar:ui:debug:physics");
@@ -30897,15 +31560,19 @@ function GameAudioToggle({
30897
31560
  size = "sm",
30898
31561
  className,
30899
31562
  onAsset,
30900
- offAsset
31563
+ offAsset,
31564
+ toggleEvent
30901
31565
  }) {
30902
31566
  const ctx = useGameAudioContextOptional();
30903
31567
  const [localMuted, setLocalMuted] = useState(false);
30904
31568
  const muted = ctx ? ctx.muted : localMuted;
30905
31569
  const setMuted = ctx ? ctx.setMuted : setLocalMuted;
31570
+ const eventBus = useEventBus();
30906
31571
  const handleToggle = useCallback(() => {
30907
- setMuted(!muted);
30908
- }, [muted, setMuted]);
31572
+ const next = !muted;
31573
+ setMuted(next);
31574
+ if (toggleEvent) eventBus.emit(`UI:${toggleEvent}`, { muted: next });
31575
+ }, [muted, setMuted, toggleEvent, eventBus]);
30909
31576
  const activeAsset = muted ? offAsset : onAsset;
30910
31577
  return /* @__PURE__ */ jsx(
30911
31578
  Button,
@@ -30924,6 +31591,7 @@ var init_GameAudioToggle = __esm({
30924
31591
  "use client";
30925
31592
  init_atoms();
30926
31593
  init_cn();
31594
+ init_useEventBus();
30927
31595
  init_GameIcon();
30928
31596
  GameAudioToggle.displayName = "GameAudioToggle";
30929
31597
  }
@@ -31195,6 +31863,47 @@ var init_useGameAudio = __esm({
31195
31863
  useGameAudio.displayName = "useGameAudio";
31196
31864
  }
31197
31865
  });
31866
+ function GameAudioCue({
31867
+ cue,
31868
+ cueSeq,
31869
+ music,
31870
+ muted,
31871
+ volume,
31872
+ manifest,
31873
+ baseUrl
31874
+ }) {
31875
+ const { play, playMusic, stopMusic, setMuted, setMasterVolume } = useGameAudio({
31876
+ manifest,
31877
+ baseUrl,
31878
+ initialMuted: muted,
31879
+ initialVolume: volume
31880
+ });
31881
+ const prevCueSeqRef = useRef(cueSeq);
31882
+ useEffect(() => {
31883
+ if (cue && cueSeq !== void 0 && cueSeq !== prevCueSeqRef.current) {
31884
+ play(cue);
31885
+ }
31886
+ prevCueSeqRef.current = cueSeq;
31887
+ }, [cue, cueSeq, play]);
31888
+ useEffect(() => {
31889
+ if (music) playMusic(music);
31890
+ else stopMusic();
31891
+ }, [music, playMusic, stopMusic]);
31892
+ useEffect(() => {
31893
+ if (muted !== void 0) setMuted(muted);
31894
+ }, [muted, setMuted]);
31895
+ useEffect(() => {
31896
+ if (volume !== void 0) setMasterVolume(volume);
31897
+ }, [volume, setMasterVolume]);
31898
+ return null;
31899
+ }
31900
+ var init_GameAudioCue = __esm({
31901
+ "components/game/atoms/GameAudioCue.tsx"() {
31902
+ "use client";
31903
+ init_useGameAudio();
31904
+ GameAudioCue.displayName = "GameAudioCue";
31905
+ }
31906
+ });
31198
31907
  function isKnownState(s) {
31199
31908
  return s in DEFAULT_STATE_STYLES;
31200
31909
  }
@@ -32091,15 +32800,18 @@ var init_physicsPresets = __esm({
32091
32800
  ];
32092
32801
  }
32093
32802
  });
32094
- var GAME_FONTS, GameShell;
32095
- var init_GameShell = __esm({
32096
- "components/game/templates/GameShell.tsx"() {
32097
- init_cn();
32098
- init_Box();
32099
- init_Card();
32100
- init_Typography();
32101
- init_AtlasImage();
32102
- GAME_FONTS = {
32803
+
32804
+ // lib/gameFonts.ts
32805
+ function resolveGameFontFamily(input) {
32806
+ if (!input) return void 0;
32807
+ const resolved = GAME_FONT_KEYS[input];
32808
+ if (resolved) return `'${resolved}', ui-sans-serif, system-ui, sans-serif`;
32809
+ return input;
32810
+ }
32811
+ var GAME_FONT_KEYS;
32812
+ var init_gameFonts = __esm({
32813
+ "lib/gameFonts.ts"() {
32814
+ GAME_FONT_KEYS = {
32103
32815
  fredoka: "Fredoka",
32104
32816
  future: "Kenney Future",
32105
32817
  "future-narrow": "Kenney Future Narrow",
@@ -32107,6 +32819,17 @@ var init_GameShell = __esm({
32107
32819
  blocks: "Kenney Blocks",
32108
32820
  mini: "Kenney Mini"
32109
32821
  };
32822
+ }
32823
+ });
32824
+ var GameShell;
32825
+ var init_GameShell = __esm({
32826
+ "components/game/templates/GameShell.tsx"() {
32827
+ init_cn();
32828
+ init_gameFonts();
32829
+ init_Box();
32830
+ init_Card();
32831
+ init_Typography();
32832
+ init_AtlasImage();
32110
32833
  GameShell = ({
32111
32834
  appName = "Game",
32112
32835
  hud,
@@ -32120,7 +32843,7 @@ var init_GameShell = __esm({
32120
32843
  fontFamily,
32121
32844
  "data-theme": dataTheme
32122
32845
  }) => {
32123
- const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
32846
+ const displayFont = resolveGameFontFamily(fontFamily);
32124
32847
  return /* @__PURE__ */ jsxs(
32125
32848
  Box,
32126
32849
  {
@@ -32139,7 +32862,7 @@ var init_GameShell = __esm({
32139
32862
  // passed — an always-on inline stamp would shadow the orbital's
32140
32863
  // inline-theme font-family-display token (inline style beats the
32141
32864
  // theme provider's vars for the whole shell subtree).
32142
- ...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
32865
+ ...displayFont ? { "--font-family-display": displayFont } : {}
32143
32866
  },
32144
32867
  children: [
32145
32868
  backgroundAsset && /* @__PURE__ */ jsx(
@@ -32272,6 +32995,7 @@ var init_molecules = __esm({
32272
32995
  init_Canvas();
32273
32996
  init_useUnitSpriteAtlas();
32274
32997
  init_GameAudioToggle();
32998
+ init_GameAudioCue();
32275
32999
  init_useGameAudio();
32276
33000
  init_useCamera();
32277
33001
  init_TraitStateViewer();
@@ -32300,6 +33024,7 @@ var init_MathCanvas = __esm({
32300
33024
  init_perf();
32301
33025
  init_atoms();
32302
33026
  init_Stack();
33027
+ init_gameFonts();
32303
33028
  init_LearningCanvas();
32304
33029
  MathCanvas = ({
32305
33030
  className,
@@ -32319,6 +33044,7 @@ var init_MathCanvas = __esm({
32319
33044
  showTickLabels = false,
32320
33045
  tickLabelFontSize = 10,
32321
33046
  labelFontSize = 12,
33047
+ fontFamily: fontFamilyProp,
32322
33048
  showCurveLabels = false,
32323
33049
  curves = [],
32324
33050
  points = [],
@@ -32341,6 +33067,7 @@ var init_MathCanvas = __esm({
32341
33067
  error
32342
33068
  }) => {
32343
33069
  const eventBus = useEventBus();
33070
+ const fontFamily = resolveGameFontFamily(fontFamilyProp);
32344
33071
  const keyMapKey = keyMap ? JSON.stringify(keyMap) : null;
32345
33072
  const keyUpMapKey = keyUpMap ? JSON.stringify(keyUpMap) : null;
32346
33073
  const stableKeyMap = useMemo(() => keyMap, [keyMapKey]);
@@ -32390,18 +33117,18 @@ var init_MathCanvas = __esm({
32390
33117
  let kx = 0;
32391
33118
  for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep, kx++) {
32392
33119
  if (kx % labelEveryX === 0 && x !== 0) {
32393
- out.push({ type: "text", x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
33120
+ out.push({ type: "text", fontFamily, x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
32394
33121
  }
32395
33122
  }
32396
33123
  const labelEveryY = Math.max(1, Math.ceil((yMax - yMin) / gridStep / Math.floor(plotH / 28)));
32397
33124
  let ky = 0;
32398
33125
  for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep, ky++) {
32399
33126
  if (ky % labelEveryY === 0 && y !== 0) {
32400
- out.push({ type: "text", x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
33127
+ out.push({ type: "text", fontFamily, x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
32401
33128
  }
32402
33129
  }
32403
33130
  if (xMin <= 0 && xMax >= 0 && yMin <= 0 && yMax >= 0) {
32404
- out.push({ type: "text", x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
33131
+ out.push({ type: "text", fontFamily, x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
32405
33132
  }
32406
33133
  }
32407
33134
  for (const region of regions) {
@@ -32428,6 +33155,7 @@ var init_MathCanvas = __esm({
32428
33155
  const mid = Math.floor(region.samples.length / 2);
32429
33156
  out.push({
32430
33157
  type: "text",
33158
+ fontFamily,
32431
33159
  x: mapX((first.x + last.x) / 2),
32432
33160
  y: (mapY(region.samples[mid].y) + mapY(baseline)) / 2,
32433
33161
  text: region.label,
@@ -32464,14 +33192,14 @@ var init_MathCanvas = __esm({
32464
33192
  const px = mapX(guide.at);
32465
33193
  out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color, dash });
32466
33194
  if (guide.label) {
32467
- out.push({ type: "text", x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
33195
+ out.push({ type: "text", fontFamily, x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
32468
33196
  }
32469
33197
  } else {
32470
33198
  if (guide.at < yMin || guide.at > yMax) continue;
32471
33199
  const py = mapY(guide.at);
32472
33200
  out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color, dash });
32473
33201
  if (guide.label) {
32474
- out.push({ type: "text", x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
33202
+ out.push({ type: "text", fontFamily, x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
32475
33203
  }
32476
33204
  }
32477
33205
  }
@@ -32510,6 +33238,7 @@ var init_MathCanvas = __esm({
32510
33238
  if (showCurveLabels && curve.label && lastInRange) {
32511
33239
  out.push({
32512
33240
  type: "text",
33241
+ fontFamily,
32513
33242
  x: mapX(lastInRange.x) + 6,
32514
33243
  y: mapY(lastInRange.y) - 6,
32515
33244
  text: curve.label,
@@ -32547,6 +33276,7 @@ var init_MathCanvas = __esm({
32547
33276
  if (hop.label) {
32548
33277
  out.push({
32549
33278
  type: "text",
33279
+ fontFamily,
32550
33280
  x: (x1 + x2) / 2,
32551
33281
  y: xAxisY - peak - 8,
32552
33282
  text: hop.label,
@@ -32574,6 +33304,7 @@ var init_MathCanvas = __esm({
32574
33304
  const rad = mid * Math.PI / 180;
32575
33305
  out.push({
32576
33306
  type: "text",
33307
+ fontFamily,
32577
33308
  x: mapX(angle.x + 1.35 * radius * Math.cos(rad)),
32578
33309
  y: mapY(angle.y + 1.35 * radius * Math.sin(rad)),
32579
33310
  text: angle.label,
@@ -32595,7 +33326,7 @@ var init_MathCanvas = __esm({
32595
33326
  fill: isOpen ? "#ffffff" : p.color ?? "#dc2626"
32596
33327
  });
32597
33328
  if (p.label) {
32598
- out.push({ type: "text", x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
33329
+ out.push({ type: "text", fontFamily, x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
32599
33330
  }
32600
33331
  }
32601
33332
  for (const v of vectors) {
@@ -32606,7 +33337,7 @@ var init_MathCanvas = __esm({
32606
33337
  const y2 = mapY(v.y + v.vy);
32607
33338
  out.push({ type: "arrow", x1, y1, x2, y2, color: v.color ?? "#7c3aed", lineWidth: 2 });
32608
33339
  if (v.label) {
32609
- out.push({ type: "text", x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
33340
+ out.push({ type: "text", fontFamily, x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
32610
33341
  }
32611
33342
  }
32612
33343
  out.push(...shapes);
@@ -32627,6 +33358,7 @@ var init_MathCanvas = __esm({
32627
33358
  showTickLabels,
32628
33359
  tickLabelFontSize,
32629
33360
  labelFontSize,
33361
+ fontFamily,
32630
33362
  showCurveLabels,
32631
33363
  curves,
32632
33364
  points,
@@ -32682,6 +33414,7 @@ var init_MathCanvas = __esm({
32682
33414
  width,
32683
33415
  height,
32684
33416
  backgroundColor,
33417
+ fontFamily,
32685
33418
  shapes: derivedShapes,
32686
33419
  drawables,
32687
33420
  projector,
@@ -33914,13 +34647,13 @@ var init_MapView = __esm({
33914
34647
  shadowSize: [41, 41]
33915
34648
  });
33916
34649
  L.Marker.prototype.options.icon = defaultIcon;
33917
- const { useEffect: useEffect70, useRef: useRef67, useCallback: useCallback109, useState: useState109 } = React79__default;
34650
+ const { useEffect: useEffect72, useRef: useRef70, useCallback: useCallback109, useState: useState110 } = React79__default;
33918
34651
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
33919
34652
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
33920
34653
  function MapUpdater({ centerLat, centerLng, zoom }) {
33921
34654
  const map = useMap();
33922
- const prevRef = useRef67({ centerLat, centerLng, zoom });
33923
- useEffect70(() => {
34655
+ const prevRef = useRef70({ centerLat, centerLng, zoom });
34656
+ useEffect72(() => {
33924
34657
  const prev = prevRef.current;
33925
34658
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
33926
34659
  map.setView([centerLat, centerLng], zoom);
@@ -33931,7 +34664,7 @@ var init_MapView = __esm({
33931
34664
  }
33932
34665
  function MapClickHandler({ onMapClick }) {
33933
34666
  const map = useMap();
33934
- useEffect70(() => {
34667
+ useEffect72(() => {
33935
34668
  if (!onMapClick) return;
33936
34669
  const handler = (e) => {
33937
34670
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -33959,7 +34692,7 @@ var init_MapView = __esm({
33959
34692
  showAttribution = true
33960
34693
  }) {
33961
34694
  const eventBus = useEventBus2();
33962
- const [clickedPosition, setClickedPosition] = useState109(null);
34695
+ const [clickedPosition, setClickedPosition] = useState110(null);
33963
34696
  const handleMapClick = useCallback109((lat, lng) => {
33964
34697
  if (showClickedPin) {
33965
34698
  setClickedPosition({ lat, lng });
@@ -48897,7 +49630,7 @@ function getAllEvents(traits2) {
48897
49630
  function EventDispatcherTab({ traits: traits2, schema }) {
48898
49631
  const eventBus = useEventBus();
48899
49632
  const { t } = useTranslate();
48900
- const [log19, setLog] = React79.useState([]);
49633
+ const [log20, setLog] = React79.useState([]);
48901
49634
  const prevStatesRef = React79.useRef(/* @__PURE__ */ new Map());
48902
49635
  React79.useEffect(() => {
48903
49636
  for (const trait of traits2) {
@@ -48961,9 +49694,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
48961
49694
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.otherEvents") }),
48962
49695
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
48963
49696
  ] }),
48964
- log19.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
49697
+ log20.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48965
49698
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.recentTransitions") }),
48966
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
49699
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log20.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
48967
49700
  /* @__PURE__ */ jsx("span", { className: "text-primary", children: entry.traitName }),
48968
49701
  " ",
48969
49702
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: entry.from }),
@@ -51154,6 +51887,7 @@ var init_component_registry_generated = __esm({
51154
51887
  init_FormSection();
51155
51888
  init_FormSectionHeader();
51156
51889
  init_FxOverlay();
51890
+ init_GameAudioCue();
51157
51891
  init_GameAudioToggle();
51158
51892
  init_GameHud();
51159
51893
  init_GameIcon();
@@ -51431,6 +52165,7 @@ var init_component_registry_generated = __esm({
51431
52165
  "FormLayout": FormLayout,
51432
52166
  "FormSectionHeader": FormSectionHeader,
51433
52167
  "FxOverlay": FxOverlay,
52168
+ "GameAudioCue": GameAudioCue,
51434
52169
  "GameAudioToggle": GameAudioToggle,
51435
52170
  "GameHud": GameHud,
51436
52171
  "GameIcon": GameIcon,
@@ -52917,7 +53652,7 @@ init_AboutPageTemplate();
52917
53652
 
52918
53653
  // components/index.ts
52919
53654
  init_cn();
52920
- var log8 = createLogger("almadar:ui:orbital-history");
53655
+ var log9 = createLogger("almadar:ui:orbital-history");
52921
53656
  function useOrbitalHistory(options) {
52922
53657
  const { appId, authToken, userId, onHistoryChange, onRevertSuccess } = options;
52923
53658
  const getHeaders = useCallback(() => {
@@ -52979,7 +53714,7 @@ function useOrbitalHistory(options) {
52979
53714
  setCurrentVersion(mergedTimeline[0].version);
52980
53715
  }
52981
53716
  } catch (err) {
52982
- log8.error("Failed to load history", { error: err instanceof Error ? err : String(err) });
53717
+ log9.error("Failed to load history", { error: err instanceof Error ? err : String(err) });
52983
53718
  setError(err instanceof Error ? err.message : "Failed to load history");
52984
53719
  } finally {
52985
53720
  setIsLoading(false);
@@ -53012,7 +53747,7 @@ function useOrbitalHistory(options) {
53012
53747
  error: data.error || "Unknown error during revert"
53013
53748
  };
53014
53749
  } catch (err) {
53015
- log8.error("Failed to revert", { error: err instanceof Error ? err : String(err) });
53750
+ log9.error("Failed to revert", { error: err instanceof Error ? err : String(err) });
53016
53751
  return {
53017
53752
  success: false,
53018
53753
  error: err instanceof Error ? err.message : "Failed to revert"
@@ -53036,7 +53771,7 @@ function useOrbitalHistory(options) {
53036
53771
  refresh
53037
53772
  };
53038
53773
  }
53039
- var log9 = createLogger("almadar:ui:filesystem");
53774
+ var log10 = createLogger("almadar:ui:filesystem");
53040
53775
  function useFileSystem() {
53041
53776
  const [status, setStatus] = useState("idle");
53042
53777
  const [error, setError] = useState(null);
@@ -53051,7 +53786,7 @@ function useFileSystem() {
53051
53786
  setError(null);
53052
53787
  setIsLoading(true);
53053
53788
  try {
53054
- log9.debug("Booting WebContainer");
53789
+ log10.debug("Booting WebContainer");
53055
53790
  await new Promise((resolve) => setTimeout(resolve, 100));
53056
53791
  setStatus("ready");
53057
53792
  } catch (err) {
@@ -53112,7 +53847,7 @@ function useFileSystem() {
53112
53847
  setFiles(newTree);
53113
53848
  setStatus("running");
53114
53849
  } catch (err) {
53115
- log9.error("Failed to mount files", { error: err instanceof Error ? err : String(err) });
53850
+ log10.error("Failed to mount files", { error: err instanceof Error ? err : String(err) });
53116
53851
  } finally {
53117
53852
  setIsLoading(false);
53118
53853
  }
@@ -53153,7 +53888,7 @@ function useFileSystem() {
53153
53888
  const path = contentArg !== void 0 ? pathOrContent : selectedPath;
53154
53889
  const content = contentArg !== void 0 ? contentArg : pathOrContent;
53155
53890
  if (!path) {
53156
- log9.warn("updateContent called without path and no file selected");
53891
+ log10.warn("updateContent called without path and no file selected");
53157
53892
  return;
53158
53893
  }
53159
53894
  setFileContents((prev) => {
@@ -53169,14 +53904,14 @@ function useFileSystem() {
53169
53904
  setSelectedFile((prev) => prev ? { ...prev, content, isDirty: true } : null);
53170
53905
  }, []);
53171
53906
  const refreshTree = useCallback(async () => {
53172
- log9.debug("Refreshing tree");
53907
+ log10.debug("Refreshing tree");
53173
53908
  }, []);
53174
53909
  const runCommand = useCallback(async (command) => {
53175
- log9.debug("Running command", { command });
53910
+ log10.debug("Running command", { command });
53176
53911
  return { exitCode: 0, output: "" };
53177
53912
  }, []);
53178
53913
  const startDevServer = useCallback(async () => {
53179
- log9.debug("Starting dev server");
53914
+ log10.debug("Starting dev server");
53180
53915
  setPreviewUrl("http://localhost:5173");
53181
53916
  }, []);
53182
53917
  return {
@@ -53199,7 +53934,7 @@ function useFileSystem() {
53199
53934
  startDevServer
53200
53935
  };
53201
53936
  }
53202
- var log10 = createLogger("almadar:ui:extensions");
53937
+ var log11 = createLogger("almadar:ui:extensions");
53203
53938
  var defaultManifest = {
53204
53939
  languages: {
53205
53940
  typescript: { extensions: [".ts", ".tsx"], icon: "ts", color: "#3178c6" },
@@ -53218,7 +53953,7 @@ function useExtensions(options) {
53218
53953
  const [isLoading, setIsLoading] = useState(false);
53219
53954
  const [error, setError] = useState(null);
53220
53955
  const loadExtension = useCallback(async (extensionId) => {
53221
- log10.debug("Loading extension", { extensionId });
53956
+ log11.debug("Loading extension", { extensionId });
53222
53957
  }, []);
53223
53958
  const loadExtensions = useCallback(async () => {
53224
53959
  setIsLoading(true);
@@ -53290,7 +54025,7 @@ function useExtensions(options) {
53290
54025
  getExtensionForFile
53291
54026
  };
53292
54027
  }
53293
- var log11 = createLogger("almadar:ui:file-editor");
54028
+ var log12 = createLogger("almadar:ui:file-editor");
53294
54029
  function useFileEditor(options) {
53295
54030
  const { extensions, fileSystem, onSchemaUpdate } = options;
53296
54031
  const [openFiles, setOpenFiles] = useState([]);
@@ -53315,7 +54050,7 @@ function useFileEditor(options) {
53315
54050
  setOpenFiles((prev) => [...prev, newFile]);
53316
54051
  setActiveFilePath(path);
53317
54052
  } catch (err) {
53318
- log11.error("Failed to open file", { error: err instanceof Error ? err : String(err) });
54053
+ log12.error("Failed to open file", { error: err instanceof Error ? err : String(err) });
53319
54054
  }
53320
54055
  }, [openFiles, fileSystem, extensions]);
53321
54056
  const closeFile = useCallback((path) => {
@@ -53376,7 +54111,7 @@ function useFileEditor(options) {
53376
54111
  }
53377
54112
  }
53378
54113
  } catch (err) {
53379
- log11.error("Failed to save file", { error: err instanceof Error ? err : String(err) });
54114
+ log12.error("Failed to save file", { error: err instanceof Error ? err : String(err) });
53380
54115
  } finally {
53381
54116
  setIsSaving(false);
53382
54117
  }
@@ -53405,7 +54140,7 @@ function useFileEditor(options) {
53405
54140
  saveAllFiles
53406
54141
  };
53407
54142
  }
53408
- var log12 = createLogger("almadar:ui:compile");
54143
+ var log13 = createLogger("almadar:ui:compile");
53409
54144
  function useCompile() {
53410
54145
  const [isCompiling, setIsCompiling] = useState(false);
53411
54146
  const [stage, setStage] = useState("idle");
@@ -53416,7 +54151,7 @@ function useCompile() {
53416
54151
  setStage("compiling");
53417
54152
  setError(null);
53418
54153
  try {
53419
- log12.debug("Compiling schema", { name: schema.name });
54154
+ log13.debug("Compiling schema", { name: schema.name });
53420
54155
  const result = {
53421
54156
  success: true,
53422
54157
  files: []
@@ -53442,7 +54177,7 @@ function useCompile() {
53442
54177
  compileSchema
53443
54178
  };
53444
54179
  }
53445
- var log13 = createLogger("almadar:ui:preview");
54180
+ var log14 = createLogger("almadar:ui:preview");
53446
54181
  function usePreview(options) {
53447
54182
  const [previewUrl, setPreviewUrl] = useState(null);
53448
54183
  const [isLoading, setIsLoading] = useState(!!options?.appId);
@@ -53476,17 +54211,17 @@ function usePreview(options) {
53476
54211
  setIsLoading(false);
53477
54212
  return;
53478
54213
  }
53479
- log13.debug("Setting up preview for app", { appId });
54214
+ log14.debug("Setting up preview for app", { appId });
53480
54215
  setPreviewUrl(`/api/orbitals/${appId}`);
53481
54216
  setIsLoading(false);
53482
54217
  }, [options?.appId]);
53483
54218
  const startPreview = useCallback(async () => {
53484
- log13.debug("startPreview called");
54219
+ log14.debug("startPreview called");
53485
54220
  }, []);
53486
54221
  const stopPreview = useCallback(async () => {
53487
54222
  setIsLoading(true);
53488
54223
  try {
53489
- log13.debug("Stopping preview server");
54224
+ log14.debug("Stopping preview server");
53490
54225
  setPreviewUrl(null);
53491
54226
  setApp(null);
53492
54227
  } finally {
@@ -53495,15 +54230,15 @@ function usePreview(options) {
53495
54230
  }, []);
53496
54231
  const refresh = useCallback(async () => {
53497
54232
  if (!previewUrl) return;
53498
- log13.debug("Refreshing preview");
54233
+ log14.debug("Refreshing preview");
53499
54234
  setPreviewUrl(`${previewUrl.split("?")[0]}?t=${Date.now()}`);
53500
54235
  }, [previewUrl]);
53501
54236
  const handleRefresh = useCallback(async () => {
53502
- log13.debug("Handle refresh");
54237
+ log14.debug("Handle refresh");
53503
54238
  await refresh();
53504
54239
  }, [refresh]);
53505
54240
  const handleReset = useCallback(async () => {
53506
- log13.debug("Resetting preview");
54241
+ log14.debug("Resetting preview");
53507
54242
  setError(null);
53508
54243
  setLoadError(null);
53509
54244
  setErrorToast(null);
@@ -53537,7 +54272,7 @@ function usePreview(options) {
53537
54272
  dismissErrorToast
53538
54273
  };
53539
54274
  }
53540
- var log14 = createLogger("almadar:ui:agent-chat");
54275
+ var log15 = createLogger("almadar:ui:agent-chat");
53541
54276
  function useAgentChat(options) {
53542
54277
  const [messages, setMessages] = useState([]);
53543
54278
  const [status, setStatus] = useState("idle");
@@ -53560,7 +54295,7 @@ function useAgentChat(options) {
53560
54295
  timestamp: Date.now()
53561
54296
  };
53562
54297
  setMessages((prev) => [...prev, userMessage]);
53563
- log14.debug("Sending message", { content });
54298
+ log15.debug("Sending message", { content });
53564
54299
  const assistantMessage = {
53565
54300
  id: (Date.now() + 1).toString(),
53566
54301
  role: "assistant",
@@ -53583,7 +54318,7 @@ function useAgentChat(options) {
53583
54318
  setError(null);
53584
54319
  const skillName = Array.isArray(skill) ? skill[0] : skill;
53585
54320
  try {
53586
- log14.debug("Starting generation", () => ({ skillName, prompt, genOptions: JSON.stringify(genOptions) }));
54321
+ log15.debug("Starting generation", () => ({ skillName, prompt, genOptions: JSON.stringify(genOptions) }));
53587
54322
  await new Promise((resolve) => setTimeout(resolve, 100));
53588
54323
  setStatus("complete");
53589
54324
  options?.onComplete?.();
@@ -53595,10 +54330,10 @@ function useAgentChat(options) {
53595
54330
  }
53596
54331
  }, [options]);
53597
54332
  const continueConversation = useCallback(async (message) => {
53598
- log14.debug("Continue conversation", { message: Array.isArray(message) ? message : [message] });
54333
+ log15.debug("Continue conversation", { message: Array.isArray(message) ? message : [message] });
53599
54334
  }, []);
53600
54335
  const resumeWithDecision = useCallback(async (decisions) => {
53601
- log14.debug("Resume with decision", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
54336
+ log15.debug("Resume with decision", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
53602
54337
  setInterrupt(null);
53603
54338
  }, []);
53604
54339
  const cancel = useCallback(() => {
@@ -53635,7 +54370,7 @@ function useAgentChat(options) {
53635
54370
  clearHistory
53636
54371
  };
53637
54372
  }
53638
- var log15 = createLogger("almadar:ui:validation");
54373
+ var log16 = createLogger("almadar:ui:validation");
53639
54374
  function useValidation() {
53640
54375
  const [result, setResult] = useState(null);
53641
54376
  const [isValidating, setIsValidating] = useState(false);
@@ -53649,7 +54384,7 @@ function useValidation() {
53649
54384
  setStage("validating");
53650
54385
  setProgressMessage("Validating schema...");
53651
54386
  try {
53652
- log15.debug("Validating app", { appId });
54387
+ log16.debug("Validating app", { appId });
53653
54388
  const validationResult = {
53654
54389
  valid: true,
53655
54390
  errors: [],
@@ -53702,7 +54437,7 @@ function useValidation() {
53702
54437
  reset
53703
54438
  };
53704
54439
  }
53705
- var log16 = createLogger("almadar:ui:deep-agent");
54440
+ var log17 = createLogger("almadar:ui:deep-agent");
53706
54441
  function useDeepAgentGeneration() {
53707
54442
  const [requests, setRequests] = useState([]);
53708
54443
  const [currentRequest, setCurrentRequest] = useState(null);
@@ -53726,7 +54461,7 @@ function useDeepAgentGeneration() {
53726
54461
  setCurrentRequest(request);
53727
54462
  setRequests((prev) => [...prev, request]);
53728
54463
  try {
53729
- log16.debug("Generating from prompt", { prompt });
54464
+ log17.debug("Generating from prompt", { prompt });
53730
54465
  await new Promise((resolve) => setTimeout(resolve, 100));
53731
54466
  request.status = "completed";
53732
54467
  setCurrentRequest(request);
@@ -53746,7 +54481,7 @@ function useDeepAgentGeneration() {
53746
54481
  }
53747
54482
  }, []);
53748
54483
  const startGeneration = useCallback(async (skill, prompt, _options) => {
53749
- log16.debug("Starting generation with skill", { skill });
54484
+ log17.debug("Starting generation with skill", { skill });
53750
54485
  await generate(prompt);
53751
54486
  }, [generate]);
53752
54487
  const cancelGeneration = useCallback(() => {
@@ -53768,7 +54503,7 @@ function useDeepAgentGeneration() {
53768
54503
  setIsComplete(false);
53769
54504
  }, []);
53770
54505
  const submitInterruptDecisions = useCallback((decisions) => {
53771
- log16.debug("Submitting interrupt decisions", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
54506
+ log17.debug("Submitting interrupt decisions", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
53772
54507
  setInterrupt(null);
53773
54508
  }, []);
53774
54509
  return {
@@ -53790,6 +54525,66 @@ function useDeepAgentGeneration() {
53790
54525
 
53791
54526
  // hooks/index.ts
53792
54527
  init_useEventBus();
54528
+
54529
+ // hooks/useKeyboardRouter.ts
54530
+ init_useEventBus();
54531
+ function useKeyboardRouter(options) {
54532
+ const {
54533
+ captureTable,
54534
+ editorFocusEvent = "EDITOR_FOCUS",
54535
+ editorBlurEvent = "EDITOR_BLUR",
54536
+ keyEvent = "KEY",
54537
+ enabled = true
54538
+ } = options;
54539
+ const eventBus = useEventBus();
54540
+ const captureTableRef = useRef(captureTable);
54541
+ captureTableRef.current = captureTable;
54542
+ const focusedEditorIdRef = useRef(null);
54543
+ useEffect(() => {
54544
+ const unsubFocus = eventBus.on(`UI:${editorFocusEvent}`, (event) => {
54545
+ const editorId = event.payload?.editorId;
54546
+ if (typeof editorId === "string") {
54547
+ focusedEditorIdRef.current = editorId;
54548
+ }
54549
+ });
54550
+ const unsubBlur = eventBus.on(`UI:${editorBlurEvent}`, (event) => {
54551
+ const editorId = event.payload?.editorId;
54552
+ if (typeof editorId === "string" && focusedEditorIdRef.current === editorId) {
54553
+ focusedEditorIdRef.current = null;
54554
+ }
54555
+ });
54556
+ return () => {
54557
+ unsubFocus();
54558
+ unsubBlur();
54559
+ };
54560
+ }, [eventBus, editorFocusEvent, editorBlurEvent]);
54561
+ useEffect(() => {
54562
+ if (!enabled) return;
54563
+ const handleKeyDown = (event) => {
54564
+ if (event.isComposing) return;
54565
+ const target = focusedEditorIdRef.current ?? "shell";
54566
+ const entry = captureTableRef.current[target];
54567
+ const captured = entry !== void 0 && (entry.mode === "any" || entry.keys.has(event.key));
54568
+ if (captured) {
54569
+ event.preventDefault();
54570
+ }
54571
+ eventBus.emit(`UI:${keyEvent}`, {
54572
+ editorId: target,
54573
+ key: event.key,
54574
+ code: event.code,
54575
+ ctrl: event.ctrlKey,
54576
+ alt: event.altKey,
54577
+ shift: event.shiftKey,
54578
+ meta: event.metaKey,
54579
+ repeat: event.repeat
54580
+ });
54581
+ };
54582
+ window.addEventListener("keydown", handleKeyDown, { capture: true });
54583
+ return () => {
54584
+ window.removeEventListener("keydown", handleKeyDown, { capture: true });
54585
+ };
54586
+ }, [eventBus, enabled, keyEvent]);
54587
+ }
53793
54588
  function expressionEqual(a, b) {
53794
54589
  if (Object.is(a, b)) return true;
53795
54590
  if (Array.isArray(a) && Array.isArray(b)) {
@@ -53872,21 +54667,12 @@ function reconcileSlotProps(prev, next) {
53872
54667
  }
53873
54668
 
53874
54669
  // hooks/useUISlots.ts
53875
- var log17 = createLogger("almadar:ui:ui-slots");
54670
+ var log18 = createLogger("almadar:ui:ui-slots");
53876
54671
  var DEFAULT_SOURCE_KEY = "__default__";
53877
54672
  var MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
53878
- var ALL_SLOTS2 = [
53879
- "main",
53880
- "sidebar",
53881
- "modal",
53882
- "drawer",
53883
- "overlay",
53884
- "center",
53885
- "toast",
53886
- "hud-top",
53887
- "hud-bottom",
53888
- "floating"
53889
- ];
54673
+ var ALL_SLOTS2 = UI_SLOTS.filter(
54674
+ (slot) => !slot.includes(".") && slot !== "hud" && slot !== "screen"
54675
+ );
53890
54676
  var DEFAULT_SLOTS = ALL_SLOTS2.reduce(
53891
54677
  (acc, slot) => {
53892
54678
  acc[slot] = null;
@@ -53949,7 +54735,7 @@ function useUISlotManager() {
53949
54735
  try {
53950
54736
  callback(slot, content);
53951
54737
  } catch (error) {
53952
- log17.error("Subscriber error", { error: error instanceof Error ? error : String(error) });
54738
+ log18.error("Subscriber error", { error: error instanceof Error ? error : String(error) });
53953
54739
  }
53954
54740
  });
53955
54741
  }, []);
@@ -53961,7 +54747,7 @@ function useUISlotManager() {
53961
54747
  try {
53962
54748
  callback(content);
53963
54749
  } catch (error) {
53964
- log17.error("Trait subscriber error", { traitName, error: error instanceof Error ? error : String(error) });
54750
+ log18.error("Trait subscriber error", { traitName, error: error instanceof Error ? error : String(error) });
53965
54751
  }
53966
54752
  });
53967
54753
  },
@@ -54018,7 +54804,7 @@ function useUISlotManager() {
54018
54804
  const slotSources = prev[config.target] ?? {};
54019
54805
  const existing = slotSources[sourceKey];
54020
54806
  if (existing && existing.priority > content.priority) {
54021
- log17.warn("Slot already has higher priority content", {
54807
+ log18.warn("Slot already has higher priority content", {
54022
54808
  slot: config.target,
54023
54809
  sourceKey,
54024
54810
  existingPriority: existing.priority,
@@ -54029,7 +54815,7 @@ function useUISlotManager() {
54029
54815
  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)) {
54030
54816
  const reconciled = reconcileSlotProps(existing.props, content.props);
54031
54817
  if (reconciled.equal) {
54032
- log17.debug("slot:flush-bail", { slot: config.target, sourceKey, pattern: content.pattern });
54818
+ log18.debug("slot:flush-bail", { slot: config.target, sourceKey, pattern: content.pattern });
54033
54819
  return prev;
54034
54820
  }
54035
54821
  content.props = reconciled.value;
@@ -54041,7 +54827,7 @@ function useUISlotManager() {
54041
54827
  const nextAll = { ...prev, [config.target]: nextSources };
54042
54828
  const priorWriters = Object.keys(slotSources);
54043
54829
  if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
54044
- log17.warn("slot:contention", {
54830
+ log18.warn("slot:contention", {
54045
54831
  slot: config.target,
54046
54832
  writers: [priorWriters[0], sourceKey],
54047
54833
  patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
@@ -54051,7 +54837,7 @@ function useUISlotManager() {
54051
54837
  indexTraitRender(content.sourceTrait, content);
54052
54838
  notifyTraitSubscribers(content.sourceTrait, content);
54053
54839
  }
54054
- log17.info("slot:written", {
54840
+ log18.info("slot:written", {
54055
54841
  slot: config.target,
54056
54842
  sourceKey,
54057
54843
  sourceTrait: content.sourceTrait,
@@ -54096,7 +54882,7 @@ function useUISlotManager() {
54096
54882
  setSources((prev) => {
54097
54883
  const slotSources = prev[slot];
54098
54884
  if (!slotSources || !(sourceKey in slotSources)) {
54099
- log17.debug("slot:clear-noop", { slot, sourceTrait, reason: !slotSources ? "no-slot" : "no-source" });
54885
+ log18.debug("slot:clear-noop", { slot, sourceTrait, reason: !slotSources ? "no-slot" : "no-source" });
54100
54886
  return prev;
54101
54887
  }
54102
54888
  const content = slotSources[sourceKey];
@@ -54112,7 +54898,7 @@ function useUISlotManager() {
54112
54898
  }
54113
54899
  const nextSources = { ...slotSources };
54114
54900
  delete nextSources[sourceKey];
54115
- log17.info("slot:cleared", { slot, sourceTrait, lastPatternType: content.pattern });
54901
+ log18.info("slot:cleared", { slot, sourceTrait, lastPatternType: content.pattern });
54116
54902
  notifySubscribers(slot, aggregateSlot(nextSources));
54117
54903
  return { ...prev, [slot]: nextSources };
54118
54904
  });
@@ -54288,7 +55074,7 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
54288
55074
  };
54289
55075
  }, [eventBus, dispatch, stableListens]);
54290
55076
  }
54291
- var log18 = createLogger("almadar:ui:shared-entity-store");
55077
+ var log19 = createLogger("almadar:ui:shared-entity-store");
54292
55078
  var EMPTY_ENTITY_STATE = {};
54293
55079
  function createSharedEntityStore() {
54294
55080
  const states = /* @__PURE__ */ new Map();
@@ -54318,7 +55104,7 @@ function createSharedEntityStore() {
54318
55104
  try {
54319
55105
  callback();
54320
55106
  } catch (error) {
54321
- log18.error("Shared entity subscriber error", {
55107
+ log19.error("Shared entity subscriber error", {
54322
55108
  entityId,
54323
55109
  error: error instanceof Error ? error : String(error)
54324
55110
  });
@@ -54924,7 +55710,8 @@ var en_default = {
54924
55710
  "richTextEditor.image": "Insert image",
54925
55711
  "richTextEditor.imagePrompt": "Image URL",
54926
55712
  "richTextEditor.placeholder": "Start writing\u2026",
54927
- "form.imageUrlFallback": "\u2026or paste an image address"
55713
+ "form.imageUrlFallback": "\u2026or paste an image address",
55714
+ "mermaid.unrenderable": "This diagram could not be displayed. Its source is shown below."
54928
55715
  };
54929
55716
 
54930
55717
  // hooks/useTranslate.ts
@@ -54945,7 +55732,7 @@ var I18nContext = createContext({
54945
55732
  });
54946
55733
  I18nContext.displayName = "I18nContext";
54947
55734
  var I18nProvider = I18nContext.Provider;
54948
- function useTranslate116() {
55735
+ function useTranslate117() {
54949
55736
  return useContext(I18nContext);
54950
55737
  }
54951
55738
  function createTranslate(messages) {
@@ -55131,4 +55918,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
55131
55918
  });
55132
55919
  }
55133
55920
 
55134
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgoGraphCanvas, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommandPalette, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DockLayout, DocumentDetails, DocumentPanel, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmojiPicker, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, FloatingToolbar, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, FxOverlay, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, ImportPreviewTree, ImportProgress, ImportSourcePicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, LearningScene3D, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichTextEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, arrowBetween, billboardLabel, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, cylinderBetween, get3DClickPayload, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, meshSphere, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, renderPatternValue, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, sanitizeRichHtml, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useMediaQuery, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate116 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
55921
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgoGraphCanvas, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommandPalette, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DockLayout, DocumentDetails, DocumentPanel, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmojiPicker, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, FloatingToolbar, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, FxOverlay, GameAudioCue, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, ImportPreviewTree, ImportProgress, ImportSourcePicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, LearningScene3D, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichTextEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, arrowBetween, billboardLabel, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, cylinderBetween, dispatchCommandPaletteCommand, get3DClickPayload, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, meshSphere, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, renderPatternValue, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, sanitizeRichHtml, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useKeyboardRouter, useLongPress, useMediaQuery, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate117 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };