@almadar/ui 6.0.0 → 6.1.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/avl/index.cjs +95 -20
- package/dist/avl/index.js +96 -21
- package/dist/{avl-schema-parser-CLIm28Wa.d.ts → avl-schema-parser-BKbH_SFt.d.ts} +1 -1
- package/dist/{avl-schema-parser-Do_LPV1o.d.cts → avl-schema-parser-C6Yz2MuW.d.cts} +1 -1
- package/dist/{cn-CFurBb2q.d.ts → cn-BbhJq_nr.d.ts} +1 -1
- package/dist/{cn-TH-RHihd.d.cts → cn-DJSBBm5W.d.cts} +1 -1
- package/dist/components/index.cjs +9784 -9708
- package/dist/components/index.d.cts +193 -60
- package/dist/components/index.d.ts +193 -60
- package/dist/components/index.js +9669 -9593
- package/dist/lib/drawable/three/index.cjs +5 -1
- package/dist/lib/drawable/three/index.d.cts +3 -3
- package/dist/lib/drawable/three/index.d.ts +3 -3
- package/dist/lib/drawable/three/index.js +5 -1
- package/dist/lib/index.d.cts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/marketing/index.d.cts +13 -5
- package/dist/marketing/index.d.ts +13 -5
- package/dist/{paintDispatch-B5n2DTB-.d.ts → paintDispatch-B5ObLnUv.d.ts} +37 -1
- package/dist/{paintDispatch-DgBctxIq.d.cts → paintDispatch-D3R8NNmV.d.cts} +37 -1
- package/dist/providers/index.cjs +95 -20
- package/dist/providers/index.js +96 -21
- package/dist/runtime/index.cjs +95 -20
- package/dist/runtime/index.js +96 -21
- package/package.json +4 -4
- package/themes/index.css +1 -1
package/dist/providers/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import React87__default, { createContext, useContext, useMemo, useRef, useEffect
|
|
|
3
3
|
import { EventBusContext, useTraitScopeChain, RenderSlotProvider, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, TraitScopeProvider, useNavStack, useCurrentPagePath, useRenderSlot, useGameAudioContextOptional, matchPathAmong } from '@almadar/ui/providers';
|
|
4
4
|
import { createLogger, isLogLevelEnabled } from '@almadar/logger';
|
|
5
5
|
import { createContextFromBindings, interpolateValue } from '@almadar/runtime';
|
|
6
|
-
import { ANONYMOUS_USER, isRenderBindingMarker, isFileValue, isInlineTrait
|
|
6
|
+
import { ANONYMOUS_USER, isRenderBindingMarker, isFileValue, isInlineTrait } from '@almadar/core';
|
|
7
7
|
export { ANONYMOUS_USER } from '@almadar/core';
|
|
8
8
|
import { clsx } from 'clsx';
|
|
9
9
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -5800,6 +5800,7 @@ function resolveFxView(item, presets) {
|
|
|
5800
5800
|
vy: item.vy ?? row.vy,
|
|
5801
5801
|
vz: item.vz ?? row.vz,
|
|
5802
5802
|
particleCount: item.particleCount ?? row.particleCount,
|
|
5803
|
+
animation: item.animation ?? row.animation,
|
|
5803
5804
|
shape: row.shape,
|
|
5804
5805
|
count: row.count,
|
|
5805
5806
|
glow: row.glow,
|
|
@@ -7332,9 +7333,6 @@ var init_isometric = __esm({
|
|
|
7332
7333
|
};
|
|
7333
7334
|
}
|
|
7334
7335
|
});
|
|
7335
|
-
function isAnimationName(name) {
|
|
7336
|
-
return ANIMATION_NAMES.includes(name);
|
|
7337
|
-
}
|
|
7338
7336
|
function frameRect(frame, row, columns, frameWidth, frameHeight) {
|
|
7339
7337
|
return {
|
|
7340
7338
|
sx: frame % columns * frameWidth,
|
|
@@ -9268,13 +9266,17 @@ var init_DrawSprite = __esm({
|
|
|
9268
9266
|
return;
|
|
9269
9267
|
}
|
|
9270
9268
|
if (isSpriteSheetAtlas(atlas)) {
|
|
9271
|
-
const def =
|
|
9269
|
+
const def = atlas.animations[node.animation];
|
|
9272
9270
|
if (!def) {
|
|
9273
9271
|
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9274
9272
|
return;
|
|
9275
9273
|
}
|
|
9276
|
-
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, dctx.time);
|
|
9274
|
+
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, node.clockMs ?? dctx.time);
|
|
9277
9275
|
const r = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
|
|
9276
|
+
if (![r.sx, r.sy, r.sw, r.sh].every(Number.isFinite)) {
|
|
9277
|
+
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9278
|
+
return;
|
|
9279
|
+
}
|
|
9278
9280
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9279
9281
|
}
|
|
9280
9282
|
}
|
|
@@ -9822,7 +9824,10 @@ function expandFxItem(view, node, epochNowMs, dim) {
|
|
|
9822
9824
|
anchor: "center",
|
|
9823
9825
|
width: spriteSize,
|
|
9824
9826
|
height: spriteSize,
|
|
9825
|
-
opacity: fade
|
|
9827
|
+
opacity: fade,
|
|
9828
|
+
animation: view.animation ?? sprite.animations?.[0],
|
|
9829
|
+
// One-shot fx rows (burst) play from the item's birth, not wall-time.
|
|
9830
|
+
clockMs: ageMs
|
|
9826
9831
|
});
|
|
9827
9832
|
} else {
|
|
9828
9833
|
out.push(...proceduralShapes(view, pos, fade, progress));
|
|
@@ -11669,6 +11674,7 @@ var init_GameShell = __esm({
|
|
|
11669
11674
|
init_Typography();
|
|
11670
11675
|
init_AtlasImage();
|
|
11671
11676
|
GAME_FONTS = {
|
|
11677
|
+
fredoka: "Fredoka",
|
|
11672
11678
|
future: "Kenney Future",
|
|
11673
11679
|
"future-narrow": "Kenney Future Narrow",
|
|
11674
11680
|
pixel: "Kenney Pixel",
|
|
@@ -11685,10 +11691,10 @@ var init_GameShell = __esm({
|
|
|
11685
11691
|
showTopBar = true,
|
|
11686
11692
|
children,
|
|
11687
11693
|
backgroundAsset,
|
|
11688
|
-
fontFamily
|
|
11694
|
+
fontFamily,
|
|
11689
11695
|
"data-theme": dataTheme
|
|
11690
11696
|
}) => {
|
|
11691
|
-
const font = GAME_FONTS[fontFamily] ?? fontFamily;
|
|
11697
|
+
const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
|
|
11692
11698
|
return /* @__PURE__ */ jsxs(
|
|
11693
11699
|
Box,
|
|
11694
11700
|
{
|
|
@@ -11703,8 +11709,11 @@ var init_GameShell = __esm({
|
|
|
11703
11709
|
color: "var(--color-foreground, #e0e0e0)",
|
|
11704
11710
|
// The fontFamily knob is a scoped override of the theme contract's
|
|
11705
11711
|
// display slot: titles/numerics take the game face, body text keeps
|
|
11706
|
-
// the active theme's --font-family-body.
|
|
11707
|
-
|
|
11712
|
+
// the active theme's --font-family-body. Set ONLY when explicitly
|
|
11713
|
+
// passed — an always-on inline stamp would shadow the orbital's
|
|
11714
|
+
// inline-theme font-family-display token (inline style beats the
|
|
11715
|
+
// theme provider's vars for the whole shell subtree).
|
|
11716
|
+
...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
|
|
11708
11717
|
},
|
|
11709
11718
|
children: [
|
|
11710
11719
|
backgroundAsset && /* @__PURE__ */ jsx(
|
|
@@ -12172,6 +12181,16 @@ function traceShapes(panel, k, width, height) {
|
|
|
12172
12181
|
}
|
|
12173
12182
|
return out;
|
|
12174
12183
|
}
|
|
12184
|
+
function drawableNeedsAnimation(nodes) {
|
|
12185
|
+
if (!nodes) return false;
|
|
12186
|
+
return nodes.some((node) => {
|
|
12187
|
+
if (node.type === "draw-sprite") return node.animation !== void 0;
|
|
12188
|
+
if (node.type === "draw-fx-layer") return Array.isArray(node.items) && node.items.length > 0;
|
|
12189
|
+
if (node.type === "draw-sprite-layer") return Array.isArray(node.items) && node.items.some((it) => it.animation !== void 0);
|
|
12190
|
+
if (node.type === "draw-group") return Array.isArray(node.items) && drawableNeedsAnimation(node.items);
|
|
12191
|
+
return false;
|
|
12192
|
+
});
|
|
12193
|
+
}
|
|
12175
12194
|
var DASH_PATTERNS, TRACE_SERIES_COLORS, LearningCanvas;
|
|
12176
12195
|
var init_LearningCanvas = __esm({
|
|
12177
12196
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
@@ -12179,6 +12198,8 @@ var init_LearningCanvas = __esm({
|
|
|
12179
12198
|
init_cn();
|
|
12180
12199
|
init_perf();
|
|
12181
12200
|
init_useEventBus();
|
|
12201
|
+
init_webPainter2d();
|
|
12202
|
+
init_paintDispatch();
|
|
12182
12203
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12183
12204
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
12184
12205
|
LearningCanvas = ({
|
|
@@ -12187,6 +12208,8 @@ var init_LearningCanvas = __esm({
|
|
|
12187
12208
|
height = 400,
|
|
12188
12209
|
backgroundColor,
|
|
12189
12210
|
shapes = [],
|
|
12211
|
+
drawables,
|
|
12212
|
+
projector,
|
|
12190
12213
|
readouts,
|
|
12191
12214
|
traces,
|
|
12192
12215
|
interactive = false,
|
|
@@ -12200,6 +12223,9 @@ var init_LearningCanvas = __esm({
|
|
|
12200
12223
|
const eventBus = useEventBus();
|
|
12201
12224
|
const animRef = useRef(0);
|
|
12202
12225
|
const hoverIndexRef = useRef(-1);
|
|
12226
|
+
const [drawVersion, setDrawVersion] = useState(0);
|
|
12227
|
+
const invalidateRef = useRef(() => setDrawVersion((v) => v + 1));
|
|
12228
|
+
const needsAnim = useMemo(() => drawableNeedsAnimation(drawables), [drawables]);
|
|
12203
12229
|
const findShapeAt = useCallback((clientX, clientY) => {
|
|
12204
12230
|
const canvas = canvasRef.current;
|
|
12205
12231
|
if (!canvas) return -1;
|
|
@@ -12243,20 +12269,29 @@ var init_LearningCanvas = __esm({
|
|
|
12243
12269
|
for (const shape of derivedShapes) {
|
|
12244
12270
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12245
12271
|
}
|
|
12272
|
+
if (drawables?.length && projector) {
|
|
12273
|
+
const painter = createWebPainter(ctx, invalidateRef.current);
|
|
12274
|
+
const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
|
|
12275
|
+
const dctx = { projector, time: timeMs, invalidate: invalidateRef.current };
|
|
12276
|
+
for (const node of drawables) {
|
|
12277
|
+
paintDrawable(painter, node, dctx);
|
|
12278
|
+
}
|
|
12279
|
+
}
|
|
12246
12280
|
perfEnd("learningcanvas:paint", _perfT);
|
|
12247
|
-
}, [width, height, backgroundColor, derivedShapes]);
|
|
12281
|
+
}, [width, height, backgroundColor, derivedShapes, drawables, projector, needsAnim]);
|
|
12248
12282
|
useEffect(() => {
|
|
12249
12283
|
draw();
|
|
12250
|
-
}, [draw]);
|
|
12284
|
+
}, [draw, drawVersion]);
|
|
12251
12285
|
useEffect(() => {
|
|
12252
|
-
|
|
12286
|
+
const shouldAnimate = animate || needsAnim;
|
|
12287
|
+
if (!shouldAnimate) return;
|
|
12253
12288
|
const loop = () => {
|
|
12254
12289
|
draw();
|
|
12255
12290
|
animRef.current = requestAnimationFrame(loop);
|
|
12256
12291
|
};
|
|
12257
12292
|
animRef.current = requestAnimationFrame(loop);
|
|
12258
12293
|
return () => cancelAnimationFrame(animRef.current);
|
|
12259
|
-
}, [animate, draw]);
|
|
12294
|
+
}, [animate, needsAnim, draw]);
|
|
12260
12295
|
const handlePointerMove = useCallback(
|
|
12261
12296
|
(e) => {
|
|
12262
12297
|
if (!interactive) return;
|
|
@@ -24898,8 +24933,9 @@ var init_DashboardLayout = __esm({
|
|
|
24898
24933
|
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
24899
24934
|
if (onNotificationClick) onNotificationClick();
|
|
24900
24935
|
};
|
|
24901
|
-
const handleTopBarActionClick = (
|
|
24902
|
-
eventBus.emit(`UI:${event}`, {});
|
|
24936
|
+
const handleTopBarActionClick = (action) => {
|
|
24937
|
+
if (action.event) eventBus.emit(`UI:${action.event}`, {});
|
|
24938
|
+
if (action.navigatesTo) eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
|
|
24903
24939
|
};
|
|
24904
24940
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
24905
24941
|
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
|
@@ -25114,7 +25150,7 @@ var init_DashboardLayout = __esm({
|
|
|
25114
25150
|
{
|
|
25115
25151
|
variant: "ghost",
|
|
25116
25152
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
25117
|
-
onClick: () => handleTopBarActionClick(action
|
|
25153
|
+
onClick: () => handleTopBarActionClick(action),
|
|
25118
25154
|
"aria-label": action.label ?? (typeof action.icon === "string" ? action.icon : void 0),
|
|
25119
25155
|
children: [
|
|
25120
25156
|
/* @__PURE__ */ jsx(Icon, { icon: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
@@ -25131,7 +25167,7 @@ var init_DashboardLayout = __esm({
|
|
|
25131
25167
|
)
|
|
25132
25168
|
]
|
|
25133
25169
|
},
|
|
25134
|
-
`${action.event}-${idx}`
|
|
25170
|
+
`${action.event ?? action.navigatesTo ?? "action"}-${idx}`
|
|
25135
25171
|
)),
|
|
25136
25172
|
notificationsEnabled && /* @__PURE__ */ jsxs(
|
|
25137
25173
|
Button,
|
|
@@ -30793,6 +30829,7 @@ var init_MathCanvas = __esm({
|
|
|
30793
30829
|
angles = [],
|
|
30794
30830
|
hops = [],
|
|
30795
30831
|
shapes = [],
|
|
30832
|
+
drawables,
|
|
30796
30833
|
readouts,
|
|
30797
30834
|
traces,
|
|
30798
30835
|
interactive = false,
|
|
@@ -31099,6 +31136,42 @@ var init_MathCanvas = __esm({
|
|
|
31099
31136
|
hops,
|
|
31100
31137
|
shapes
|
|
31101
31138
|
]);
|
|
31139
|
+
const projector = useMemo(() => {
|
|
31140
|
+
if (!drawables?.length) return void 0;
|
|
31141
|
+
const margin = 24;
|
|
31142
|
+
const plotW = width - margin * 2;
|
|
31143
|
+
const plotH = height - margin * 2;
|
|
31144
|
+
const xScale = plotW / (xMax - xMin);
|
|
31145
|
+
const mapX = (x) => margin + (x - xMin) / (xMax - xMin) * plotW;
|
|
31146
|
+
const mapY = (y) => height - (margin + (y - yMin) / (yMax - yMin) * plotH);
|
|
31147
|
+
const project = (pos) => ({ x: mapX(pos.x), y: mapY(pos.y) });
|
|
31148
|
+
const anchorPoint = (pos, anchor) => {
|
|
31149
|
+
const base = project(pos);
|
|
31150
|
+
if (anchor === "top-left") return base;
|
|
31151
|
+
const cx = base.x + xScale / 2;
|
|
31152
|
+
if (anchor === "ground") return { x: cx, y: base.y + xScale * 0.92 };
|
|
31153
|
+
return { x: cx, y: base.y + xScale / 2 };
|
|
31154
|
+
};
|
|
31155
|
+
const cellPath = (pos) => {
|
|
31156
|
+
const base = project(pos);
|
|
31157
|
+
return [
|
|
31158
|
+
{ x: base.x, y: base.y },
|
|
31159
|
+
{ x: base.x + xScale, y: base.y },
|
|
31160
|
+
{ x: base.x + xScale, y: base.y + xScale },
|
|
31161
|
+
{ x: base.x, y: base.y + xScale }
|
|
31162
|
+
];
|
|
31163
|
+
};
|
|
31164
|
+
return {
|
|
31165
|
+
project,
|
|
31166
|
+
anchorPoint,
|
|
31167
|
+
cellPath,
|
|
31168
|
+
tileWidth: xScale,
|
|
31169
|
+
floorHeight: xScale / 2,
|
|
31170
|
+
diamondTopY: 0,
|
|
31171
|
+
squareGrid: true,
|
|
31172
|
+
worldPixelDirect: false
|
|
31173
|
+
};
|
|
31174
|
+
}, [drawables?.length, width, height, xMin, xMax, yMin, yMax]);
|
|
31102
31175
|
return /* @__PURE__ */ jsx(Card, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
31103
31176
|
title ? /* @__PURE__ */ jsx(Typography, { variant: "h4", children: title }) : null,
|
|
31104
31177
|
/* @__PURE__ */ jsx(
|
|
@@ -31108,6 +31181,8 @@ var init_MathCanvas = __esm({
|
|
|
31108
31181
|
height,
|
|
31109
31182
|
backgroundColor,
|
|
31110
31183
|
shapes: derivedShapes,
|
|
31184
|
+
drawables,
|
|
31185
|
+
projector,
|
|
31111
31186
|
readouts,
|
|
31112
31187
|
traces,
|
|
31113
31188
|
interactive,
|
|
@@ -32337,7 +32412,7 @@ var init_MapView = __esm({
|
|
|
32337
32412
|
shadowSize: [41, 41]
|
|
32338
32413
|
});
|
|
32339
32414
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32340
|
-
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState:
|
|
32415
|
+
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState: useState98 } = React87__default;
|
|
32341
32416
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32342
32417
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32343
32418
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -32382,7 +32457,7 @@ var init_MapView = __esm({
|
|
|
32382
32457
|
showAttribution = true
|
|
32383
32458
|
}) {
|
|
32384
32459
|
const eventBus = useEventBus2();
|
|
32385
|
-
const [clickedPosition, setClickedPosition] =
|
|
32460
|
+
const [clickedPosition, setClickedPosition] = useState98(null);
|
|
32386
32461
|
const handleMapClick = useCallback97((lat, lng) => {
|
|
32387
32462
|
if (showClickedPin) {
|
|
32388
32463
|
setClickedPosition({ lat, lng });
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -6332,6 +6332,7 @@ function resolveFxView(item, presets) {
|
|
|
6332
6332
|
vy: item.vy ?? row.vy,
|
|
6333
6333
|
vz: item.vz ?? row.vz,
|
|
6334
6334
|
particleCount: item.particleCount ?? row.particleCount,
|
|
6335
|
+
animation: item.animation ?? row.animation,
|
|
6335
6336
|
shape: row.shape,
|
|
6336
6337
|
count: row.count,
|
|
6337
6338
|
glow: row.glow,
|
|
@@ -7863,9 +7864,6 @@ var init_isometric = __esm({
|
|
|
7863
7864
|
};
|
|
7864
7865
|
}
|
|
7865
7866
|
});
|
|
7866
|
-
function isAnimationName(name) {
|
|
7867
|
-
return core.ANIMATION_NAMES.includes(name);
|
|
7868
|
-
}
|
|
7869
7867
|
function frameRect(frame, row, columns, frameWidth, frameHeight) {
|
|
7870
7868
|
return {
|
|
7871
7869
|
sx: frame % columns * frameWidth,
|
|
@@ -9692,13 +9690,17 @@ var init_DrawSprite = __esm({
|
|
|
9692
9690
|
return;
|
|
9693
9691
|
}
|
|
9694
9692
|
if (isSpriteSheetAtlas(atlas)) {
|
|
9695
|
-
const def =
|
|
9693
|
+
const def = atlas.animations[node.animation];
|
|
9696
9694
|
if (!def) {
|
|
9697
9695
|
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9698
9696
|
return;
|
|
9699
9697
|
}
|
|
9700
|
-
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, dctx.time);
|
|
9698
|
+
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, node.clockMs ?? dctx.time);
|
|
9701
9699
|
const r = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
|
|
9700
|
+
if (![r.sx, r.sy, r.sw, r.sh].every(Number.isFinite)) {
|
|
9701
|
+
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9702
|
+
return;
|
|
9703
|
+
}
|
|
9702
9704
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9703
9705
|
}
|
|
9704
9706
|
}
|
|
@@ -10246,7 +10248,10 @@ function expandFxItem(view, node, epochNowMs, dim) {
|
|
|
10246
10248
|
anchor: "center",
|
|
10247
10249
|
width: spriteSize,
|
|
10248
10250
|
height: spriteSize,
|
|
10249
|
-
opacity: fade
|
|
10251
|
+
opacity: fade,
|
|
10252
|
+
animation: view.animation ?? sprite.animations?.[0],
|
|
10253
|
+
// One-shot fx rows (burst) play from the item's birth, not wall-time.
|
|
10254
|
+
clockMs: ageMs
|
|
10250
10255
|
});
|
|
10251
10256
|
} else {
|
|
10252
10257
|
out.push(...proceduralShapes(view, pos, fade, progress));
|
|
@@ -11826,6 +11831,7 @@ var init_GameShell = __esm({
|
|
|
11826
11831
|
init_Typography();
|
|
11827
11832
|
init_AtlasImage();
|
|
11828
11833
|
GAME_FONTS = {
|
|
11834
|
+
fredoka: "Fredoka",
|
|
11829
11835
|
future: "Kenney Future",
|
|
11830
11836
|
"future-narrow": "Kenney Future Narrow",
|
|
11831
11837
|
pixel: "Kenney Pixel",
|
|
@@ -11842,10 +11848,10 @@ var init_GameShell = __esm({
|
|
|
11842
11848
|
showTopBar = true,
|
|
11843
11849
|
children,
|
|
11844
11850
|
backgroundAsset,
|
|
11845
|
-
fontFamily
|
|
11851
|
+
fontFamily,
|
|
11846
11852
|
"data-theme": dataTheme
|
|
11847
11853
|
}) => {
|
|
11848
|
-
const font = GAME_FONTS[fontFamily] ?? fontFamily;
|
|
11854
|
+
const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
|
|
11849
11855
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11850
11856
|
Box,
|
|
11851
11857
|
{
|
|
@@ -11860,8 +11866,11 @@ var init_GameShell = __esm({
|
|
|
11860
11866
|
color: "var(--color-foreground, #e0e0e0)",
|
|
11861
11867
|
// The fontFamily knob is a scoped override of the theme contract's
|
|
11862
11868
|
// display slot: titles/numerics take the game face, body text keeps
|
|
11863
|
-
// the active theme's --font-family-body.
|
|
11864
|
-
|
|
11869
|
+
// the active theme's --font-family-body. Set ONLY when explicitly
|
|
11870
|
+
// passed — an always-on inline stamp would shadow the orbital's
|
|
11871
|
+
// inline-theme font-family-display token (inline style beats the
|
|
11872
|
+
// theme provider's vars for the whole shell subtree).
|
|
11873
|
+
...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
|
|
11865
11874
|
},
|
|
11866
11875
|
children: [
|
|
11867
11876
|
backgroundAsset && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -12325,6 +12334,16 @@ function traceShapes(panel, k, width, height) {
|
|
|
12325
12334
|
}
|
|
12326
12335
|
return out;
|
|
12327
12336
|
}
|
|
12337
|
+
function drawableNeedsAnimation(nodes) {
|
|
12338
|
+
if (!nodes) return false;
|
|
12339
|
+
return nodes.some((node) => {
|
|
12340
|
+
if (node.type === "draw-sprite") return node.animation !== void 0;
|
|
12341
|
+
if (node.type === "draw-fx-layer") return Array.isArray(node.items) && node.items.length > 0;
|
|
12342
|
+
if (node.type === "draw-sprite-layer") return Array.isArray(node.items) && node.items.some((it) => it.animation !== void 0);
|
|
12343
|
+
if (node.type === "draw-group") return Array.isArray(node.items) && drawableNeedsAnimation(node.items);
|
|
12344
|
+
return false;
|
|
12345
|
+
});
|
|
12346
|
+
}
|
|
12328
12347
|
var DASH_PATTERNS, TRACE_SERIES_COLORS, LearningCanvas;
|
|
12329
12348
|
var init_LearningCanvas = __esm({
|
|
12330
12349
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
@@ -12332,6 +12351,8 @@ var init_LearningCanvas = __esm({
|
|
|
12332
12351
|
init_cn();
|
|
12333
12352
|
init_perf();
|
|
12334
12353
|
init_useEventBus();
|
|
12354
|
+
init_webPainter2d();
|
|
12355
|
+
init_paintDispatch();
|
|
12335
12356
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12336
12357
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
12337
12358
|
LearningCanvas = ({
|
|
@@ -12340,6 +12361,8 @@ var init_LearningCanvas = __esm({
|
|
|
12340
12361
|
height = 400,
|
|
12341
12362
|
backgroundColor,
|
|
12342
12363
|
shapes = [],
|
|
12364
|
+
drawables,
|
|
12365
|
+
projector,
|
|
12343
12366
|
readouts,
|
|
12344
12367
|
traces,
|
|
12345
12368
|
interactive = false,
|
|
@@ -12353,6 +12376,9 @@ var init_LearningCanvas = __esm({
|
|
|
12353
12376
|
const eventBus = useEventBus();
|
|
12354
12377
|
const animRef = React85.useRef(0);
|
|
12355
12378
|
const hoverIndexRef = React85.useRef(-1);
|
|
12379
|
+
const [drawVersion, setDrawVersion] = React85.useState(0);
|
|
12380
|
+
const invalidateRef = React85.useRef(() => setDrawVersion((v) => v + 1));
|
|
12381
|
+
const needsAnim = React85.useMemo(() => drawableNeedsAnimation(drawables), [drawables]);
|
|
12356
12382
|
const findShapeAt = React85.useCallback((clientX, clientY) => {
|
|
12357
12383
|
const canvas = canvasRef.current;
|
|
12358
12384
|
if (!canvas) return -1;
|
|
@@ -12396,20 +12422,29 @@ var init_LearningCanvas = __esm({
|
|
|
12396
12422
|
for (const shape of derivedShapes) {
|
|
12397
12423
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12398
12424
|
}
|
|
12425
|
+
if (drawables?.length && projector) {
|
|
12426
|
+
const painter = createWebPainter(ctx, invalidateRef.current);
|
|
12427
|
+
const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
|
|
12428
|
+
const dctx = { projector, time: timeMs, invalidate: invalidateRef.current };
|
|
12429
|
+
for (const node of drawables) {
|
|
12430
|
+
paintDrawable(painter, node, dctx);
|
|
12431
|
+
}
|
|
12432
|
+
}
|
|
12399
12433
|
ui.perfEnd("learningcanvas:paint", _perfT);
|
|
12400
|
-
}, [width, height, backgroundColor, derivedShapes]);
|
|
12434
|
+
}, [width, height, backgroundColor, derivedShapes, drawables, projector, needsAnim]);
|
|
12401
12435
|
React85.useEffect(() => {
|
|
12402
12436
|
draw();
|
|
12403
|
-
}, [draw]);
|
|
12437
|
+
}, [draw, drawVersion]);
|
|
12404
12438
|
React85.useEffect(() => {
|
|
12405
|
-
|
|
12439
|
+
const shouldAnimate = animate || needsAnim;
|
|
12440
|
+
if (!shouldAnimate) return;
|
|
12406
12441
|
const loop = () => {
|
|
12407
12442
|
draw();
|
|
12408
12443
|
animRef.current = requestAnimationFrame(loop);
|
|
12409
12444
|
};
|
|
12410
12445
|
animRef.current = requestAnimationFrame(loop);
|
|
12411
12446
|
return () => cancelAnimationFrame(animRef.current);
|
|
12412
|
-
}, [animate, draw]);
|
|
12447
|
+
}, [animate, needsAnim, draw]);
|
|
12413
12448
|
const handlePointerMove = React85.useCallback(
|
|
12414
12449
|
(e) => {
|
|
12415
12450
|
if (!interactive) return;
|
|
@@ -24537,8 +24572,9 @@ var init_DashboardLayout = __esm({
|
|
|
24537
24572
|
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
24538
24573
|
if (onNotificationClick) onNotificationClick();
|
|
24539
24574
|
};
|
|
24540
|
-
const handleTopBarActionClick = (
|
|
24541
|
-
eventBus.emit(`UI:${event}`, {});
|
|
24575
|
+
const handleTopBarActionClick = (action) => {
|
|
24576
|
+
if (action.event) eventBus.emit(`UI:${action.event}`, {});
|
|
24577
|
+
if (action.navigatesTo) eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
|
|
24542
24578
|
};
|
|
24543
24579
|
const [sidebarOpen, setSidebarOpen] = React85.useState(false);
|
|
24544
24580
|
const [userMenuOpen, setUserMenuOpen] = React85.useState(false);
|
|
@@ -24753,7 +24789,7 @@ var init_DashboardLayout = __esm({
|
|
|
24753
24789
|
{
|
|
24754
24790
|
variant: "ghost",
|
|
24755
24791
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
24756
|
-
onClick: () => handleTopBarActionClick(action
|
|
24792
|
+
onClick: () => handleTopBarActionClick(action),
|
|
24757
24793
|
"aria-label": action.label ?? (typeof action.icon === "string" ? action.icon : void 0),
|
|
24758
24794
|
children: [
|
|
24759
24795
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
@@ -24770,7 +24806,7 @@ var init_DashboardLayout = __esm({
|
|
|
24770
24806
|
)
|
|
24771
24807
|
]
|
|
24772
24808
|
},
|
|
24773
|
-
`${action.event}-${idx}`
|
|
24809
|
+
`${action.event ?? action.navigatesTo ?? "action"}-${idx}`
|
|
24774
24810
|
)),
|
|
24775
24811
|
notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24776
24812
|
Button,
|
|
@@ -30368,6 +30404,7 @@ var init_MathCanvas = __esm({
|
|
|
30368
30404
|
angles = [],
|
|
30369
30405
|
hops = [],
|
|
30370
30406
|
shapes = [],
|
|
30407
|
+
drawables,
|
|
30371
30408
|
readouts,
|
|
30372
30409
|
traces,
|
|
30373
30410
|
interactive = false,
|
|
@@ -30674,6 +30711,42 @@ var init_MathCanvas = __esm({
|
|
|
30674
30711
|
hops,
|
|
30675
30712
|
shapes
|
|
30676
30713
|
]);
|
|
30714
|
+
const projector = React85.useMemo(() => {
|
|
30715
|
+
if (!drawables?.length) return void 0;
|
|
30716
|
+
const margin = 24;
|
|
30717
|
+
const plotW = width - margin * 2;
|
|
30718
|
+
const plotH = height - margin * 2;
|
|
30719
|
+
const xScale = plotW / (xMax - xMin);
|
|
30720
|
+
const mapX = (x) => margin + (x - xMin) / (xMax - xMin) * plotW;
|
|
30721
|
+
const mapY = (y) => height - (margin + (y - yMin) / (yMax - yMin) * plotH);
|
|
30722
|
+
const project = (pos) => ({ x: mapX(pos.x), y: mapY(pos.y) });
|
|
30723
|
+
const anchorPoint = (pos, anchor) => {
|
|
30724
|
+
const base = project(pos);
|
|
30725
|
+
if (anchor === "top-left") return base;
|
|
30726
|
+
const cx = base.x + xScale / 2;
|
|
30727
|
+
if (anchor === "ground") return { x: cx, y: base.y + xScale * 0.92 };
|
|
30728
|
+
return { x: cx, y: base.y + xScale / 2 };
|
|
30729
|
+
};
|
|
30730
|
+
const cellPath = (pos) => {
|
|
30731
|
+
const base = project(pos);
|
|
30732
|
+
return [
|
|
30733
|
+
{ x: base.x, y: base.y },
|
|
30734
|
+
{ x: base.x + xScale, y: base.y },
|
|
30735
|
+
{ x: base.x + xScale, y: base.y + xScale },
|
|
30736
|
+
{ x: base.x, y: base.y + xScale }
|
|
30737
|
+
];
|
|
30738
|
+
};
|
|
30739
|
+
return {
|
|
30740
|
+
project,
|
|
30741
|
+
anchorPoint,
|
|
30742
|
+
cellPath,
|
|
30743
|
+
tileWidth: xScale,
|
|
30744
|
+
floorHeight: xScale / 2,
|
|
30745
|
+
diamondTopY: 0,
|
|
30746
|
+
squareGrid: true,
|
|
30747
|
+
worldPixelDirect: false
|
|
30748
|
+
};
|
|
30749
|
+
}, [drawables?.length, width, height, xMin, xMax, yMin, yMax]);
|
|
30677
30750
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
30678
30751
|
title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
|
|
30679
30752
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -30683,6 +30756,8 @@ var init_MathCanvas = __esm({
|
|
|
30683
30756
|
height,
|
|
30684
30757
|
backgroundColor,
|
|
30685
30758
|
shapes: derivedShapes,
|
|
30759
|
+
drawables,
|
|
30760
|
+
projector,
|
|
30686
30761
|
readouts,
|
|
30687
30762
|
traces,
|
|
30688
30763
|
interactive,
|
|
@@ -31912,7 +31987,7 @@ var init_MapView = __esm({
|
|
|
31912
31987
|
shadowSize: [41, 41]
|
|
31913
31988
|
});
|
|
31914
31989
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
31915
|
-
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState:
|
|
31990
|
+
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState: useState95 } = React85__namespace.default;
|
|
31916
31991
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
31917
31992
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
31918
31993
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -31957,7 +32032,7 @@ var init_MapView = __esm({
|
|
|
31957
32032
|
showAttribution = true
|
|
31958
32033
|
}) {
|
|
31959
32034
|
const eventBus = useEventBus2();
|
|
31960
|
-
const [clickedPosition, setClickedPosition] =
|
|
32035
|
+
const [clickedPosition, setClickedPosition] = useState95(null);
|
|
31961
32036
|
const handleMapClick = useCallback90((lat, lng) => {
|
|
31962
32037
|
if (showClickedPin) {
|
|
31963
32038
|
setClickedPosition({ lat, lng });
|