@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.
- package/dist/{EntityBindingContext-0Evn_LcT.d.cts → EntityBindingContext-Bn3ePJQC.d.cts} +1 -1
- package/dist/{EntityBindingContext-0Evn_LcT.d.ts → EntityBindingContext-Bn3ePJQC.d.ts} +1 -1
- package/dist/{GameAudioProvider-B48iXwz3.d.ts → GameAudioProvider-Ctceau1s.d.ts} +6 -18
- package/dist/{GameAudioProvider-CQAdPreB.d.cts → GameAudioProvider-Dk_Y3LN3.d.cts} +6 -18
- package/dist/avl/index.cjs +1216 -206
- package/dist/avl/index.js +1217 -207
- package/dist/{avl-schema-parser-dvJKXn-o.d.ts → avl-schema-parser-DncJLEn9.d.ts} +18 -0
- package/dist/{avl-schema-parser-Bt4NzAam.d.cts → avl-schema-parser-FQ1474v8.d.cts} +18 -0
- package/dist/{cn-DJSBBm5W.d.cts → cn-CCjFspAo.d.cts} +25 -1
- package/dist/{cn-BbhJq_nr.d.ts → cn-sgpqpN0U.d.ts} +25 -1
- package/dist/components/index.cjs +1025 -235
- package/dist/components/index.d.cts +176 -23
- package/dist/components/index.d.ts +176 -23
- package/dist/components/index.js +1023 -236
- package/dist/context/index.cjs +10 -13
- package/dist/context/index.js +10 -13
- package/dist/hooks/index.cjs +63 -13
- package/dist/hooks/index.d.cts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +64 -15
- package/dist/lib/drawable/three/index.cjs +126 -13
- package/dist/lib/drawable/three/index.d.cts +2 -2
- package/dist/lib/drawable/three/index.d.ts +2 -2
- package/dist/lib/drawable/three/index.js +127 -14
- package/dist/lib/index.cjs +180 -0
- package/dist/lib/index.d.cts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +178 -1
- package/dist/locales/index.cjs +6 -3
- package/dist/locales/index.js +6 -3
- package/dist/providers/index.cjs +922 -188
- package/dist/providers/index.d.cts +2 -2
- package/dist/providers/index.d.ts +2 -2
- package/dist/providers/index.js +922 -188
- package/dist/runtime/index.cjs +1505 -182
- package/dist/runtime/index.d.cts +78 -6
- package/dist/runtime/index.d.ts +78 -6
- package/dist/runtime/index.js +1504 -184
- package/dist/{useEventBus-CQWyAWpK.d.ts → useKeyboardRouter-D84cNWmA.d.ts} +31 -1
- package/dist/{useEventBus-Ckr4wqW3.d.cts → useKeyboardRouter-DQEE_9mq.d.cts} +31 -1
- package/locales/ar.json +2 -1
- package/locales/en.json +2 -1
- package/locales/sl.json +2 -1
- package/package.json +4 -4
- package/themes/comic.css +437 -0
- package/themes/index.css +1 -0
package/dist/providers/index.js
CHANGED
|
@@ -9971,7 +9971,7 @@ function collectDrawnItems(nodes) {
|
|
|
9971
9971
|
for (const n of nodes) {
|
|
9972
9972
|
switch (n.type) {
|
|
9973
9973
|
case "draw-sprite":
|
|
9974
|
-
if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height });
|
|
9974
|
+
if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotation });
|
|
9975
9975
|
break;
|
|
9976
9976
|
case "draw-shape":
|
|
9977
9977
|
case "draw-text":
|
|
@@ -9981,7 +9981,7 @@ function collectDrawnItems(nodes) {
|
|
|
9981
9981
|
break;
|
|
9982
9982
|
case "draw-sprite-layer":
|
|
9983
9983
|
for (const it of n.items) {
|
|
9984
|
-
if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height });
|
|
9984
|
+
if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height, rotation: it.rotation });
|
|
9985
9985
|
}
|
|
9986
9986
|
break;
|
|
9987
9987
|
case "draw-shape-layer":
|
|
@@ -10001,15 +10001,39 @@ function buildHitIndex(items) {
|
|
|
10001
10001
|
}
|
|
10002
10002
|
return m;
|
|
10003
10003
|
}
|
|
10004
|
+
function withPreviewPosition(nodes, id, pos) {
|
|
10005
|
+
return nodes.map((n) => {
|
|
10006
|
+
if (n.type === "draw-sprite-layer" || n.type === "draw-shape-layer" || n.type === "draw-text-layer") {
|
|
10007
|
+
if (!n.items.some((it) => it.id === id)) return n;
|
|
10008
|
+
return { ...n, items: n.items.map((it) => it.id === id ? { ...it, position: pos } : it) };
|
|
10009
|
+
}
|
|
10010
|
+
if (n.type === "draw-group") {
|
|
10011
|
+
if (!Array.isArray(n.items)) return n;
|
|
10012
|
+
return { ...n, items: withPreviewPosition(n.items, id, pos) };
|
|
10013
|
+
}
|
|
10014
|
+
if (n.id === id && "position" in n) {
|
|
10015
|
+
return { ...n, position: pos };
|
|
10016
|
+
}
|
|
10017
|
+
return n;
|
|
10018
|
+
});
|
|
10019
|
+
}
|
|
10004
10020
|
function hitTestSprites(items, projector, point) {
|
|
10005
10021
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
10006
10022
|
const it = items[i];
|
|
10007
10023
|
if (it.id === void 0) continue;
|
|
10008
10024
|
const r = spriteRect(projector, { position: it.pos, anchor: it.anchor, width: it.width, height: it.height });
|
|
10009
|
-
|
|
10025
|
+
const test = it.rotation ? rotatePoint(point, { x: r.x + r.w / 2, y: r.y + r.h / 2 }, -it.rotation) : point;
|
|
10026
|
+
if (test.x >= r.x && test.x <= r.x + r.w && test.y >= r.y && test.y <= r.y + r.h) return it.id;
|
|
10010
10027
|
}
|
|
10011
10028
|
return void 0;
|
|
10012
10029
|
}
|
|
10030
|
+
function rotatePoint(p, center, radians) {
|
|
10031
|
+
const cos = Math.cos(radians);
|
|
10032
|
+
const sin = Math.sin(radians);
|
|
10033
|
+
const dx = p.x - center.x;
|
|
10034
|
+
const dy = p.y - center.y;
|
|
10035
|
+
return { x: center.x + dx * cos - dy * sin, y: center.y + dx * sin + dy * cos };
|
|
10036
|
+
}
|
|
10013
10037
|
var init_hitTest = __esm({
|
|
10014
10038
|
"lib/drawable/hitTest.ts"() {
|
|
10015
10039
|
init_contract();
|
|
@@ -10018,6 +10042,41 @@ var init_hitTest = __esm({
|
|
|
10018
10042
|
function normalizeBackdrop(bg) {
|
|
10019
10043
|
return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
|
|
10020
10044
|
}
|
|
10045
|
+
function selectionOverlayNodes(projector, item) {
|
|
10046
|
+
const r = spriteRect(projector, { position: item.pos, anchor: item.anchor, width: item.width, height: item.height });
|
|
10047
|
+
const tw = projector.tileWidth;
|
|
10048
|
+
const cellTopLeft = projector.anchorPoint(item.pos, "top-left");
|
|
10049
|
+
const offsetX = (r.x - cellTopLeft.x) / tw;
|
|
10050
|
+
const offsetY = (r.y - cellTopLeft.y) / tw;
|
|
10051
|
+
const width = r.w / tw;
|
|
10052
|
+
const height = r.h / tw;
|
|
10053
|
+
const handle = EDIT_HANDLE_SIZE_PX / tw;
|
|
10054
|
+
const ring = {
|
|
10055
|
+
type: "draw-shape",
|
|
10056
|
+
shape: "rect",
|
|
10057
|
+
position: item.pos,
|
|
10058
|
+
anchor: "top-left",
|
|
10059
|
+
offsetX,
|
|
10060
|
+
offsetY,
|
|
10061
|
+
width,
|
|
10062
|
+
height,
|
|
10063
|
+
stroke: EDIT_SELECTION_COLOR,
|
|
10064
|
+
strokeWidth: 2,
|
|
10065
|
+
fill: "none"
|
|
10066
|
+
};
|
|
10067
|
+
const handles = EDIT_SELECTION_CORNERS.map(([cx, cy]) => ({
|
|
10068
|
+
type: "draw-shape",
|
|
10069
|
+
shape: "rect",
|
|
10070
|
+
position: item.pos,
|
|
10071
|
+
anchor: "top-left",
|
|
10072
|
+
offsetX: offsetX + cx * width - handle / 2,
|
|
10073
|
+
offsetY: offsetY + cy * height - handle / 2,
|
|
10074
|
+
width: handle,
|
|
10075
|
+
height: handle,
|
|
10076
|
+
fill: EDIT_SELECTION_COLOR
|
|
10077
|
+
}));
|
|
10078
|
+
return [ring, ...handles];
|
|
10079
|
+
}
|
|
10021
10080
|
function Canvas2D({
|
|
10022
10081
|
className,
|
|
10023
10082
|
isLoading = false,
|
|
@@ -10031,6 +10090,12 @@ function Canvas2D({
|
|
|
10031
10090
|
tileLeaveEvent,
|
|
10032
10091
|
keyMap,
|
|
10033
10092
|
keyUpMap,
|
|
10093
|
+
editable = false,
|
|
10094
|
+
selectedId = null,
|
|
10095
|
+
onSelect,
|
|
10096
|
+
onMove,
|
|
10097
|
+
selectEvent,
|
|
10098
|
+
moveEvent,
|
|
10034
10099
|
camera = "pan-zoom",
|
|
10035
10100
|
scale = 0.4,
|
|
10036
10101
|
tileWidth,
|
|
@@ -10288,10 +10353,22 @@ function Canvas2D({
|
|
|
10288
10353
|
painter.scale(cam.zoom, cam.zoom);
|
|
10289
10354
|
painter.translate(-viewportSize.width / 2 - cam.x, -viewportSize.height / 2 - cam.y);
|
|
10290
10355
|
const dctx = { projector, time: timeMs, invalidate: bumpAtlas };
|
|
10291
|
-
|
|
10356
|
+
let paintNodes = drawables;
|
|
10357
|
+
if (editable) {
|
|
10358
|
+
const drag = editDragRef.current;
|
|
10359
|
+
if (drag && drag.moved) {
|
|
10360
|
+
paintNodes = withPreviewPosition(paintNodes, drag.id, { x: drag.previewX, y: drag.previewY });
|
|
10361
|
+
}
|
|
10362
|
+
const selectedItem = selectedId != null ? drawnItems.find((it) => it.id === selectedId) : void 0;
|
|
10363
|
+
if (selectedItem) {
|
|
10364
|
+
const overlaySource = drag && drag.moved && drag.id === selectedId ? { ...selectedItem, pos: { x: drag.previewX, y: drag.previewY } } : selectedItem;
|
|
10365
|
+
paintNodes = [...paintNodes, ...selectionOverlayNodes(projector, overlaySource)];
|
|
10366
|
+
}
|
|
10367
|
+
}
|
|
10368
|
+
for (const node of paintNodes) paintDrawable(painter, node, dctx);
|
|
10292
10369
|
painter.restore();
|
|
10293
|
-
scheduleAnimation(
|
|
10294
|
-
}, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
|
|
10370
|
+
scheduleAnimation(paintNodes);
|
|
10371
|
+
}, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance, editable, selectedId, drawnItems]);
|
|
10295
10372
|
useEffect(() => {
|
|
10296
10373
|
drawTimeRef.current = draw;
|
|
10297
10374
|
}, [draw]);
|
|
@@ -10336,23 +10413,83 @@ function Canvas2D({
|
|
|
10336
10413
|
};
|
|
10337
10414
|
}, [camera, followTarget, lerpToTarget, draw]);
|
|
10338
10415
|
const singlePointerActiveRef = useRef(false);
|
|
10416
|
+
const editDragRef = useRef(null);
|
|
10417
|
+
const pointerToScene = useCallback((clientX, clientY) => {
|
|
10418
|
+
const canvas = canvasRef.current;
|
|
10419
|
+
if (!canvas) return { x: 0, y: 0 };
|
|
10420
|
+
const world = screenToWorld(clientX, clientY, canvas, viewportSize);
|
|
10421
|
+
const adjustedX = world.x - scaledTileWidth / 2;
|
|
10422
|
+
const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
10423
|
+
return unproject(adjustedX, adjustedY);
|
|
10424
|
+
}, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject]);
|
|
10339
10425
|
const handleCanvasPointerDown = useCallback((e) => {
|
|
10340
10426
|
singlePointerActiveRef.current = true;
|
|
10427
|
+
if (editable) {
|
|
10428
|
+
if (!canvasRef.current) return;
|
|
10429
|
+
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
10430
|
+
const hitId = hitTestSprites(drawnItems, projector, world);
|
|
10431
|
+
if (hitId === void 0) return;
|
|
10432
|
+
const item = [...drawnItems].reverse().find((it) => it.id === hitId);
|
|
10433
|
+
if (!item) return;
|
|
10434
|
+
editDragRef.current = {
|
|
10435
|
+
id: hitId,
|
|
10436
|
+
pointerId: e.pointerId,
|
|
10437
|
+
startClientX: e.clientX,
|
|
10438
|
+
startClientY: e.clientY,
|
|
10439
|
+
startSceneX: item.pos.x,
|
|
10440
|
+
startSceneY: item.pos.y,
|
|
10441
|
+
moved: false,
|
|
10442
|
+
previewX: item.pos.x,
|
|
10443
|
+
previewY: item.pos.y
|
|
10444
|
+
};
|
|
10445
|
+
return;
|
|
10446
|
+
}
|
|
10341
10447
|
if (enableCamera) handlePointerDown(e);
|
|
10342
|
-
}, [enableCamera, handlePointerDown]);
|
|
10448
|
+
}, [editable, screenToWorld, viewportSize, drawnItems, projector, enableCamera, handlePointerDown]);
|
|
10343
10449
|
const handleCanvasPointerMove = useCallback((e) => {
|
|
10450
|
+
if (editable) {
|
|
10451
|
+
const drag = editDragRef.current;
|
|
10452
|
+
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
10453
|
+
const dxPx = e.clientX - drag.startClientX;
|
|
10454
|
+
const dyPx = e.clientY - drag.startClientY;
|
|
10455
|
+
if (!drag.moved && Math.abs(dxPx) + Math.abs(dyPx) <= 5) return;
|
|
10456
|
+
drag.moved = true;
|
|
10457
|
+
const nowScene = pointerToScene(e.clientX, e.clientY);
|
|
10458
|
+
const startScene = pointerToScene(drag.startClientX, drag.startClientY);
|
|
10459
|
+
drag.previewX = drag.startSceneX + (nowScene.x - startScene.x);
|
|
10460
|
+
drag.previewY = drag.startSceneY + (nowScene.y - startScene.y);
|
|
10461
|
+
draw();
|
|
10462
|
+
return;
|
|
10463
|
+
}
|
|
10344
10464
|
if (enableCamera) handlePointerMove(e, () => draw());
|
|
10345
|
-
}, [
|
|
10465
|
+
}, [editable, pointerToScene, draw, enableCamera, handlePointerMove]);
|
|
10346
10466
|
const handleCanvasHover = useCallback((e) => {
|
|
10347
10467
|
if (singlePointerActiveRef.current) return;
|
|
10348
10468
|
if (!tileHoverEvent || !canvasRef.current) return;
|
|
10349
|
-
const
|
|
10350
|
-
const adjustedX = world.x - scaledTileWidth / 2;
|
|
10351
|
-
const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
10352
|
-
const isoPos = unproject(adjustedX, adjustedY);
|
|
10469
|
+
const isoPos = pointerToScene(e.clientX, e.clientY);
|
|
10353
10470
|
eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
10354
|
-
}, [
|
|
10471
|
+
}, [pointerToScene, tileHoverEvent, eventBus]);
|
|
10355
10472
|
const handleCanvasPointerUp = useCallback((e) => {
|
|
10473
|
+
if (editable) {
|
|
10474
|
+
singlePointerActiveRef.current = false;
|
|
10475
|
+
const drag = editDragRef.current;
|
|
10476
|
+
if (drag && drag.pointerId === e.pointerId) {
|
|
10477
|
+
editDragRef.current = null;
|
|
10478
|
+
if (drag.moved) {
|
|
10479
|
+
onMove?.(drag.id, drag.previewX, drag.previewY);
|
|
10480
|
+
if (moveEvent) eventBus.emit(`UI:${moveEvent}`, { id: drag.id, x: drag.previewX, y: drag.previewY });
|
|
10481
|
+
draw();
|
|
10482
|
+
return;
|
|
10483
|
+
}
|
|
10484
|
+
const next = selectedId === drag.id ? null : drag.id;
|
|
10485
|
+
onSelect?.(next);
|
|
10486
|
+
if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
10487
|
+
return;
|
|
10488
|
+
}
|
|
10489
|
+
onSelect?.(null);
|
|
10490
|
+
if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: null });
|
|
10491
|
+
return;
|
|
10492
|
+
}
|
|
10356
10493
|
singlePointerActiveRef.current = false;
|
|
10357
10494
|
if (enableCamera) handlePointerUp();
|
|
10358
10495
|
if (dragDistance() > 5) return;
|
|
@@ -10363,16 +10500,14 @@ function Canvas2D({
|
|
|
10363
10500
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId: spriteHit });
|
|
10364
10501
|
return;
|
|
10365
10502
|
}
|
|
10366
|
-
const
|
|
10367
|
-
const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
10368
|
-
const isoPos = unproject(adjustedX, adjustedY);
|
|
10503
|
+
const isoPos = pointerToScene(e.clientX, e.clientY);
|
|
10369
10504
|
const hitId = hitIndex.get(`${isoPos.x},${isoPos.y}`);
|
|
10370
10505
|
if (hitId !== void 0 && unitClickEvent) {
|
|
10371
10506
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId: hitId });
|
|
10372
10507
|
} else if (tileClickEvent) {
|
|
10373
10508
|
eventBus.emit(`UI:${tileClickEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
10374
10509
|
}
|
|
10375
|
-
}, [
|
|
10510
|
+
}, [editable, selectedId, onMove, moveEvent, onSelect, selectEvent, eventBus, draw, enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, drawnItems, projector, tileClickEvent, unitClickEvent, hitIndex, pointerToScene]);
|
|
10376
10511
|
const handleCanvasPointerLeave = useCallback(() => {
|
|
10377
10512
|
handleMouseLeave();
|
|
10378
10513
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -10391,7 +10526,7 @@ function Canvas2D({
|
|
|
10391
10526
|
}, [enableCamera, handlePointerUp]);
|
|
10392
10527
|
const gestureHandlers = useCanvasGestures({
|
|
10393
10528
|
canvasRef,
|
|
10394
|
-
enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent,
|
|
10529
|
+
enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent || editable,
|
|
10395
10530
|
onPointerDown: handleCanvasPointerDown,
|
|
10396
10531
|
onPointerMove: handleCanvasPointerMove,
|
|
10397
10532
|
onPointerUp: handleCanvasPointerUp,
|
|
@@ -10523,7 +10658,7 @@ function Canvas2D({
|
|
|
10523
10658
|
}
|
|
10524
10659
|
) });
|
|
10525
10660
|
}
|
|
10526
|
-
var canvas2DLog;
|
|
10661
|
+
var canvas2DLog, EDIT_SELECTION_COLOR, EDIT_HANDLE_SIZE_PX, EDIT_SELECTION_CORNERS;
|
|
10527
10662
|
var init_Canvas2D = __esm({
|
|
10528
10663
|
"components/game/molecules/Canvas2D.tsx"() {
|
|
10529
10664
|
"use client";
|
|
@@ -10548,8 +10683,12 @@ var init_Canvas2D = __esm({
|
|
|
10548
10683
|
init_DrawGroup();
|
|
10549
10684
|
init_registry();
|
|
10550
10685
|
init_hitTest();
|
|
10686
|
+
init_contract();
|
|
10551
10687
|
init_isometric();
|
|
10552
10688
|
canvas2DLog = createLogger("almadar:ui:game-canvas");
|
|
10689
|
+
EDIT_SELECTION_COLOR = "#3b82f6";
|
|
10690
|
+
EDIT_HANDLE_SIZE_PX = 8;
|
|
10691
|
+
EDIT_SELECTION_CORNERS = [[0, 0], [1, 0], [0, 1], [1, 1]];
|
|
10553
10692
|
Canvas2D.displayName = "Canvas2D";
|
|
10554
10693
|
}
|
|
10555
10694
|
});
|
|
@@ -10591,6 +10730,12 @@ function Canvas({
|
|
|
10591
10730
|
featureClickEvent,
|
|
10592
10731
|
keyMap,
|
|
10593
10732
|
keyUpMap,
|
|
10733
|
+
editable,
|
|
10734
|
+
selectedId,
|
|
10735
|
+
onSelect,
|
|
10736
|
+
onMove,
|
|
10737
|
+
selectEvent,
|
|
10738
|
+
moveEvent,
|
|
10594
10739
|
children
|
|
10595
10740
|
}) {
|
|
10596
10741
|
canvasLog.debug("Canvas render", { mode, drawablesCount: drawables?.length, projection, camera: camera ? JSON.stringify(camera) : void 0 });
|
|
@@ -10668,6 +10813,12 @@ function Canvas({
|
|
|
10668
10813
|
tileLeaveEvent,
|
|
10669
10814
|
keyMap,
|
|
10670
10815
|
keyUpMap,
|
|
10816
|
+
editable,
|
|
10817
|
+
selectedId,
|
|
10818
|
+
onSelect,
|
|
10819
|
+
onMove,
|
|
10820
|
+
selectEvent,
|
|
10821
|
+
moveEvent,
|
|
10671
10822
|
...children !== void 0 ? { children } : {}
|
|
10672
10823
|
}
|
|
10673
10824
|
);
|
|
@@ -10689,15 +10840,19 @@ function GameAudioToggle({
|
|
|
10689
10840
|
size = "sm",
|
|
10690
10841
|
className,
|
|
10691
10842
|
onAsset,
|
|
10692
|
-
offAsset
|
|
10843
|
+
offAsset,
|
|
10844
|
+
toggleEvent
|
|
10693
10845
|
}) {
|
|
10694
10846
|
const ctx = useGameAudioContextOptional();
|
|
10695
10847
|
const [localMuted, setLocalMuted] = useState(false);
|
|
10696
10848
|
const muted = ctx ? ctx.muted : localMuted;
|
|
10697
10849
|
const setMuted = ctx ? ctx.setMuted : setLocalMuted;
|
|
10850
|
+
const eventBus = useEventBus();
|
|
10698
10851
|
const handleToggle = useCallback(() => {
|
|
10699
|
-
|
|
10700
|
-
|
|
10852
|
+
const next = !muted;
|
|
10853
|
+
setMuted(next);
|
|
10854
|
+
if (toggleEvent) eventBus.emit(`UI:${toggleEvent}`, { muted: next });
|
|
10855
|
+
}, [muted, setMuted, toggleEvent, eventBus]);
|
|
10701
10856
|
const activeAsset = muted ? offAsset : onAsset;
|
|
10702
10857
|
return /* @__PURE__ */ jsx(
|
|
10703
10858
|
Button,
|
|
@@ -10716,6 +10871,7 @@ var init_GameAudioToggle = __esm({
|
|
|
10716
10871
|
"use client";
|
|
10717
10872
|
init_atoms();
|
|
10718
10873
|
init_cn();
|
|
10874
|
+
init_useEventBus();
|
|
10719
10875
|
init_GameIcon();
|
|
10720
10876
|
GameAudioToggle.displayName = "GameAudioToggle";
|
|
10721
10877
|
}
|
|
@@ -10987,6 +11143,47 @@ var init_useGameAudio = __esm({
|
|
|
10987
11143
|
useGameAudio.displayName = "useGameAudio";
|
|
10988
11144
|
}
|
|
10989
11145
|
});
|
|
11146
|
+
function GameAudioCue({
|
|
11147
|
+
cue,
|
|
11148
|
+
cueSeq,
|
|
11149
|
+
music,
|
|
11150
|
+
muted,
|
|
11151
|
+
volume,
|
|
11152
|
+
manifest,
|
|
11153
|
+
baseUrl
|
|
11154
|
+
}) {
|
|
11155
|
+
const { play, playMusic, stopMusic, setMuted, setMasterVolume } = useGameAudio({
|
|
11156
|
+
manifest,
|
|
11157
|
+
baseUrl,
|
|
11158
|
+
initialMuted: muted,
|
|
11159
|
+
initialVolume: volume
|
|
11160
|
+
});
|
|
11161
|
+
const prevCueSeqRef = useRef(cueSeq);
|
|
11162
|
+
useEffect(() => {
|
|
11163
|
+
if (cue && cueSeq !== void 0 && cueSeq !== prevCueSeqRef.current) {
|
|
11164
|
+
play(cue);
|
|
11165
|
+
}
|
|
11166
|
+
prevCueSeqRef.current = cueSeq;
|
|
11167
|
+
}, [cue, cueSeq, play]);
|
|
11168
|
+
useEffect(() => {
|
|
11169
|
+
if (music) playMusic(music);
|
|
11170
|
+
else stopMusic();
|
|
11171
|
+
}, [music, playMusic, stopMusic]);
|
|
11172
|
+
useEffect(() => {
|
|
11173
|
+
if (muted !== void 0) setMuted(muted);
|
|
11174
|
+
}, [muted, setMuted]);
|
|
11175
|
+
useEffect(() => {
|
|
11176
|
+
if (volume !== void 0) setMasterVolume(volume);
|
|
11177
|
+
}, [volume, setMasterVolume]);
|
|
11178
|
+
return null;
|
|
11179
|
+
}
|
|
11180
|
+
var init_GameAudioCue = __esm({
|
|
11181
|
+
"components/game/atoms/GameAudioCue.tsx"() {
|
|
11182
|
+
"use client";
|
|
11183
|
+
init_useGameAudio();
|
|
11184
|
+
GameAudioCue.displayName = "GameAudioCue";
|
|
11185
|
+
}
|
|
11186
|
+
});
|
|
10990
11187
|
function isKnownState(s) {
|
|
10991
11188
|
return s in DEFAULT_STATE_STYLES;
|
|
10992
11189
|
}
|
|
@@ -11685,15 +11882,18 @@ var init_StateJsonView = __esm({
|
|
|
11685
11882
|
StateJsonView.displayName = "StateJsonView";
|
|
11686
11883
|
}
|
|
11687
11884
|
});
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
|
|
11696
|
-
|
|
11885
|
+
|
|
11886
|
+
// lib/gameFonts.ts
|
|
11887
|
+
function resolveGameFontFamily(input) {
|
|
11888
|
+
if (!input) return void 0;
|
|
11889
|
+
const resolved = GAME_FONT_KEYS[input];
|
|
11890
|
+
if (resolved) return `'${resolved}', ui-sans-serif, system-ui, sans-serif`;
|
|
11891
|
+
return input;
|
|
11892
|
+
}
|
|
11893
|
+
var GAME_FONT_KEYS;
|
|
11894
|
+
var init_gameFonts = __esm({
|
|
11895
|
+
"lib/gameFonts.ts"() {
|
|
11896
|
+
GAME_FONT_KEYS = {
|
|
11697
11897
|
fredoka: "Fredoka",
|
|
11698
11898
|
future: "Kenney Future",
|
|
11699
11899
|
"future-narrow": "Kenney Future Narrow",
|
|
@@ -11701,6 +11901,17 @@ var init_GameShell = __esm({
|
|
|
11701
11901
|
blocks: "Kenney Blocks",
|
|
11702
11902
|
mini: "Kenney Mini"
|
|
11703
11903
|
};
|
|
11904
|
+
}
|
|
11905
|
+
});
|
|
11906
|
+
var GameShell;
|
|
11907
|
+
var init_GameShell = __esm({
|
|
11908
|
+
"components/game/templates/GameShell.tsx"() {
|
|
11909
|
+
init_cn();
|
|
11910
|
+
init_gameFonts();
|
|
11911
|
+
init_Box();
|
|
11912
|
+
init_Card();
|
|
11913
|
+
init_Typography();
|
|
11914
|
+
init_AtlasImage();
|
|
11704
11915
|
GameShell = ({
|
|
11705
11916
|
appName = "Game",
|
|
11706
11917
|
hud,
|
|
@@ -11714,7 +11925,7 @@ var init_GameShell = __esm({
|
|
|
11714
11925
|
fontFamily,
|
|
11715
11926
|
"data-theme": dataTheme
|
|
11716
11927
|
}) => {
|
|
11717
|
-
const
|
|
11928
|
+
const displayFont = resolveGameFontFamily(fontFamily);
|
|
11718
11929
|
return /* @__PURE__ */ jsxs(
|
|
11719
11930
|
Box,
|
|
11720
11931
|
{
|
|
@@ -11733,7 +11944,7 @@ var init_GameShell = __esm({
|
|
|
11733
11944
|
// passed — an always-on inline stamp would shadow the orbital's
|
|
11734
11945
|
// inline-theme font-family-display token (inline style beats the
|
|
11735
11946
|
// theme provider's vars for the whole shell subtree).
|
|
11736
|
-
...
|
|
11947
|
+
...displayFont ? { "--font-family-display": displayFont } : {}
|
|
11737
11948
|
},
|
|
11738
11949
|
children: [
|
|
11739
11950
|
backgroundAsset && /* @__PURE__ */ jsx(
|
|
@@ -11935,14 +12146,15 @@ function drawArrowHead(ctx, x1, y1, x2, y2, size) {
|
|
|
11935
12146
|
ctx.closePath();
|
|
11936
12147
|
ctx.fill();
|
|
11937
12148
|
}
|
|
11938
|
-
function drawShape(ctx, shape, width, height, allShapes) {
|
|
12149
|
+
function drawShape(ctx, shape, width, height, allShapes, fontFamily) {
|
|
11939
12150
|
ctx.save();
|
|
11940
12151
|
const opacity = shape.opacity ?? 1;
|
|
11941
12152
|
ctx.globalAlpha = opacity;
|
|
11942
12153
|
const stroke = resolveColor2(shape.color, ctx, "#333333");
|
|
11943
12154
|
const fill = shape.fill ? resolveColor2(shape.fill, ctx, "#cccccc") : void 0;
|
|
11944
12155
|
ctx.lineWidth = shape.lineWidth ?? 2;
|
|
11945
|
-
|
|
12156
|
+
const dashPattern = shape.dash ? DASH_PATTERNS[shape.dash] : void 0;
|
|
12157
|
+
if (dashPattern) ctx.setLineDash([...dashPattern]);
|
|
11946
12158
|
switch (shape.type) {
|
|
11947
12159
|
case "grid": {
|
|
11948
12160
|
const step = shape.step ?? 40;
|
|
@@ -12064,7 +12276,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
|
|
|
12064
12276
|
case "text": {
|
|
12065
12277
|
if (shape.x == null || shape.y == null || !shape.text) break;
|
|
12066
12278
|
ctx.fillStyle = stroke;
|
|
12067
|
-
ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
|
|
12279
|
+
ctx.font = `${shape.fontSize ?? 14}px ${shape.fontFamily ?? fontFamily ?? themeBodyFont(ctx.canvas)}`;
|
|
12068
12280
|
ctx.textAlign = shape.align ?? "left";
|
|
12069
12281
|
ctx.textBaseline = "middle";
|
|
12070
12282
|
ctx.fillText(shape.text, shape.x, shape.y);
|
|
@@ -12106,7 +12318,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
|
|
|
12106
12318
|
}
|
|
12107
12319
|
ctx.restore();
|
|
12108
12320
|
}
|
|
12109
|
-
function readoutShapes(readouts, width) {
|
|
12321
|
+
function readoutShapes(readouts, width, fontFamily) {
|
|
12110
12322
|
const out = [];
|
|
12111
12323
|
const chipH = 18;
|
|
12112
12324
|
const gap = 6;
|
|
@@ -12130,13 +12342,14 @@ function readoutShapes(readouts, width) {
|
|
|
12130
12342
|
text,
|
|
12131
12343
|
color: "#ffffff",
|
|
12132
12344
|
fontSize: 10,
|
|
12133
|
-
align: "center"
|
|
12345
|
+
align: "center",
|
|
12346
|
+
fontFamily
|
|
12134
12347
|
});
|
|
12135
12348
|
rightEdge = chipX - gap;
|
|
12136
12349
|
}
|
|
12137
12350
|
return out;
|
|
12138
12351
|
}
|
|
12139
|
-
function traceShapes(panel, k, width, height) {
|
|
12352
|
+
function traceShapes(panel, k, width, height, fontFamily) {
|
|
12140
12353
|
const w = panel.width ?? Math.round(width * 0.32);
|
|
12141
12354
|
const h = panel.height ?? Math.round(height * 0.28);
|
|
12142
12355
|
const x = panel.x ?? width - w - 8;
|
|
@@ -12190,14 +12403,14 @@ function traceShapes(panel, k, width, height) {
|
|
|
12190
12403
|
out.push({ type: "circle", x: last.x, y: last.y, radius: 2, color, fill: color });
|
|
12191
12404
|
}
|
|
12192
12405
|
if (series.label) {
|
|
12193
|
-
out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9 });
|
|
12406
|
+
out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9, fontFamily });
|
|
12194
12407
|
}
|
|
12195
12408
|
});
|
|
12196
12409
|
if (panel.yLabel) {
|
|
12197
|
-
out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right" });
|
|
12410
|
+
out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
|
|
12198
12411
|
}
|
|
12199
12412
|
if (panel.xLabel) {
|
|
12200
|
-
out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right" });
|
|
12413
|
+
out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
|
|
12201
12414
|
}
|
|
12202
12415
|
return out;
|
|
12203
12416
|
}
|
|
@@ -12220,13 +12433,14 @@ var init_LearningCanvas = __esm({
|
|
|
12220
12433
|
init_useEventBus();
|
|
12221
12434
|
init_webPainter2d();
|
|
12222
12435
|
init_paintDispatch();
|
|
12223
|
-
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12436
|
+
DASH_PATTERNS = { solid: [], dashed: [6, 4], dotted: [2, 3] };
|
|
12224
12437
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
12225
12438
|
LearningCanvas = ({
|
|
12226
12439
|
className,
|
|
12227
12440
|
width = 600,
|
|
12228
12441
|
height = 400,
|
|
12229
12442
|
backgroundColor,
|
|
12443
|
+
fontFamily,
|
|
12230
12444
|
shapes = [],
|
|
12231
12445
|
drawables,
|
|
12232
12446
|
projector,
|
|
@@ -12262,10 +12476,10 @@ var init_LearningCanvas = __esm({
|
|
|
12262
12476
|
}, [shapes]);
|
|
12263
12477
|
const derivedShapes = useMemo(() => {
|
|
12264
12478
|
if (!traces?.length && !readouts?.length) return shapes;
|
|
12265
|
-
const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height));
|
|
12266
|
-
const readoutOut = readouts?.length ? readoutShapes(readouts, width) : [];
|
|
12479
|
+
const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height, fontFamily));
|
|
12480
|
+
const readoutOut = readouts?.length ? readoutShapes(readouts, width, fontFamily) : [];
|
|
12267
12481
|
return [...shapes, ...traceOut, ...readoutOut];
|
|
12268
|
-
}, [shapes, traces, readouts, width, height]);
|
|
12482
|
+
}, [shapes, traces, readouts, width, height, fontFamily]);
|
|
12269
12483
|
const draw = useCallback(() => {
|
|
12270
12484
|
const _perfT = perfStart("learningcanvas:paint");
|
|
12271
12485
|
const canvas = canvasRef.current;
|
|
@@ -12284,15 +12498,15 @@ var init_LearningCanvas = __esm({
|
|
|
12284
12498
|
ctx.fillRect(0, 0, width, height);
|
|
12285
12499
|
}
|
|
12286
12500
|
for (const shape of derivedShapes) {
|
|
12287
|
-
if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12501
|
+
if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
|
|
12288
12502
|
}
|
|
12289
12503
|
for (const shape of derivedShapes) {
|
|
12290
|
-
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12504
|
+
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
|
|
12291
12505
|
}
|
|
12292
12506
|
if (drawables?.length && projector) {
|
|
12293
12507
|
const painter = createWebPainter(ctx, invalidateRef.current);
|
|
12294
12508
|
const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
|
|
12295
|
-
const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: themeBodyFont(canvas) };
|
|
12509
|
+
const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: fontFamily || themeBodyFont(canvas) };
|
|
12296
12510
|
for (const node of drawables) {
|
|
12297
12511
|
paintDrawable(painter, node, dctx);
|
|
12298
12512
|
}
|
|
@@ -17274,6 +17488,250 @@ var init_EmptyState = __esm({
|
|
|
17274
17488
|
EmptyState.displayName = "EmptyState";
|
|
17275
17489
|
}
|
|
17276
17490
|
});
|
|
17491
|
+
|
|
17492
|
+
// lib/editorMotions.ts
|
|
17493
|
+
function clamp(value, min, max) {
|
|
17494
|
+
return Math.max(min, Math.min(max, value));
|
|
17495
|
+
}
|
|
17496
|
+
function computeLines(text) {
|
|
17497
|
+
const lines = [];
|
|
17498
|
+
let start = 0;
|
|
17499
|
+
for (let i = 0; i <= text.length; i++) {
|
|
17500
|
+
if (i === text.length || text[i] === "\n") {
|
|
17501
|
+
lines.push({ start, end: i });
|
|
17502
|
+
start = i + 1;
|
|
17503
|
+
}
|
|
17504
|
+
}
|
|
17505
|
+
return lines;
|
|
17506
|
+
}
|
|
17507
|
+
function lineIndexAt(lines, pos) {
|
|
17508
|
+
for (let i = 0; i < lines.length; i++) {
|
|
17509
|
+
if (pos <= lines[i].end) return i;
|
|
17510
|
+
}
|
|
17511
|
+
return lines.length - 1;
|
|
17512
|
+
}
|
|
17513
|
+
function findWords(text) {
|
|
17514
|
+
const words = [];
|
|
17515
|
+
const re = /\w+|\S+/g;
|
|
17516
|
+
let m;
|
|
17517
|
+
while ((m = re.exec(text)) !== null) {
|
|
17518
|
+
words.push({ start: m.index, end: m.index + m[0].length });
|
|
17519
|
+
}
|
|
17520
|
+
return words;
|
|
17521
|
+
}
|
|
17522
|
+
function nextWordStart(text, pos) {
|
|
17523
|
+
for (const w of findWords(text)) {
|
|
17524
|
+
if (w.start > pos) return w.start;
|
|
17525
|
+
}
|
|
17526
|
+
return text.length;
|
|
17527
|
+
}
|
|
17528
|
+
function prevWordStart(text, pos) {
|
|
17529
|
+
let result = 0;
|
|
17530
|
+
for (const w of findWords(text)) {
|
|
17531
|
+
if (w.start < pos) result = w.start;
|
|
17532
|
+
else break;
|
|
17533
|
+
}
|
|
17534
|
+
return result;
|
|
17535
|
+
}
|
|
17536
|
+
function nextWordEnd(text, pos) {
|
|
17537
|
+
for (const w of findWords(text)) {
|
|
17538
|
+
const lastChar = w.end - 1;
|
|
17539
|
+
if (lastChar > pos) return lastChar;
|
|
17540
|
+
}
|
|
17541
|
+
return text.length > 0 ? text.length - 1 : 0;
|
|
17542
|
+
}
|
|
17543
|
+
function firstNonBlank(text, line) {
|
|
17544
|
+
let i = line.start;
|
|
17545
|
+
while (i < line.end && (text[i] === " " || text[i] === " ")) i++;
|
|
17546
|
+
return i;
|
|
17547
|
+
}
|
|
17548
|
+
function nextParagraphBoundary(lines, fromLineIdx, textLength) {
|
|
17549
|
+
for (let i = fromLineIdx + 1; i < lines.length; i++) {
|
|
17550
|
+
if (lines[i].start === lines[i].end) return lines[i].start;
|
|
17551
|
+
}
|
|
17552
|
+
return textLength;
|
|
17553
|
+
}
|
|
17554
|
+
function prevParagraphBoundary(lines, fromLineIdx) {
|
|
17555
|
+
for (let i = fromLineIdx - 1; i >= 0; i--) {
|
|
17556
|
+
if (lines[i].start === lines[i].end) return lines[i].start;
|
|
17557
|
+
}
|
|
17558
|
+
return 0;
|
|
17559
|
+
}
|
|
17560
|
+
function applyMotion(text, caret, motion, count) {
|
|
17561
|
+
const n = Math.max(1, count);
|
|
17562
|
+
const lines = computeLines(text);
|
|
17563
|
+
const lineIdx = lineIndexAt(lines, caret);
|
|
17564
|
+
const line = lines[lineIdx];
|
|
17565
|
+
switch (motion) {
|
|
17566
|
+
case "left":
|
|
17567
|
+
return clamp(caret - n, line.start, line.end);
|
|
17568
|
+
case "right":
|
|
17569
|
+
return clamp(caret + n, line.start, line.end);
|
|
17570
|
+
case "up": {
|
|
17571
|
+
const col = caret - line.start;
|
|
17572
|
+
const targetIdx = clamp(lineIdx - n, 0, lines.length - 1);
|
|
17573
|
+
const target = lines[targetIdx];
|
|
17574
|
+
return clamp(target.start + col, target.start, target.end);
|
|
17575
|
+
}
|
|
17576
|
+
case "down": {
|
|
17577
|
+
const col = caret - line.start;
|
|
17578
|
+
const targetIdx = clamp(lineIdx + n, 0, lines.length - 1);
|
|
17579
|
+
const target = lines[targetIdx];
|
|
17580
|
+
return clamp(target.start + col, target.start, target.end);
|
|
17581
|
+
}
|
|
17582
|
+
case "word-forward": {
|
|
17583
|
+
let pos = caret;
|
|
17584
|
+
for (let i = 0; i < n; i++) pos = nextWordStart(text, pos);
|
|
17585
|
+
return pos;
|
|
17586
|
+
}
|
|
17587
|
+
case "word-back": {
|
|
17588
|
+
let pos = caret;
|
|
17589
|
+
for (let i = 0; i < n; i++) pos = prevWordStart(text, pos);
|
|
17590
|
+
return pos;
|
|
17591
|
+
}
|
|
17592
|
+
case "word-end": {
|
|
17593
|
+
let pos = caret;
|
|
17594
|
+
for (let i = 0; i < n; i++) pos = nextWordEnd(text, pos);
|
|
17595
|
+
return pos;
|
|
17596
|
+
}
|
|
17597
|
+
case "line-start":
|
|
17598
|
+
return line.start;
|
|
17599
|
+
case "line-end":
|
|
17600
|
+
return line.end > line.start ? line.end - 1 : line.start;
|
|
17601
|
+
case "first-nonblank":
|
|
17602
|
+
return firstNonBlank(text, line);
|
|
17603
|
+
case "doc-start":
|
|
17604
|
+
return 0;
|
|
17605
|
+
case "doc-end":
|
|
17606
|
+
return text.length;
|
|
17607
|
+
case "paragraph-forward": {
|
|
17608
|
+
let pos = caret;
|
|
17609
|
+
for (let i = 0; i < n; i++) {
|
|
17610
|
+
pos = nextParagraphBoundary(lines, lineIndexAt(lines, pos), text.length);
|
|
17611
|
+
}
|
|
17612
|
+
return pos;
|
|
17613
|
+
}
|
|
17614
|
+
case "paragraph-back": {
|
|
17615
|
+
let pos = caret;
|
|
17616
|
+
for (let i = 0; i < n; i++) {
|
|
17617
|
+
pos = prevParagraphBoundary(lines, lineIndexAt(lines, pos));
|
|
17618
|
+
}
|
|
17619
|
+
return pos;
|
|
17620
|
+
}
|
|
17621
|
+
case "line":
|
|
17622
|
+
case "selection":
|
|
17623
|
+
return caret;
|
|
17624
|
+
default: {
|
|
17625
|
+
const _exhaustive = motion;
|
|
17626
|
+
return _exhaustive;
|
|
17627
|
+
}
|
|
17628
|
+
}
|
|
17629
|
+
}
|
|
17630
|
+
function motionRange(text, caret, motion, count, selection) {
|
|
17631
|
+
if (motion === "selection") {
|
|
17632
|
+
if (!selection) return [caret, caret];
|
|
17633
|
+
return [Math.min(selection[0], selection[1]), Math.max(selection[0], selection[1])];
|
|
17634
|
+
}
|
|
17635
|
+
const lines = computeLines(text);
|
|
17636
|
+
if (motion === "line") {
|
|
17637
|
+
const n = Math.max(1, count);
|
|
17638
|
+
const startIdx = lineIndexAt(lines, caret);
|
|
17639
|
+
const endIdx = clamp(startIdx + n - 1, 0, lines.length - 1);
|
|
17640
|
+
const start2 = lines[startIdx].start;
|
|
17641
|
+
const rawEnd = lines[endIdx].end;
|
|
17642
|
+
const end2 = rawEnd < text.length ? rawEnd + 1 : rawEnd;
|
|
17643
|
+
return [start2, end2];
|
|
17644
|
+
}
|
|
17645
|
+
const newCaret = applyMotion(text, caret, motion, count);
|
|
17646
|
+
let start = Math.min(caret, newCaret);
|
|
17647
|
+
let end = Math.max(caret, newCaret);
|
|
17648
|
+
if (motion === "word-end" || motion === "line-end") {
|
|
17649
|
+
end = Math.min(Math.max(start, newCaret) + 1, text.length);
|
|
17650
|
+
} else if (motion === "word-forward" && newCaret > caret) {
|
|
17651
|
+
const startLine = lineIndexAt(lines, caret);
|
|
17652
|
+
const endLine = lineIndexAt(lines, newCaret);
|
|
17653
|
+
if (endLine !== startLine) {
|
|
17654
|
+
end = lines[startLine].end;
|
|
17655
|
+
}
|
|
17656
|
+
}
|
|
17657
|
+
return [start, end];
|
|
17658
|
+
}
|
|
17659
|
+
function applyOperator(text, range, operator, register) {
|
|
17660
|
+
const start = clamp(range[0], 0, text.length);
|
|
17661
|
+
const end = clamp(range[1], start, text.length);
|
|
17662
|
+
const removed = text.slice(start, end);
|
|
17663
|
+
if (operator === "yank") {
|
|
17664
|
+
return { text, caret: start, register: removed };
|
|
17665
|
+
}
|
|
17666
|
+
return { text: text.slice(0, start) + text.slice(end), caret: start, register: removed };
|
|
17667
|
+
}
|
|
17668
|
+
var init_editorMotions = __esm({
|
|
17669
|
+
"lib/editorMotions.ts"() {
|
|
17670
|
+
}
|
|
17671
|
+
});
|
|
17672
|
+
function isMotionPayload(payload) {
|
|
17673
|
+
return !!payload && typeof payload.editorId === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
|
|
17674
|
+
}
|
|
17675
|
+
function isOperatePayload(payload) {
|
|
17676
|
+
return !!payload && typeof payload.editorId === "string" && typeof payload.operator === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
|
|
17677
|
+
}
|
|
17678
|
+
function isInsertTextPayload(payload) {
|
|
17679
|
+
return !!payload && typeof payload.editorId === "string" && typeof payload.text === "string";
|
|
17680
|
+
}
|
|
17681
|
+
function isSetModePayload(payload) {
|
|
17682
|
+
return !!payload && typeof payload.editorId === "string" && typeof payload.mode === "string" && typeof payload.caret === "string";
|
|
17683
|
+
}
|
|
17684
|
+
function useEditorCapabilities(args) {
|
|
17685
|
+
const [caretMode, setCaretMode] = useState("bar");
|
|
17686
|
+
const registerRef = useRef("");
|
|
17687
|
+
useEventListener(`UI:${args.events.onMotion}`, (evt) => {
|
|
17688
|
+
if (!args.editorId || !isMotionPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
|
|
17689
|
+
const ta = args.textareaRef.current;
|
|
17690
|
+
if (!ta) return;
|
|
17691
|
+
const { motion, count } = evt.payload;
|
|
17692
|
+
const newCaret = applyMotion(ta.value, ta.selectionStart, motion, count);
|
|
17693
|
+
if (ta.selectionStart !== ta.selectionEnd) {
|
|
17694
|
+
ta.setSelectionRange(ta.selectionStart, newCaret);
|
|
17695
|
+
} else {
|
|
17696
|
+
ta.setSelectionRange(newCaret, newCaret);
|
|
17697
|
+
}
|
|
17698
|
+
});
|
|
17699
|
+
useEventListener(`UI:${args.events.onOperate}`, (evt) => {
|
|
17700
|
+
if (!args.editorId || !isOperatePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
|
|
17701
|
+
const ta = args.textareaRef.current;
|
|
17702
|
+
if (!ta) return;
|
|
17703
|
+
const { operator, motion, count } = evt.payload;
|
|
17704
|
+
const selection = motion === "selection" ? [ta.selectionStart, ta.selectionEnd] : void 0;
|
|
17705
|
+
const range = motionRange(ta.value, ta.selectionStart, motion, count, selection);
|
|
17706
|
+
const result = applyOperator(ta.value, range, operator, registerRef.current);
|
|
17707
|
+
registerRef.current = result.register;
|
|
17708
|
+
if (operator === "yank") {
|
|
17709
|
+
ta.setSelectionRange(range[0], range[0]);
|
|
17710
|
+
} else {
|
|
17711
|
+
ta.setRangeText("", range[0], range[1], "end");
|
|
17712
|
+
}
|
|
17713
|
+
args.applyChange(ta.value);
|
|
17714
|
+
});
|
|
17715
|
+
useEventListener(`UI:${args.events.onInsertText}`, (evt) => {
|
|
17716
|
+
if (!args.editorId || !isInsertTextPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
|
|
17717
|
+
const ta = args.textareaRef.current;
|
|
17718
|
+
if (!ta) return;
|
|
17719
|
+
ta.setRangeText(evt.payload.text, ta.selectionStart, ta.selectionEnd, "end");
|
|
17720
|
+
args.applyChange(ta.value);
|
|
17721
|
+
});
|
|
17722
|
+
useEventListener(`UI:${args.events.onSetMode}`, (evt) => {
|
|
17723
|
+
if (!args.editorId || !isSetModePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
|
|
17724
|
+
setCaretMode(evt.payload.caret);
|
|
17725
|
+
});
|
|
17726
|
+
return { caretMode };
|
|
17727
|
+
}
|
|
17728
|
+
var init_useEditorCapabilities = __esm({
|
|
17729
|
+
"components/core/molecules/markdown/useEditorCapabilities.ts"() {
|
|
17730
|
+
"use client";
|
|
17731
|
+
init_useEventBus();
|
|
17732
|
+
init_editorMotions();
|
|
17733
|
+
}
|
|
17734
|
+
});
|
|
17277
17735
|
function isLanguageRegistered(lang) {
|
|
17278
17736
|
return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
|
|
17279
17737
|
}
|
|
@@ -17359,7 +17817,36 @@ function useLanguageReady(language) {
|
|
|
17359
17817
|
}, [language]);
|
|
17360
17818
|
return ready;
|
|
17361
17819
|
}
|
|
17362
|
-
|
|
17820
|
+
function resolveHighlightStyle(lang) {
|
|
17821
|
+
if (lang === "orb") return orbStyle;
|
|
17822
|
+
if (lang === "lolo") return loloStyle;
|
|
17823
|
+
return dark;
|
|
17824
|
+
}
|
|
17825
|
+
function plainCodeColorOf(style) {
|
|
17826
|
+
return style['code[class*="language-"]']?.color ?? "#d4d4d4";
|
|
17827
|
+
}
|
|
17828
|
+
function buildLineProps(errorLines, extraClassName) {
|
|
17829
|
+
return (lineNumber) => {
|
|
17830
|
+
const base = {
|
|
17831
|
+
"data-line": String(lineNumber - 1),
|
|
17832
|
+
...extraClassName ? { className: extraClassName } : {}
|
|
17833
|
+
};
|
|
17834
|
+
const severity = errorLines?.get(lineNumber);
|
|
17835
|
+
if (!severity) return base;
|
|
17836
|
+
return {
|
|
17837
|
+
...base,
|
|
17838
|
+
style: {
|
|
17839
|
+
display: "block",
|
|
17840
|
+
backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
|
|
17841
|
+
// amber-400 @ 18%
|
|
17842
|
+
borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
|
|
17843
|
+
paddingLeft: "0.5rem",
|
|
17844
|
+
marginLeft: "-0.5rem"
|
|
17845
|
+
}
|
|
17846
|
+
};
|
|
17847
|
+
};
|
|
17848
|
+
}
|
|
17849
|
+
var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, 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;
|
|
17363
17850
|
var init_CodeBlock = __esm({
|
|
17364
17851
|
"components/core/molecules/markdown/CodeBlock.tsx"() {
|
|
17365
17852
|
init_cn();
|
|
@@ -17375,6 +17862,7 @@ var init_CodeBlock = __esm({
|
|
|
17375
17862
|
init_Textarea();
|
|
17376
17863
|
init_Icon();
|
|
17377
17864
|
init_useEventBus();
|
|
17865
|
+
init_useEditorCapabilities();
|
|
17378
17866
|
SyntaxHighlighter.registerLanguage("json", langJson);
|
|
17379
17867
|
SyntaxHighlighter.registerLanguage("javascript", langJavascript);
|
|
17380
17868
|
SyntaxHighlighter.registerLanguage("js", langJavascript);
|
|
@@ -17593,6 +18081,15 @@ var init_CodeBlock = __esm({
|
|
|
17593
18081
|
LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
|
|
17594
18082
|
HIDDEN_LINE_NUMBERS = { display: "none" };
|
|
17595
18083
|
HIGHLIGHT_CAPACITY_BYTES = 512 * 1024;
|
|
18084
|
+
MONO_FONT_FAMILY = 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace';
|
|
18085
|
+
VIEWER_LINE_NUMBER_STYLE = {
|
|
18086
|
+
minWidth: "2.5em",
|
|
18087
|
+
paddingRight: "1rem",
|
|
18088
|
+
textAlign: "right",
|
|
18089
|
+
userSelect: "none",
|
|
18090
|
+
opacity: 0.5,
|
|
18091
|
+
fontVariantNumeric: "tabular-nums"
|
|
18092
|
+
};
|
|
17596
18093
|
CodeBlock = React89__default.memo(
|
|
17597
18094
|
({
|
|
17598
18095
|
code: rawCode,
|
|
@@ -17617,15 +18114,39 @@ var init_CodeBlock = __esm({
|
|
|
17617
18114
|
actions,
|
|
17618
18115
|
isLoading = false,
|
|
17619
18116
|
error,
|
|
17620
|
-
showCopy
|
|
18117
|
+
showCopy,
|
|
18118
|
+
// editor capability surface — P1 wires these
|
|
18119
|
+
editorId,
|
|
18120
|
+
onEditorFocus = "EDITOR_FOCUS",
|
|
18121
|
+
onEditorBlur = "EDITOR_BLUR",
|
|
18122
|
+
onMotion = "MOTION",
|
|
18123
|
+
onOperate = "OPERATE",
|
|
18124
|
+
onInsertText = "INSERT_TEXT",
|
|
18125
|
+
onSetMode = "SET_MODE",
|
|
18126
|
+
motions = [
|
|
18127
|
+
"left",
|
|
18128
|
+
"right",
|
|
18129
|
+
"up",
|
|
18130
|
+
"down",
|
|
18131
|
+
"word-forward",
|
|
18132
|
+
"word-back",
|
|
18133
|
+
"word-end",
|
|
18134
|
+
"line-start",
|
|
18135
|
+
"line-end",
|
|
18136
|
+
"first-nonblank",
|
|
18137
|
+
"doc-start",
|
|
18138
|
+
"doc-end",
|
|
18139
|
+
"paragraph-forward",
|
|
18140
|
+
"paragraph-back",
|
|
18141
|
+
"line",
|
|
18142
|
+
"selection"
|
|
18143
|
+
],
|
|
18144
|
+
operators = ["delete", "yank", "change"]
|
|
17621
18145
|
}) => {
|
|
17622
18146
|
const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
|
|
17623
|
-
const
|
|
17624
|
-
const isLolo = language === "lolo";
|
|
17625
|
-
const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark;
|
|
18147
|
+
const activeStyle = resolveHighlightStyle(language);
|
|
17626
18148
|
const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
|
|
17627
|
-
const plainCodeColor = activeStyle
|
|
17628
|
-
const languageReady = useLanguageReady(language);
|
|
18149
|
+
const plainCodeColor = plainCodeColorOf(activeStyle);
|
|
17629
18150
|
const eventBus = useEventBus();
|
|
17630
18151
|
const { t } = useTranslate();
|
|
17631
18152
|
const scrollRef = useRef(null);
|
|
@@ -17637,6 +18158,9 @@ var init_CodeBlock = __esm({
|
|
|
17637
18158
|
const activeFile = files?.[activeFileIndex];
|
|
17638
18159
|
const activeCode = activeFile?.code ?? code;
|
|
17639
18160
|
const activeLanguage = activeFile?.language ?? language;
|
|
18161
|
+
const languageReady = useLanguageReady(activeLanguage);
|
|
18162
|
+
const viewerStyle = resolveHighlightStyle(activeLanguage);
|
|
18163
|
+
const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
|
|
17640
18164
|
const diffLines = useMemo(() => {
|
|
17641
18165
|
if (propDiff) return propDiff;
|
|
17642
18166
|
if (mode === "diff" && oldValue !== void 0 && newValue !== void 0) {
|
|
@@ -17666,28 +18190,28 @@ var init_CodeBlock = __esm({
|
|
|
17666
18190
|
ov.scrollLeft = ta.scrollLeft;
|
|
17667
18191
|
}
|
|
17668
18192
|
}, []);
|
|
17669
|
-
const
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
|
|
17678
|
-
|
|
17679
|
-
|
|
17680
|
-
|
|
17681
|
-
|
|
17682
|
-
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
|
|
17687
|
-
|
|
17688
|
-
|
|
17689
|
-
|
|
17690
|
-
|
|
18193
|
+
const handleEditableChange = useCallback((v) => {
|
|
18194
|
+
lastPropCodeRef.current = v;
|
|
18195
|
+
setEditableValue(v);
|
|
18196
|
+
onChange?.(v);
|
|
18197
|
+
}, [onChange]);
|
|
18198
|
+
const { caretMode } = useEditorCapabilities({
|
|
18199
|
+
editorId: editable ? editorId : void 0,
|
|
18200
|
+
textareaRef: editableTextareaRef,
|
|
18201
|
+
events: { onMotion, onOperate, onInsertText, onSetMode },
|
|
18202
|
+
applyChange: handleEditableChange
|
|
18203
|
+
});
|
|
18204
|
+
const [caretIndex, setCaretIndex] = useState(0);
|
|
18205
|
+
const caretRowCol = useMemo(() => {
|
|
18206
|
+
const before = editableValue.slice(0, Math.min(caretIndex, editableValue.length));
|
|
18207
|
+
const lines = before.split("\n");
|
|
18208
|
+
return { row: lines.length - 1, col: lines[lines.length - 1].length };
|
|
18209
|
+
}, [editableValue, caretIndex]);
|
|
18210
|
+
const errorLineProps = useMemo(() => buildLineProps(errorLines), [errorLines]);
|
|
18211
|
+
const viewerLineProps = useMemo(
|
|
18212
|
+
() => buildLineProps(errorLines, "px-4 py-0.5 hover:bg-muted/50"),
|
|
18213
|
+
[errorLines]
|
|
18214
|
+
);
|
|
17691
18215
|
const isFoldable = foldableProp ?? true;
|
|
17692
18216
|
const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
|
|
17693
18217
|
const foldRegions = useMemo(
|
|
@@ -17810,6 +18334,110 @@ var init_CodeBlock = __esm({
|
|
|
17810
18334
|
),
|
|
17811
18335
|
[code, overCapacity, plainCodeColor, language, activeStyle, languageReady]
|
|
17812
18336
|
);
|
|
18337
|
+
const viewerOverCapacity = activeCode.length > HIGHLIGHT_CAPACITY_BYTES;
|
|
18338
|
+
const viewerHighlightedElement = useMemo(
|
|
18339
|
+
() => viewerOverCapacity ? /* @__PURE__ */ jsx(
|
|
18340
|
+
"div",
|
|
18341
|
+
{
|
|
18342
|
+
className: "px-4 py-0.5",
|
|
18343
|
+
style: {
|
|
18344
|
+
margin: 0,
|
|
18345
|
+
whiteSpace: wrap ? "pre-wrap" : "pre",
|
|
18346
|
+
wordBreak: wrap ? "break-all" : "normal",
|
|
18347
|
+
color: viewerPlainCodeColor,
|
|
18348
|
+
fontFamily: MONO_FONT_FAMILY,
|
|
18349
|
+
fontSize: "12px",
|
|
18350
|
+
lineHeight: "1.6"
|
|
18351
|
+
},
|
|
18352
|
+
children: activeCode
|
|
18353
|
+
}
|
|
18354
|
+
) : /* @__PURE__ */ jsx(
|
|
18355
|
+
SyntaxHighlighter,
|
|
18356
|
+
{
|
|
18357
|
+
PreTag: "div",
|
|
18358
|
+
language: activeLanguage,
|
|
18359
|
+
style: viewerStyle,
|
|
18360
|
+
wrapLines: true,
|
|
18361
|
+
wrapLongLines: wrap,
|
|
18362
|
+
showLineNumbers,
|
|
18363
|
+
lineNumberStyle: VIEWER_LINE_NUMBER_STYLE,
|
|
18364
|
+
lineProps: viewerLineProps,
|
|
18365
|
+
customStyle: {
|
|
18366
|
+
backgroundColor: "transparent",
|
|
18367
|
+
borderRadius: 0,
|
|
18368
|
+
padding: "0.25rem 0",
|
|
18369
|
+
margin: 0,
|
|
18370
|
+
whiteSpace: wrap ? "pre-wrap" : "pre",
|
|
18371
|
+
wordBreak: wrap ? "break-all" : "normal",
|
|
18372
|
+
fontFamily: MONO_FONT_FAMILY,
|
|
18373
|
+
fontSize: "12px",
|
|
18374
|
+
lineHeight: "1.6"
|
|
18375
|
+
},
|
|
18376
|
+
codeTagProps: { style: { fontFamily: MONO_FONT_FAMILY, fontSize: "12px", lineHeight: "1.6" } },
|
|
18377
|
+
children: activeCode
|
|
18378
|
+
}
|
|
18379
|
+
),
|
|
18380
|
+
[activeCode, viewerOverCapacity, viewerPlainCodeColor, activeLanguage, viewerStyle, wrap, showLineNumbers, viewerLineProps, languageReady]
|
|
18381
|
+
);
|
|
18382
|
+
const diffOverCapacity = useMemo(
|
|
18383
|
+
() => !!diffLines && diffLines.reduce((n, l) => n + l.content.length + 1, 0) > HIGHLIGHT_CAPACITY_BYTES,
|
|
18384
|
+
[diffLines]
|
|
18385
|
+
);
|
|
18386
|
+
const diffRowElements = useMemo(() => {
|
|
18387
|
+
if (!diffLines) return null;
|
|
18388
|
+
return diffLines.map((line, idx) => {
|
|
18389
|
+
const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
|
|
18390
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
|
|
18391
|
+
showLineNumbers && /* @__PURE__ */ jsx(
|
|
18392
|
+
Typography,
|
|
18393
|
+
{
|
|
18394
|
+
variant: "caption",
|
|
18395
|
+
color: "secondary",
|
|
18396
|
+
className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
|
|
18397
|
+
children: line.lineNumber ?? ""
|
|
18398
|
+
}
|
|
18399
|
+
),
|
|
18400
|
+
/* @__PURE__ */ jsxs(
|
|
18401
|
+
Typography,
|
|
18402
|
+
{
|
|
18403
|
+
variant: "caption",
|
|
18404
|
+
className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
|
|
18405
|
+
children: [
|
|
18406
|
+
/* @__PURE__ */ jsx(Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
|
|
18407
|
+
diffOverCapacity ? line.content || " " : /* @__PURE__ */ jsx(
|
|
18408
|
+
SyntaxHighlighter,
|
|
18409
|
+
{
|
|
18410
|
+
PreTag: "span",
|
|
18411
|
+
CodeTag: "span",
|
|
18412
|
+
language: activeLanguage,
|
|
18413
|
+
style: viewerStyle,
|
|
18414
|
+
customStyle: {
|
|
18415
|
+
display: "inline",
|
|
18416
|
+
background: "transparent",
|
|
18417
|
+
padding: 0,
|
|
18418
|
+
margin: 0,
|
|
18419
|
+
whiteSpace: wrap ? "pre-wrap" : "pre",
|
|
18420
|
+
wordBreak: wrap ? "break-all" : "normal",
|
|
18421
|
+
fontFamily: "inherit",
|
|
18422
|
+
fontSize: "inherit",
|
|
18423
|
+
lineHeight: "inherit"
|
|
18424
|
+
},
|
|
18425
|
+
codeTagProps: {
|
|
18426
|
+
style: {
|
|
18427
|
+
whiteSpace: wrap ? "pre-wrap" : "pre",
|
|
18428
|
+
fontFamily: "inherit",
|
|
18429
|
+
fontSize: "inherit"
|
|
18430
|
+
}
|
|
18431
|
+
},
|
|
18432
|
+
children: line.content || " "
|
|
18433
|
+
}
|
|
18434
|
+
)
|
|
18435
|
+
]
|
|
18436
|
+
}
|
|
18437
|
+
)
|
|
18438
|
+
] }, idx);
|
|
18439
|
+
});
|
|
18440
|
+
}, [diffLines, showLineNumbers, wrap, diffOverCapacity, activeLanguage, viewerStyle, languageReady]);
|
|
17813
18441
|
useLayoutEffect(() => {
|
|
17814
18442
|
const container = codeRef.current;
|
|
17815
18443
|
if (!container) return;
|
|
@@ -17953,7 +18581,6 @@ var init_CodeBlock = __esm({
|
|
|
17953
18581
|
label: file.label,
|
|
17954
18582
|
content: null
|
|
17955
18583
|
}));
|
|
17956
|
-
const lines = activeCode.split("\n");
|
|
17957
18584
|
return /* @__PURE__ */ jsx(Card, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
|
|
17958
18585
|
tabItems && tabItems.length > 1 && /* @__PURE__ */ jsx(Box, { className: "border-b border-border", children: /* @__PURE__ */ jsx(
|
|
17959
18586
|
Tabs,
|
|
@@ -18016,49 +18643,7 @@ var init_CodeBlock = __esm({
|
|
|
18016
18643
|
]
|
|
18017
18644
|
}
|
|
18018
18645
|
),
|
|
18019
|
-
/* @__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:
|
|
18020
|
-
const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
|
|
18021
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
|
|
18022
|
-
showLineNumbers && /* @__PURE__ */ jsx(
|
|
18023
|
-
Typography,
|
|
18024
|
-
{
|
|
18025
|
-
variant: "caption",
|
|
18026
|
-
color: "secondary",
|
|
18027
|
-
className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
|
|
18028
|
-
children: line.lineNumber ?? ""
|
|
18029
|
-
}
|
|
18030
|
-
),
|
|
18031
|
-
/* @__PURE__ */ jsxs(
|
|
18032
|
-
Typography,
|
|
18033
|
-
{
|
|
18034
|
-
variant: "caption",
|
|
18035
|
-
className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
|
|
18036
|
-
children: [
|
|
18037
|
-
/* @__PURE__ */ jsx(Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
|
|
18038
|
-
line.content
|
|
18039
|
-
]
|
|
18040
|
-
}
|
|
18041
|
-
)
|
|
18042
|
-
] }, idx);
|
|
18043
|
-
}) }) : /* @__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: [
|
|
18044
|
-
showLineNumbers && /* @__PURE__ */ jsx(
|
|
18045
|
-
Typography,
|
|
18046
|
-
{
|
|
18047
|
-
variant: "caption",
|
|
18048
|
-
color: "secondary",
|
|
18049
|
-
className: "w-8 text-right mr-4 select-none tabular-nums flex-shrink-0",
|
|
18050
|
-
children: idx + 1
|
|
18051
|
-
}
|
|
18052
|
-
),
|
|
18053
|
-
/* @__PURE__ */ jsx(
|
|
18054
|
-
Typography,
|
|
18055
|
-
{
|
|
18056
|
-
variant: "caption",
|
|
18057
|
-
className: cn("font-mono flex-1 min-w-0", wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
|
|
18058
|
-
children: line || " "
|
|
18059
|
-
}
|
|
18060
|
-
)
|
|
18061
|
-
] }, idx)) }) })
|
|
18646
|
+
/* @__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 }) })
|
|
18062
18647
|
] }) });
|
|
18063
18648
|
}
|
|
18064
18649
|
const hasHeader = showLanguageBadge || effectiveCopy;
|
|
@@ -18145,13 +18730,11 @@ var init_CodeBlock = __esm({
|
|
|
18145
18730
|
{
|
|
18146
18731
|
ref: editableTextareaRef,
|
|
18147
18732
|
defaultValue: code,
|
|
18148
|
-
onChange: (e) =>
|
|
18149
|
-
const v = e.target.value;
|
|
18150
|
-
lastPropCodeRef.current = v;
|
|
18151
|
-
setEditableValue(v);
|
|
18152
|
-
onChange?.(v);
|
|
18153
|
-
},
|
|
18733
|
+
onChange: (e) => handleEditableChange(e.target.value),
|
|
18154
18734
|
onScroll: handleEditableScroll,
|
|
18735
|
+
onSelect: (e) => setCaretIndex(e.currentTarget.selectionStart),
|
|
18736
|
+
onFocus: editorId ? () => eventBus.emit(`UI:${onEditorFocus}`, { editorId }) : void 0,
|
|
18737
|
+
onBlur: editorId ? () => eventBus.emit(`UI:${onEditorBlur}`, { editorId }) : void 0,
|
|
18155
18738
|
spellCheck: false,
|
|
18156
18739
|
style: {
|
|
18157
18740
|
position: "absolute",
|
|
@@ -18166,7 +18749,7 @@ var init_CodeBlock = __esm({
|
|
|
18166
18749
|
resize: "none",
|
|
18167
18750
|
backgroundColor: "transparent",
|
|
18168
18751
|
color: "transparent",
|
|
18169
|
-
caretColor: "#e6e6e6",
|
|
18752
|
+
caretColor: caretMode === "block" ? "transparent" : "#e6e6e6",
|
|
18170
18753
|
WebkitTextFillColor: "transparent",
|
|
18171
18754
|
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
|
|
18172
18755
|
fontSize: "13px",
|
|
@@ -18177,6 +18760,22 @@ var init_CodeBlock = __esm({
|
|
|
18177
18760
|
}
|
|
18178
18761
|
},
|
|
18179
18762
|
editableTextareaKey
|
|
18763
|
+
),
|
|
18764
|
+
caretMode !== "bar" && /* @__PURE__ */ jsx(
|
|
18765
|
+
"span",
|
|
18766
|
+
{
|
|
18767
|
+
"aria-hidden": true,
|
|
18768
|
+
style: {
|
|
18769
|
+
position: "absolute",
|
|
18770
|
+
top: `calc(1rem + ${caretRowCol.row * 19.5}px)`,
|
|
18771
|
+
left: `calc(1rem + ${caretRowCol.col}ch)`,
|
|
18772
|
+
width: "1ch",
|
|
18773
|
+
height: caretMode === "block" ? "19.5px" : "2px",
|
|
18774
|
+
backgroundColor: caretMode === "block" ? "rgba(230, 230, 230, 0.5)" : void 0,
|
|
18775
|
+
borderBottom: caretMode === "underline" ? "2px solid #e6e6e6" : void 0,
|
|
18776
|
+
pointerEvents: "none"
|
|
18777
|
+
}
|
|
18778
|
+
}
|
|
18180
18779
|
)
|
|
18181
18780
|
]
|
|
18182
18781
|
}
|
|
@@ -18204,55 +18803,175 @@ var init_CodeBlock = __esm({
|
|
|
18204
18803
|
)
|
|
18205
18804
|
] });
|
|
18206
18805
|
},
|
|
18207
|
-
(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
|
|
18806
|
+
(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
|
|
18208
18807
|
);
|
|
18209
18808
|
CodeBlock.displayName = "CodeBlock";
|
|
18210
18809
|
}
|
|
18211
18810
|
});
|
|
18811
|
+
|
|
18812
|
+
// components/core/molecules/markdown/mermaidSource.ts
|
|
18813
|
+
function isQuoted(label) {
|
|
18814
|
+
const trimmed = label.trim();
|
|
18815
|
+
return trimmed.length === 0 || trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1;
|
|
18816
|
+
}
|
|
18817
|
+
function quote(label) {
|
|
18818
|
+
return `"${label.replace(/"/g, "#quot;")}"`;
|
|
18819
|
+
}
|
|
18820
|
+
function isIdentifierChar(ch) {
|
|
18821
|
+
return /[A-Za-z0-9_\-.]/.test(ch);
|
|
18822
|
+
}
|
|
18823
|
+
function declaredType(code) {
|
|
18824
|
+
for (const line of code.split("\n")) {
|
|
18825
|
+
const trimmed = line.trim();
|
|
18826
|
+
if (trimmed.length === 0 || trimmed.startsWith("%%")) continue;
|
|
18827
|
+
return trimmed;
|
|
18828
|
+
}
|
|
18829
|
+
return "";
|
|
18830
|
+
}
|
|
18831
|
+
function isFlowchart(code) {
|
|
18832
|
+
return FLOWCHART_DIRECTIVE.test(declaredType(code));
|
|
18833
|
+
}
|
|
18834
|
+
function quoteNodeLabels(code) {
|
|
18835
|
+
let out = "";
|
|
18836
|
+
let i = 0;
|
|
18837
|
+
while (i < code.length) {
|
|
18838
|
+
const shape = NODE_SHAPES.find(([open2]) => code.startsWith(open2, i));
|
|
18839
|
+
const precededByIdentifier = i > 0 && isIdentifierChar(code[i - 1] ?? "");
|
|
18840
|
+
if (shape === void 0 || !precededByIdentifier) {
|
|
18841
|
+
out += code[i];
|
|
18842
|
+
i += 1;
|
|
18843
|
+
continue;
|
|
18844
|
+
}
|
|
18845
|
+
const [open, close] = shape;
|
|
18846
|
+
const contentStart = i + open.length;
|
|
18847
|
+
const closeAt = code.indexOf(close, contentStart);
|
|
18848
|
+
const newlineAt = code.indexOf("\n", contentStart);
|
|
18849
|
+
if (closeAt === -1 || newlineAt !== -1 && newlineAt < closeAt) {
|
|
18850
|
+
out += code[i];
|
|
18851
|
+
i += 1;
|
|
18852
|
+
continue;
|
|
18853
|
+
}
|
|
18854
|
+
const label = code.slice(contentStart, closeAt);
|
|
18855
|
+
out += open + (isQuoted(label) ? label : quote(label)) + close;
|
|
18856
|
+
i = closeAt + close.length;
|
|
18857
|
+
}
|
|
18858
|
+
return out;
|
|
18859
|
+
}
|
|
18860
|
+
function quoteEdgeLabels(code) {
|
|
18861
|
+
return code.split("\n").map((line) => {
|
|
18862
|
+
let out = "";
|
|
18863
|
+
let rest = line;
|
|
18864
|
+
for (; ; ) {
|
|
18865
|
+
const open = rest.indexOf("|");
|
|
18866
|
+
if (open === -1) break;
|
|
18867
|
+
const close = rest.indexOf("|", open + 1);
|
|
18868
|
+
if (close === -1) break;
|
|
18869
|
+
const label = rest.slice(open + 1, close);
|
|
18870
|
+
out += rest.slice(0, open + 1) + (isQuoted(label) ? label : quote(label)) + "|";
|
|
18871
|
+
rest = rest.slice(close + 1);
|
|
18872
|
+
}
|
|
18873
|
+
return out + rest;
|
|
18874
|
+
}).join("\n");
|
|
18875
|
+
}
|
|
18876
|
+
function quoteSubgraphTitles(code) {
|
|
18877
|
+
return code.split("\n").map((line) => {
|
|
18878
|
+
const match = /^(\s*subgraph\s+)(.+?)(\s*)$/.exec(line);
|
|
18879
|
+
if (match === null) return line;
|
|
18880
|
+
const [, prefix, title, trailing] = match;
|
|
18881
|
+
if (title === void 0 || prefix === void 0) return line;
|
|
18882
|
+
if (isQuoted(title) || title.includes("[")) return line;
|
|
18883
|
+
return prefix + quote(title) + (trailing ?? "");
|
|
18884
|
+
}).join("\n");
|
|
18885
|
+
}
|
|
18886
|
+
function mermaidRepairCandidates(code) {
|
|
18887
|
+
if (!isFlowchart(code)) return [];
|
|
18888
|
+
const nodes = quoteNodeLabels(code);
|
|
18889
|
+
const nodesAndEdges = quoteEdgeLabels(nodes);
|
|
18890
|
+
const all = quoteSubgraphTitles(nodesAndEdges);
|
|
18891
|
+
const ordered2 = [nodes, nodesAndEdges, all];
|
|
18892
|
+
const seen = /* @__PURE__ */ new Set([code]);
|
|
18893
|
+
const candidates = [];
|
|
18894
|
+
for (const candidate of ordered2) {
|
|
18895
|
+
if (seen.has(candidate)) continue;
|
|
18896
|
+
seen.add(candidate);
|
|
18897
|
+
candidates.push(candidate);
|
|
18898
|
+
}
|
|
18899
|
+
return candidates;
|
|
18900
|
+
}
|
|
18901
|
+
var NODE_SHAPES, FLOWCHART_DIRECTIVE;
|
|
18902
|
+
var init_mermaidSource = __esm({
|
|
18903
|
+
"components/core/molecules/markdown/mermaidSource.ts"() {
|
|
18904
|
+
NODE_SHAPES = [
|
|
18905
|
+
["[[", "]]"],
|
|
18906
|
+
["[(", ")]"],
|
|
18907
|
+
["([", "])"],
|
|
18908
|
+
["((", "))"],
|
|
18909
|
+
["{{", "}}"],
|
|
18910
|
+
["[", "]"],
|
|
18911
|
+
["(", ")"],
|
|
18912
|
+
["{", "}"]
|
|
18913
|
+
];
|
|
18914
|
+
FLOWCHART_DIRECTIVE = /^(?:graph|flowchart)\b/;
|
|
18915
|
+
}
|
|
18916
|
+
});
|
|
18212
18917
|
function loadMermaid() {
|
|
18213
18918
|
mermaidModule ?? (mermaidModule = import('mermaid').then((m) => m.default));
|
|
18214
18919
|
return mermaidModule;
|
|
18215
18920
|
}
|
|
18216
|
-
var mermaidModule, MermaidDiagram;
|
|
18921
|
+
var log8, mermaidModule, MermaidDiagram;
|
|
18217
18922
|
var init_MermaidDiagram = __esm({
|
|
18218
18923
|
"components/core/molecules/markdown/MermaidDiagram.tsx"() {
|
|
18219
18924
|
init_Box();
|
|
18220
18925
|
init_Typography();
|
|
18221
18926
|
init_CodeBlock();
|
|
18927
|
+
init_mermaidSource();
|
|
18222
18928
|
init_cn();
|
|
18929
|
+
log8 = createLogger("almadar:ui:mermaid-diagram");
|
|
18223
18930
|
mermaidModule = null;
|
|
18224
18931
|
MermaidDiagram = React89__default.memo(
|
|
18225
18932
|
({ code, className }) => {
|
|
18226
18933
|
const { resolvedMode } = useTheme();
|
|
18934
|
+
const { t } = useTranslate();
|
|
18227
18935
|
const containerRef = useRef(null);
|
|
18228
|
-
const [
|
|
18936
|
+
const [unrenderable, setUnrenderable] = useState(false);
|
|
18229
18937
|
const reactId = useId();
|
|
18230
18938
|
useEffect(() => {
|
|
18231
18939
|
let active = true;
|
|
18232
18940
|
void (async () => {
|
|
18233
|
-
|
|
18234
|
-
|
|
18235
|
-
|
|
18236
|
-
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
|
|
18243
|
-
|
|
18244
|
-
|
|
18245
|
-
|
|
18246
|
-
|
|
18941
|
+
const mermaid = await loadMermaid();
|
|
18942
|
+
mermaid.initialize({
|
|
18943
|
+
startOnLoad: false,
|
|
18944
|
+
securityLevel: "strict",
|
|
18945
|
+
theme: resolvedMode === "dark" ? "dark" : "default"
|
|
18946
|
+
});
|
|
18947
|
+
const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
|
|
18948
|
+
let firstError = null;
|
|
18949
|
+
for (const [index, source] of [code, ...mermaidRepairCandidates(code)].entries()) {
|
|
18950
|
+
try {
|
|
18951
|
+
const { svg } = await mermaid.render(domId, source);
|
|
18952
|
+
if (!active) return;
|
|
18953
|
+
const container = containerRef.current;
|
|
18954
|
+
if (container === null) return;
|
|
18955
|
+
container.innerHTML = svg;
|
|
18956
|
+
container.dataset.mermaidRepaired = String(index > 0);
|
|
18957
|
+
setUnrenderable(false);
|
|
18958
|
+
if (index > 0) log8.debug("mermaid:repaired", { candidate: index });
|
|
18959
|
+
return;
|
|
18960
|
+
} catch (err) {
|
|
18961
|
+
firstError ?? (firstError = err instanceof Error ? err : new Error(String(err)));
|
|
18962
|
+
}
|
|
18247
18963
|
}
|
|
18964
|
+
if (!active) return;
|
|
18965
|
+
log8.warn("mermaid:unrenderable", { error: firstError?.message ?? "", code });
|
|
18966
|
+
setUnrenderable(true);
|
|
18248
18967
|
})();
|
|
18249
18968
|
return () => {
|
|
18250
18969
|
active = false;
|
|
18251
18970
|
};
|
|
18252
18971
|
}, [code, resolvedMode, reactId]);
|
|
18253
18972
|
return /* @__PURE__ */ jsxs(Box, { className: cn("not-prose my-4", className), children: [
|
|
18254
|
-
|
|
18255
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-
|
|
18973
|
+
unrenderable && /* @__PURE__ */ jsxs(Box, { className: "space-y-2 mb-2", "data-testid": "mermaid-unrenderable", children: [
|
|
18974
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("mermaid.unrenderable") }),
|
|
18256
18975
|
/* @__PURE__ */ jsx(CodeBlock, { code, language: "mermaid" })
|
|
18257
18976
|
] }),
|
|
18258
18977
|
/* @__PURE__ */ jsx(
|
|
@@ -18261,7 +18980,7 @@ var init_MermaidDiagram = __esm({
|
|
|
18261
18980
|
ref: containerRef,
|
|
18262
18981
|
"data-testid": "mermaid-diagram",
|
|
18263
18982
|
className: "overflow-x-auto",
|
|
18264
|
-
style:
|
|
18983
|
+
style: unrenderable ? { display: "none" } : void 0
|
|
18265
18984
|
}
|
|
18266
18985
|
)
|
|
18267
18986
|
] });
|
|
@@ -21666,14 +22385,14 @@ function useSafeEventBus2() {
|
|
|
21666
22385
|
} };
|
|
21667
22386
|
}
|
|
21668
22387
|
}
|
|
21669
|
-
var
|
|
22388
|
+
var log9, lookStyles4, ButtonGroup;
|
|
21670
22389
|
var init_ButtonGroup = __esm({
|
|
21671
22390
|
"components/core/molecules/ButtonGroup.tsx"() {
|
|
21672
22391
|
"use client";
|
|
21673
22392
|
init_cn();
|
|
21674
22393
|
init_atoms();
|
|
21675
22394
|
init_useEventBus();
|
|
21676
|
-
|
|
22395
|
+
log9 = createLogger("almadar:ui:button-group");
|
|
21677
22396
|
lookStyles4 = {
|
|
21678
22397
|
"right-aligned-buttons": "",
|
|
21679
22398
|
"floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
|
|
@@ -21754,7 +22473,7 @@ var init_ButtonGroup = __esm({
|
|
|
21754
22473
|
{
|
|
21755
22474
|
variant: "ghost",
|
|
21756
22475
|
onClick: () => {
|
|
21757
|
-
|
|
22476
|
+
log9.debug("Filter clicked", { field: filter.field });
|
|
21758
22477
|
},
|
|
21759
22478
|
children: filter.label
|
|
21760
22479
|
},
|
|
@@ -24538,6 +25257,12 @@ function commandMatches(command, query) {
|
|
|
24538
25257
|
if (matchesQuery(query, command.label)) return true;
|
|
24539
25258
|
return (command.keywords ?? []).some((keyword) => matchesQuery(query, keyword));
|
|
24540
25259
|
}
|
|
25260
|
+
function dispatchCommandPaletteCommand(command, deps) {
|
|
25261
|
+
if (command.disabled) return;
|
|
25262
|
+
if (command.event) deps.emit(`UI:${command.event}`, { commandId: command.id });
|
|
25263
|
+
if (command.action) deps.emit(`UI:${command.action}`, command.actionPayload ?? {});
|
|
25264
|
+
deps.onSelect?.(command);
|
|
25265
|
+
}
|
|
24541
25266
|
var UNGROUPED, CommandPalette;
|
|
24542
25267
|
var init_CommandPalette = __esm({
|
|
24543
25268
|
"components/core/molecules/CommandPalette.tsx"() {
|
|
@@ -24592,9 +25317,7 @@ var init_CommandPalette = __esm({
|
|
|
24592
25317
|
const handleSelect = useCallback(
|
|
24593
25318
|
(command) => {
|
|
24594
25319
|
if (command.disabled) return;
|
|
24595
|
-
|
|
24596
|
-
if (command.action) eventBus.emit(`UI:${command.action}`, command.actionPayload ?? {});
|
|
24597
|
-
onSelect?.(command);
|
|
25320
|
+
dispatchCommandPaletteCommand(command, { emit: eventBus.emit, onSelect });
|
|
24598
25321
|
handleClose();
|
|
24599
25322
|
},
|
|
24600
25323
|
[eventBus, onSelect, handleClose]
|
|
@@ -29573,9 +30296,9 @@ function debug(...args) {
|
|
|
29573
30296
|
const [first, ...rest] = args;
|
|
29574
30297
|
const message = typeof first === "string" ? first : "<debug>";
|
|
29575
30298
|
if (rest.length === 0 && typeof first === "string") {
|
|
29576
|
-
|
|
30299
|
+
log10.debug(message);
|
|
29577
30300
|
} else {
|
|
29578
|
-
|
|
30301
|
+
log10.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
|
|
29579
30302
|
}
|
|
29580
30303
|
}
|
|
29581
30304
|
function debugGroup(label) {
|
|
@@ -29603,11 +30326,11 @@ function toLogMetaValue(v) {
|
|
|
29603
30326
|
}
|
|
29604
30327
|
return String(v);
|
|
29605
30328
|
}
|
|
29606
|
-
var NAMESPACE,
|
|
30329
|
+
var NAMESPACE, log10;
|
|
29607
30330
|
var init_debug = __esm({
|
|
29608
30331
|
"lib/debug.ts"() {
|
|
29609
30332
|
NAMESPACE = "almadar:ui:debug";
|
|
29610
|
-
|
|
30333
|
+
log10 = createLogger(NAMESPACE);
|
|
29611
30334
|
createLogger("almadar:ui:debug:input");
|
|
29612
30335
|
createLogger("almadar:ui:debug:collision");
|
|
29613
30336
|
createLogger("almadar:ui:debug:physics");
|
|
@@ -31260,6 +31983,7 @@ var init_MathCanvas = __esm({
|
|
|
31260
31983
|
init_perf();
|
|
31261
31984
|
init_atoms();
|
|
31262
31985
|
init_Stack();
|
|
31986
|
+
init_gameFonts();
|
|
31263
31987
|
init_LearningCanvas();
|
|
31264
31988
|
MathCanvas = ({
|
|
31265
31989
|
className,
|
|
@@ -31279,6 +32003,7 @@ var init_MathCanvas = __esm({
|
|
|
31279
32003
|
showTickLabels = false,
|
|
31280
32004
|
tickLabelFontSize = 10,
|
|
31281
32005
|
labelFontSize = 12,
|
|
32006
|
+
fontFamily: fontFamilyProp,
|
|
31282
32007
|
showCurveLabels = false,
|
|
31283
32008
|
curves = [],
|
|
31284
32009
|
points = [],
|
|
@@ -31301,6 +32026,7 @@ var init_MathCanvas = __esm({
|
|
|
31301
32026
|
error
|
|
31302
32027
|
}) => {
|
|
31303
32028
|
const eventBus = useEventBus();
|
|
32029
|
+
const fontFamily = resolveGameFontFamily(fontFamilyProp);
|
|
31304
32030
|
const keyMapKey = keyMap ? JSON.stringify(keyMap) : null;
|
|
31305
32031
|
const keyUpMapKey = keyUpMap ? JSON.stringify(keyUpMap) : null;
|
|
31306
32032
|
const stableKeyMap = useMemo(() => keyMap, [keyMapKey]);
|
|
@@ -31350,18 +32076,18 @@ var init_MathCanvas = __esm({
|
|
|
31350
32076
|
let kx = 0;
|
|
31351
32077
|
for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep, kx++) {
|
|
31352
32078
|
if (kx % labelEveryX === 0 && x !== 0) {
|
|
31353
|
-
out.push({ type: "text", x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
|
|
32079
|
+
out.push({ type: "text", fontFamily, x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
|
|
31354
32080
|
}
|
|
31355
32081
|
}
|
|
31356
32082
|
const labelEveryY = Math.max(1, Math.ceil((yMax - yMin) / gridStep / Math.floor(plotH / 28)));
|
|
31357
32083
|
let ky = 0;
|
|
31358
32084
|
for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep, ky++) {
|
|
31359
32085
|
if (ky % labelEveryY === 0 && y !== 0) {
|
|
31360
|
-
out.push({ type: "text", x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
|
|
32086
|
+
out.push({ type: "text", fontFamily, x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
|
|
31361
32087
|
}
|
|
31362
32088
|
}
|
|
31363
32089
|
if (xMin <= 0 && xMax >= 0 && yMin <= 0 && yMax >= 0) {
|
|
31364
|
-
out.push({ type: "text", x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
|
|
32090
|
+
out.push({ type: "text", fontFamily, x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
|
|
31365
32091
|
}
|
|
31366
32092
|
}
|
|
31367
32093
|
for (const region of regions) {
|
|
@@ -31388,6 +32114,7 @@ var init_MathCanvas = __esm({
|
|
|
31388
32114
|
const mid = Math.floor(region.samples.length / 2);
|
|
31389
32115
|
out.push({
|
|
31390
32116
|
type: "text",
|
|
32117
|
+
fontFamily,
|
|
31391
32118
|
x: mapX((first.x + last.x) / 2),
|
|
31392
32119
|
y: (mapY(region.samples[mid].y) + mapY(baseline)) / 2,
|
|
31393
32120
|
text: region.label,
|
|
@@ -31424,14 +32151,14 @@ var init_MathCanvas = __esm({
|
|
|
31424
32151
|
const px = mapX(guide.at);
|
|
31425
32152
|
out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color, dash });
|
|
31426
32153
|
if (guide.label) {
|
|
31427
|
-
out.push({ type: "text", x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
|
|
32154
|
+
out.push({ type: "text", fontFamily, x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
|
|
31428
32155
|
}
|
|
31429
32156
|
} else {
|
|
31430
32157
|
if (guide.at < yMin || guide.at > yMax) continue;
|
|
31431
32158
|
const py = mapY(guide.at);
|
|
31432
32159
|
out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color, dash });
|
|
31433
32160
|
if (guide.label) {
|
|
31434
|
-
out.push({ type: "text", x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
|
|
32161
|
+
out.push({ type: "text", fontFamily, x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
|
|
31435
32162
|
}
|
|
31436
32163
|
}
|
|
31437
32164
|
}
|
|
@@ -31470,6 +32197,7 @@ var init_MathCanvas = __esm({
|
|
|
31470
32197
|
if (showCurveLabels && curve.label && lastInRange) {
|
|
31471
32198
|
out.push({
|
|
31472
32199
|
type: "text",
|
|
32200
|
+
fontFamily,
|
|
31473
32201
|
x: mapX(lastInRange.x) + 6,
|
|
31474
32202
|
y: mapY(lastInRange.y) - 6,
|
|
31475
32203
|
text: curve.label,
|
|
@@ -31507,6 +32235,7 @@ var init_MathCanvas = __esm({
|
|
|
31507
32235
|
if (hop.label) {
|
|
31508
32236
|
out.push({
|
|
31509
32237
|
type: "text",
|
|
32238
|
+
fontFamily,
|
|
31510
32239
|
x: (x1 + x2) / 2,
|
|
31511
32240
|
y: xAxisY - peak - 8,
|
|
31512
32241
|
text: hop.label,
|
|
@@ -31534,6 +32263,7 @@ var init_MathCanvas = __esm({
|
|
|
31534
32263
|
const rad = mid * Math.PI / 180;
|
|
31535
32264
|
out.push({
|
|
31536
32265
|
type: "text",
|
|
32266
|
+
fontFamily,
|
|
31537
32267
|
x: mapX(angle.x + 1.35 * radius * Math.cos(rad)),
|
|
31538
32268
|
y: mapY(angle.y + 1.35 * radius * Math.sin(rad)),
|
|
31539
32269
|
text: angle.label,
|
|
@@ -31555,7 +32285,7 @@ var init_MathCanvas = __esm({
|
|
|
31555
32285
|
fill: isOpen ? "#ffffff" : p.color ?? "#dc2626"
|
|
31556
32286
|
});
|
|
31557
32287
|
if (p.label) {
|
|
31558
|
-
out.push({ type: "text", x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
|
|
32288
|
+
out.push({ type: "text", fontFamily, x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
|
|
31559
32289
|
}
|
|
31560
32290
|
}
|
|
31561
32291
|
for (const v of vectors) {
|
|
@@ -31566,7 +32296,7 @@ var init_MathCanvas = __esm({
|
|
|
31566
32296
|
const y2 = mapY(v.y + v.vy);
|
|
31567
32297
|
out.push({ type: "arrow", x1, y1, x2, y2, color: v.color ?? "#7c3aed", lineWidth: 2 });
|
|
31568
32298
|
if (v.label) {
|
|
31569
|
-
out.push({ type: "text", x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
|
|
32299
|
+
out.push({ type: "text", fontFamily, x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
|
|
31570
32300
|
}
|
|
31571
32301
|
}
|
|
31572
32302
|
out.push(...shapes);
|
|
@@ -31587,6 +32317,7 @@ var init_MathCanvas = __esm({
|
|
|
31587
32317
|
showTickLabels,
|
|
31588
32318
|
tickLabelFontSize,
|
|
31589
32319
|
labelFontSize,
|
|
32320
|
+
fontFamily,
|
|
31590
32321
|
showCurveLabels,
|
|
31591
32322
|
curves,
|
|
31592
32323
|
points,
|
|
@@ -31642,6 +32373,7 @@ var init_MathCanvas = __esm({
|
|
|
31642
32373
|
width,
|
|
31643
32374
|
height,
|
|
31644
32375
|
backgroundColor,
|
|
32376
|
+
fontFamily,
|
|
31645
32377
|
shapes: derivedShapes,
|
|
31646
32378
|
drawables,
|
|
31647
32379
|
projector,
|
|
@@ -32874,13 +33606,13 @@ var init_MapView = __esm({
|
|
|
32874
33606
|
shadowSize: [41, 41]
|
|
32875
33607
|
});
|
|
32876
33608
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32877
|
-
const { useEffect:
|
|
33609
|
+
const { useEffect: useEffect69, useRef: useRef69, useCallback: useCallback100, useState: useState103 } = React89__default;
|
|
32878
33610
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32879
33611
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32880
33612
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
32881
33613
|
const map = useMap();
|
|
32882
|
-
const prevRef =
|
|
32883
|
-
|
|
33614
|
+
const prevRef = useRef69({ centerLat, centerLng, zoom });
|
|
33615
|
+
useEffect69(() => {
|
|
32884
33616
|
const prev = prevRef.current;
|
|
32885
33617
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
32886
33618
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -32891,7 +33623,7 @@ var init_MapView = __esm({
|
|
|
32891
33623
|
}
|
|
32892
33624
|
function MapClickHandler({ onMapClick }) {
|
|
32893
33625
|
const map = useMap();
|
|
32894
|
-
|
|
33626
|
+
useEffect69(() => {
|
|
32895
33627
|
if (!onMapClick) return;
|
|
32896
33628
|
const handler = (e) => {
|
|
32897
33629
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -32919,7 +33651,7 @@ var init_MapView = __esm({
|
|
|
32919
33651
|
showAttribution = true
|
|
32920
33652
|
}) {
|
|
32921
33653
|
const eventBus = useEventBus2();
|
|
32922
|
-
const [clickedPosition, setClickedPosition] =
|
|
33654
|
+
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
32923
33655
|
const handleMapClick = useCallback100((lat, lng) => {
|
|
32924
33656
|
if (showClickedPin) {
|
|
32925
33657
|
setClickedPosition({ lat, lng });
|
|
@@ -47628,7 +48360,7 @@ function getAllEvents(traits2) {
|
|
|
47628
48360
|
function EventDispatcherTab({ traits: traits2, schema }) {
|
|
47629
48361
|
const eventBus = useEventBus();
|
|
47630
48362
|
const { t } = useTranslate();
|
|
47631
|
-
const [
|
|
48363
|
+
const [log14, setLog] = React89.useState([]);
|
|
47632
48364
|
const prevStatesRef = React89.useRef(/* @__PURE__ */ new Map());
|
|
47633
48365
|
React89.useEffect(() => {
|
|
47634
48366
|
for (const trait of traits2) {
|
|
@@ -47692,9 +48424,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
47692
48424
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.otherEvents") }),
|
|
47693
48425
|
/* @__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)) })
|
|
47694
48426
|
] }),
|
|
47695
|
-
|
|
48427
|
+
log14.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
47696
48428
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.recentTransitions") }),
|
|
47697
|
-
/* @__PURE__ */ jsx(Stack, { gap: "xs", children:
|
|
48429
|
+
/* @__PURE__ */ jsx(Stack, { gap: "xs", children: log14.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
|
|
47698
48430
|
/* @__PURE__ */ jsx("span", { className: "text-primary", children: entry.traitName }),
|
|
47699
48431
|
" ",
|
|
47700
48432
|
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: entry.from }),
|
|
@@ -49885,6 +50617,7 @@ var init_component_registry_generated = __esm({
|
|
|
49885
50617
|
init_FormSection();
|
|
49886
50618
|
init_FormSectionHeader();
|
|
49887
50619
|
init_FxOverlay();
|
|
50620
|
+
init_GameAudioCue();
|
|
49888
50621
|
init_GameAudioToggle();
|
|
49889
50622
|
init_GameHud();
|
|
49890
50623
|
init_GameIcon();
|
|
@@ -50162,6 +50895,7 @@ var init_component_registry_generated = __esm({
|
|
|
50162
50895
|
"FormLayout": FormLayout,
|
|
50163
50896
|
"FormSectionHeader": FormSectionHeader,
|
|
50164
50897
|
"FxOverlay": FxOverlay,
|
|
50898
|
+
"GameAudioCue": GameAudioCue,
|
|
50165
50899
|
"GameAudioToggle": GameAudioToggle,
|
|
50166
50900
|
"GameHud": GameHud,
|
|
50167
50901
|
"GameIcon": GameIcon,
|
|
@@ -51657,7 +52391,7 @@ init_UISlotRenderer();
|
|
|
51657
52391
|
// providers/VerificationProvider.tsx
|
|
51658
52392
|
init_useEventBus();
|
|
51659
52393
|
init_verificationRegistry();
|
|
51660
|
-
var
|
|
52394
|
+
var log11 = createLogger("almadar:verify");
|
|
51661
52395
|
var DISPATCH_SUFFIX = ":DISPATCH";
|
|
51662
52396
|
var SUCCESS_SUFFIX = ":SUCCESS";
|
|
51663
52397
|
var ERROR_SUFFIX = ":ERROR";
|
|
@@ -51704,7 +52438,7 @@ function VerificationProvider({
|
|
|
51704
52438
|
const verificationProviderLifecycleListener = (evt) => {
|
|
51705
52439
|
const parsed = parseLifecycleEvent(evt.type);
|
|
51706
52440
|
if (!parsed) return;
|
|
51707
|
-
|
|
52441
|
+
log11.debug("lifecycle:event", { kind: parsed.kind, traitName: parsed.traitName, event: parsed.event, type: evt.type });
|
|
51708
52442
|
const payload = evt.payload ?? {};
|
|
51709
52443
|
if (parsed.kind === "dispatch") {
|
|
51710
52444
|
const key = `${parsed.traitName}:${String(payload["event"] ?? "")}`;
|
|
@@ -51760,7 +52494,7 @@ function VerificationProvider({
|
|
|
51760
52494
|
},
|
|
51761
52495
|
timestamp: Date.now()
|
|
51762
52496
|
});
|
|
51763
|
-
|
|
52497
|
+
log11.debug("transition:success", { trait: parsed.traitName, event: parsed.event, from: pending?.from, to: newState, effectCount: effects.length });
|
|
51764
52498
|
} else if (parsed.kind === "error" && parsed.event) {
|
|
51765
52499
|
const key = `${parsed.traitName}:${parsed.event}`;
|
|
51766
52500
|
const pending = pendingRef.current.get(key);
|
|
@@ -51790,7 +52524,7 @@ function VerificationProvider({
|
|
|
51790
52524
|
},
|
|
51791
52525
|
timestamp: Date.now()
|
|
51792
52526
|
});
|
|
51793
|
-
|
|
52527
|
+
log11.warn("transition:error", { trait: parsed.traitName, event: parsed.event, from: fromState, error: errorMsg });
|
|
51794
52528
|
}
|
|
51795
52529
|
};
|
|
51796
52530
|
Object.defineProperty(verificationProviderLifecycleListener, "name", {
|
|
@@ -52252,7 +52986,7 @@ function useEntitySchema() {
|
|
|
52252
52986
|
function useEntitySchemaOptional6() {
|
|
52253
52987
|
return useContext(EntitySchemaContext);
|
|
52254
52988
|
}
|
|
52255
|
-
var
|
|
52989
|
+
var log12 = createLogger("almadar:ui:navigation");
|
|
52256
52990
|
function matchPath2(pattern, path) {
|
|
52257
52991
|
const normalizeSegment = (p) => {
|
|
52258
52992
|
let normalized = p.trim();
|
|
@@ -52413,12 +53147,12 @@ function NavigationProvider2({
|
|
|
52413
53147
|
const navigateTo = useCallback((path, payload) => {
|
|
52414
53148
|
const result = findPageByPath2(schema, path);
|
|
52415
53149
|
if (!result) {
|
|
52416
|
-
|
|
53150
|
+
log12.error("No page found for path", { path });
|
|
52417
53151
|
return;
|
|
52418
53152
|
}
|
|
52419
53153
|
const { page, params } = result;
|
|
52420
53154
|
const finalPayload = { ...params, ...payload };
|
|
52421
|
-
|
|
53155
|
+
log12.debug("Navigating to", () => ({
|
|
52422
53156
|
path,
|
|
52423
53157
|
page: page.name,
|
|
52424
53158
|
params,
|
|
@@ -52435,7 +53169,7 @@ function NavigationProvider2({
|
|
|
52435
53169
|
try {
|
|
52436
53170
|
window.history.pushState(finalPayload, "", path);
|
|
52437
53171
|
} catch (e) {
|
|
52438
|
-
|
|
53172
|
+
log12.warn("Could not update URL", { error: e instanceof Error ? e : String(e) });
|
|
52439
53173
|
}
|
|
52440
53174
|
}
|
|
52441
53175
|
if (onNavigate) {
|
|
@@ -52445,12 +53179,12 @@ function NavigationProvider2({
|
|
|
52445
53179
|
const navigateToPage = useCallback((pageName, payload) => {
|
|
52446
53180
|
const result = findPageByName2(schema, pageName);
|
|
52447
53181
|
if (!result) {
|
|
52448
|
-
|
|
53182
|
+
log12.error("No page found with name", { pageName });
|
|
52449
53183
|
return;
|
|
52450
53184
|
}
|
|
52451
53185
|
const { page } = result;
|
|
52452
53186
|
const path = page.path || `/${pageName.toLowerCase()}`;
|
|
52453
|
-
|
|
53187
|
+
log12.debug("Navigating to page", () => ({
|
|
52454
53188
|
pageName,
|
|
52455
53189
|
path,
|
|
52456
53190
|
payload: JSON.stringify(payload)
|
|
@@ -52465,7 +53199,7 @@ function NavigationProvider2({
|
|
|
52465
53199
|
try {
|
|
52466
53200
|
window.history.pushState(payload || {}, "", path);
|
|
52467
53201
|
} catch (e) {
|
|
52468
|
-
|
|
53202
|
+
log12.warn("Could not update URL", { error: e instanceof Error ? e : String(e) });
|
|
52469
53203
|
}
|
|
52470
53204
|
}
|
|
52471
53205
|
if (onNavigate) {
|
|
@@ -52487,7 +53221,7 @@ function useNavigation2() {
|
|
|
52487
53221
|
function useNavigateTo2() {
|
|
52488
53222
|
const context = useContext(NavigationContext);
|
|
52489
53223
|
const noOp = useCallback((path, _payload) => {
|
|
52490
|
-
|
|
53224
|
+
log12.warn("navigateTo called outside NavigationProvider", { path });
|
|
52491
53225
|
}, []);
|
|
52492
53226
|
return context?.navigateTo || noOp;
|
|
52493
53227
|
}
|
|
@@ -52830,7 +53564,7 @@ function ServerBridgeProvider({
|
|
|
52830
53564
|
}, [serverUrl, eventBus]);
|
|
52831
53565
|
return /* @__PURE__ */ jsx(ServerBridgeContext.Provider, { value: { connected, sendEvent }, children });
|
|
52832
53566
|
}
|
|
52833
|
-
var
|
|
53567
|
+
var log13 = createLogger("almadar:ui:trait-provider");
|
|
52834
53568
|
var TraitContext = createContext(null);
|
|
52835
53569
|
function TraitProvider({
|
|
52836
53570
|
traits: traitBindings,
|
|
@@ -52847,7 +53581,7 @@ function TraitProvider({
|
|
|
52847
53581
|
currentState: stateName,
|
|
52848
53582
|
availableEvents: trait.transitions.filter((t) => t.from === stateName).map((t) => t.event),
|
|
52849
53583
|
dispatch: (eventKey, payload) => {
|
|
52850
|
-
|
|
53584
|
+
log13.debug("Dispatch", () => ({
|
|
52851
53585
|
trait: trait.name,
|
|
52852
53586
|
event: eventKey,
|
|
52853
53587
|
payloadKeys: payload ? Object.keys(payload) : []
|