@almadar/ui 5.77.0 → 5.79.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 +863 -98
- package/dist/avl/index.css +3 -3
- package/dist/avl/index.js +863 -98
- package/dist/components/core/atoms/FlipContainer.d.ts +1 -1
- package/dist/components/core/atoms/index.d.ts +2 -1
- package/dist/components/core/molecules/Card.d.ts +1 -1
- package/dist/components/core/molecules/DataGrid.d.ts +1 -1
- package/dist/components/core/molecules/DataList.d.ts +1 -1
- package/dist/components/core/molecules/DocPagination.d.ts +8 -1
- package/dist/components/core/molecules/DocSearch.d.ts +8 -1
- package/dist/components/core/molecules/FlipCard.d.ts +1 -1
- package/dist/components/core/molecules/MapView.d.ts +18 -1
- package/dist/components/core/molecules/PropertyInspector.d.ts +2 -0
- package/dist/components/core/molecules/SortableList.d.ts +1 -1
- package/dist/components/core/molecules/TableView.d.ts +1 -1
- package/dist/components/core/molecules/index.d.ts +4 -0
- package/dist/components/core/organisms/DataTable.d.ts +1 -1
- package/dist/components/core/organisms/debug/RuntimeDebugger.d.ts +10 -1
- package/dist/components/core/organisms/debug/tabs/EntitiesTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/EventDispatcherTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/EventFlowTab.d.ts +6 -1
- package/dist/components/core/organisms/debug/tabs/GuardsPanel.d.ts +6 -1
- package/dist/components/core/organisms/debug/tabs/ServerBridgeTab.d.ts +12 -1
- package/dist/components/core/organisms/debug/tabs/TicksTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/TraitsTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/TransitionTimeline.d.ts +11 -1
- package/dist/components/core/organisms/debug/tabs/VerificationTab.d.ts +8 -1
- package/dist/components/game/2d/atoms/ActionButton.d.ts +2 -1
- package/dist/components/game/2d/atoms/ChoiceButton.d.ts +2 -1
- package/dist/components/game/2d/atoms/ComboCounter.d.ts +2 -1
- package/dist/components/game/2d/atoms/ControlButton.d.ts +2 -1
- package/dist/components/game/2d/atoms/DamageNumber.d.ts +2 -1
- package/dist/components/game/2d/atoms/DialogueBubble.d.ts +2 -1
- package/dist/components/game/2d/atoms/GameIcon.d.ts +2 -1
- package/dist/components/game/2d/atoms/HealthBar.d.ts +2 -1
- package/dist/components/game/2d/atoms/ItemSlot.d.ts +2 -1
- package/dist/components/game/2d/atoms/MiniMap.d.ts +2 -1
- package/dist/components/game/2d/atoms/ResourceCounter.d.ts +2 -1
- package/dist/components/game/2d/atoms/ScoreDisplay.d.ts +2 -1
- package/dist/components/game/2d/atoms/StatusEffect.d.ts +2 -1
- package/dist/components/game/2d/atoms/TimerDisplay.d.ts +2 -1
- package/dist/components/game/2d/atoms/TurnIndicator.d.ts +2 -1
- package/dist/components/game/2d/atoms/WaypointMarker.d.ts +2 -1
- package/dist/components/game/2d/molecules/GameHud.d.ts +2 -1
- package/dist/components/game/2d/molecules/GameMenu.d.ts +2 -1
- package/dist/components/game/2d/molecules/InventoryGrid.d.ts +2 -1
- package/dist/components/game/2d/molecules/ResourceBar.d.ts +2 -1
- package/dist/components/game/2d/molecules/StatBadge.d.ts +2 -1
- package/dist/components/game/shared/lib/editorUtils.d.ts +8 -8
- package/dist/components/index.cjs +2212 -1525
- package/dist/components/index.css +3 -3
- package/dist/components/index.js +1002 -315
- package/dist/components/learning/atoms/LearningCanvas.d.ts +80 -0
- package/dist/components/learning/molecules/BiologyCanvas.d.ts +47 -0
- package/dist/components/learning/molecules/ChemistryCanvas.d.ts +55 -0
- package/dist/components/learning/molecules/MathCanvas.d.ts +61 -0
- package/dist/components/learning/molecules/PhysicsCanvas.d.ts +54 -0
- package/dist/components/marketing/atoms/MarketingStatCard.d.ts +2 -2
- package/dist/hooks/useGitHub.d.ts +7 -7
- package/dist/marketing/index.cjs +2 -2
- package/dist/marketing/index.js +2 -2
- package/dist/providers/EventBusProvider.d.ts +1 -1
- package/dist/providers/SelectionProvider.d.ts +1 -1
- package/dist/providers/ServerBridge.d.ts +1 -1
- package/dist/providers/index.cjs +859 -94
- package/dist/providers/index.css +3 -3
- package/dist/providers/index.js +859 -94
- package/dist/runtime/index.cjs +859 -94
- package/dist/runtime/index.css +3 -3
- package/dist/runtime/index.js +859 -94
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -630,7 +630,7 @@ var init_AvlFieldType = __esm({
|
|
|
630
630
|
}
|
|
631
631
|
});
|
|
632
632
|
|
|
633
|
-
// node_modules/clsx/dist/clsx.mjs
|
|
633
|
+
// node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
634
634
|
function r(e) {
|
|
635
635
|
var t, f3, n = "";
|
|
636
636
|
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
@@ -645,11 +645,11 @@ function clsx() {
|
|
|
645
645
|
return n;
|
|
646
646
|
}
|
|
647
647
|
var init_clsx = __esm({
|
|
648
|
-
"node_modules/clsx/dist/clsx.mjs"() {
|
|
648
|
+
"node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
|
|
649
649
|
}
|
|
650
650
|
});
|
|
651
651
|
|
|
652
|
-
// node_modules/tailwind-merge/dist/bundle-mjs.mjs
|
|
652
|
+
// node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
|
|
653
653
|
function twJoin() {
|
|
654
654
|
let index = 0;
|
|
655
655
|
let argument;
|
|
@@ -693,7 +693,7 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
|
|
|
693
693
|
}
|
|
694
694
|
var CLASS_PART_SEPARATOR, createClassGroupUtils, getGroupRecursive, arbitraryPropertyRegex, getGroupIdForArbitraryProperty, createClassMap, processClassesRecursively, getPart, isThemeGetter, getPrefixedClassGroupEntries, createLruCache, IMPORTANT_MODIFIER, createParseClassName, sortModifiers, createConfigUtils, SPLIT_CLASSES_REGEX, mergeClassList, toValue, fromTheme, arbitraryValueRegex, fractionRegex, stringLengths, tshirtUnitRegex, lengthUnitRegex, colorFunctionRegex, shadowRegex, imageRegex, isLength, isArbitraryLength, isNumber, isArbitraryNumber, isInteger, isPercent, isArbitraryValue, isTshirtSize, sizeLabels, isArbitrarySize, isArbitraryPosition, imageLabels, isArbitraryImage, isArbitraryShadow, isAny, getIsArbitraryValue, isLengthOnly, isNever, isShadow, isImage, getDefaultConfig, twMerge;
|
|
695
695
|
var init_bundle_mjs = __esm({
|
|
696
|
-
"node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
|
|
696
|
+
"node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
|
|
697
697
|
CLASS_PART_SEPARATOR = "-";
|
|
698
698
|
createClassGroupUtils = (config) => {
|
|
699
699
|
const classMap = createClassMap(config);
|
|
@@ -9419,6 +9419,66 @@ var init_RangeSlider = __esm({
|
|
|
9419
9419
|
RangeSlider.displayName = "RangeSlider";
|
|
9420
9420
|
}
|
|
9421
9421
|
});
|
|
9422
|
+
function easeOut(t) {
|
|
9423
|
+
return t * (2 - t);
|
|
9424
|
+
}
|
|
9425
|
+
var AnimatedCounter;
|
|
9426
|
+
var init_AnimatedCounter = __esm({
|
|
9427
|
+
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
9428
|
+
"use client";
|
|
9429
|
+
init_cn();
|
|
9430
|
+
init_Typography();
|
|
9431
|
+
AnimatedCounter = ({
|
|
9432
|
+
value: rawValue,
|
|
9433
|
+
duration = 600,
|
|
9434
|
+
prefix,
|
|
9435
|
+
suffix,
|
|
9436
|
+
className
|
|
9437
|
+
}) => {
|
|
9438
|
+
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
9439
|
+
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
9440
|
+
const [displayValue, setDisplayValue] = React114.useState(value);
|
|
9441
|
+
const previousValueRef = React114.useRef(value);
|
|
9442
|
+
const animationFrameRef = React114.useRef(null);
|
|
9443
|
+
React114.useEffect(() => {
|
|
9444
|
+
const from = previousValueRef.current;
|
|
9445
|
+
const to = value;
|
|
9446
|
+
previousValueRef.current = value;
|
|
9447
|
+
if (from === to) {
|
|
9448
|
+
setDisplayValue(to);
|
|
9449
|
+
return;
|
|
9450
|
+
}
|
|
9451
|
+
const startTime = performance.now();
|
|
9452
|
+
const diff = to - from;
|
|
9453
|
+
function animate(currentTime) {
|
|
9454
|
+
const elapsed = currentTime - startTime;
|
|
9455
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
9456
|
+
const easedProgress = easeOut(progress);
|
|
9457
|
+
setDisplayValue(from + diff * easedProgress);
|
|
9458
|
+
if (progress < 1) {
|
|
9459
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9460
|
+
} else {
|
|
9461
|
+
setDisplayValue(to);
|
|
9462
|
+
}
|
|
9463
|
+
}
|
|
9464
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9465
|
+
return () => {
|
|
9466
|
+
if (animationFrameRef.current !== null) {
|
|
9467
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
9468
|
+
}
|
|
9469
|
+
};
|
|
9470
|
+
}, [value, duration]);
|
|
9471
|
+
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
9472
|
+
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
9473
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
9474
|
+
prefix,
|
|
9475
|
+
formattedValue,
|
|
9476
|
+
suffix
|
|
9477
|
+
] });
|
|
9478
|
+
};
|
|
9479
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
9480
|
+
}
|
|
9481
|
+
});
|
|
9422
9482
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
9423
9483
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
9424
9484
|
const observerRef = React114.useRef(null);
|
|
@@ -9715,6 +9775,34 @@ var init_SectionHeader = __esm({
|
|
|
9715
9775
|
SectionHeader.displayName = "SectionHeader";
|
|
9716
9776
|
}
|
|
9717
9777
|
});
|
|
9778
|
+
var sizeClasses6, MarketingStatCard;
|
|
9779
|
+
var init_MarketingStatCard = __esm({
|
|
9780
|
+
"components/marketing/atoms/MarketingStatCard.tsx"() {
|
|
9781
|
+
init_cn();
|
|
9782
|
+
init_Stack();
|
|
9783
|
+
init_Typography();
|
|
9784
|
+
sizeClasses6 = {
|
|
9785
|
+
sm: "text-2xl",
|
|
9786
|
+
md: "text-4xl",
|
|
9787
|
+
lg: "text-5xl"
|
|
9788
|
+
};
|
|
9789
|
+
MarketingStatCard = ({ value, label, size = "md", className }) => {
|
|
9790
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "center", className: cn(className), children: [
|
|
9791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9792
|
+
Typography,
|
|
9793
|
+
{
|
|
9794
|
+
weight: "bold",
|
|
9795
|
+
color: "primary",
|
|
9796
|
+
className: cn(sizeClasses6[size]),
|
|
9797
|
+
children: value
|
|
9798
|
+
}
|
|
9799
|
+
),
|
|
9800
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", children: label })
|
|
9801
|
+
] });
|
|
9802
|
+
};
|
|
9803
|
+
MarketingStatCard.displayName = "MarketingStatCard";
|
|
9804
|
+
}
|
|
9805
|
+
});
|
|
9718
9806
|
var backgroundClasses, paddingClasses, ContentSection;
|
|
9719
9807
|
var init_ContentSection = __esm({
|
|
9720
9808
|
"components/marketing/atoms/ContentSection.tsx"() {
|
|
@@ -23559,6 +23647,315 @@ var init_molecules = __esm({
|
|
|
23559
23647
|
init_puzzleObject();
|
|
23560
23648
|
}
|
|
23561
23649
|
});
|
|
23650
|
+
function resolveColor2(color, ctx, fallback) {
|
|
23651
|
+
if (!color) return fallback;
|
|
23652
|
+
if (color.startsWith("var(")) {
|
|
23653
|
+
ctx.canvas.style;
|
|
23654
|
+
const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color);
|
|
23655
|
+
if (m) {
|
|
23656
|
+
const computed = getComputedStyle(ctx.canvas).getPropertyValue(m[1]).trim();
|
|
23657
|
+
return computed || m[2]?.trim() || fallback;
|
|
23658
|
+
}
|
|
23659
|
+
}
|
|
23660
|
+
return color;
|
|
23661
|
+
}
|
|
23662
|
+
function shapeBounds(shape) {
|
|
23663
|
+
switch (shape.type) {
|
|
23664
|
+
case "line":
|
|
23665
|
+
case "arrow":
|
|
23666
|
+
if (shape.x1 == null || shape.y1 == null || shape.x2 == null || shape.y2 == null) return null;
|
|
23667
|
+
return {
|
|
23668
|
+
x: Math.min(shape.x1, shape.x2) - 6,
|
|
23669
|
+
y: Math.min(shape.y1, shape.y2) - 6,
|
|
23670
|
+
w: Math.abs(shape.x2 - shape.x1) + 12,
|
|
23671
|
+
h: Math.abs(shape.y2 - shape.y1) + 12
|
|
23672
|
+
};
|
|
23673
|
+
case "circle":
|
|
23674
|
+
if (shape.x == null || shape.y == null || shape.radius == null) return null;
|
|
23675
|
+
return {
|
|
23676
|
+
x: shape.x - shape.radius - 4,
|
|
23677
|
+
y: shape.y - shape.radius - 4,
|
|
23678
|
+
w: shape.radius * 2 + 8,
|
|
23679
|
+
h: shape.radius * 2 + 8
|
|
23680
|
+
};
|
|
23681
|
+
case "rect":
|
|
23682
|
+
if (shape.x == null || shape.y == null || shape.width == null || shape.height == null) return null;
|
|
23683
|
+
return { x: shape.x - 4, y: shape.y - 4, w: shape.width + 8, h: shape.height + 8 };
|
|
23684
|
+
case "polygon":
|
|
23685
|
+
if (!shape.points || shape.points.length === 0) return null;
|
|
23686
|
+
{
|
|
23687
|
+
const xs = shape.points.map((p2) => p2.x);
|
|
23688
|
+
const ys = shape.points.map((p2) => p2.y);
|
|
23689
|
+
const minX = Math.min(...xs);
|
|
23690
|
+
const minY = Math.min(...ys);
|
|
23691
|
+
return {
|
|
23692
|
+
x: minX - 4,
|
|
23693
|
+
y: minY - 4,
|
|
23694
|
+
w: Math.max(...xs) - minX + 8,
|
|
23695
|
+
h: Math.max(...ys) - minY + 8
|
|
23696
|
+
};
|
|
23697
|
+
}
|
|
23698
|
+
case "text":
|
|
23699
|
+
if (shape.x == null || shape.y == null) return null;
|
|
23700
|
+
return { x: shape.x - 4, y: shape.y - (shape.fontSize ?? 14) - 4, w: 120, h: (shape.fontSize ?? 14) + 8 };
|
|
23701
|
+
default:
|
|
23702
|
+
return null;
|
|
23703
|
+
}
|
|
23704
|
+
}
|
|
23705
|
+
function drawArrowHead(ctx, x1, y1, x2, y2, size) {
|
|
23706
|
+
const angle = Math.atan2(y2 - y1, x2 - x1);
|
|
23707
|
+
ctx.beginPath();
|
|
23708
|
+
ctx.moveTo(x2, y2);
|
|
23709
|
+
ctx.lineTo(x2 - size * Math.cos(angle - Math.PI / 6), y2 - size * Math.sin(angle - Math.PI / 6));
|
|
23710
|
+
ctx.lineTo(x2 - size * Math.cos(angle + Math.PI / 6), y2 - size * Math.sin(angle + Math.PI / 6));
|
|
23711
|
+
ctx.closePath();
|
|
23712
|
+
ctx.fill();
|
|
23713
|
+
}
|
|
23714
|
+
function drawShape(ctx, shape, width, height) {
|
|
23715
|
+
ctx.save();
|
|
23716
|
+
const opacity = shape.opacity ?? 1;
|
|
23717
|
+
ctx.globalAlpha = opacity;
|
|
23718
|
+
const stroke = resolveColor2(shape.color, ctx, "#333333");
|
|
23719
|
+
const fill = shape.fill ? resolveColor2(shape.fill, ctx, "#cccccc") : void 0;
|
|
23720
|
+
ctx.lineWidth = shape.lineWidth ?? 2;
|
|
23721
|
+
switch (shape.type) {
|
|
23722
|
+
case "grid": {
|
|
23723
|
+
const step = shape.step ?? 40;
|
|
23724
|
+
ctx.strokeStyle = stroke;
|
|
23725
|
+
ctx.globalAlpha = opacity * 0.25;
|
|
23726
|
+
ctx.lineWidth = 1;
|
|
23727
|
+
ctx.beginPath();
|
|
23728
|
+
for (let x = 0; x <= width; x += step) {
|
|
23729
|
+
ctx.moveTo(x, 0);
|
|
23730
|
+
ctx.lineTo(x, height);
|
|
23731
|
+
}
|
|
23732
|
+
for (let y = 0; y <= height; y += step) {
|
|
23733
|
+
ctx.moveTo(0, y);
|
|
23734
|
+
ctx.lineTo(width, y);
|
|
23735
|
+
}
|
|
23736
|
+
ctx.stroke();
|
|
23737
|
+
break;
|
|
23738
|
+
}
|
|
23739
|
+
case "axis": {
|
|
23740
|
+
const axis = shape.axis ?? "x";
|
|
23741
|
+
ctx.strokeStyle = stroke;
|
|
23742
|
+
ctx.lineWidth = shape.lineWidth ?? 2;
|
|
23743
|
+
ctx.beginPath();
|
|
23744
|
+
if (axis === "x") {
|
|
23745
|
+
ctx.moveTo(0, height / 2);
|
|
23746
|
+
ctx.lineTo(width, height / 2);
|
|
23747
|
+
} else {
|
|
23748
|
+
ctx.moveTo(width / 2, 0);
|
|
23749
|
+
ctx.lineTo(width / 2, height);
|
|
23750
|
+
}
|
|
23751
|
+
ctx.stroke();
|
|
23752
|
+
break;
|
|
23753
|
+
}
|
|
23754
|
+
case "line": {
|
|
23755
|
+
if (shape.x1 == null || shape.y1 == null || shape.x2 == null || shape.y2 == null) break;
|
|
23756
|
+
ctx.strokeStyle = stroke;
|
|
23757
|
+
ctx.beginPath();
|
|
23758
|
+
ctx.moveTo(shape.x1, shape.y1);
|
|
23759
|
+
ctx.lineTo(shape.x2, shape.y2);
|
|
23760
|
+
ctx.stroke();
|
|
23761
|
+
break;
|
|
23762
|
+
}
|
|
23763
|
+
case "arrow": {
|
|
23764
|
+
if (shape.x1 == null || shape.y1 == null || shape.x2 == null || shape.y2 == null) break;
|
|
23765
|
+
ctx.strokeStyle = stroke;
|
|
23766
|
+
ctx.fillStyle = stroke;
|
|
23767
|
+
ctx.beginPath();
|
|
23768
|
+
ctx.moveTo(shape.x1, shape.y1);
|
|
23769
|
+
ctx.lineTo(shape.x2, shape.y2);
|
|
23770
|
+
ctx.stroke();
|
|
23771
|
+
drawArrowHead(ctx, shape.x1, shape.y1, shape.x2, shape.y2, 10);
|
|
23772
|
+
break;
|
|
23773
|
+
}
|
|
23774
|
+
case "circle": {
|
|
23775
|
+
if (shape.x == null || shape.y == null || shape.radius == null) break;
|
|
23776
|
+
ctx.beginPath();
|
|
23777
|
+
ctx.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2);
|
|
23778
|
+
if (fill) {
|
|
23779
|
+
ctx.fillStyle = fill;
|
|
23780
|
+
ctx.fill();
|
|
23781
|
+
}
|
|
23782
|
+
ctx.strokeStyle = stroke;
|
|
23783
|
+
ctx.stroke();
|
|
23784
|
+
break;
|
|
23785
|
+
}
|
|
23786
|
+
case "rect": {
|
|
23787
|
+
if (shape.x == null || shape.y == null || shape.width == null || shape.height == null) break;
|
|
23788
|
+
if (fill) {
|
|
23789
|
+
ctx.fillStyle = fill;
|
|
23790
|
+
ctx.fillRect(shape.x, shape.y, shape.width, shape.height);
|
|
23791
|
+
}
|
|
23792
|
+
ctx.strokeStyle = stroke;
|
|
23793
|
+
ctx.strokeRect(shape.x, shape.y, shape.width, shape.height);
|
|
23794
|
+
break;
|
|
23795
|
+
}
|
|
23796
|
+
case "polygon": {
|
|
23797
|
+
if (!shape.points || shape.points.length < 2) break;
|
|
23798
|
+
ctx.beginPath();
|
|
23799
|
+
ctx.moveTo(shape.points[0].x, shape.points[0].y);
|
|
23800
|
+
for (let i = 1; i < shape.points.length; i++) {
|
|
23801
|
+
ctx.lineTo(shape.points[i].x, shape.points[i].y);
|
|
23802
|
+
}
|
|
23803
|
+
ctx.closePath();
|
|
23804
|
+
if (fill) {
|
|
23805
|
+
ctx.fillStyle = fill;
|
|
23806
|
+
ctx.fill();
|
|
23807
|
+
}
|
|
23808
|
+
ctx.strokeStyle = stroke;
|
|
23809
|
+
ctx.stroke();
|
|
23810
|
+
break;
|
|
23811
|
+
}
|
|
23812
|
+
case "path": {
|
|
23813
|
+
if (!shape.path) break;
|
|
23814
|
+
const p2 = new Path2D(shape.path);
|
|
23815
|
+
if (fill) {
|
|
23816
|
+
ctx.fillStyle = fill;
|
|
23817
|
+
ctx.fill(p2);
|
|
23818
|
+
}
|
|
23819
|
+
ctx.strokeStyle = stroke;
|
|
23820
|
+
ctx.stroke(p2);
|
|
23821
|
+
break;
|
|
23822
|
+
}
|
|
23823
|
+
case "text": {
|
|
23824
|
+
if (shape.x == null || shape.y == null || !shape.text) break;
|
|
23825
|
+
ctx.fillStyle = stroke;
|
|
23826
|
+
ctx.font = `${shape.fontSize ?? 14}px system-ui, sans-serif`;
|
|
23827
|
+
ctx.textAlign = shape.align ?? "left";
|
|
23828
|
+
ctx.textBaseline = "middle";
|
|
23829
|
+
ctx.fillText(shape.text, shape.x, shape.y);
|
|
23830
|
+
break;
|
|
23831
|
+
}
|
|
23832
|
+
}
|
|
23833
|
+
ctx.restore();
|
|
23834
|
+
}
|
|
23835
|
+
var LearningCanvas;
|
|
23836
|
+
var init_LearningCanvas = __esm({
|
|
23837
|
+
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
23838
|
+
"use client";
|
|
23839
|
+
init_cn();
|
|
23840
|
+
init_useEventBus();
|
|
23841
|
+
LearningCanvas = ({
|
|
23842
|
+
className,
|
|
23843
|
+
width = 600,
|
|
23844
|
+
height = 400,
|
|
23845
|
+
backgroundColor,
|
|
23846
|
+
shapes = [],
|
|
23847
|
+
interactive = false,
|
|
23848
|
+
animate = false,
|
|
23849
|
+
onShapeClick,
|
|
23850
|
+
onShapeHover,
|
|
23851
|
+
isLoading,
|
|
23852
|
+
error
|
|
23853
|
+
}) => {
|
|
23854
|
+
const canvasRef = React114.useRef(null);
|
|
23855
|
+
const eventBus = useEventBus();
|
|
23856
|
+
const animRef = React114.useRef(0);
|
|
23857
|
+
const hoverIndexRef = React114.useRef(-1);
|
|
23858
|
+
const findShapeAt = React114.useCallback((clientX, clientY) => {
|
|
23859
|
+
const canvas = canvasRef.current;
|
|
23860
|
+
if (!canvas) return -1;
|
|
23861
|
+
const rect = canvas.getBoundingClientRect();
|
|
23862
|
+
const x = clientX - rect.left;
|
|
23863
|
+
const y = clientY - rect.top;
|
|
23864
|
+
for (let i = shapes.length - 1; i >= 0; i--) {
|
|
23865
|
+
const b = shapeBounds(shapes[i]);
|
|
23866
|
+
if (b && x >= b.x && x <= b.x + b.w && y >= b.y && y <= b.y + b.h) {
|
|
23867
|
+
return i;
|
|
23868
|
+
}
|
|
23869
|
+
}
|
|
23870
|
+
return -1;
|
|
23871
|
+
}, [shapes]);
|
|
23872
|
+
const draw = React114.useCallback(() => {
|
|
23873
|
+
const canvas = canvasRef.current;
|
|
23874
|
+
if (!canvas) return;
|
|
23875
|
+
const ctx = canvas.getContext("2d");
|
|
23876
|
+
if (!ctx) return;
|
|
23877
|
+
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
23878
|
+
canvas.width = Math.max(1, Math.floor(width * dpr));
|
|
23879
|
+
canvas.height = Math.max(1, Math.floor(height * dpr));
|
|
23880
|
+
canvas.style.width = `${width}px`;
|
|
23881
|
+
canvas.style.height = `${height}px`;
|
|
23882
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
23883
|
+
ctx.clearRect(0, 0, width, height);
|
|
23884
|
+
if (backgroundColor) {
|
|
23885
|
+
ctx.fillStyle = backgroundColor;
|
|
23886
|
+
ctx.fillRect(0, 0, width, height);
|
|
23887
|
+
}
|
|
23888
|
+
for (const shape of shapes) {
|
|
23889
|
+
drawShape(ctx, shape, width, height);
|
|
23890
|
+
}
|
|
23891
|
+
}, [width, height, backgroundColor, shapes]);
|
|
23892
|
+
React114.useEffect(() => {
|
|
23893
|
+
draw();
|
|
23894
|
+
}, [draw]);
|
|
23895
|
+
React114.useEffect(() => {
|
|
23896
|
+
if (!animate) return;
|
|
23897
|
+
const loop = () => {
|
|
23898
|
+
draw();
|
|
23899
|
+
animRef.current = requestAnimationFrame(loop);
|
|
23900
|
+
};
|
|
23901
|
+
animRef.current = requestAnimationFrame(loop);
|
|
23902
|
+
return () => cancelAnimationFrame(animRef.current);
|
|
23903
|
+
}, [animate, draw]);
|
|
23904
|
+
const handlePointerMove = React114.useCallback(
|
|
23905
|
+
(e) => {
|
|
23906
|
+
if (!interactive) return;
|
|
23907
|
+
const idx = findShapeAt(e.clientX, e.clientY);
|
|
23908
|
+
if (idx !== hoverIndexRef.current) {
|
|
23909
|
+
hoverIndexRef.current = idx;
|
|
23910
|
+
if (idx >= 0) {
|
|
23911
|
+
const shape = shapes[idx];
|
|
23912
|
+
const payload = { id: shape.id, type: shape.type, index: idx };
|
|
23913
|
+
if (onShapeHover) onShapeHover(payload);
|
|
23914
|
+
else if (eventBus) eventBus.emit(`UI:SHAPE_HOVER`, payload);
|
|
23915
|
+
}
|
|
23916
|
+
}
|
|
23917
|
+
},
|
|
23918
|
+
[interactive, onShapeHover, eventBus, findShapeAt, shapes]
|
|
23919
|
+
);
|
|
23920
|
+
const handleClick = React114.useCallback(
|
|
23921
|
+
(e) => {
|
|
23922
|
+
if (!interactive) return;
|
|
23923
|
+
const idx = findShapeAt(e.clientX, e.clientY);
|
|
23924
|
+
if (idx >= 0) {
|
|
23925
|
+
const shape = shapes[idx];
|
|
23926
|
+
const payload = { id: shape.id, type: shape.type, index: idx };
|
|
23927
|
+
if (onShapeClick) onShapeClick(payload);
|
|
23928
|
+
else if (eventBus) eventBus.emit(`UI:SHAPE_CLICK`, payload);
|
|
23929
|
+
}
|
|
23930
|
+
},
|
|
23931
|
+
[interactive, onShapeClick, eventBus, findShapeAt, shapes]
|
|
23932
|
+
);
|
|
23933
|
+
if (isLoading || error) {
|
|
23934
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23935
|
+
"div",
|
|
23936
|
+
{
|
|
23937
|
+
className: cn(
|
|
23938
|
+
"flex items-center justify-center rounded border border-border bg-surface",
|
|
23939
|
+
className
|
|
23940
|
+
),
|
|
23941
|
+
style: { width, height },
|
|
23942
|
+
children: error ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-destructive", children: error.message }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Loading canvas\u2026" })
|
|
23943
|
+
}
|
|
23944
|
+
);
|
|
23945
|
+
}
|
|
23946
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23947
|
+
"canvas",
|
|
23948
|
+
{
|
|
23949
|
+
ref: canvasRef,
|
|
23950
|
+
className: cn("block touch-none rounded border border-border", className),
|
|
23951
|
+
style: { width, height },
|
|
23952
|
+
onClick: handleClick,
|
|
23953
|
+
onPointerMove: handlePointerMove
|
|
23954
|
+
}
|
|
23955
|
+
);
|
|
23956
|
+
};
|
|
23957
|
+
}
|
|
23958
|
+
});
|
|
23562
23959
|
|
|
23563
23960
|
// components/core/atoms/index.ts
|
|
23564
23961
|
var init_atoms = __esm({
|
|
@@ -25044,91 +25441,6 @@ var init_ComponentPatterns = __esm({
|
|
|
25044
25441
|
AlertPattern.displayName = "AlertPattern";
|
|
25045
25442
|
}
|
|
25046
25443
|
});
|
|
25047
|
-
function parseValue(value) {
|
|
25048
|
-
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
25049
|
-
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
25050
|
-
if (!match) {
|
|
25051
|
-
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
25052
|
-
}
|
|
25053
|
-
const numStr = match[2];
|
|
25054
|
-
const decimalIdx = numStr.indexOf(".");
|
|
25055
|
-
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
25056
|
-
return {
|
|
25057
|
-
prefix: match[1],
|
|
25058
|
-
num: parseFloat(numStr),
|
|
25059
|
-
suffix: match[3],
|
|
25060
|
-
decimals
|
|
25061
|
-
};
|
|
25062
|
-
}
|
|
25063
|
-
var AnimatedCounter;
|
|
25064
|
-
var init_AnimatedCounter = __esm({
|
|
25065
|
-
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
25066
|
-
"use client";
|
|
25067
|
-
init_cn();
|
|
25068
|
-
init_Box();
|
|
25069
|
-
init_Typography();
|
|
25070
|
-
AnimatedCounter = ({
|
|
25071
|
-
value,
|
|
25072
|
-
label,
|
|
25073
|
-
duration = 1500,
|
|
25074
|
-
className
|
|
25075
|
-
}) => {
|
|
25076
|
-
const ref = React114.useRef(null);
|
|
25077
|
-
const [displayValue, setDisplayValue] = React114.useState("0");
|
|
25078
|
-
const [hasAnimated, setHasAnimated] = React114.useState(false);
|
|
25079
|
-
const animate = React114.useCallback(() => {
|
|
25080
|
-
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
25081
|
-
if (num2 === 0) {
|
|
25082
|
-
setDisplayValue(String(value));
|
|
25083
|
-
return;
|
|
25084
|
-
}
|
|
25085
|
-
const startTime = performance.now();
|
|
25086
|
-
const tick = (now2) => {
|
|
25087
|
-
const elapsed = now2 - startTime;
|
|
25088
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
25089
|
-
const eased = 1 - Math.pow(1 - progress, 3);
|
|
25090
|
-
const current = eased * num2;
|
|
25091
|
-
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
25092
|
-
if (progress < 1) {
|
|
25093
|
-
requestAnimationFrame(tick);
|
|
25094
|
-
} else {
|
|
25095
|
-
setDisplayValue(String(value));
|
|
25096
|
-
}
|
|
25097
|
-
};
|
|
25098
|
-
requestAnimationFrame(tick);
|
|
25099
|
-
}, [value, duration]);
|
|
25100
|
-
React114.useEffect(() => {
|
|
25101
|
-
if (hasAnimated) return;
|
|
25102
|
-
const el = ref.current;
|
|
25103
|
-
if (!el) return;
|
|
25104
|
-
const observer2 = new IntersectionObserver(
|
|
25105
|
-
(entries) => {
|
|
25106
|
-
if (entries[0].isIntersecting) {
|
|
25107
|
-
setHasAnimated(true);
|
|
25108
|
-
animate();
|
|
25109
|
-
observer2.disconnect();
|
|
25110
|
-
}
|
|
25111
|
-
},
|
|
25112
|
-
{ threshold: 0.3 }
|
|
25113
|
-
);
|
|
25114
|
-
observer2.observe(el);
|
|
25115
|
-
return () => observer2.disconnect();
|
|
25116
|
-
}, [hasAnimated, animate]);
|
|
25117
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
25118
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25119
|
-
Typography,
|
|
25120
|
-
{
|
|
25121
|
-
variant: "h2",
|
|
25122
|
-
className: "text-primary font-bold tabular-nums",
|
|
25123
|
-
children: hasAnimated ? displayValue : "0"
|
|
25124
|
-
}
|
|
25125
|
-
),
|
|
25126
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
25127
|
-
] });
|
|
25128
|
-
};
|
|
25129
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
25130
|
-
}
|
|
25131
|
-
});
|
|
25132
25444
|
var AuthLayout;
|
|
25133
25445
|
var init_AuthLayout = __esm({
|
|
25134
25446
|
"components/marketing/templates/AuthLayout.tsx"() {
|
|
@@ -25270,10 +25582,107 @@ var init_AuthLayout = __esm({
|
|
|
25270
25582
|
AuthLayout.displayName = "AuthLayout";
|
|
25271
25583
|
}
|
|
25272
25584
|
});
|
|
25585
|
+
var BiologyCanvas;
|
|
25586
|
+
var init_BiologyCanvas = __esm({
|
|
25587
|
+
"components/learning/molecules/BiologyCanvas.tsx"() {
|
|
25588
|
+
"use client";
|
|
25589
|
+
init_atoms();
|
|
25590
|
+
init_Stack();
|
|
25591
|
+
init_LearningCanvas();
|
|
25592
|
+
BiologyCanvas = ({
|
|
25593
|
+
className,
|
|
25594
|
+
width = 600,
|
|
25595
|
+
height = 400,
|
|
25596
|
+
title,
|
|
25597
|
+
backgroundColor,
|
|
25598
|
+
nodes = [],
|
|
25599
|
+
edges = [],
|
|
25600
|
+
shapes = [],
|
|
25601
|
+
interactive = false,
|
|
25602
|
+
animate = false,
|
|
25603
|
+
onShapeClick,
|
|
25604
|
+
isLoading,
|
|
25605
|
+
error
|
|
25606
|
+
}) => {
|
|
25607
|
+
const derivedShapes = React114.useMemo(() => {
|
|
25608
|
+
const out = [];
|
|
25609
|
+
const nodeById = /* @__PURE__ */ new Map();
|
|
25610
|
+
for (const n of nodes) {
|
|
25611
|
+
if (n.id) nodeById.set(n.id, n);
|
|
25612
|
+
}
|
|
25613
|
+
for (const e of edges) {
|
|
25614
|
+
const a = nodeById.get(e.from);
|
|
25615
|
+
const b = nodeById.get(e.to);
|
|
25616
|
+
if (!a || !b) continue;
|
|
25617
|
+
out.push({
|
|
25618
|
+
type: "line",
|
|
25619
|
+
x1: a.x,
|
|
25620
|
+
y1: a.y,
|
|
25621
|
+
x2: b.x,
|
|
25622
|
+
y2: b.y,
|
|
25623
|
+
color: e.color ?? "#9ca3af",
|
|
25624
|
+
lineWidth: 2
|
|
25625
|
+
});
|
|
25626
|
+
if (e.label) {
|
|
25627
|
+
out.push({
|
|
25628
|
+
type: "text",
|
|
25629
|
+
x: (a.x + b.x) / 2 + 4,
|
|
25630
|
+
y: (a.y + b.y) / 2 - 4,
|
|
25631
|
+
text: e.label,
|
|
25632
|
+
color: "#374151",
|
|
25633
|
+
fontSize: 11
|
|
25634
|
+
});
|
|
25635
|
+
}
|
|
25636
|
+
}
|
|
25637
|
+
for (const n of nodes) {
|
|
25638
|
+
out.push({
|
|
25639
|
+
type: "circle",
|
|
25640
|
+
x: n.x,
|
|
25641
|
+
y: n.y,
|
|
25642
|
+
radius: n.radius ?? 16,
|
|
25643
|
+
color: n.color ?? "#16a34a",
|
|
25644
|
+
fill: `${n.color ?? "#16a34a"}33`,
|
|
25645
|
+
id: n.id
|
|
25646
|
+
});
|
|
25647
|
+
if (n.label) {
|
|
25648
|
+
out.push({
|
|
25649
|
+
type: "text",
|
|
25650
|
+
x: n.x,
|
|
25651
|
+
y: n.y + (n.radius ?? 16) + 14,
|
|
25652
|
+
text: n.label,
|
|
25653
|
+
color: "#111827",
|
|
25654
|
+
fontSize: 12,
|
|
25655
|
+
align: "center"
|
|
25656
|
+
});
|
|
25657
|
+
}
|
|
25658
|
+
}
|
|
25659
|
+
out.push(...shapes);
|
|
25660
|
+
return out;
|
|
25661
|
+
}, [nodes, edges, shapes]);
|
|
25662
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
25663
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
|
|
25664
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25665
|
+
LearningCanvas,
|
|
25666
|
+
{
|
|
25667
|
+
width,
|
|
25668
|
+
height,
|
|
25669
|
+
backgroundColor,
|
|
25670
|
+
shapes: derivedShapes,
|
|
25671
|
+
interactive,
|
|
25672
|
+
animate,
|
|
25673
|
+
onShapeClick,
|
|
25674
|
+
isLoading,
|
|
25675
|
+
error
|
|
25676
|
+
}
|
|
25677
|
+
)
|
|
25678
|
+
] }) });
|
|
25679
|
+
};
|
|
25680
|
+
}
|
|
25681
|
+
});
|
|
25273
25682
|
|
|
25274
|
-
// node_modules/katex/dist/katex.min.css
|
|
25683
|
+
// node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css
|
|
25275
25684
|
var init_katex_min = __esm({
|
|
25276
|
-
"node_modules/katex/dist/katex.min.css"() {
|
|
25685
|
+
"node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css"() {
|
|
25277
25686
|
}
|
|
25278
25687
|
});
|
|
25279
25688
|
var Tabs;
|
|
@@ -31759,6 +32168,122 @@ var init_ChatBar = __esm({
|
|
|
31759
32168
|
ChatBar.displayName = "ChatBar";
|
|
31760
32169
|
}
|
|
31761
32170
|
});
|
|
32171
|
+
var ChemistryCanvas;
|
|
32172
|
+
var init_ChemistryCanvas = __esm({
|
|
32173
|
+
"components/learning/molecules/ChemistryCanvas.tsx"() {
|
|
32174
|
+
"use client";
|
|
32175
|
+
init_atoms();
|
|
32176
|
+
init_Stack();
|
|
32177
|
+
init_LearningCanvas();
|
|
32178
|
+
ChemistryCanvas = ({
|
|
32179
|
+
className,
|
|
32180
|
+
width = 600,
|
|
32181
|
+
height = 400,
|
|
32182
|
+
title,
|
|
32183
|
+
backgroundColor,
|
|
32184
|
+
atoms = [],
|
|
32185
|
+
bonds = [],
|
|
32186
|
+
arrows = [],
|
|
32187
|
+
shapes = [],
|
|
32188
|
+
interactive = false,
|
|
32189
|
+
animate = false,
|
|
32190
|
+
onShapeClick,
|
|
32191
|
+
isLoading,
|
|
32192
|
+
error
|
|
32193
|
+
}) => {
|
|
32194
|
+
const derivedShapes = React114.useMemo(() => {
|
|
32195
|
+
const out = [];
|
|
32196
|
+
const atomById = /* @__PURE__ */ new Map();
|
|
32197
|
+
for (const a of atoms) {
|
|
32198
|
+
if (a.id) atomById.set(a.id, a);
|
|
32199
|
+
}
|
|
32200
|
+
for (const b of bonds) {
|
|
32201
|
+
const a = atomById.get(b.from);
|
|
32202
|
+
const c = atomById.get(b.to);
|
|
32203
|
+
if (!a || !c) continue;
|
|
32204
|
+
const color = b.color ?? "#6b7280";
|
|
32205
|
+
const strokeWidth = b.type === "double" ? 4 : b.type === "triple" ? 6 : 2;
|
|
32206
|
+
out.push({
|
|
32207
|
+
type: "line",
|
|
32208
|
+
x1: a.x,
|
|
32209
|
+
y1: a.y,
|
|
32210
|
+
x2: c.x,
|
|
32211
|
+
y2: c.y,
|
|
32212
|
+
color,
|
|
32213
|
+
lineWidth: strokeWidth
|
|
32214
|
+
});
|
|
32215
|
+
}
|
|
32216
|
+
for (const a of arrows) {
|
|
32217
|
+
const angle = (a.angle ?? 0) * (Math.PI / 180);
|
|
32218
|
+
const len = a.length ?? 60;
|
|
32219
|
+
const x2 = a.x + Math.cos(angle) * len;
|
|
32220
|
+
const y2 = a.y + Math.sin(angle) * len;
|
|
32221
|
+
out.push({
|
|
32222
|
+
type: "arrow",
|
|
32223
|
+
x1: a.x,
|
|
32224
|
+
y1: a.y,
|
|
32225
|
+
x2,
|
|
32226
|
+
y2,
|
|
32227
|
+
color: a.color ?? "#dc2626",
|
|
32228
|
+
lineWidth: 2
|
|
32229
|
+
});
|
|
32230
|
+
if (a.label) {
|
|
32231
|
+
out.push({
|
|
32232
|
+
type: "text",
|
|
32233
|
+
x: (a.x + x2) / 2,
|
|
32234
|
+
y: (a.y + y2) / 2 - 10,
|
|
32235
|
+
text: a.label,
|
|
32236
|
+
color: "#111827",
|
|
32237
|
+
fontSize: 12,
|
|
32238
|
+
align: "center"
|
|
32239
|
+
});
|
|
32240
|
+
}
|
|
32241
|
+
}
|
|
32242
|
+
for (const a of atoms) {
|
|
32243
|
+
out.push({
|
|
32244
|
+
type: "circle",
|
|
32245
|
+
x: a.x,
|
|
32246
|
+
y: a.y,
|
|
32247
|
+
radius: a.radius ?? 14,
|
|
32248
|
+
color: a.color ?? "#2563eb",
|
|
32249
|
+
fill: a.color ?? "#2563eb",
|
|
32250
|
+
id: a.id
|
|
32251
|
+
});
|
|
32252
|
+
if (a.element) {
|
|
32253
|
+
out.push({
|
|
32254
|
+
type: "text",
|
|
32255
|
+
x: a.x,
|
|
32256
|
+
y: a.y,
|
|
32257
|
+
text: a.element,
|
|
32258
|
+
color: "#ffffff",
|
|
32259
|
+
fontSize: 12,
|
|
32260
|
+
align: "center"
|
|
32261
|
+
});
|
|
32262
|
+
}
|
|
32263
|
+
}
|
|
32264
|
+
out.push(...shapes);
|
|
32265
|
+
return out;
|
|
32266
|
+
}, [atoms, bonds, arrows, shapes]);
|
|
32267
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
32268
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
|
|
32269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
32270
|
+
LearningCanvas,
|
|
32271
|
+
{
|
|
32272
|
+
width,
|
|
32273
|
+
height,
|
|
32274
|
+
backgroundColor,
|
|
32275
|
+
shapes: derivedShapes,
|
|
32276
|
+
interactive,
|
|
32277
|
+
animate,
|
|
32278
|
+
onShapeClick,
|
|
32279
|
+
isLoading,
|
|
32280
|
+
error
|
|
32281
|
+
}
|
|
32282
|
+
)
|
|
32283
|
+
] }) });
|
|
32284
|
+
};
|
|
32285
|
+
}
|
|
32286
|
+
});
|
|
31762
32287
|
var CodeRunnerPanel;
|
|
31763
32288
|
var init_CodeRunnerPanel = __esm({
|
|
31764
32289
|
"components/core/organisms/CodeRunnerPanel.tsx"() {
|
|
@@ -37456,6 +37981,234 @@ var init_ProgressDots = __esm({
|
|
|
37456
37981
|
ProgressDots.displayName = "ProgressDots";
|
|
37457
37982
|
}
|
|
37458
37983
|
});
|
|
37984
|
+
var MathCanvas;
|
|
37985
|
+
var init_MathCanvas = __esm({
|
|
37986
|
+
"components/learning/molecules/MathCanvas.tsx"() {
|
|
37987
|
+
"use client";
|
|
37988
|
+
init_atoms();
|
|
37989
|
+
init_Stack();
|
|
37990
|
+
init_LearningCanvas();
|
|
37991
|
+
MathCanvas = ({
|
|
37992
|
+
className,
|
|
37993
|
+
width = 600,
|
|
37994
|
+
height = 400,
|
|
37995
|
+
title,
|
|
37996
|
+
xMin = -10,
|
|
37997
|
+
xMax = 10,
|
|
37998
|
+
yMin = -10,
|
|
37999
|
+
yMax = 10,
|
|
38000
|
+
showAxes = true,
|
|
38001
|
+
showGrid = true,
|
|
38002
|
+
gridStep = 1,
|
|
38003
|
+
curves = [],
|
|
38004
|
+
points = [],
|
|
38005
|
+
vectors = [],
|
|
38006
|
+
shapes = [],
|
|
38007
|
+
interactive = false,
|
|
38008
|
+
animate = false,
|
|
38009
|
+
onShapeClick,
|
|
38010
|
+
isLoading,
|
|
38011
|
+
error
|
|
38012
|
+
}) => {
|
|
38013
|
+
const derivedShapes = React114.useMemo(() => {
|
|
38014
|
+
const out = [];
|
|
38015
|
+
const margin = 24;
|
|
38016
|
+
const plotW = width - margin * 2;
|
|
38017
|
+
const plotH = height - margin * 2;
|
|
38018
|
+
const mapX = (x) => margin + (x - xMin) / (xMax - xMin) * plotW;
|
|
38019
|
+
const mapY = (y) => height - (margin + (y - yMin) / (yMax - yMin) * plotH);
|
|
38020
|
+
if (showGrid) {
|
|
38021
|
+
for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep) {
|
|
38022
|
+
const px = mapX(x);
|
|
38023
|
+
out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color: "#e5e7eb", lineWidth: 1 });
|
|
38024
|
+
}
|
|
38025
|
+
for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep) {
|
|
38026
|
+
const py = mapY(y);
|
|
38027
|
+
out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color: "#e5e7eb", lineWidth: 1 });
|
|
38028
|
+
}
|
|
38029
|
+
}
|
|
38030
|
+
if (showAxes) {
|
|
38031
|
+
const xAxisY = Math.max(margin, Math.min(height - margin, mapY(0)));
|
|
38032
|
+
const yAxisX = Math.max(margin, Math.min(width - margin, mapX(0)));
|
|
38033
|
+
out.push({ type: "line", x1: margin, y1: xAxisY, x2: width - margin, y2: xAxisY, color: "#374151", lineWidth: 2 });
|
|
38034
|
+
out.push({ type: "line", x1: yAxisX, y1: margin, x2: yAxisX, y2: height - margin, color: "#374151", lineWidth: 2 });
|
|
38035
|
+
}
|
|
38036
|
+
for (const curve of curves) {
|
|
38037
|
+
if (!curve.samples || curve.samples.length < 2) continue;
|
|
38038
|
+
for (let i = 1; i < curve.samples.length; i++) {
|
|
38039
|
+
const a = curve.samples[i - 1];
|
|
38040
|
+
const b = curve.samples[i];
|
|
38041
|
+
if (a.x < xMin || a.x > xMax || b.x < xMin || b.x > xMax) continue;
|
|
38042
|
+
out.push({
|
|
38043
|
+
type: "line",
|
|
38044
|
+
x1: mapX(a.x),
|
|
38045
|
+
y1: mapY(a.y),
|
|
38046
|
+
x2: mapX(b.x),
|
|
38047
|
+
y2: mapY(b.y),
|
|
38048
|
+
color: curve.color ?? "#2563eb",
|
|
38049
|
+
lineWidth: 2
|
|
38050
|
+
});
|
|
38051
|
+
}
|
|
38052
|
+
}
|
|
38053
|
+
for (const p2 of points) {
|
|
38054
|
+
if (p2.x < xMin || p2.x > xMax || p2.y < yMin || p2.y > yMax) continue;
|
|
38055
|
+
out.push({
|
|
38056
|
+
type: "circle",
|
|
38057
|
+
x: mapX(p2.x),
|
|
38058
|
+
y: mapY(p2.y),
|
|
38059
|
+
radius: p2.radius ?? 4,
|
|
38060
|
+
color: p2.color ?? "#dc2626",
|
|
38061
|
+
fill: p2.color ?? "#dc2626"
|
|
38062
|
+
});
|
|
38063
|
+
if (p2.label) {
|
|
38064
|
+
out.push({ type: "text", x: mapX(p2.x) + 8, y: mapY(p2.y) - 8, text: p2.label, color: "#111827", fontSize: 12 });
|
|
38065
|
+
}
|
|
38066
|
+
}
|
|
38067
|
+
for (const v of vectors) {
|
|
38068
|
+
if (v.x < xMin || v.x > xMax || v.y < yMin || v.y > yMax) continue;
|
|
38069
|
+
const x1 = mapX(v.x);
|
|
38070
|
+
const y1 = mapY(v.y);
|
|
38071
|
+
const x2 = mapX(v.x + v.vx);
|
|
38072
|
+
const y2 = mapY(v.y + v.vy);
|
|
38073
|
+
out.push({ type: "arrow", x1, y1, x2, y2, color: v.color ?? "#7c3aed", lineWidth: 2 });
|
|
38074
|
+
if (v.label) {
|
|
38075
|
+
out.push({ type: "text", x: x2 + 6, y: y2 - 6, text: v.label, color: "#111827", fontSize: 12 });
|
|
38076
|
+
}
|
|
38077
|
+
}
|
|
38078
|
+
out.push(...shapes);
|
|
38079
|
+
return out;
|
|
38080
|
+
}, [width, height, xMin, xMax, yMin, yMax, showAxes, showGrid, gridStep, curves, points, vectors, shapes]);
|
|
38081
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
38082
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
|
|
38083
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
38084
|
+
LearningCanvas,
|
|
38085
|
+
{
|
|
38086
|
+
width,
|
|
38087
|
+
height,
|
|
38088
|
+
shapes: derivedShapes,
|
|
38089
|
+
interactive,
|
|
38090
|
+
animate,
|
|
38091
|
+
onShapeClick,
|
|
38092
|
+
isLoading,
|
|
38093
|
+
error
|
|
38094
|
+
}
|
|
38095
|
+
)
|
|
38096
|
+
] }) });
|
|
38097
|
+
};
|
|
38098
|
+
}
|
|
38099
|
+
});
|
|
38100
|
+
var PhysicsCanvas;
|
|
38101
|
+
var init_PhysicsCanvas = __esm({
|
|
38102
|
+
"components/learning/molecules/PhysicsCanvas.tsx"() {
|
|
38103
|
+
"use client";
|
|
38104
|
+
init_atoms();
|
|
38105
|
+
init_Stack();
|
|
38106
|
+
init_LearningCanvas();
|
|
38107
|
+
PhysicsCanvas = ({
|
|
38108
|
+
className,
|
|
38109
|
+
width = 600,
|
|
38110
|
+
height = 400,
|
|
38111
|
+
title,
|
|
38112
|
+
backgroundColor,
|
|
38113
|
+
bodies = [],
|
|
38114
|
+
constraints = [],
|
|
38115
|
+
showVelocity = true,
|
|
38116
|
+
showForces = false,
|
|
38117
|
+
velocityScale = 20,
|
|
38118
|
+
forceScale = 20,
|
|
38119
|
+
shapes = [],
|
|
38120
|
+
interactive = false,
|
|
38121
|
+
animate = false,
|
|
38122
|
+
onShapeClick,
|
|
38123
|
+
isLoading,
|
|
38124
|
+
error
|
|
38125
|
+
}) => {
|
|
38126
|
+
const derivedShapes = React114.useMemo(() => {
|
|
38127
|
+
const out = [];
|
|
38128
|
+
const bodyById = /* @__PURE__ */ new Map();
|
|
38129
|
+
for (const b of bodies) {
|
|
38130
|
+
if (b.id) bodyById.set(b.id, b);
|
|
38131
|
+
}
|
|
38132
|
+
for (const c of constraints) {
|
|
38133
|
+
const a = bodyById.get(c.from);
|
|
38134
|
+
const b = bodyById.get(c.to);
|
|
38135
|
+
if (!a || !b) continue;
|
|
38136
|
+
out.push({
|
|
38137
|
+
type: "line",
|
|
38138
|
+
x1: a.x,
|
|
38139
|
+
y1: a.y,
|
|
38140
|
+
x2: b.x,
|
|
38141
|
+
y2: b.y,
|
|
38142
|
+
color: c.color ?? "#9ca3af",
|
|
38143
|
+
lineWidth: 2
|
|
38144
|
+
});
|
|
38145
|
+
}
|
|
38146
|
+
for (const b of bodies) {
|
|
38147
|
+
out.push({
|
|
38148
|
+
type: "circle",
|
|
38149
|
+
x: b.x,
|
|
38150
|
+
y: b.y,
|
|
38151
|
+
radius: b.radius ?? 12,
|
|
38152
|
+
color: b.color ?? "#2563eb",
|
|
38153
|
+
fill: b.color ?? "#2563eb",
|
|
38154
|
+
id: b.id
|
|
38155
|
+
});
|
|
38156
|
+
if (b.label) {
|
|
38157
|
+
out.push({
|
|
38158
|
+
type: "text",
|
|
38159
|
+
x: b.x + (b.radius ?? 12) + 6,
|
|
38160
|
+
y: b.y - (b.radius ?? 12) - 6,
|
|
38161
|
+
text: b.label,
|
|
38162
|
+
color: "#111827",
|
|
38163
|
+
fontSize: 12
|
|
38164
|
+
});
|
|
38165
|
+
}
|
|
38166
|
+
if (showVelocity && b.vx != null && b.vy != null && (b.vx !== 0 || b.vy !== 0)) {
|
|
38167
|
+
out.push({
|
|
38168
|
+
type: "arrow",
|
|
38169
|
+
x1: b.x,
|
|
38170
|
+
y1: b.y,
|
|
38171
|
+
x2: b.x + b.vx * velocityScale,
|
|
38172
|
+
y2: b.y + b.vy * velocityScale,
|
|
38173
|
+
color: "#16a34a",
|
|
38174
|
+
lineWidth: 2
|
|
38175
|
+
});
|
|
38176
|
+
}
|
|
38177
|
+
if (showForces && b.fx != null && b.fy != null && (b.fx !== 0 || b.fy !== 0)) {
|
|
38178
|
+
out.push({
|
|
38179
|
+
type: "arrow",
|
|
38180
|
+
x1: b.x,
|
|
38181
|
+
y1: b.y,
|
|
38182
|
+
x2: b.x + b.fx * forceScale,
|
|
38183
|
+
y2: b.y + b.fy * forceScale,
|
|
38184
|
+
color: "#dc2626",
|
|
38185
|
+
lineWidth: 2
|
|
38186
|
+
});
|
|
38187
|
+
}
|
|
38188
|
+
}
|
|
38189
|
+
out.push(...shapes);
|
|
38190
|
+
return out;
|
|
38191
|
+
}, [bodies, constraints, showVelocity, showForces, velocityScale, forceScale, shapes]);
|
|
38192
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
38193
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
|
|
38194
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
38195
|
+
LearningCanvas,
|
|
38196
|
+
{
|
|
38197
|
+
width,
|
|
38198
|
+
height,
|
|
38199
|
+
backgroundColor,
|
|
38200
|
+
shapes: derivedShapes,
|
|
38201
|
+
interactive,
|
|
38202
|
+
animate,
|
|
38203
|
+
onShapeClick,
|
|
38204
|
+
isLoading,
|
|
38205
|
+
error
|
|
38206
|
+
}
|
|
38207
|
+
)
|
|
38208
|
+
] }) });
|
|
38209
|
+
};
|
|
38210
|
+
}
|
|
38211
|
+
});
|
|
37459
38212
|
function resolveNodeColor(node, groups) {
|
|
37460
38213
|
if (node.color) return node.color;
|
|
37461
38214
|
if (node.group) {
|
|
@@ -37827,13 +38580,13 @@ var init_MapView = __esm({
|
|
|
37827
38580
|
shadowSize: [41, 41]
|
|
37828
38581
|
});
|
|
37829
38582
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
37830
|
-
const { useEffect:
|
|
38583
|
+
const { useEffect: useEffect79, useRef: useRef79, useCallback: useCallback118, useState: useState115 } = React114__namespace.default;
|
|
37831
38584
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
37832
38585
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
37833
38586
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
37834
38587
|
const map = useMap();
|
|
37835
|
-
const prevRef =
|
|
37836
|
-
|
|
38588
|
+
const prevRef = useRef79({ centerLat, centerLng, zoom });
|
|
38589
|
+
useEffect79(() => {
|
|
37837
38590
|
const prev = prevRef.current;
|
|
37838
38591
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
37839
38592
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -37844,7 +38597,7 @@ var init_MapView = __esm({
|
|
|
37844
38597
|
}
|
|
37845
38598
|
function MapClickHandler({ onMapClick }) {
|
|
37846
38599
|
const map = useMap();
|
|
37847
|
-
|
|
38600
|
+
useEffect79(() => {
|
|
37848
38601
|
if (!onMapClick) return;
|
|
37849
38602
|
const handler = (e) => {
|
|
37850
38603
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -45876,7 +46629,7 @@ function getGroupColor(group, groups) {
|
|
|
45876
46629
|
const idx = groups.indexOf(group);
|
|
45877
46630
|
return GROUP_COLORS2[idx % GROUP_COLORS2.length];
|
|
45878
46631
|
}
|
|
45879
|
-
function
|
|
46632
|
+
function resolveColor3(color, el) {
|
|
45880
46633
|
const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
|
|
45881
46634
|
if (!m) return color;
|
|
45882
46635
|
const resolved = getComputedStyle(el).getPropertyValue(m[1]).trim();
|
|
@@ -46137,7 +46890,7 @@ var init_GraphCanvas = __esm({
|
|
|
46137
46890
|
const w = logicalW;
|
|
46138
46891
|
const h = height;
|
|
46139
46892
|
const nodes = nodesRef.current;
|
|
46140
|
-
const accentColor =
|
|
46893
|
+
const accentColor = resolveColor3("var(--color-accent)", canvas);
|
|
46141
46894
|
const dpr = typeof window !== "undefined" && window.devicePixelRatio || 1;
|
|
46142
46895
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
46143
46896
|
ctx.clearRect(0, 0, w, h);
|
|
@@ -46176,7 +46929,7 @@ var init_GraphCanvas = __esm({
|
|
|
46176
46929
|
ctx.globalAlpha = 1;
|
|
46177
46930
|
for (const node of nodes) {
|
|
46178
46931
|
const size = node.size || 8;
|
|
46179
|
-
const color =
|
|
46932
|
+
const color = resolveColor3(node.color || getGroupColor(node.group, groups), canvas);
|
|
46180
46933
|
const isHovered = hoveredNode === node.id;
|
|
46181
46934
|
const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
|
|
46182
46935
|
ctx.globalAlpha = hoveredNode && !neighbors.has(node.id) ? 0.2 : 1;
|
|
@@ -53074,6 +53827,7 @@ var init_component_registry_generated = __esm({
|
|
|
53074
53827
|
init_BattleBoard();
|
|
53075
53828
|
init_BattleTemplate();
|
|
53076
53829
|
init_BehaviorView();
|
|
53830
|
+
init_BiologyCanvas();
|
|
53077
53831
|
init_BloomQuizBlock();
|
|
53078
53832
|
init_BoardgameBoard();
|
|
53079
53833
|
init_BookChapterView();
|
|
@@ -53103,6 +53857,7 @@ var init_component_registry_generated = __esm({
|
|
|
53103
53857
|
init_ChartLegend();
|
|
53104
53858
|
init_ChatBar();
|
|
53105
53859
|
init_Checkbox();
|
|
53860
|
+
init_ChemistryCanvas();
|
|
53106
53861
|
init_ChoiceButton();
|
|
53107
53862
|
init_CityBuilderBoard();
|
|
53108
53863
|
init_CityBuilderTemplate();
|
|
@@ -53194,6 +53949,7 @@ var init_component_registry_generated = __esm({
|
|
|
53194
53949
|
init_JazariStateMachine();
|
|
53195
53950
|
init_LandingPageTemplate();
|
|
53196
53951
|
init_LawReferenceTooltip();
|
|
53952
|
+
init_LearningCanvas();
|
|
53197
53953
|
init_Lightbox();
|
|
53198
53954
|
init_LikertScale();
|
|
53199
53955
|
init_LineChart();
|
|
@@ -53202,9 +53958,11 @@ var init_component_registry_generated = __esm({
|
|
|
53202
53958
|
init_MapView();
|
|
53203
53959
|
init_MarkdownContent();
|
|
53204
53960
|
init_MarketingFooter();
|
|
53961
|
+
init_MarketingStatCard();
|
|
53205
53962
|
init_MasterDetail();
|
|
53206
53963
|
init_MasterDetailLayout();
|
|
53207
53964
|
init_MatchPuzzleBoard();
|
|
53965
|
+
init_MathCanvas();
|
|
53208
53966
|
init_MatrixQuestion();
|
|
53209
53967
|
init_MediaGallery();
|
|
53210
53968
|
init_Menu();
|
|
@@ -53223,6 +53981,7 @@ var init_component_registry_generated = __esm({
|
|
|
53223
53981
|
init_PageHeader();
|
|
53224
53982
|
init_Pagination();
|
|
53225
53983
|
init_PatternTile();
|
|
53984
|
+
init_PhysicsCanvas();
|
|
53226
53985
|
init_PinballBoard();
|
|
53227
53986
|
init_PirateBoard();
|
|
53228
53987
|
init_PlatformerBoard();
|
|
@@ -53399,6 +54158,7 @@ var init_component_registry_generated = __esm({
|
|
|
53399
54158
|
"BattleBoard": BattleBoard,
|
|
53400
54159
|
"BattleTemplate": BattleTemplate,
|
|
53401
54160
|
"BehaviorView": exports.BehaviorView,
|
|
54161
|
+
"BiologyCanvas": BiologyCanvas,
|
|
53402
54162
|
"BloomQuizBlock": BloomQuizBlock,
|
|
53403
54163
|
"BoardgameBoard": BoardgameBoard,
|
|
53404
54164
|
"BookChapterView": BookChapterView,
|
|
@@ -53431,6 +54191,7 @@ var init_component_registry_generated = __esm({
|
|
|
53431
54191
|
"ChartLegend": ChartLegend,
|
|
53432
54192
|
"ChatBar": ChatBar,
|
|
53433
54193
|
"Checkbox": Checkbox,
|
|
54194
|
+
"ChemistryCanvas": ChemistryCanvas,
|
|
53434
54195
|
"ChoiceButton": ChoiceButton,
|
|
53435
54196
|
"CityBuilderBoard": CityBuilderBoard,
|
|
53436
54197
|
"CityBuilderTemplate": CityBuilderTemplate,
|
|
@@ -53532,6 +54293,7 @@ var init_component_registry_generated = __esm({
|
|
|
53532
54293
|
"LabelPattern": LabelPattern,
|
|
53533
54294
|
"LandingPageTemplate": LandingPageTemplate,
|
|
53534
54295
|
"LawReferenceTooltip": LawReferenceTooltip,
|
|
54296
|
+
"LearningCanvas": LearningCanvas,
|
|
53535
54297
|
"Lightbox": Lightbox,
|
|
53536
54298
|
"LikertScale": LikertScale,
|
|
53537
54299
|
"LineChart": LineChart2,
|
|
@@ -53540,9 +54302,11 @@ var init_component_registry_generated = __esm({
|
|
|
53540
54302
|
"MapView": MapView,
|
|
53541
54303
|
"MarkdownContent": MarkdownContent,
|
|
53542
54304
|
"MarketingFooter": MarketingFooter,
|
|
54305
|
+
"MarketingStatCard": MarketingStatCard,
|
|
53543
54306
|
"MasterDetail": MasterDetail,
|
|
53544
54307
|
"MasterDetailLayout": MasterDetailLayout,
|
|
53545
54308
|
"MatchPuzzleBoard": MatchPuzzleBoard,
|
|
54309
|
+
"MathCanvas": MathCanvas,
|
|
53546
54310
|
"MatrixQuestion": MatrixQuestion,
|
|
53547
54311
|
"MediaGallery": MediaGallery,
|
|
53548
54312
|
"Menu": Menu,
|
|
@@ -53561,6 +54325,7 @@ var init_component_registry_generated = __esm({
|
|
|
53561
54325
|
"PageHeader": PageHeader,
|
|
53562
54326
|
"Pagination": Pagination,
|
|
53563
54327
|
"PatternTile": PatternTile,
|
|
54328
|
+
"PhysicsCanvas": PhysicsCanvas,
|
|
53564
54329
|
"PinballBoard": PinballBoard,
|
|
53565
54330
|
"PirateBoard": PirateBoard,
|
|
53566
54331
|
"PlatformerBoard": PlatformerBoard,
|