@almadar/ui 5.32.2 → 5.32.3

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.
@@ -28819,7 +28819,7 @@ var init_MapView = __esm({
28819
28819
  shadowSize: [41, 41]
28820
28820
  });
28821
28821
  L.Marker.prototype.options.icon = defaultIcon;
28822
- const { useEffect: useEffect72, useRef: useRef69, useCallback: useCallback114, useState: useState101 } = React74__namespace.default;
28822
+ const { useEffect: useEffect72, useRef: useRef69, useCallback: useCallback115, useState: useState105 } = React74__namespace.default;
28823
28823
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
28824
28824
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
28825
28825
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -28864,8 +28864,8 @@ var init_MapView = __esm({
28864
28864
  showAttribution = true
28865
28865
  }) {
28866
28866
  const eventBus = useEventBus2();
28867
- const [clickedPosition, setClickedPosition] = useState101(null);
28868
- const handleMapClick = useCallback114((lat, lng) => {
28867
+ const [clickedPosition, setClickedPosition] = useState105(null);
28868
+ const handleMapClick = useCallback115((lat, lng) => {
28869
28869
  if (showClickedPin) {
28870
28870
  setClickedPosition({ lat, lng });
28871
28871
  }
@@ -28874,7 +28874,7 @@ var init_MapView = __esm({
28874
28874
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
28875
28875
  }
28876
28876
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
28877
- const handleMarkerClick = useCallback114((marker) => {
28877
+ const handleMarkerClick = useCallback115((marker) => {
28878
28878
  onMarkerClick?.(marker);
28879
28879
  if (markerClickEvent) {
28880
28880
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -37577,6 +37577,384 @@ var init_GraphCanvas = __esm({
37577
37577
  exports.GraphCanvas.displayName = "GraphCanvas";
37578
37578
  }
37579
37579
  });
37580
+ exports.ActivationBlock = void 0;
37581
+ var init_ActivationBlock = __esm({
37582
+ "components/core/molecules/ActivationBlock.tsx"() {
37583
+ "use client";
37584
+ init_useEventBus();
37585
+ init_cn();
37586
+ exports.ActivationBlock = ({
37587
+ question,
37588
+ savedResponse,
37589
+ saveEvent = "SAVE_ACTIVATION",
37590
+ className
37591
+ }) => {
37592
+ const [response, setResponse] = React74.useState(savedResponse ?? "");
37593
+ const [isExpanded, setIsExpanded] = React74.useState(!savedResponse);
37594
+ const { emit } = useEventBus();
37595
+ const handleSubmit = () => {
37596
+ emit(`UI:${saveEvent}`, { response });
37597
+ setIsExpanded(false);
37598
+ };
37599
+ return /* @__PURE__ */ jsxRuntime.jsx(
37600
+ "div",
37601
+ {
37602
+ className: cn(
37603
+ "bg-indigo-50 dark:bg-indigo-900/20 border-2 border-indigo-200 dark:border-indigo-800 rounded-lg p-5 mb-6",
37604
+ className
37605
+ ),
37606
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
37607
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.Lightbulb, { className: "text-indigo-600 dark:text-indigo-400 flex-shrink-0 mt-1", size: 24 }),
37608
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
37609
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-indigo-900 dark:text-indigo-100 mb-2", children: "Before You Begin..." }),
37610
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-700 dark:text-gray-300 mb-3 text-sm md:text-base", children: question }),
37611
+ isExpanded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
37612
+ /* @__PURE__ */ jsxRuntime.jsx(
37613
+ "textarea",
37614
+ {
37615
+ className: "w-full p-3 border border-indigo-300 dark:border-indigo-700 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-indigo-500 focus:border-transparent text-sm",
37616
+ placeholder: "Jot down your thoughts...",
37617
+ value: response,
37618
+ onChange: (e) => setResponse(e.target.value),
37619
+ rows: 3
37620
+ }
37621
+ ),
37622
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 mt-3", children: [
37623
+ /* @__PURE__ */ jsxRuntime.jsx(
37624
+ "button",
37625
+ {
37626
+ onClick: handleSubmit,
37627
+ className: "px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 text-sm font-medium transition-colors",
37628
+ children: "Continue to Lesson \u2192"
37629
+ }
37630
+ ),
37631
+ /* @__PURE__ */ jsxRuntime.jsx(
37632
+ "button",
37633
+ {
37634
+ onClick: () => {
37635
+ emit(`UI:${saveEvent}`, { response: "" });
37636
+ setIsExpanded(false);
37637
+ },
37638
+ className: "px-4 py-2 text-indigo-600 dark:text-indigo-400 hover:underline text-sm",
37639
+ children: "Skip for now"
37640
+ }
37641
+ )
37642
+ ] })
37643
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
37644
+ "button",
37645
+ {
37646
+ onClick: () => setIsExpanded(true),
37647
+ className: "text-sm text-indigo-600 dark:text-indigo-400 hover:underline font-medium",
37648
+ children: "\u2713 Answered \xB7 Edit response"
37649
+ }
37650
+ )
37651
+ ] })
37652
+ ] })
37653
+ }
37654
+ );
37655
+ };
37656
+ exports.ActivationBlock.displayName = "ActivationBlock";
37657
+ }
37658
+ });
37659
+ exports.ReflectionBlock = void 0;
37660
+ var init_ReflectionBlock = __esm({
37661
+ "components/core/molecules/ReflectionBlock.tsx"() {
37662
+ "use client";
37663
+ init_useEventBus();
37664
+ init_cn();
37665
+ exports.ReflectionBlock = ({
37666
+ prompt,
37667
+ index,
37668
+ savedNote,
37669
+ saveEvent = "SAVE_REFLECTION",
37670
+ className
37671
+ }) => {
37672
+ const [note, setNote] = React74.useState(savedNote ?? "");
37673
+ const [isExpanded, setIsExpanded] = React74.useState(false);
37674
+ const { emit } = useEventBus();
37675
+ const handleSave = () => {
37676
+ emit(`UI:${saveEvent}`, { index, note });
37677
+ setIsExpanded(false);
37678
+ };
37679
+ return /* @__PURE__ */ jsxRuntime.jsx(
37680
+ "div",
37681
+ {
37682
+ className: cn(
37683
+ "my-6 border-l-4 border-amber-400 bg-amber-50 dark:bg-amber-900/20 rounded-r-lg p-4",
37684
+ className
37685
+ ),
37686
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
37687
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.PauseCircle, { className: "text-amber-600 dark:text-amber-400 flex-shrink-0 mt-1", size: 20 }),
37688
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
37689
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-amber-900 dark:text-amber-100 mb-2", children: "Pause & Reflect" }),
37690
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-700 dark:text-gray-300 text-sm mb-3", children: prompt }),
37691
+ isExpanded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
37692
+ /* @__PURE__ */ jsxRuntime.jsx(
37693
+ "textarea",
37694
+ {
37695
+ className: "w-full p-2 border border-amber-300 dark:border-amber-700 rounded text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-amber-500 focus:border-transparent",
37696
+ placeholder: "Your thoughts...",
37697
+ value: note,
37698
+ onChange: (e) => setNote(e.target.value),
37699
+ rows: 2
37700
+ }
37701
+ ),
37702
+ /* @__PURE__ */ jsxRuntime.jsx(
37703
+ "button",
37704
+ {
37705
+ onClick: handleSave,
37706
+ className: "mt-2 text-sm px-3 py-1 bg-amber-600 text-white rounded hover:bg-amber-700 transition-colors",
37707
+ children: "Save & Continue"
37708
+ }
37709
+ )
37710
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
37711
+ "button",
37712
+ {
37713
+ onClick: () => setIsExpanded(true),
37714
+ className: "text-sm text-amber-600 dark:text-amber-400 hover:underline",
37715
+ children: savedNote ? "\u2713 Answered \xB7 Edit" : "Answer this question"
37716
+ }
37717
+ )
37718
+ ] })
37719
+ ] })
37720
+ }
37721
+ );
37722
+ };
37723
+ exports.ReflectionBlock.displayName = "ReflectionBlock";
37724
+ }
37725
+ });
37726
+ exports.ConnectionBlock = void 0;
37727
+ var init_ConnectionBlock = __esm({
37728
+ "components/core/molecules/ConnectionBlock.tsx"() {
37729
+ "use client";
37730
+ init_MarkdownContent();
37731
+ init_cn();
37732
+ exports.ConnectionBlock = ({ content, className }) => /* @__PURE__ */ jsxRuntime.jsx(
37733
+ "div",
37734
+ {
37735
+ className: cn(
37736
+ "bg-emerald-50 dark:bg-emerald-900/20 border-l-4 border-emerald-500 rounded-r-lg p-5 mb-6",
37737
+ className
37738
+ ),
37739
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
37740
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.Link2, { className: "text-emerald-600 dark:text-emerald-400 flex-shrink-0 mt-1", size: 20 }),
37741
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
37742
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-emerald-900 dark:text-emerald-100 mb-2", children: "Building On What You Know" }),
37743
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose dark:prose-invert prose-sm max-w-none text-gray-700 dark:text-gray-300", children: /* @__PURE__ */ jsxRuntime.jsx(exports.MarkdownContent, { content }) })
37744
+ ] })
37745
+ ] })
37746
+ }
37747
+ );
37748
+ exports.ConnectionBlock.displayName = "ConnectionBlock";
37749
+ }
37750
+ });
37751
+
37752
+ // components/core/molecules/lessonSegmentUtils.ts
37753
+ function parseMarkdownWithCodeBlocks2(content) {
37754
+ const segments = [];
37755
+ const codeBlockRegex = /```([\w-]+)?(?:\s+(run))?\n([\s\S]*?)```/g;
37756
+ let lastIndex = 0;
37757
+ let match;
37758
+ while ((match = codeBlockRegex.exec(content)) !== null) {
37759
+ const before = content.slice(lastIndex, match.index);
37760
+ if (before.trim()) {
37761
+ segments.push({ type: "markdown", content: before });
37762
+ }
37763
+ const rawLanguage = match[1] ?? "text";
37764
+ const runModifier = !!match[2];
37765
+ const suffixRunnable = rawLanguage.endsWith("-runnable");
37766
+ const runnable = runModifier || suffixRunnable;
37767
+ const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
37768
+ segments.push({ type: "code", language: baseLanguage, content: match[3].trim(), runnable });
37769
+ lastIndex = codeBlockRegex.lastIndex;
37770
+ }
37771
+ const remaining = content.slice(lastIndex);
37772
+ if (remaining.trim()) {
37773
+ segments.push({ type: "markdown", content: remaining });
37774
+ }
37775
+ return segments;
37776
+ }
37777
+ var init_lessonSegmentUtils = __esm({
37778
+ "components/core/molecules/lessonSegmentUtils.ts"() {
37779
+ }
37780
+ });
37781
+ var BLOOM_CONFIG; exports.BloomQuizBlock = void 0;
37782
+ var init_BloomQuizBlock = __esm({
37783
+ "components/core/molecules/BloomQuizBlock.tsx"() {
37784
+ "use client";
37785
+ init_MarkdownContent();
37786
+ init_CodeBlock();
37787
+ init_lessonSegmentUtils();
37788
+ init_useEventBus();
37789
+ init_cn();
37790
+ BLOOM_CONFIG = {
37791
+ remember: { color: "bg-gray-500", bgColor: "bg-gray-50 dark:bg-gray-900/30", label: "Remember" },
37792
+ understand: { color: "bg-blue-500", bgColor: "bg-blue-50 dark:bg-blue-900/30", label: "Understand" },
37793
+ apply: { color: "bg-green-500", bgColor: "bg-green-50 dark:bg-green-900/30", label: "Apply" },
37794
+ analyze: { color: "bg-yellow-500", bgColor: "bg-yellow-50 dark:bg-yellow-900/30", label: "Analyze" },
37795
+ evaluate: { color: "bg-orange-500", bgColor: "bg-orange-50 dark:bg-orange-900/30", label: "Evaluate" },
37796
+ create: { color: "bg-purple-500", bgColor: "bg-purple-50 dark:bg-purple-900/30", label: "Create" }
37797
+ };
37798
+ exports.BloomQuizBlock = ({
37799
+ level,
37800
+ question,
37801
+ answer,
37802
+ index,
37803
+ isAnswered,
37804
+ answerEvent = "ANSWER_BLOOM",
37805
+ className
37806
+ }) => {
37807
+ const [revealed, setRevealed] = React74.useState(false);
37808
+ const config = BLOOM_CONFIG[level];
37809
+ const { emit } = useEventBus();
37810
+ const questionSegments = React74.useMemo(() => parseMarkdownWithCodeBlocks2(question), [question]);
37811
+ const answerSegments = React74.useMemo(() => parseMarkdownWithCodeBlocks2(answer), [answer]);
37812
+ const handleReveal = () => {
37813
+ if (!revealed) {
37814
+ emit(`UI:${answerEvent}`, { index: index ?? 0, level });
37815
+ }
37816
+ setRevealed(!revealed);
37817
+ };
37818
+ return /* @__PURE__ */ jsxRuntime.jsxs(
37819
+ "div",
37820
+ {
37821
+ className: cn(
37822
+ "rounded-lg border border-indigo-100 dark:border-indigo-800 p-4 my-4 transition-all",
37823
+ config.bgColor,
37824
+ className
37825
+ ),
37826
+ children: [
37827
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
37828
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
37829
+ index !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-500 dark:text-gray-400 font-medium text-sm", children: [
37830
+ "Question ",
37831
+ index + 1
37832
+ ] }),
37833
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(config.color, "text-white text-xs px-2 py-1 rounded-full font-medium"), children: config.label })
37834
+ ] }),
37835
+ isAnswered && /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.CheckCircle, { className: "text-green-600 dark:text-green-400 flex-shrink-0", size: 20 })
37836
+ ] }),
37837
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-indigo-900 dark:text-indigo-200 mb-3 space-y-2", children: questionSegments.map(
37838
+ (segment, idx) => segment.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(exports.MarkdownContent, { content: segment.content }, `q-md-${idx}`) : /* @__PURE__ */ jsxRuntime.jsx(
37839
+ exports.CodeBlock,
37840
+ {
37841
+ language: segment.language ?? "text",
37842
+ code: segment.content
37843
+ },
37844
+ `q-code-${idx}`
37845
+ )
37846
+ ) }),
37847
+ /* @__PURE__ */ jsxRuntime.jsx(
37848
+ "button",
37849
+ {
37850
+ type: "button",
37851
+ className: "inline-flex items-center rounded-md bg-indigo-600 dark:bg-indigo-500 px-3 py-1.5 text-sm font-medium text-white hover:bg-indigo-700 dark:hover:bg-indigo-600 transition-colors",
37852
+ onClick: handleReveal,
37853
+ children: revealed ? "Hide Answer" : "Reveal Answer"
37854
+ }
37855
+ ),
37856
+ revealed && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-white/80 dark:bg-gray-800/80 p-3 text-sm text-slate-800 dark:text-gray-200 shadow-sm border border-indigo-100 dark:border-indigo-800 mt-3 space-y-2", children: [
37857
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-600 dark:text-gray-400 mb-1 font-medium uppercase tracking-wide", children: "Answer:" }),
37858
+ answerSegments.map(
37859
+ (segment, idx) => segment.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(exports.MarkdownContent, { content: segment.content }, `a-md-${idx}`) : /* @__PURE__ */ jsxRuntime.jsx(
37860
+ exports.CodeBlock,
37861
+ {
37862
+ language: segment.language ?? "text",
37863
+ code: segment.content
37864
+ },
37865
+ `a-code-${idx}`
37866
+ )
37867
+ )
37868
+ ] })
37869
+ ]
37870
+ }
37871
+ );
37872
+ };
37873
+ exports.BloomQuizBlock.displayName = "BloomQuizBlock";
37874
+ }
37875
+ });
37876
+
37877
+ // components/core/molecules/parseLessonSegments.ts
37878
+ function extractTagContent(content, tagName) {
37879
+ const closedTagRegex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, "i");
37880
+ const closedMatch = content.match(closedTagRegex);
37881
+ if (closedMatch) {
37882
+ return { content: closedMatch[1].trim(), fullMatch: closedMatch[0] };
37883
+ }
37884
+ const unclosedTagRegex = new RegExp(
37885
+ `<${tagName}>([\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$)`,
37886
+ "i"
37887
+ );
37888
+ const unclosedMatch = content.match(unclosedTagRegex);
37889
+ if (unclosedMatch) {
37890
+ return { content: unclosedMatch[1].trim(), fullMatch: unclosedMatch[0] };
37891
+ }
37892
+ return null;
37893
+ }
37894
+ function parseLessonSegments(lesson) {
37895
+ if (!lesson) return [];
37896
+ let content = lesson.replace(/<prq>[\s\S]*?<\/prq>/gi, "").trim();
37897
+ const segments = [];
37898
+ const activateResult = extractTagContent(content, "activate");
37899
+ if (activateResult) {
37900
+ segments.push({ type: "activate", question: activateResult.content });
37901
+ content = content.replace(activateResult.fullMatch, "").trim();
37902
+ }
37903
+ const connectResult = extractTagContent(content, "connect");
37904
+ if (connectResult) {
37905
+ segments.push({ type: "connect", content: connectResult.content });
37906
+ content = content.replace(connectResult.fullMatch, "").trim();
37907
+ }
37908
+ const tagRegex = new RegExp(
37909
+ '(?<reflect><reflect>(?<reflectClosed>[\\s\\S]*?)<\\/reflect>)|(?<reflectUnclosed><reflect>(?<reflectOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<bloom><bloom\\s+level="(?<bloomLevel>remember|understand|apply|analyze|evaluate|create)">(?<bloomClosed>[\\s\\S]*?)<\\/bloom>)|(?<bloomUnclosed><bloom\\s+level="(?<bloomLevelUn>remember|understand|apply|analyze|evaluate|create)">(?<bloomOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<quiz><question>(?<quizQuestion>[\\s\\S]*?)<\\/question>\\s*<answer>(?<quizAnswer>[\\s\\S]*?)<\\/answer>)|(?<visualize><visualize\\s+type="(?<vizType>chart|simulation)"\\s+description="(?<vizDesc>[^"]*?)"\\s*\\/?>)',
37910
+ "gi"
37911
+ );
37912
+ let lastIndex = 0;
37913
+ let match;
37914
+ while ((match = tagRegex.exec(content)) !== null) {
37915
+ const before = content.slice(lastIndex, match.index);
37916
+ if (before.trim()) {
37917
+ segments.push(...parseMarkdownWithCodeBlocks2(before));
37918
+ }
37919
+ const g = match.groups ?? {};
37920
+ if (g.reflect || g.reflectUnclosed) {
37921
+ const prompt = (g.reflectClosed ?? g.reflectOpen ?? "").trim();
37922
+ if (prompt) segments.push({ type: "reflect", prompt });
37923
+ } else if (g.bloom || g.bloomUnclosed) {
37924
+ const level = g.bloomLevel ?? g.bloomLevelUn;
37925
+ const bloomContent = g.bloomClosed ?? g.bloomOpen ?? "";
37926
+ if (level && bloomContent) {
37927
+ const qMatch = bloomContent.match(/<question>([\s\S]*?)<\/question>/i);
37928
+ const aMatch = bloomContent.match(/<answer>([\s\S]*?)<\/answer>/i);
37929
+ if (qMatch && aMatch) {
37930
+ segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: aMatch[1].trim() });
37931
+ } else if (qMatch) {
37932
+ segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: "(Answer not provided)" });
37933
+ } else {
37934
+ const clean = bloomContent.replace(/^\*\*Question\s*\d*:?\*\*\s*/i, "").replace(/^\*\*Q\d*:?\*\*\s*/i, "").trim();
37935
+ if (clean) segments.push({ type: "bloom", level, question: clean, answer: "(See answers section below)" });
37936
+ }
37937
+ }
37938
+ } else if (g.quiz) {
37939
+ segments.push({ type: "quiz", question: g.quizQuestion.trim(), answer: g.quizAnswer.trim() });
37940
+ } else if (g.visualize) {
37941
+ segments.push({
37942
+ type: "visualization",
37943
+ visualizationType: g.vizType,
37944
+ description: g.vizDesc ?? ""
37945
+ });
37946
+ }
37947
+ lastIndex = tagRegex.lastIndex;
37948
+ }
37949
+ const remaining = content.slice(lastIndex);
37950
+ if (remaining.trim()) segments.push(...parseMarkdownWithCodeBlocks2(remaining));
37951
+ return segments;
37952
+ }
37953
+ var init_parseLessonSegments = __esm({
37954
+ "components/core/molecules/parseLessonSegments.ts"() {
37955
+ init_lessonSegmentUtils();
37956
+ }
37957
+ });
37580
37958
 
37581
37959
  // components/core/molecules/index.ts
37582
37960
  var init_molecules2 = __esm({
@@ -37708,6 +38086,12 @@ var init_molecules2 = __esm({
37708
38086
  init_SignaturePad();
37709
38087
  init_DocumentViewer();
37710
38088
  init_GraphCanvas();
38089
+ init_ActivationBlock();
38090
+ init_ReflectionBlock();
38091
+ init_ConnectionBlock();
38092
+ init_BloomQuizBlock();
38093
+ init_parseLessonSegments();
38094
+ init_lessonSegmentUtils();
37711
38095
  }
37712
38096
  });
37713
38097
 
@@ -50091,6 +50475,271 @@ init_ShowcaseOrganism();
50091
50475
  init_TeamOrganism();
50092
50476
  init_CaseStudyOrganism();
50093
50477
 
50478
+ // components/core/organisms/CodeRunnerPanel.tsx
50479
+ init_Box();
50480
+ init_Button();
50481
+ init_Badge();
50482
+ init_Typography();
50483
+ init_Stack();
50484
+ init_CodeBlock();
50485
+ init_useEventBus();
50486
+ init_cn();
50487
+ var CodeRunnerPanel = ({
50488
+ code: initialCode,
50489
+ language,
50490
+ runnable = true,
50491
+ onRun,
50492
+ runEvent = "RUN_CODE",
50493
+ className
50494
+ }) => {
50495
+ const eventBus = useEventBus();
50496
+ const { t } = hooks.useTranslate();
50497
+ const [code, setCode] = React74.useState(initialCode);
50498
+ const [output, setOutput] = React74.useState(null);
50499
+ const [error, setError] = React74.useState(null);
50500
+ const [isRunning, setIsRunning] = React74.useState(false);
50501
+ const handleRun = React74.useCallback(async () => {
50502
+ if (!onRun) return;
50503
+ setIsRunning(true);
50504
+ setError(null);
50505
+ setOutput(null);
50506
+ try {
50507
+ const result = await onRun(code);
50508
+ setOutput(result);
50509
+ eventBus.emit(`UI:${runEvent}`, { language, exitCode: result.exitCode });
50510
+ } catch (err) {
50511
+ const message = err instanceof Error ? err.message : t("common.error");
50512
+ setError(message);
50513
+ eventBus.emit(`UI:${runEvent}`, { language, exitCode: 1, error: message });
50514
+ } finally {
50515
+ setIsRunning(false);
50516
+ }
50517
+ }, [code, language, onRun, runEvent, eventBus, t]);
50518
+ const handleReset = React74.useCallback(() => {
50519
+ setCode(initialCode);
50520
+ setOutput(null);
50521
+ setError(null);
50522
+ }, [initialCode]);
50523
+ if (!runnable || !onRun) {
50524
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className, children: /* @__PURE__ */ jsxRuntime.jsx(exports.CodeBlock, { language, code }) });
50525
+ }
50526
+ const hasOutput = output !== null || error !== null;
50527
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: cn("space-y-3", className), children: [
50528
+ /* @__PURE__ */ jsxRuntime.jsx(
50529
+ exports.CodeBlock,
50530
+ {
50531
+ language,
50532
+ code,
50533
+ editable: true,
50534
+ onChange: setCode,
50535
+ showLanguageBadge: true,
50536
+ showCopyButton: true
50537
+ }
50538
+ ),
50539
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", justify: "between", children: [
50540
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", children: [
50541
+ /* @__PURE__ */ jsxRuntime.jsx(
50542
+ exports.Button,
50543
+ {
50544
+ variant: "primary",
50545
+ size: "sm",
50546
+ onClick: handleRun,
50547
+ disabled: isRunning,
50548
+ className: "min-w-[5rem]",
50549
+ children: isRunning ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", children: [
50550
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.RotateCcw, { size: 16, className: "animate-spin" }),
50551
+ t("common.loading")
50552
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", children: [
50553
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.Play, { size: 16 }),
50554
+ "Run"
50555
+ ] })
50556
+ }
50557
+ ),
50558
+ /* @__PURE__ */ jsxRuntime.jsx(
50559
+ exports.Button,
50560
+ {
50561
+ variant: "secondary",
50562
+ size: "sm",
50563
+ onClick: handleReset,
50564
+ disabled: isRunning,
50565
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", children: [
50566
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.RotateCcw, { size: 16 }),
50567
+ "Reset"
50568
+ ] })
50569
+ }
50570
+ )
50571
+ ] }),
50572
+ output && /* @__PURE__ */ jsxRuntime.jsxs(
50573
+ exports.Badge,
50574
+ {
50575
+ variant: output.exitCode === 0 ? "success" : "danger",
50576
+ size: "sm",
50577
+ children: [
50578
+ "Exit ",
50579
+ output.exitCode
50580
+ ]
50581
+ }
50582
+ )
50583
+ ] }),
50584
+ hasOutput && /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "rounded-lg border border-gray-700 bg-[#0d0d0d] overflow-hidden", children: [
50585
+ /* @__PURE__ */ jsxRuntime.jsxs(
50586
+ exports.HStack,
50587
+ {
50588
+ gap: "sm",
50589
+ align: "center",
50590
+ className: "px-3 py-2 bg-gray-800 border-b border-gray-700",
50591
+ children: [
50592
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.Terminal, { size: 16, className: "text-gray-400" }),
50593
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "text-gray-300 font-medium", children: "Output" })
50594
+ ]
50595
+ }
50596
+ ),
50597
+ /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "none", className: "p-3 font-mono text-sm", children: error ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "text-red-400 whitespace-pre-wrap", children: error }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
50598
+ output?.stdout ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "text-gray-200 whitespace-pre-wrap", children: output.stdout }) : null,
50599
+ output?.stderr ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "text-red-400 whitespace-pre-wrap", children: output.stderr }) : null,
50600
+ !output?.stdout && !output?.stderr ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "text-gray-500 italic", children: "No output" }) : null,
50601
+ output && output.testResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mt-3 pt-3 border-t border-gray-700 space-y-2", children: output.testResults.map((test, index) => /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", align: "start", className: "text-xs", children: [
50602
+ test.passed ? /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.CheckCircle, { size: 14, className: "text-green-400 mt-0.5" }) : /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.XCircle, { size: 14, className: "text-red-400 mt-0.5" }),
50603
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", className: "flex-1", children: [
50604
+ /* @__PURE__ */ jsxRuntime.jsxs(
50605
+ exports.Typography,
50606
+ {
50607
+ variant: "small",
50608
+ className: test.passed ? "text-green-400" : "text-red-400",
50609
+ children: [
50610
+ "Test ",
50611
+ index + 1,
50612
+ ": ",
50613
+ test.passed ? "passed" : "failed"
50614
+ ]
50615
+ }
50616
+ ),
50617
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "text-gray-400", children: [
50618
+ "Input: ",
50619
+ test.input
50620
+ ] }),
50621
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "text-gray-400", children: [
50622
+ "Expected: ",
50623
+ test.expectedOutput
50624
+ ] }),
50625
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "text-gray-400", children: [
50626
+ "Actual: ",
50627
+ test.actualOutput
50628
+ ] })
50629
+ ] })
50630
+ ] }, index)) })
50631
+ ] }) })
50632
+ ] })
50633
+ ] });
50634
+ };
50635
+ CodeRunnerPanel.displayName = "CodeRunnerPanel";
50636
+
50637
+ // components/core/organisms/SegmentRenderer.tsx
50638
+ init_MarkdownContent();
50639
+ init_CodeBlock();
50640
+ init_QuizBlock();
50641
+ init_ActivationBlock();
50642
+ init_ConnectionBlock();
50643
+ init_ReflectionBlock();
50644
+ init_BloomQuizBlock();
50645
+ init_cn();
50646
+ var SegmentRenderer = ({
50647
+ segments,
50648
+ className,
50649
+ containerClassName,
50650
+ userProgress,
50651
+ onRunCodeSimulation,
50652
+ onRenderVisualization
50653
+ }) => {
50654
+ if (segments.length === 0) return null;
50655
+ let reflectIndex = 0;
50656
+ let bloomIndex = 0;
50657
+ return /* @__PURE__ */ jsxRuntime.jsx(
50658
+ "div",
50659
+ {
50660
+ className: cn(
50661
+ "border border-gray-200 dark:border-gray-700 rounded-lg p-2 md:p-4 overflow-x-auto space-y-6",
50662
+ containerClassName,
50663
+ className
50664
+ ),
50665
+ children: segments.map((segment, index) => {
50666
+ if (segment.type === "markdown") {
50667
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.MarkdownContent, { content: segment.content }, `md-${index}`);
50668
+ }
50669
+ if (segment.type === "code") {
50670
+ if (segment.runnable && onRunCodeSimulation) {
50671
+ return /* @__PURE__ */ jsxRuntime.jsx(
50672
+ CodeRunnerPanel,
50673
+ {
50674
+ language: segment.language,
50675
+ code: segment.content,
50676
+ runnable: true,
50677
+ onRun: (code) => onRunCodeSimulation(code, segment.language)
50678
+ },
50679
+ `code-${index}`
50680
+ );
50681
+ }
50682
+ return /* @__PURE__ */ jsxRuntime.jsx(
50683
+ exports.CodeBlock,
50684
+ {
50685
+ language: segment.language ?? "text",
50686
+ code: segment.content
50687
+ },
50688
+ `code-${index}`
50689
+ );
50690
+ }
50691
+ if (segment.type === "quiz") {
50692
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.QuizBlock, { question: segment.question, answer: segment.answer }, `quiz-${index}`);
50693
+ }
50694
+ if (segment.type === "activate") {
50695
+ return /* @__PURE__ */ jsxRuntime.jsx(
50696
+ exports.ActivationBlock,
50697
+ {
50698
+ question: segment.question,
50699
+ savedResponse: userProgress?.activationResponse
50700
+ },
50701
+ `activate-${index}`
50702
+ );
50703
+ }
50704
+ if (segment.type === "connect") {
50705
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.ConnectionBlock, { content: segment.content }, `connect-${index}`);
50706
+ }
50707
+ if (segment.type === "reflect") {
50708
+ const ri = reflectIndex++;
50709
+ return /* @__PURE__ */ jsxRuntime.jsx(
50710
+ exports.ReflectionBlock,
50711
+ {
50712
+ prompt: segment.prompt,
50713
+ index: ri,
50714
+ savedNote: userProgress?.reflectionNotes?.[ri]
50715
+ },
50716
+ `reflect-${index}`
50717
+ );
50718
+ }
50719
+ if (segment.type === "bloom") {
50720
+ const bi = bloomIndex++;
50721
+ return /* @__PURE__ */ jsxRuntime.jsx(
50722
+ exports.BloomQuizBlock,
50723
+ {
50724
+ level: segment.level,
50725
+ question: segment.question,
50726
+ answer: segment.answer,
50727
+ index: bi,
50728
+ isAnswered: userProgress?.bloomAnswered?.[bi]
50729
+ },
50730
+ `bloom-${index}`
50731
+ );
50732
+ }
50733
+ if (segment.type === "visualization") {
50734
+ return onRenderVisualization ? onRenderVisualization(segment.visualizationType, segment.description, index) ?? null : null;
50735
+ }
50736
+ return null;
50737
+ })
50738
+ }
50739
+ );
50740
+ };
50741
+ SegmentRenderer.displayName = "SegmentRenderer";
50742
+
50094
50743
  // components/core/templates/index.ts
50095
50744
  init_DashboardLayout();
50096
50745
  init_AuthLayout();
@@ -50123,6 +50772,7 @@ exports.CastleBoard = CastleBoard;
50123
50772
  exports.CastleTemplate = CastleTemplate;
50124
50773
  exports.ChoiceButton = ChoiceButton;
50125
50774
  exports.ClassifierBoard = ClassifierBoard;
50775
+ exports.CodeRunnerPanel = CodeRunnerPanel;
50126
50776
  exports.CollapsibleSection = CollapsibleSection;
50127
50777
  exports.CombatLog = CombatLog;
50128
50778
  exports.ComboCounter = ComboCounter;
@@ -50180,6 +50830,7 @@ exports.SHEET_COLUMNS = SHEET_COLUMNS;
50180
50830
  exports.SPRITE_SHEET_LAYOUT = SPRITE_SHEET_LAYOUT;
50181
50831
  exports.ScoreBoard = ScoreBoard;
50182
50832
  exports.ScoreDisplay = ScoreDisplay;
50833
+ exports.SegmentRenderer = SegmentRenderer;
50183
50834
  exports.SequenceBar = SequenceBar;
50184
50835
  exports.SequencerBoard = SequencerBoard;
50185
50836
  exports.SimulationCanvas = SimulationCanvas;
@@ -50233,6 +50884,8 @@ exports.getTileDimensions = getTileDimensions;
50233
50884
  exports.inferDirection = inferDirection;
50234
50885
  exports.isoToScreen = isoToScreen;
50235
50886
  exports.mapBookData = mapBookData;
50887
+ exports.parseLessonSegments = parseLessonSegments;
50888
+ exports.parseMarkdownWithCodeBlocks = parseMarkdownWithCodeBlocks2;
50236
50889
  exports.resolveFieldMap = resolveFieldMap;
50237
50890
  exports.resolveFrame = resolveFrame;
50238
50891
  exports.resolveSheetDirection = resolveSheetDirection;