@contractspec/lib.example-shared-ui 6.0.6 → 6.0.7

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 (81) hide show
  1. package/.turbo/turbo-build.log +90 -84
  2. package/AGENTS.md +43 -25
  3. package/README.md +63 -35
  4. package/dist/EvolutionDashboard.js +9 -9
  5. package/dist/EvolutionSidebar.js +15 -15
  6. package/dist/LocalDataIndicator.js +3 -3
  7. package/dist/MarkdownView.d.ts +0 -7
  8. package/dist/MarkdownView.js +76 -172
  9. package/dist/PersonalizationInsights.js +12 -12
  10. package/dist/SaveToStudioButton.js +2 -2
  11. package/dist/SpecDrivenTemplateShell.d.ts +1 -1
  12. package/dist/SpecDrivenTemplateShell.js +10 -10
  13. package/dist/SpecEditorPanel.js +3 -3
  14. package/dist/TemplateShell.js +10 -10
  15. package/dist/browser/EvolutionDashboard.js +9 -9
  16. package/dist/browser/EvolutionSidebar.js +15 -15
  17. package/dist/browser/LocalDataIndicator.js +3 -3
  18. package/dist/browser/MarkdownView.js +76 -172
  19. package/dist/browser/PersonalizationInsights.js +12 -12
  20. package/dist/browser/SaveToStudioButton.js +2 -2
  21. package/dist/browser/SpecDrivenTemplateShell.js +10 -10
  22. package/dist/browser/SpecEditorPanel.js +3 -3
  23. package/dist/browser/TemplateShell.js +10 -10
  24. package/dist/browser/hooks/index.js +29 -29
  25. package/dist/browser/index.js +193 -286
  26. package/dist/browser/lib/component-registry.js +1 -1
  27. package/dist/browser/markdown/formatPresentationName.js +9 -0
  28. package/dist/browser/markdown/useMarkdownPresentation.js +65 -0
  29. package/dist/hooks/index.d.ts +3 -3
  30. package/dist/hooks/index.js +29 -29
  31. package/dist/index.d.ts +12 -11
  32. package/dist/index.js +193 -286
  33. package/dist/lib/component-registry.js +1 -1
  34. package/dist/markdown/formatPresentationName.d.ts +1 -0
  35. package/dist/markdown/formatPresentationName.js +10 -0
  36. package/dist/markdown/useMarkdownPresentation.d.ts +21 -0
  37. package/dist/markdown/useMarkdownPresentation.js +66 -0
  38. package/dist/node/EvolutionDashboard.js +9 -9
  39. package/dist/node/EvolutionSidebar.js +15 -15
  40. package/dist/node/LocalDataIndicator.js +3 -3
  41. package/dist/node/MarkdownView.js +76 -172
  42. package/dist/node/PersonalizationInsights.js +12 -12
  43. package/dist/node/SaveToStudioButton.js +2 -2
  44. package/dist/node/SpecDrivenTemplateShell.js +10 -10
  45. package/dist/node/SpecEditorPanel.js +3 -3
  46. package/dist/node/TemplateShell.js +10 -10
  47. package/dist/node/hooks/index.js +29 -29
  48. package/dist/node/index.js +193 -286
  49. package/dist/node/lib/component-registry.js +1 -1
  50. package/dist/node/markdown/formatPresentationName.js +9 -0
  51. package/dist/node/markdown/useMarkdownPresentation.js +65 -0
  52. package/dist/utils/index.d.ts +1 -1
  53. package/package.json +38 -11
  54. package/src/EvolutionDashboard.tsx +415 -415
  55. package/src/EvolutionSidebar.tsx +245 -245
  56. package/src/LocalDataIndicator.tsx +28 -28
  57. package/src/MarkdownView.tsx +119 -372
  58. package/src/OverlayContextProvider.tsx +272 -272
  59. package/src/PersonalizationInsights.tsx +232 -232
  60. package/src/SaveToStudioButton.tsx +51 -51
  61. package/src/SpecDrivenTemplateShell.tsx +59 -59
  62. package/src/SpecEditorPanel.tsx +138 -138
  63. package/src/TemplateShell.tsx +50 -50
  64. package/src/bundles/ExampleTemplateBundle.ts +78 -78
  65. package/src/hooks/index.ts +3 -3
  66. package/src/hooks/useBehaviorTracking.ts +252 -252
  67. package/src/hooks/useEvolution.ts +437 -437
  68. package/src/hooks/useRegistryTemplates.ts +42 -42
  69. package/src/hooks/useSpecContent.ts +214 -214
  70. package/src/hooks/useWorkflowComposer.ts +567 -567
  71. package/src/index.ts +12 -11
  72. package/src/lib/component-registry.tsx +40 -40
  73. package/src/lib/runtime-context.tsx +31 -31
  74. package/src/lib/types.ts +57 -57
  75. package/src/markdown/formatPresentationName.ts +9 -0
  76. package/src/markdown/useMarkdownPresentation.ts +107 -0
  77. package/src/overlay-types.ts +15 -15
  78. package/src/utils/fetchPresentationData.ts +13 -13
  79. package/src/utils/generateSpecFromTemplate.ts +29 -29
  80. package/src/utils/index.ts +1 -1
  81. package/tsconfig.json +8 -8
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // src/lib/component-registry.tsx
3
- import { useState, useEffect } from "react";
3
+ import { useEffect, useState } from "react";
4
4
  "use client";
5
5
 
6
6
  class TemplateComponentRegistry {
@@ -0,0 +1 @@
1
+ export declare function formatPresentationName(name: string): string;
@@ -0,0 +1,10 @@
1
+ // @bun
2
+ // src/markdown/formatPresentationName.ts
3
+ function formatPresentationName(name) {
4
+ const parts = name.split(".");
5
+ const lastPart = parts[parts.length - 1] ?? name;
6
+ return lastPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
7
+ }
8
+ export {
9
+ formatPresentationName
10
+ };
@@ -0,0 +1,21 @@
1
+ import type { TransformEngine } from '@contractspec/lib.contracts-spec/presentations/transform-engine';
2
+ interface UseMarkdownPresentationOptions {
3
+ engine?: TransformEngine | null;
4
+ fetchData: (presentationId: string) => Promise<{
5
+ data: unknown;
6
+ }>;
7
+ presentationId?: string;
8
+ presentations: string[];
9
+ resolvePresentation?: (presentationId: string) => unknown;
10
+ templateId?: string;
11
+ }
12
+ interface UseMarkdownPresentationResult {
13
+ error: Error | null;
14
+ loading: boolean;
15
+ markdownContent: string;
16
+ renderMarkdown: () => Promise<void>;
17
+ selectedPresentation: string;
18
+ setSelectedPresentation: (presentationId: string) => void;
19
+ }
20
+ export declare function useMarkdownPresentation({ engine, fetchData, presentationId, presentations, resolvePresentation, templateId, }: UseMarkdownPresentationOptions): UseMarkdownPresentationResult;
21
+ export {};
@@ -0,0 +1,66 @@
1
+ // @bun
2
+ // src/markdown/useMarkdownPresentation.ts
3
+ import { useCallback, useEffect, useState } from "react";
4
+ "use client";
5
+ function useMarkdownPresentation({
6
+ engine,
7
+ fetchData,
8
+ presentationId,
9
+ presentations,
10
+ resolvePresentation,
11
+ templateId
12
+ }) {
13
+ const [selectedPresentation, setSelectedPresentation] = useState("");
14
+ const [markdownContent, setMarkdownContent] = useState("");
15
+ const [loading, setLoading] = useState(false);
16
+ const [error, setError] = useState(null);
17
+ useEffect(() => {
18
+ if (presentationId && presentations.includes(presentationId)) {
19
+ setSelectedPresentation(presentationId);
20
+ return;
21
+ }
22
+ if (presentations.length === 0) {
23
+ setSelectedPresentation("");
24
+ return;
25
+ }
26
+ if (!presentations.includes(selectedPresentation)) {
27
+ setSelectedPresentation(presentations[0] ?? "");
28
+ }
29
+ }, [presentationId, presentations, selectedPresentation, templateId]);
30
+ const renderMarkdown = useCallback(async () => {
31
+ if (!selectedPresentation || !engine)
32
+ return;
33
+ setLoading(true);
34
+ setError(null);
35
+ try {
36
+ if (!resolvePresentation) {
37
+ throw new Error("resolvePresentation not available in runtime context");
38
+ }
39
+ const descriptor = resolvePresentation(selectedPresentation);
40
+ if (!descriptor) {
41
+ throw new Error(`Presentation descriptor not found: ${selectedPresentation}`);
42
+ }
43
+ const dataResult = await fetchData(selectedPresentation);
44
+ const result = await engine.render("markdown", descriptor, { data: dataResult.data });
45
+ setMarkdownContent(result.body);
46
+ } catch (err) {
47
+ setError(err instanceof Error ? err : new Error("Failed to render markdown"));
48
+ } finally {
49
+ setLoading(false);
50
+ }
51
+ }, [engine, fetchData, resolvePresentation, selectedPresentation]);
52
+ useEffect(() => {
53
+ renderMarkdown();
54
+ }, [renderMarkdown]);
55
+ return {
56
+ error,
57
+ loading,
58
+ markdownContent,
59
+ renderMarkdown,
60
+ selectedPresentation,
61
+ setSelectedPresentation
62
+ };
63
+ }
64
+ export {
65
+ useMarkdownPresentation
66
+ };
@@ -257,10 +257,10 @@ function generateRecommendedActions(anomaly) {
257
257
  }
258
258
 
259
259
  // src/EvolutionDashboard.tsx
260
- import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
261
260
  import { Button, LoaderBlock } from "@contractspec/lib.design-system";
262
- import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
263
261
  import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
262
+ import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
263
+ import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
264
264
  import { jsxDEV } from "react/jsx-dev-runtime";
265
265
  "use client";
266
266
  function EvolutionDashboard({
@@ -339,7 +339,7 @@ function EvolutionDashboard({
339
339
  /* @__PURE__ */ jsxDEV("div", {
340
340
  children: [
341
341
  /* @__PURE__ */ jsxDEV("h2", {
342
- className: "text-xl font-semibold",
342
+ className: "font-semibold text-xl",
343
343
  children: "AI Evolution Engine"
344
344
  }, undefined, false, undefined, this),
345
345
  /* @__PURE__ */ jsxDEV("p", {
@@ -397,7 +397,7 @@ function EvolutionDashboard({
397
397
  ]
398
398
  }, undefined, true, undefined, this),
399
399
  /* @__PURE__ */ jsxDEV("p", {
400
- className: "text-muted-foreground mt-2 text-xs",
400
+ className: "mt-2 text-muted-foreground text-xs",
401
401
  children: "Simulate sandbox operations, analyze patterns, and generate AI improvement suggestions."
402
402
  }, undefined, false, undefined, this)
403
403
  ]
@@ -514,7 +514,7 @@ function UsageStatCard({ stat }) {
514
514
  className: "mb-2 flex items-center justify-between",
515
515
  children: [
516
516
  /* @__PURE__ */ jsxDEV("span", {
517
- className: "font-mono text-sm font-medium",
517
+ className: "font-medium font-mono text-sm",
518
518
  children: stat.operation.name
519
519
  }, undefined, false, undefined, this),
520
520
  /* @__PURE__ */ jsxDEV(Badge, {
@@ -616,7 +616,7 @@ function AnomalyCard({ anomaly }) {
616
616
  /* @__PURE__ */ jsxDEV("div", {
617
617
  children: [
618
618
  /* @__PURE__ */ jsxDEV("p", {
619
- className: "text-sm font-medium",
619
+ className: "font-medium text-sm",
620
620
  children: anomaly.description
621
621
  }, undefined, false, undefined, this),
622
622
  /* @__PURE__ */ jsxDEV("p", {
@@ -686,7 +686,7 @@ function SuggestionCard({
686
686
  ]
687
687
  }, undefined, true, undefined, this),
688
688
  /* @__PURE__ */ jsxDEV("p", {
689
- className: "text-muted-foreground mt-1 text-sm",
689
+ className: "mt-1 text-muted-foreground text-sm",
690
690
  children: suggestion.proposal.rationale
691
691
  }, undefined, false, undefined, this)
692
692
  ]
@@ -702,7 +702,7 @@ function SuggestionCard({
702
702
  className: "mt-3",
703
703
  children: [
704
704
  /* @__PURE__ */ jsxDEV("p", {
705
- className: "mb-1 text-xs font-semibold text-violet-400 uppercase",
705
+ className: "mb-1 font-semibold text-violet-400 text-xs uppercase",
706
706
  children: "Recommended Actions"
707
707
  }, undefined, false, undefined, this),
708
708
  /* @__PURE__ */ jsxDEV("ul", {
@@ -783,7 +783,7 @@ function HintCard({ hint }) {
783
783
  children: hint.summary
784
784
  }, undefined, false, undefined, this),
785
785
  /* @__PURE__ */ jsxDEV("p", {
786
- className: "text-muted-foreground mt-1 text-xs",
786
+ className: "mt-1 text-muted-foreground text-xs",
787
787
  children: hint.justification
788
788
  }, undefined, false, undefined, this),
789
789
  hint.recommendedActions.length > 0 && /* @__PURE__ */ jsxDEV("ul", {
@@ -257,10 +257,10 @@ function generateRecommendedActions(anomaly) {
257
257
  }
258
258
 
259
259
  // src/EvolutionSidebar.tsx
260
- import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
261
260
  import { Button } from "@contractspec/lib.design-system";
262
- import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
263
261
  import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
262
+ import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
263
+ import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
264
264
  import { jsxDEV } from "react/jsx-dev-runtime";
265
265
  "use client";
266
266
  function EvolutionSidebar({
@@ -319,7 +319,7 @@ function EvolutionSidebar({
319
319
  className: "w-80 overflow-hidden",
320
320
  children: [
321
321
  /* @__PURE__ */ jsxDEV("div", {
322
- className: "flex items-center justify-between border-b border-violet-500/20 bg-violet-500/5 px-3 py-2",
322
+ className: "flex items-center justify-between border-violet-500/20 border-b bg-violet-500/5 px-3 py-2",
323
323
  children: [
324
324
  /* @__PURE__ */ jsxDEV("div", {
325
325
  className: "flex items-center gap-2",
@@ -328,7 +328,7 @@ function EvolutionSidebar({
328
328
  children: "\uD83E\uDD16"
329
329
  }, undefined, false, undefined, this),
330
330
  /* @__PURE__ */ jsxDEV("span", {
331
- className: "text-sm font-semibold",
331
+ className: "font-semibold text-sm",
332
332
  children: "Evolution"
333
333
  }, undefined, false, undefined, this)
334
334
  ]
@@ -344,7 +344,7 @@ function EvolutionSidebar({
344
344
  }, undefined, false, undefined, this),
345
345
  /* @__PURE__ */ jsxDEV("button", {
346
346
  onClick: onToggle,
347
- className: "text-muted-foreground hover:text-foreground p-1",
347
+ className: "p-1 text-muted-foreground hover:text-foreground",
348
348
  type: "button",
349
349
  title: "Collapse",
350
350
  children: "✕"
@@ -389,14 +389,14 @@ function EvolutionSidebar({
389
389
  ]
390
390
  }, undefined, true, undefined, this),
391
391
  loading && /* @__PURE__ */ jsxDEV("div", {
392
- className: "text-muted-foreground py-4 text-center text-sm",
392
+ className: "py-4 text-center text-muted-foreground text-sm",
393
393
  children: "Generating suggestions..."
394
394
  }, undefined, false, undefined, this),
395
395
  topAnomalies.length > 0 && /* @__PURE__ */ jsxDEV("div", {
396
396
  className: "mb-4",
397
397
  children: [
398
398
  /* @__PURE__ */ jsxDEV("p", {
399
- className: "mb-2 text-xs font-semibold text-violet-400 uppercase",
399
+ className: "mb-2 font-semibold text-violet-400 text-xs uppercase",
400
400
  children: "Top Issues"
401
401
  }, undefined, false, undefined, this),
402
402
  /* @__PURE__ */ jsxDEV("div", {
@@ -417,7 +417,7 @@ function EvolutionSidebar({
417
417
  ]
418
418
  }, undefined, true, undefined, this),
419
419
  /* @__PURE__ */ jsxDEV("p", {
420
- className: "text-muted-foreground mt-1 truncate",
420
+ className: "mt-1 truncate text-muted-foreground",
421
421
  children: anomaly.description
422
422
  }, undefined, false, undefined, this)
423
423
  ]
@@ -428,7 +428,7 @@ function EvolutionSidebar({
428
428
  pendingSuggestions.length > 0 && /* @__PURE__ */ jsxDEV("div", {
429
429
  children: [
430
430
  /* @__PURE__ */ jsxDEV("p", {
431
- className: "mb-2 text-xs font-semibold text-violet-400 uppercase",
431
+ className: "mb-2 font-semibold text-violet-400 text-xs uppercase",
432
432
  children: "Pending Suggestions"
433
433
  }, undefined, false, undefined, this),
434
434
  /* @__PURE__ */ jsxDEV("div", {
@@ -440,7 +440,7 @@ function EvolutionSidebar({
440
440
  onReject: handleReject
441
441
  }, suggestion.id, false, undefined, this)),
442
442
  pendingSuggestions.length > 3 && /* @__PURE__ */ jsxDEV("p", {
443
- className: "text-muted-foreground text-center text-xs",
443
+ className: "text-center text-muted-foreground text-xs",
444
444
  children: [
445
445
  "+",
446
446
  pendingSuggestions.length - 3,
@@ -452,13 +452,13 @@ function EvolutionSidebar({
452
452
  ]
453
453
  }, undefined, true, undefined, this),
454
454
  anomalies.length === 0 && pendingSuggestions.length === 0 && !loading && /* @__PURE__ */ jsxDEV("div", {
455
- className: "text-muted-foreground py-4 text-center text-xs",
455
+ className: "py-4 text-center text-muted-foreground text-xs",
456
456
  children: "No issues detected. Keep coding!"
457
457
  }, undefined, false, undefined, this)
458
458
  ]
459
459
  }, undefined, true, undefined, this),
460
460
  onOpenEvolution && /* @__PURE__ */ jsxDEV("div", {
461
- className: "border-t border-violet-500/20 p-2",
461
+ className: "border-violet-500/20 border-t p-2",
462
462
  children: /* @__PURE__ */ jsxDEV(Button, {
463
463
  variant: "ghost",
464
464
  size: "sm",
@@ -484,7 +484,7 @@ function CompactSuggestionCard({
484
484
  className: "min-w-0 flex-1",
485
485
  children: [
486
486
  /* @__PURE__ */ jsxDEV("p", {
487
- className: "truncate text-xs font-medium",
487
+ className: "truncate font-medium text-xs",
488
488
  children: suggestion.proposal.summary
489
489
  }, undefined, false, undefined, this),
490
490
  /* @__PURE__ */ jsxDEV("div", {
@@ -511,13 +511,13 @@ function CompactSuggestionCard({
511
511
  children: [
512
512
  /* @__PURE__ */ jsxDEV("button", {
513
513
  onClick: () => onReject(suggestion.id),
514
- className: "rounded px-2 py-0.5 text-xs text-red-400 hover:bg-red-400/10",
514
+ className: "rounded px-2 py-0.5 text-red-400 text-xs hover:bg-red-400/10",
515
515
  type: "button",
516
516
  children: "Reject"
517
517
  }, undefined, false, undefined, this),
518
518
  /* @__PURE__ */ jsxDEV("button", {
519
519
  onClick: () => onApprove(suggestion.id),
520
- className: "rounded bg-violet-500/20 px-2 py-0.5 text-xs text-violet-400 hover:bg-violet-500/30",
520
+ className: "rounded bg-violet-500/20 px-2 py-0.5 text-violet-400 text-xs hover:bg-violet-500/30",
521
521
  type: "button",
522
522
  children: "Approve"
523
523
  }, undefined, false, undefined, this)
@@ -27,7 +27,7 @@ function LocalDataIndicator() {
27
27
  }
28
28
  };
29
29
  return /* @__PURE__ */ jsxDEV("div", {
30
- className: "border-border bg-muted/40 text-muted-foreground inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs",
30
+ className: "inline-flex items-center gap-2 rounded-full border border-border bg-muted/40 px-3 py-1 text-muted-foreground text-xs",
31
31
  children: [
32
32
  /* @__PURE__ */ jsxDEV(Shield, {
33
33
  className: "h-3.5 w-3.5 text-violet-400"
@@ -37,14 +37,14 @@ function LocalDataIndicator() {
37
37
  "Local runtime ·",
38
38
  " ",
39
39
  /* @__PURE__ */ jsxDEV("span", {
40
- className: "text-foreground font-semibold",
40
+ className: "font-semibold text-foreground",
41
41
  children: template.name
42
42
  }, undefined, false, undefined, this)
43
43
  ]
44
44
  }, undefined, true, undefined, this),
45
45
  /* @__PURE__ */ jsxDEV("button", {
46
46
  type: "button",
47
- className: "border-border text-muted-foreground hover:text-foreground inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[11px] font-semibold",
47
+ className: "inline-flex items-center gap-1 rounded-full border border-border px-2 py-0.5 font-semibold text-[11px] text-muted-foreground hover:text-foreground",
48
48
  onClick: handleReset,
49
49
  disabled: isResetting,
50
50
  children: [
@@ -10,31 +10,24 @@ function useTemplateRuntime() {
10
10
  return context;
11
11
  }
12
12
 
13
- // src/MarkdownView.tsx
13
+ // src/markdown/formatPresentationName.ts
14
+ function formatPresentationName(name) {
15
+ const parts = name.split(".");
16
+ const lastPart = parts[parts.length - 1] ?? name;
17
+ return lastPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
18
+ }
19
+
20
+ // src/markdown/useMarkdownPresentation.ts
14
21
  import { useCallback, useEffect, useState } from "react";
15
- import {
16
- Button,
17
- ErrorState,
18
- LoaderBlock
19
- } from "@contractspec/lib.design-system";
20
- import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
21
- import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
22
- import { jsxDEV } from "react/jsx-dev-runtime";
23
22
  "use client";
24
- function MarkdownView({
25
- templateId: propTemplateId,
23
+ function useMarkdownPresentation({
24
+ engine,
25
+ fetchData,
26
26
  presentationId,
27
- className
27
+ presentations,
28
+ resolvePresentation,
29
+ templateId
28
30
  }) {
29
- const {
30
- engine,
31
- template,
32
- templateId: contextTemplateId,
33
- resolvePresentation,
34
- fetchData
35
- } = useTemplateRuntime();
36
- const templateId = propTemplateId ?? contextTemplateId;
37
- const presentations = template?.presentations ?? [];
38
31
  const [selectedPresentation, setSelectedPresentation] = useState("");
39
32
  const [markdownContent, setMarkdownContent] = useState("");
40
33
  const [loading, setLoading] = useState(false);
@@ -42,10 +35,16 @@ function MarkdownView({
42
35
  useEffect(() => {
43
36
  if (presentationId && presentations.includes(presentationId)) {
44
37
  setSelectedPresentation(presentationId);
45
- } else if (presentations.length > 0 && !selectedPresentation) {
38
+ return;
39
+ }
40
+ if (presentations.length === 0) {
41
+ setSelectedPresentation("");
42
+ return;
43
+ }
44
+ if (!presentations.includes(selectedPresentation)) {
46
45
  setSelectedPresentation(presentations[0] ?? "");
47
46
  }
48
- }, [presentationId, presentations, selectedPresentation]);
47
+ }, [presentationId, presentations, selectedPresentation, templateId]);
49
48
  const renderMarkdown = useCallback(async () => {
50
49
  if (!selectedPresentation || !engine)
51
50
  return;
@@ -67,16 +66,61 @@ function MarkdownView({
67
66
  } finally {
68
67
  setLoading(false);
69
68
  }
70
- }, [
69
+ }, [engine, fetchData, resolvePresentation, selectedPresentation]);
70
+ useEffect(() => {
71
+ renderMarkdown();
72
+ }, [renderMarkdown]);
73
+ return {
74
+ error,
75
+ loading,
76
+ markdownContent,
77
+ renderMarkdown,
71
78
  selectedPresentation,
72
- templateId,
79
+ setSelectedPresentation
80
+ };
81
+ }
82
+
83
+ // src/MarkdownView.tsx
84
+ import {
85
+ Button,
86
+ ErrorState,
87
+ LoaderBlock,
88
+ MarkdownRenderer
89
+ } from "@contractspec/lib.design-system";
90
+ import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
91
+ import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
92
+ import { useCallback as useCallback2 } from "react";
93
+ import { jsxDEV } from "react/jsx-dev-runtime";
94
+ "use client";
95
+ function MarkdownView({
96
+ templateId: propTemplateId,
97
+ presentationId,
98
+ className
99
+ }) {
100
+ const {
73
101
  engine,
102
+ template,
103
+ templateId: contextTemplateId,
74
104
  resolvePresentation,
75
105
  fetchData
76
- ]);
77
- useEffect(() => {
78
- renderMarkdown();
79
- }, [renderMarkdown]);
106
+ } = useTemplateRuntime();
107
+ const templateId = propTemplateId ?? contextTemplateId;
108
+ const presentations = template?.presentations ?? [];
109
+ const {
110
+ error,
111
+ loading,
112
+ markdownContent,
113
+ renderMarkdown,
114
+ selectedPresentation,
115
+ setSelectedPresentation
116
+ } = useMarkdownPresentation({
117
+ engine,
118
+ fetchData,
119
+ presentationId,
120
+ presentations,
121
+ resolvePresentation,
122
+ templateId
123
+ });
80
124
  if (!presentations.length) {
81
125
  return /* @__PURE__ */ jsxDEV(Card, {
82
126
  className,
@@ -89,7 +133,7 @@ function MarkdownView({
89
133
  }, undefined, false, undefined, this)
90
134
  }, undefined, false, undefined, this);
91
135
  }
92
- const handleCopy = useCallback(() => {
136
+ const handleCopy = useCallback2(() => {
93
137
  if (markdownContent) {
94
138
  navigator.clipboard.writeText(markdownContent);
95
139
  }
@@ -101,7 +145,7 @@ function MarkdownView({
101
145
  className: "mb-4 flex flex-wrap items-center gap-2",
102
146
  children: [
103
147
  /* @__PURE__ */ jsxDEV("span", {
104
- className: "text-muted-foreground text-sm font-medium",
148
+ className: "font-medium text-muted-foreground text-sm",
105
149
  children: "Presentation:"
106
150
  }, undefined, false, undefined, this),
107
151
  presentations.map((name) => /* @__PURE__ */ jsxDEV(Button, {
@@ -158,146 +202,6 @@ function MarkdownView({
158
202
  ]
159
203
  }, undefined, true, undefined, this);
160
204
  }
161
- function MarkdownRenderer({ content }) {
162
- const lines = content.split(`
163
- `);
164
- const rendered = [];
165
- let i = 0;
166
- while (i < lines.length) {
167
- const line = lines[i] ?? "";
168
- if (line.startsWith("|") && lines[i + 1]?.match(/^\|[\s-|]+\|$/)) {
169
- const tableLines = [line];
170
- i++;
171
- while (i < lines.length && (lines[i]?.startsWith("|") ?? false)) {
172
- tableLines.push(lines[i] ?? "");
173
- i++;
174
- }
175
- rendered.push(renderTable(tableLines, rendered.length));
176
- continue;
177
- }
178
- if (line.startsWith("# ")) {
179
- rendered.push(/* @__PURE__ */ jsxDEV("h1", {
180
- className: "mb-4 text-2xl font-bold",
181
- children: line.slice(2)
182
- }, i, false, undefined, this));
183
- } else if (line.startsWith("## ")) {
184
- rendered.push(/* @__PURE__ */ jsxDEV("h2", {
185
- className: "mt-6 mb-3 text-xl font-semibold",
186
- children: line.slice(3)
187
- }, i, false, undefined, this));
188
- } else if (line.startsWith("### ")) {
189
- rendered.push(/* @__PURE__ */ jsxDEV("h3", {
190
- className: "mt-4 mb-2 text-lg font-medium",
191
- children: line.slice(4)
192
- }, i, false, undefined, this));
193
- } else if (line.startsWith("> ")) {
194
- rendered.push(/* @__PURE__ */ jsxDEV("blockquote", {
195
- className: "text-muted-foreground my-2 border-l-4 border-violet-500/50 pl-4 italic",
196
- children: line.slice(2)
197
- }, i, false, undefined, this));
198
- } else if (line.startsWith("- ")) {
199
- rendered.push(/* @__PURE__ */ jsxDEV("li", {
200
- className: "ml-4 list-disc",
201
- children: formatInlineMarkdown(line.slice(2))
202
- }, i, false, undefined, this));
203
- } else if (line.startsWith("**") && line.includes(":**")) {
204
- const [label, ...rest] = line.split(":**");
205
- rendered.push(/* @__PURE__ */ jsxDEV("p", {
206
- className: "my-1",
207
- children: [
208
- /* @__PURE__ */ jsxDEV("strong", {
209
- children: [
210
- label?.slice(2),
211
- ":"
212
- ]
213
- }, undefined, true, undefined, this),
214
- rest.join(":**")
215
- ]
216
- }, i, true, undefined, this));
217
- } else if (line.startsWith("_") && line.endsWith("_")) {
218
- rendered.push(/* @__PURE__ */ jsxDEV("p", {
219
- className: "text-muted-foreground my-1 italic",
220
- children: line.slice(1, -1)
221
- }, i, false, undefined, this));
222
- } else if (!line.trim()) {
223
- rendered.push(/* @__PURE__ */ jsxDEV("div", {
224
- className: "h-2"
225
- }, i, false, undefined, this));
226
- } else {
227
- rendered.push(/* @__PURE__ */ jsxDEV("p", {
228
- className: "my-1",
229
- children: formatInlineMarkdown(line)
230
- }, i, false, undefined, this));
231
- }
232
- i++;
233
- }
234
- return /* @__PURE__ */ jsxDEV("div", {
235
- className: "prose prose-sm dark:prose-invert max-w-none",
236
- children: rendered
237
- }, undefined, false, undefined, this);
238
- }
239
- function renderTable(lines, keyPrefix) {
240
- if (lines.length < 2)
241
- return null;
242
- const parseRow = (row) => row.split("|").slice(1, -1).map((cell) => cell.trim());
243
- const headers = parseRow(lines[0] ?? "");
244
- const dataRows = lines.slice(2).map(parseRow);
245
- return /* @__PURE__ */ jsxDEV("div", {
246
- className: "my-4 overflow-x-auto",
247
- children: /* @__PURE__ */ jsxDEV("table", {
248
- className: "border-border min-w-full border-collapse border text-sm",
249
- children: [
250
- /* @__PURE__ */ jsxDEV("thead", {
251
- children: /* @__PURE__ */ jsxDEV("tr", {
252
- className: "bg-muted/50",
253
- children: headers.map((header, idx) => /* @__PURE__ */ jsxDEV("th", {
254
- className: "border-border border px-3 py-2 text-left font-semibold",
255
- children: header
256
- }, idx, false, undefined, this))
257
- }, undefined, false, undefined, this)
258
- }, undefined, false, undefined, this),
259
- /* @__PURE__ */ jsxDEV("tbody", {
260
- children: dataRows.map((row, rowIdx) => /* @__PURE__ */ jsxDEV("tr", {
261
- className: "hover:bg-muted/30",
262
- children: row.map((cell, cellIdx) => /* @__PURE__ */ jsxDEV("td", {
263
- className: "border-border border px-3 py-2",
264
- children: formatInlineMarkdown(cell)
265
- }, cellIdx, false, undefined, this))
266
- }, rowIdx, false, undefined, this))
267
- }, undefined, false, undefined, this)
268
- ]
269
- }, undefined, true, undefined, this)
270
- }, `table-${keyPrefix}`, false, undefined, this);
271
- }
272
- function formatInlineMarkdown(text) {
273
- const parts = text.split(/(\*\*[^*]+\*\*)/g);
274
- return parts.map((part, i) => {
275
- if (part.startsWith("**") && part.endsWith("**")) {
276
- return /* @__PURE__ */ jsxDEV("strong", {
277
- children: part.slice(2, -2)
278
- }, i, false, undefined, this);
279
- }
280
- if (part.includes("`")) {
281
- const codeParts = part.split(/(`[^`]+`)/g);
282
- return codeParts.map((cp, j) => {
283
- if (cp.startsWith("`") && cp.endsWith("`")) {
284
- return /* @__PURE__ */ jsxDEV("code", {
285
- className: "rounded bg-violet-500/10 px-1.5 py-0.5 font-mono text-sm",
286
- children: cp.slice(1, -1)
287
- }, `${i}-${j}`, false, undefined, this);
288
- }
289
- return cp;
290
- });
291
- }
292
- return part;
293
- });
294
- }
295
- function formatPresentationName(name) {
296
- const parts = name.split(".");
297
- const lastPart = parts[parts.length - 1] ?? name;
298
- return lastPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
299
- }
300
205
  export {
301
- MarkdownView,
302
- MarkdownRenderer
206
+ MarkdownView
303
207
  };