@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.
Files changed (71) hide show
  1. package/dist/avl/index.cjs +863 -98
  2. package/dist/avl/index.css +3 -3
  3. package/dist/avl/index.js +863 -98
  4. package/dist/components/core/atoms/FlipContainer.d.ts +1 -1
  5. package/dist/components/core/atoms/index.d.ts +2 -1
  6. package/dist/components/core/molecules/Card.d.ts +1 -1
  7. package/dist/components/core/molecules/DataGrid.d.ts +1 -1
  8. package/dist/components/core/molecules/DataList.d.ts +1 -1
  9. package/dist/components/core/molecules/DocPagination.d.ts +8 -1
  10. package/dist/components/core/molecules/DocSearch.d.ts +8 -1
  11. package/dist/components/core/molecules/FlipCard.d.ts +1 -1
  12. package/dist/components/core/molecules/MapView.d.ts +18 -1
  13. package/dist/components/core/molecules/PropertyInspector.d.ts +2 -0
  14. package/dist/components/core/molecules/SortableList.d.ts +1 -1
  15. package/dist/components/core/molecules/TableView.d.ts +1 -1
  16. package/dist/components/core/molecules/index.d.ts +4 -0
  17. package/dist/components/core/organisms/DataTable.d.ts +1 -1
  18. package/dist/components/core/organisms/debug/RuntimeDebugger.d.ts +10 -1
  19. package/dist/components/core/organisms/debug/tabs/EntitiesTab.d.ts +2 -1
  20. package/dist/components/core/organisms/debug/tabs/EventDispatcherTab.d.ts +2 -1
  21. package/dist/components/core/organisms/debug/tabs/EventFlowTab.d.ts +6 -1
  22. package/dist/components/core/organisms/debug/tabs/GuardsPanel.d.ts +6 -1
  23. package/dist/components/core/organisms/debug/tabs/ServerBridgeTab.d.ts +12 -1
  24. package/dist/components/core/organisms/debug/tabs/TicksTab.d.ts +2 -1
  25. package/dist/components/core/organisms/debug/tabs/TraitsTab.d.ts +2 -1
  26. package/dist/components/core/organisms/debug/tabs/TransitionTimeline.d.ts +11 -1
  27. package/dist/components/core/organisms/debug/tabs/VerificationTab.d.ts +8 -1
  28. package/dist/components/game/2d/atoms/ActionButton.d.ts +2 -1
  29. package/dist/components/game/2d/atoms/ChoiceButton.d.ts +2 -1
  30. package/dist/components/game/2d/atoms/ComboCounter.d.ts +2 -1
  31. package/dist/components/game/2d/atoms/ControlButton.d.ts +2 -1
  32. package/dist/components/game/2d/atoms/DamageNumber.d.ts +2 -1
  33. package/dist/components/game/2d/atoms/DialogueBubble.d.ts +2 -1
  34. package/dist/components/game/2d/atoms/GameIcon.d.ts +2 -1
  35. package/dist/components/game/2d/atoms/HealthBar.d.ts +2 -1
  36. package/dist/components/game/2d/atoms/ItemSlot.d.ts +2 -1
  37. package/dist/components/game/2d/atoms/MiniMap.d.ts +2 -1
  38. package/dist/components/game/2d/atoms/ResourceCounter.d.ts +2 -1
  39. package/dist/components/game/2d/atoms/ScoreDisplay.d.ts +2 -1
  40. package/dist/components/game/2d/atoms/StatusEffect.d.ts +2 -1
  41. package/dist/components/game/2d/atoms/TimerDisplay.d.ts +2 -1
  42. package/dist/components/game/2d/atoms/TurnIndicator.d.ts +2 -1
  43. package/dist/components/game/2d/atoms/WaypointMarker.d.ts +2 -1
  44. package/dist/components/game/2d/molecules/GameHud.d.ts +2 -1
  45. package/dist/components/game/2d/molecules/GameMenu.d.ts +2 -1
  46. package/dist/components/game/2d/molecules/InventoryGrid.d.ts +2 -1
  47. package/dist/components/game/2d/molecules/ResourceBar.d.ts +2 -1
  48. package/dist/components/game/2d/molecules/StatBadge.d.ts +2 -1
  49. package/dist/components/game/shared/lib/editorUtils.d.ts +8 -8
  50. package/dist/components/index.cjs +2212 -1525
  51. package/dist/components/index.css +3 -3
  52. package/dist/components/index.js +1002 -315
  53. package/dist/components/learning/atoms/LearningCanvas.d.ts +80 -0
  54. package/dist/components/learning/molecules/BiologyCanvas.d.ts +47 -0
  55. package/dist/components/learning/molecules/ChemistryCanvas.d.ts +55 -0
  56. package/dist/components/learning/molecules/MathCanvas.d.ts +61 -0
  57. package/dist/components/learning/molecules/PhysicsCanvas.d.ts +54 -0
  58. package/dist/components/marketing/atoms/MarketingStatCard.d.ts +2 -2
  59. package/dist/hooks/useGitHub.d.ts +7 -7
  60. package/dist/marketing/index.cjs +2 -2
  61. package/dist/marketing/index.js +2 -2
  62. package/dist/providers/EventBusProvider.d.ts +1 -1
  63. package/dist/providers/SelectionProvider.d.ts +1 -1
  64. package/dist/providers/ServerBridge.d.ts +1 -1
  65. package/dist/providers/index.cjs +859 -94
  66. package/dist/providers/index.css +3 -3
  67. package/dist/providers/index.js +859 -94
  68. package/dist/runtime/index.cjs +859 -94
  69. package/dist/runtime/index.css +3 -3
  70. package/dist/runtime/index.js +859 -94
  71. package/package.json +1 -1
@@ -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: useEffect78, useRef: useRef78, useCallback: useCallback118, useState: useState115 } = React114__namespace.default;
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 = useRef78({ centerLat, centerLng, zoom });
37836
- useEffect78(() => {
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
- useEffect78(() => {
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 resolveColor2(color, el) {
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 = resolveColor2("var(--color-accent)", canvas);
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 = resolveColor2(node.color || getGroupColor(node.group, groups), canvas);
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,