@almadar/ui 6.0.0 → 6.2.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 +104 -22
- package/dist/avl/index.d.cts +3 -3
- package/dist/avl/index.d.ts +3 -3
- package/dist/avl/index.js +105 -23
- package/dist/{avl-schema-parser-Do_LPV1o.d.cts → avl-schema-parser-Bt4NzAam.d.cts} +4 -4
- package/dist/{avl-schema-parser-CLIm28Wa.d.ts → avl-schema-parser-dvJKXn-o.d.ts} +4 -4
- 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 +9792 -9709
- package/dist/components/index.d.cts +213 -80
- package/dist/components/index.d.ts +213 -80
- package/dist/components/index.js +9678 -9595
- 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 +104 -22
- package/dist/providers/index.js +105 -23
- package/dist/runtime/index.cjs +104 -22
- package/dist/runtime/index.js +105 -23
- 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';
|
|
@@ -3240,9 +3240,16 @@ var init_Input = __esm({
|
|
|
3240
3240
|
}
|
|
3241
3241
|
};
|
|
3242
3242
|
const handleKeyDown = (e) => {
|
|
3243
|
-
if (action
|
|
3244
|
-
|
|
3243
|
+
if (!action || e.key !== "Enter") return;
|
|
3244
|
+
const raw = e.currentTarget.value;
|
|
3245
|
+
if (type === "number") {
|
|
3246
|
+
if (raw.trim() === "") return;
|
|
3247
|
+
const numeric = Number(raw);
|
|
3248
|
+
if (Number.isNaN(numeric)) return;
|
|
3249
|
+
eventBus.emit(`UI:${action}`, { value: numeric });
|
|
3250
|
+
return;
|
|
3245
3251
|
}
|
|
3252
|
+
eventBus.emit(`UI:${action}`, { value: raw });
|
|
3246
3253
|
};
|
|
3247
3254
|
const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
|
|
3248
3255
|
label && /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
|
|
@@ -5800,6 +5807,7 @@ function resolveFxView(item, presets) {
|
|
|
5800
5807
|
vy: item.vy ?? row.vy,
|
|
5801
5808
|
vz: item.vz ?? row.vz,
|
|
5802
5809
|
particleCount: item.particleCount ?? row.particleCount,
|
|
5810
|
+
animation: item.animation ?? row.animation,
|
|
5803
5811
|
shape: row.shape,
|
|
5804
5812
|
count: row.count,
|
|
5805
5813
|
glow: row.glow,
|
|
@@ -7332,9 +7340,6 @@ var init_isometric = __esm({
|
|
|
7332
7340
|
};
|
|
7333
7341
|
}
|
|
7334
7342
|
});
|
|
7335
|
-
function isAnimationName(name) {
|
|
7336
|
-
return ANIMATION_NAMES.includes(name);
|
|
7337
|
-
}
|
|
7338
7343
|
function frameRect(frame, row, columns, frameWidth, frameHeight) {
|
|
7339
7344
|
return {
|
|
7340
7345
|
sx: frame % columns * frameWidth,
|
|
@@ -9268,13 +9273,17 @@ var init_DrawSprite = __esm({
|
|
|
9268
9273
|
return;
|
|
9269
9274
|
}
|
|
9270
9275
|
if (isSpriteSheetAtlas(atlas)) {
|
|
9271
|
-
const def =
|
|
9276
|
+
const def = atlas.animations[node.animation];
|
|
9272
9277
|
if (!def) {
|
|
9273
9278
|
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9274
9279
|
return;
|
|
9275
9280
|
}
|
|
9276
|
-
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, dctx.time);
|
|
9281
|
+
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, node.clockMs ?? dctx.time);
|
|
9277
9282
|
const r = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
|
|
9283
|
+
if (![r.sx, r.sy, r.sw, r.sh].every(Number.isFinite)) {
|
|
9284
|
+
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9285
|
+
return;
|
|
9286
|
+
}
|
|
9278
9287
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9279
9288
|
}
|
|
9280
9289
|
}
|
|
@@ -9822,7 +9831,10 @@ function expandFxItem(view, node, epochNowMs, dim) {
|
|
|
9822
9831
|
anchor: "center",
|
|
9823
9832
|
width: spriteSize,
|
|
9824
9833
|
height: spriteSize,
|
|
9825
|
-
opacity: fade
|
|
9834
|
+
opacity: fade,
|
|
9835
|
+
animation: view.animation ?? sprite.animations?.[0],
|
|
9836
|
+
// One-shot fx rows (burst) play from the item's birth, not wall-time.
|
|
9837
|
+
clockMs: ageMs
|
|
9826
9838
|
});
|
|
9827
9839
|
} else {
|
|
9828
9840
|
out.push(...proceduralShapes(view, pos, fade, progress));
|
|
@@ -11669,6 +11681,7 @@ var init_GameShell = __esm({
|
|
|
11669
11681
|
init_Typography();
|
|
11670
11682
|
init_AtlasImage();
|
|
11671
11683
|
GAME_FONTS = {
|
|
11684
|
+
fredoka: "Fredoka",
|
|
11672
11685
|
future: "Kenney Future",
|
|
11673
11686
|
"future-narrow": "Kenney Future Narrow",
|
|
11674
11687
|
pixel: "Kenney Pixel",
|
|
@@ -11685,10 +11698,10 @@ var init_GameShell = __esm({
|
|
|
11685
11698
|
showTopBar = true,
|
|
11686
11699
|
children,
|
|
11687
11700
|
backgroundAsset,
|
|
11688
|
-
fontFamily
|
|
11701
|
+
fontFamily,
|
|
11689
11702
|
"data-theme": dataTheme
|
|
11690
11703
|
}) => {
|
|
11691
|
-
const font = GAME_FONTS[fontFamily] ?? fontFamily;
|
|
11704
|
+
const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
|
|
11692
11705
|
return /* @__PURE__ */ jsxs(
|
|
11693
11706
|
Box,
|
|
11694
11707
|
{
|
|
@@ -11703,8 +11716,11 @@ var init_GameShell = __esm({
|
|
|
11703
11716
|
color: "var(--color-foreground, #e0e0e0)",
|
|
11704
11717
|
// The fontFamily knob is a scoped override of the theme contract's
|
|
11705
11718
|
// display slot: titles/numerics take the game face, body text keeps
|
|
11706
|
-
// the active theme's --font-family-body.
|
|
11707
|
-
|
|
11719
|
+
// the active theme's --font-family-body. Set ONLY when explicitly
|
|
11720
|
+
// passed — an always-on inline stamp would shadow the orbital's
|
|
11721
|
+
// inline-theme font-family-display token (inline style beats the
|
|
11722
|
+
// theme provider's vars for the whole shell subtree).
|
|
11723
|
+
...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
|
|
11708
11724
|
},
|
|
11709
11725
|
children: [
|
|
11710
11726
|
backgroundAsset && /* @__PURE__ */ jsx(
|
|
@@ -12172,6 +12188,16 @@ function traceShapes(panel, k, width, height) {
|
|
|
12172
12188
|
}
|
|
12173
12189
|
return out;
|
|
12174
12190
|
}
|
|
12191
|
+
function drawableNeedsAnimation(nodes) {
|
|
12192
|
+
if (!nodes) return false;
|
|
12193
|
+
return nodes.some((node) => {
|
|
12194
|
+
if (node.type === "draw-sprite") return node.animation !== void 0;
|
|
12195
|
+
if (node.type === "draw-fx-layer") return Array.isArray(node.items) && node.items.length > 0;
|
|
12196
|
+
if (node.type === "draw-sprite-layer") return Array.isArray(node.items) && node.items.some((it) => it.animation !== void 0);
|
|
12197
|
+
if (node.type === "draw-group") return Array.isArray(node.items) && drawableNeedsAnimation(node.items);
|
|
12198
|
+
return false;
|
|
12199
|
+
});
|
|
12200
|
+
}
|
|
12175
12201
|
var DASH_PATTERNS, TRACE_SERIES_COLORS, LearningCanvas;
|
|
12176
12202
|
var init_LearningCanvas = __esm({
|
|
12177
12203
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
@@ -12179,6 +12205,8 @@ var init_LearningCanvas = __esm({
|
|
|
12179
12205
|
init_cn();
|
|
12180
12206
|
init_perf();
|
|
12181
12207
|
init_useEventBus();
|
|
12208
|
+
init_webPainter2d();
|
|
12209
|
+
init_paintDispatch();
|
|
12182
12210
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12183
12211
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
12184
12212
|
LearningCanvas = ({
|
|
@@ -12187,6 +12215,8 @@ var init_LearningCanvas = __esm({
|
|
|
12187
12215
|
height = 400,
|
|
12188
12216
|
backgroundColor,
|
|
12189
12217
|
shapes = [],
|
|
12218
|
+
drawables,
|
|
12219
|
+
projector,
|
|
12190
12220
|
readouts,
|
|
12191
12221
|
traces,
|
|
12192
12222
|
interactive = false,
|
|
@@ -12200,6 +12230,9 @@ var init_LearningCanvas = __esm({
|
|
|
12200
12230
|
const eventBus = useEventBus();
|
|
12201
12231
|
const animRef = useRef(0);
|
|
12202
12232
|
const hoverIndexRef = useRef(-1);
|
|
12233
|
+
const [drawVersion, setDrawVersion] = useState(0);
|
|
12234
|
+
const invalidateRef = useRef(() => setDrawVersion((v) => v + 1));
|
|
12235
|
+
const needsAnim = useMemo(() => drawableNeedsAnimation(drawables), [drawables]);
|
|
12203
12236
|
const findShapeAt = useCallback((clientX, clientY) => {
|
|
12204
12237
|
const canvas = canvasRef.current;
|
|
12205
12238
|
if (!canvas) return -1;
|
|
@@ -12243,20 +12276,29 @@ var init_LearningCanvas = __esm({
|
|
|
12243
12276
|
for (const shape of derivedShapes) {
|
|
12244
12277
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12245
12278
|
}
|
|
12279
|
+
if (drawables?.length && projector) {
|
|
12280
|
+
const painter = createWebPainter(ctx, invalidateRef.current);
|
|
12281
|
+
const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
|
|
12282
|
+
const dctx = { projector, time: timeMs, invalidate: invalidateRef.current };
|
|
12283
|
+
for (const node of drawables) {
|
|
12284
|
+
paintDrawable(painter, node, dctx);
|
|
12285
|
+
}
|
|
12286
|
+
}
|
|
12246
12287
|
perfEnd("learningcanvas:paint", _perfT);
|
|
12247
|
-
}, [width, height, backgroundColor, derivedShapes]);
|
|
12288
|
+
}, [width, height, backgroundColor, derivedShapes, drawables, projector, needsAnim]);
|
|
12248
12289
|
useEffect(() => {
|
|
12249
12290
|
draw();
|
|
12250
|
-
}, [draw]);
|
|
12291
|
+
}, [draw, drawVersion]);
|
|
12251
12292
|
useEffect(() => {
|
|
12252
|
-
|
|
12293
|
+
const shouldAnimate = animate || needsAnim;
|
|
12294
|
+
if (!shouldAnimate) return;
|
|
12253
12295
|
const loop = () => {
|
|
12254
12296
|
draw();
|
|
12255
12297
|
animRef.current = requestAnimationFrame(loop);
|
|
12256
12298
|
};
|
|
12257
12299
|
animRef.current = requestAnimationFrame(loop);
|
|
12258
12300
|
return () => cancelAnimationFrame(animRef.current);
|
|
12259
|
-
}, [animate, draw]);
|
|
12301
|
+
}, [animate, needsAnim, draw]);
|
|
12260
12302
|
const handlePointerMove = useCallback(
|
|
12261
12303
|
(e) => {
|
|
12262
12304
|
if (!interactive) return;
|
|
@@ -24898,8 +24940,9 @@ var init_DashboardLayout = __esm({
|
|
|
24898
24940
|
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
24899
24941
|
if (onNotificationClick) onNotificationClick();
|
|
24900
24942
|
};
|
|
24901
|
-
const handleTopBarActionClick = (
|
|
24902
|
-
eventBus.emit(`UI:${event}`, {});
|
|
24943
|
+
const handleTopBarActionClick = (action) => {
|
|
24944
|
+
if (action.event) eventBus.emit(`UI:${action.event}`, {});
|
|
24945
|
+
if (action.navigatesTo) eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
|
|
24903
24946
|
};
|
|
24904
24947
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
24905
24948
|
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
|
@@ -25114,7 +25157,7 @@ var init_DashboardLayout = __esm({
|
|
|
25114
25157
|
{
|
|
25115
25158
|
variant: "ghost",
|
|
25116
25159
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
25117
|
-
onClick: () => handleTopBarActionClick(action
|
|
25160
|
+
onClick: () => handleTopBarActionClick(action),
|
|
25118
25161
|
"aria-label": action.label ?? (typeof action.icon === "string" ? action.icon : void 0),
|
|
25119
25162
|
children: [
|
|
25120
25163
|
/* @__PURE__ */ jsx(Icon, { icon: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
@@ -25131,7 +25174,7 @@ var init_DashboardLayout = __esm({
|
|
|
25131
25174
|
)
|
|
25132
25175
|
]
|
|
25133
25176
|
},
|
|
25134
|
-
`${action.event}-${idx}`
|
|
25177
|
+
`${action.event ?? action.navigatesTo ?? "action"}-${idx}`
|
|
25135
25178
|
)),
|
|
25136
25179
|
notificationsEnabled && /* @__PURE__ */ jsxs(
|
|
25137
25180
|
Button,
|
|
@@ -30793,6 +30836,7 @@ var init_MathCanvas = __esm({
|
|
|
30793
30836
|
angles = [],
|
|
30794
30837
|
hops = [],
|
|
30795
30838
|
shapes = [],
|
|
30839
|
+
drawables,
|
|
30796
30840
|
readouts,
|
|
30797
30841
|
traces,
|
|
30798
30842
|
interactive = false,
|
|
@@ -31099,6 +31143,42 @@ var init_MathCanvas = __esm({
|
|
|
31099
31143
|
hops,
|
|
31100
31144
|
shapes
|
|
31101
31145
|
]);
|
|
31146
|
+
const projector = useMemo(() => {
|
|
31147
|
+
if (!drawables?.length) return void 0;
|
|
31148
|
+
const margin = 24;
|
|
31149
|
+
const plotW = width - margin * 2;
|
|
31150
|
+
const plotH = height - margin * 2;
|
|
31151
|
+
const xScale = plotW / (xMax - xMin);
|
|
31152
|
+
const mapX = (x) => margin + (x - xMin) / (xMax - xMin) * plotW;
|
|
31153
|
+
const mapY = (y) => height - (margin + (y - yMin) / (yMax - yMin) * plotH);
|
|
31154
|
+
const project = (pos) => ({ x: mapX(pos.x), y: mapY(pos.y) });
|
|
31155
|
+
const anchorPoint = (pos, anchor) => {
|
|
31156
|
+
const base = project(pos);
|
|
31157
|
+
if (anchor === "top-left") return base;
|
|
31158
|
+
const cx = base.x + xScale / 2;
|
|
31159
|
+
if (anchor === "ground") return { x: cx, y: base.y + xScale * 0.92 };
|
|
31160
|
+
return { x: cx, y: base.y + xScale / 2 };
|
|
31161
|
+
};
|
|
31162
|
+
const cellPath = (pos) => {
|
|
31163
|
+
const base = project(pos);
|
|
31164
|
+
return [
|
|
31165
|
+
{ x: base.x, y: base.y },
|
|
31166
|
+
{ x: base.x + xScale, y: base.y },
|
|
31167
|
+
{ x: base.x + xScale, y: base.y + xScale },
|
|
31168
|
+
{ x: base.x, y: base.y + xScale }
|
|
31169
|
+
];
|
|
31170
|
+
};
|
|
31171
|
+
return {
|
|
31172
|
+
project,
|
|
31173
|
+
anchorPoint,
|
|
31174
|
+
cellPath,
|
|
31175
|
+
tileWidth: xScale,
|
|
31176
|
+
floorHeight: xScale / 2,
|
|
31177
|
+
diamondTopY: 0,
|
|
31178
|
+
squareGrid: true,
|
|
31179
|
+
worldPixelDirect: false
|
|
31180
|
+
};
|
|
31181
|
+
}, [drawables?.length, width, height, xMin, xMax, yMin, yMax]);
|
|
31102
31182
|
return /* @__PURE__ */ jsx(Card, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
31103
31183
|
title ? /* @__PURE__ */ jsx(Typography, { variant: "h4", children: title }) : null,
|
|
31104
31184
|
/* @__PURE__ */ jsx(
|
|
@@ -31108,6 +31188,8 @@ var init_MathCanvas = __esm({
|
|
|
31108
31188
|
height,
|
|
31109
31189
|
backgroundColor,
|
|
31110
31190
|
shapes: derivedShapes,
|
|
31191
|
+
drawables,
|
|
31192
|
+
projector,
|
|
31111
31193
|
readouts,
|
|
31112
31194
|
traces,
|
|
31113
31195
|
interactive,
|
|
@@ -32337,7 +32419,7 @@ var init_MapView = __esm({
|
|
|
32337
32419
|
shadowSize: [41, 41]
|
|
32338
32420
|
});
|
|
32339
32421
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32340
|
-
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState:
|
|
32422
|
+
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState: useState98 } = React87__default;
|
|
32341
32423
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32342
32424
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32343
32425
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -32382,7 +32464,7 @@ var init_MapView = __esm({
|
|
|
32382
32464
|
showAttribution = true
|
|
32383
32465
|
}) {
|
|
32384
32466
|
const eventBus = useEventBus2();
|
|
32385
|
-
const [clickedPosition, setClickedPosition] =
|
|
32467
|
+
const [clickedPosition, setClickedPosition] = useState98(null);
|
|
32386
32468
|
const handleMapClick = useCallback97((lat, lng) => {
|
|
32387
32469
|
if (showClickedPin) {
|
|
32388
32470
|
setClickedPosition({ lat, lng });
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -3807,9 +3807,16 @@ var init_Input = __esm({
|
|
|
3807
3807
|
}
|
|
3808
3808
|
};
|
|
3809
3809
|
const handleKeyDown = (e) => {
|
|
3810
|
-
if (action
|
|
3811
|
-
|
|
3810
|
+
if (!action || e.key !== "Enter") return;
|
|
3811
|
+
const raw = e.currentTarget.value;
|
|
3812
|
+
if (type === "number") {
|
|
3813
|
+
if (raw.trim() === "") return;
|
|
3814
|
+
const numeric = Number(raw);
|
|
3815
|
+
if (Number.isNaN(numeric)) return;
|
|
3816
|
+
eventBus.emit(`UI:${action}`, { value: numeric });
|
|
3817
|
+
return;
|
|
3812
3818
|
}
|
|
3819
|
+
eventBus.emit(`UI:${action}`, { value: raw });
|
|
3813
3820
|
};
|
|
3814
3821
|
const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
|
|
3815
3822
|
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
|
|
@@ -6332,6 +6339,7 @@ function resolveFxView(item, presets) {
|
|
|
6332
6339
|
vy: item.vy ?? row.vy,
|
|
6333
6340
|
vz: item.vz ?? row.vz,
|
|
6334
6341
|
particleCount: item.particleCount ?? row.particleCount,
|
|
6342
|
+
animation: item.animation ?? row.animation,
|
|
6335
6343
|
shape: row.shape,
|
|
6336
6344
|
count: row.count,
|
|
6337
6345
|
glow: row.glow,
|
|
@@ -7863,9 +7871,6 @@ var init_isometric = __esm({
|
|
|
7863
7871
|
};
|
|
7864
7872
|
}
|
|
7865
7873
|
});
|
|
7866
|
-
function isAnimationName(name) {
|
|
7867
|
-
return core.ANIMATION_NAMES.includes(name);
|
|
7868
|
-
}
|
|
7869
7874
|
function frameRect(frame, row, columns, frameWidth, frameHeight) {
|
|
7870
7875
|
return {
|
|
7871
7876
|
sx: frame % columns * frameWidth,
|
|
@@ -9692,13 +9697,17 @@ var init_DrawSprite = __esm({
|
|
|
9692
9697
|
return;
|
|
9693
9698
|
}
|
|
9694
9699
|
if (isSpriteSheetAtlas(atlas)) {
|
|
9695
|
-
const def =
|
|
9700
|
+
const def = atlas.animations[node.animation];
|
|
9696
9701
|
if (!def) {
|
|
9697
9702
|
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9698
9703
|
return;
|
|
9699
9704
|
}
|
|
9700
|
-
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, dctx.time);
|
|
9705
|
+
const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, node.clockMs ?? dctx.time);
|
|
9701
9706
|
const r = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
|
|
9707
|
+
if (![r.sx, r.sy, r.sw, r.sh].every(Number.isFinite)) {
|
|
9708
|
+
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9709
|
+
return;
|
|
9710
|
+
}
|
|
9702
9711
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9703
9712
|
}
|
|
9704
9713
|
}
|
|
@@ -10246,7 +10255,10 @@ function expandFxItem(view, node, epochNowMs, dim) {
|
|
|
10246
10255
|
anchor: "center",
|
|
10247
10256
|
width: spriteSize,
|
|
10248
10257
|
height: spriteSize,
|
|
10249
|
-
opacity: fade
|
|
10258
|
+
opacity: fade,
|
|
10259
|
+
animation: view.animation ?? sprite.animations?.[0],
|
|
10260
|
+
// One-shot fx rows (burst) play from the item's birth, not wall-time.
|
|
10261
|
+
clockMs: ageMs
|
|
10250
10262
|
});
|
|
10251
10263
|
} else {
|
|
10252
10264
|
out.push(...proceduralShapes(view, pos, fade, progress));
|
|
@@ -11826,6 +11838,7 @@ var init_GameShell = __esm({
|
|
|
11826
11838
|
init_Typography();
|
|
11827
11839
|
init_AtlasImage();
|
|
11828
11840
|
GAME_FONTS = {
|
|
11841
|
+
fredoka: "Fredoka",
|
|
11829
11842
|
future: "Kenney Future",
|
|
11830
11843
|
"future-narrow": "Kenney Future Narrow",
|
|
11831
11844
|
pixel: "Kenney Pixel",
|
|
@@ -11842,10 +11855,10 @@ var init_GameShell = __esm({
|
|
|
11842
11855
|
showTopBar = true,
|
|
11843
11856
|
children,
|
|
11844
11857
|
backgroundAsset,
|
|
11845
|
-
fontFamily
|
|
11858
|
+
fontFamily,
|
|
11846
11859
|
"data-theme": dataTheme
|
|
11847
11860
|
}) => {
|
|
11848
|
-
const font = GAME_FONTS[fontFamily] ?? fontFamily;
|
|
11861
|
+
const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
|
|
11849
11862
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11850
11863
|
Box,
|
|
11851
11864
|
{
|
|
@@ -11860,8 +11873,11 @@ var init_GameShell = __esm({
|
|
|
11860
11873
|
color: "var(--color-foreground, #e0e0e0)",
|
|
11861
11874
|
// The fontFamily knob is a scoped override of the theme contract's
|
|
11862
11875
|
// display slot: titles/numerics take the game face, body text keeps
|
|
11863
|
-
// the active theme's --font-family-body.
|
|
11864
|
-
|
|
11876
|
+
// the active theme's --font-family-body. Set ONLY when explicitly
|
|
11877
|
+
// passed — an always-on inline stamp would shadow the orbital's
|
|
11878
|
+
// inline-theme font-family-display token (inline style beats the
|
|
11879
|
+
// theme provider's vars for the whole shell subtree).
|
|
11880
|
+
...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
|
|
11865
11881
|
},
|
|
11866
11882
|
children: [
|
|
11867
11883
|
backgroundAsset && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -12325,6 +12341,16 @@ function traceShapes(panel, k, width, height) {
|
|
|
12325
12341
|
}
|
|
12326
12342
|
return out;
|
|
12327
12343
|
}
|
|
12344
|
+
function drawableNeedsAnimation(nodes) {
|
|
12345
|
+
if (!nodes) return false;
|
|
12346
|
+
return nodes.some((node) => {
|
|
12347
|
+
if (node.type === "draw-sprite") return node.animation !== void 0;
|
|
12348
|
+
if (node.type === "draw-fx-layer") return Array.isArray(node.items) && node.items.length > 0;
|
|
12349
|
+
if (node.type === "draw-sprite-layer") return Array.isArray(node.items) && node.items.some((it) => it.animation !== void 0);
|
|
12350
|
+
if (node.type === "draw-group") return Array.isArray(node.items) && drawableNeedsAnimation(node.items);
|
|
12351
|
+
return false;
|
|
12352
|
+
});
|
|
12353
|
+
}
|
|
12328
12354
|
var DASH_PATTERNS, TRACE_SERIES_COLORS, LearningCanvas;
|
|
12329
12355
|
var init_LearningCanvas = __esm({
|
|
12330
12356
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
@@ -12332,6 +12358,8 @@ var init_LearningCanvas = __esm({
|
|
|
12332
12358
|
init_cn();
|
|
12333
12359
|
init_perf();
|
|
12334
12360
|
init_useEventBus();
|
|
12361
|
+
init_webPainter2d();
|
|
12362
|
+
init_paintDispatch();
|
|
12335
12363
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12336
12364
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
12337
12365
|
LearningCanvas = ({
|
|
@@ -12340,6 +12368,8 @@ var init_LearningCanvas = __esm({
|
|
|
12340
12368
|
height = 400,
|
|
12341
12369
|
backgroundColor,
|
|
12342
12370
|
shapes = [],
|
|
12371
|
+
drawables,
|
|
12372
|
+
projector,
|
|
12343
12373
|
readouts,
|
|
12344
12374
|
traces,
|
|
12345
12375
|
interactive = false,
|
|
@@ -12353,6 +12383,9 @@ var init_LearningCanvas = __esm({
|
|
|
12353
12383
|
const eventBus = useEventBus();
|
|
12354
12384
|
const animRef = React85.useRef(0);
|
|
12355
12385
|
const hoverIndexRef = React85.useRef(-1);
|
|
12386
|
+
const [drawVersion, setDrawVersion] = React85.useState(0);
|
|
12387
|
+
const invalidateRef = React85.useRef(() => setDrawVersion((v) => v + 1));
|
|
12388
|
+
const needsAnim = React85.useMemo(() => drawableNeedsAnimation(drawables), [drawables]);
|
|
12356
12389
|
const findShapeAt = React85.useCallback((clientX, clientY) => {
|
|
12357
12390
|
const canvas = canvasRef.current;
|
|
12358
12391
|
if (!canvas) return -1;
|
|
@@ -12396,20 +12429,29 @@ var init_LearningCanvas = __esm({
|
|
|
12396
12429
|
for (const shape of derivedShapes) {
|
|
12397
12430
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12398
12431
|
}
|
|
12432
|
+
if (drawables?.length && projector) {
|
|
12433
|
+
const painter = createWebPainter(ctx, invalidateRef.current);
|
|
12434
|
+
const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
|
|
12435
|
+
const dctx = { projector, time: timeMs, invalidate: invalidateRef.current };
|
|
12436
|
+
for (const node of drawables) {
|
|
12437
|
+
paintDrawable(painter, node, dctx);
|
|
12438
|
+
}
|
|
12439
|
+
}
|
|
12399
12440
|
ui.perfEnd("learningcanvas:paint", _perfT);
|
|
12400
|
-
}, [width, height, backgroundColor, derivedShapes]);
|
|
12441
|
+
}, [width, height, backgroundColor, derivedShapes, drawables, projector, needsAnim]);
|
|
12401
12442
|
React85.useEffect(() => {
|
|
12402
12443
|
draw();
|
|
12403
|
-
}, [draw]);
|
|
12444
|
+
}, [draw, drawVersion]);
|
|
12404
12445
|
React85.useEffect(() => {
|
|
12405
|
-
|
|
12446
|
+
const shouldAnimate = animate || needsAnim;
|
|
12447
|
+
if (!shouldAnimate) return;
|
|
12406
12448
|
const loop = () => {
|
|
12407
12449
|
draw();
|
|
12408
12450
|
animRef.current = requestAnimationFrame(loop);
|
|
12409
12451
|
};
|
|
12410
12452
|
animRef.current = requestAnimationFrame(loop);
|
|
12411
12453
|
return () => cancelAnimationFrame(animRef.current);
|
|
12412
|
-
}, [animate, draw]);
|
|
12454
|
+
}, [animate, needsAnim, draw]);
|
|
12413
12455
|
const handlePointerMove = React85.useCallback(
|
|
12414
12456
|
(e) => {
|
|
12415
12457
|
if (!interactive) return;
|
|
@@ -24537,8 +24579,9 @@ var init_DashboardLayout = __esm({
|
|
|
24537
24579
|
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
24538
24580
|
if (onNotificationClick) onNotificationClick();
|
|
24539
24581
|
};
|
|
24540
|
-
const handleTopBarActionClick = (
|
|
24541
|
-
eventBus.emit(`UI:${event}`, {});
|
|
24582
|
+
const handleTopBarActionClick = (action) => {
|
|
24583
|
+
if (action.event) eventBus.emit(`UI:${action.event}`, {});
|
|
24584
|
+
if (action.navigatesTo) eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
|
|
24542
24585
|
};
|
|
24543
24586
|
const [sidebarOpen, setSidebarOpen] = React85.useState(false);
|
|
24544
24587
|
const [userMenuOpen, setUserMenuOpen] = React85.useState(false);
|
|
@@ -24753,7 +24796,7 @@ var init_DashboardLayout = __esm({
|
|
|
24753
24796
|
{
|
|
24754
24797
|
variant: "ghost",
|
|
24755
24798
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
24756
|
-
onClick: () => handleTopBarActionClick(action
|
|
24799
|
+
onClick: () => handleTopBarActionClick(action),
|
|
24757
24800
|
"aria-label": action.label ?? (typeof action.icon === "string" ? action.icon : void 0),
|
|
24758
24801
|
children: [
|
|
24759
24802
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
@@ -24770,7 +24813,7 @@ var init_DashboardLayout = __esm({
|
|
|
24770
24813
|
)
|
|
24771
24814
|
]
|
|
24772
24815
|
},
|
|
24773
|
-
`${action.event}-${idx}`
|
|
24816
|
+
`${action.event ?? action.navigatesTo ?? "action"}-${idx}`
|
|
24774
24817
|
)),
|
|
24775
24818
|
notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24776
24819
|
Button,
|
|
@@ -30368,6 +30411,7 @@ var init_MathCanvas = __esm({
|
|
|
30368
30411
|
angles = [],
|
|
30369
30412
|
hops = [],
|
|
30370
30413
|
shapes = [],
|
|
30414
|
+
drawables,
|
|
30371
30415
|
readouts,
|
|
30372
30416
|
traces,
|
|
30373
30417
|
interactive = false,
|
|
@@ -30674,6 +30718,42 @@ var init_MathCanvas = __esm({
|
|
|
30674
30718
|
hops,
|
|
30675
30719
|
shapes
|
|
30676
30720
|
]);
|
|
30721
|
+
const projector = React85.useMemo(() => {
|
|
30722
|
+
if (!drawables?.length) return void 0;
|
|
30723
|
+
const margin = 24;
|
|
30724
|
+
const plotW = width - margin * 2;
|
|
30725
|
+
const plotH = height - margin * 2;
|
|
30726
|
+
const xScale = plotW / (xMax - xMin);
|
|
30727
|
+
const mapX = (x) => margin + (x - xMin) / (xMax - xMin) * plotW;
|
|
30728
|
+
const mapY = (y) => height - (margin + (y - yMin) / (yMax - yMin) * plotH);
|
|
30729
|
+
const project = (pos) => ({ x: mapX(pos.x), y: mapY(pos.y) });
|
|
30730
|
+
const anchorPoint = (pos, anchor) => {
|
|
30731
|
+
const base = project(pos);
|
|
30732
|
+
if (anchor === "top-left") return base;
|
|
30733
|
+
const cx = base.x + xScale / 2;
|
|
30734
|
+
if (anchor === "ground") return { x: cx, y: base.y + xScale * 0.92 };
|
|
30735
|
+
return { x: cx, y: base.y + xScale / 2 };
|
|
30736
|
+
};
|
|
30737
|
+
const cellPath = (pos) => {
|
|
30738
|
+
const base = project(pos);
|
|
30739
|
+
return [
|
|
30740
|
+
{ x: base.x, y: base.y },
|
|
30741
|
+
{ x: base.x + xScale, y: base.y },
|
|
30742
|
+
{ x: base.x + xScale, y: base.y + xScale },
|
|
30743
|
+
{ x: base.x, y: base.y + xScale }
|
|
30744
|
+
];
|
|
30745
|
+
};
|
|
30746
|
+
return {
|
|
30747
|
+
project,
|
|
30748
|
+
anchorPoint,
|
|
30749
|
+
cellPath,
|
|
30750
|
+
tileWidth: xScale,
|
|
30751
|
+
floorHeight: xScale / 2,
|
|
30752
|
+
diamondTopY: 0,
|
|
30753
|
+
squareGrid: true,
|
|
30754
|
+
worldPixelDirect: false
|
|
30755
|
+
};
|
|
30756
|
+
}, [drawables?.length, width, height, xMin, xMax, yMin, yMax]);
|
|
30677
30757
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
30678
30758
|
title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
|
|
30679
30759
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -30683,6 +30763,8 @@ var init_MathCanvas = __esm({
|
|
|
30683
30763
|
height,
|
|
30684
30764
|
backgroundColor,
|
|
30685
30765
|
shapes: derivedShapes,
|
|
30766
|
+
drawables,
|
|
30767
|
+
projector,
|
|
30686
30768
|
readouts,
|
|
30687
30769
|
traces,
|
|
30688
30770
|
interactive,
|
|
@@ -31912,7 +31994,7 @@ var init_MapView = __esm({
|
|
|
31912
31994
|
shadowSize: [41, 41]
|
|
31913
31995
|
});
|
|
31914
31996
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
31915
|
-
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState:
|
|
31997
|
+
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState: useState95 } = React85__namespace.default;
|
|
31916
31998
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
31917
31999
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
31918
32000
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -31957,7 +32039,7 @@ var init_MapView = __esm({
|
|
|
31957
32039
|
showAttribution = true
|
|
31958
32040
|
}) {
|
|
31959
32041
|
const eventBus = useEventBus2();
|
|
31960
|
-
const [clickedPosition, setClickedPosition] =
|
|
32042
|
+
const [clickedPosition, setClickedPosition] = useState95(null);
|
|
31961
32043
|
const handleMapClick = useCallback90((lat, lng) => {
|
|
31962
32044
|
if (showClickedPin) {
|
|
31963
32045
|
setClickedPosition({ lat, lng });
|