@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.
- package/.turbo/turbo-build.log +90 -84
- package/AGENTS.md +43 -25
- package/README.md +63 -35
- package/dist/EvolutionDashboard.js +9 -9
- package/dist/EvolutionSidebar.js +15 -15
- package/dist/LocalDataIndicator.js +3 -3
- package/dist/MarkdownView.d.ts +0 -7
- package/dist/MarkdownView.js +76 -172
- package/dist/PersonalizationInsights.js +12 -12
- package/dist/SaveToStudioButton.js +2 -2
- package/dist/SpecDrivenTemplateShell.d.ts +1 -1
- package/dist/SpecDrivenTemplateShell.js +10 -10
- package/dist/SpecEditorPanel.js +3 -3
- package/dist/TemplateShell.js +10 -10
- package/dist/browser/EvolutionDashboard.js +9 -9
- package/dist/browser/EvolutionSidebar.js +15 -15
- package/dist/browser/LocalDataIndicator.js +3 -3
- package/dist/browser/MarkdownView.js +76 -172
- package/dist/browser/PersonalizationInsights.js +12 -12
- package/dist/browser/SaveToStudioButton.js +2 -2
- package/dist/browser/SpecDrivenTemplateShell.js +10 -10
- package/dist/browser/SpecEditorPanel.js +3 -3
- package/dist/browser/TemplateShell.js +10 -10
- package/dist/browser/hooks/index.js +29 -29
- package/dist/browser/index.js +193 -286
- package/dist/browser/lib/component-registry.js +1 -1
- package/dist/browser/markdown/formatPresentationName.js +9 -0
- package/dist/browser/markdown/useMarkdownPresentation.js +65 -0
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +29 -29
- package/dist/index.d.ts +12 -11
- package/dist/index.js +193 -286
- package/dist/lib/component-registry.js +1 -1
- package/dist/markdown/formatPresentationName.d.ts +1 -0
- package/dist/markdown/formatPresentationName.js +10 -0
- package/dist/markdown/useMarkdownPresentation.d.ts +21 -0
- package/dist/markdown/useMarkdownPresentation.js +66 -0
- package/dist/node/EvolutionDashboard.js +9 -9
- package/dist/node/EvolutionSidebar.js +15 -15
- package/dist/node/LocalDataIndicator.js +3 -3
- package/dist/node/MarkdownView.js +76 -172
- package/dist/node/PersonalizationInsights.js +12 -12
- package/dist/node/SaveToStudioButton.js +2 -2
- package/dist/node/SpecDrivenTemplateShell.js +10 -10
- package/dist/node/SpecEditorPanel.js +3 -3
- package/dist/node/TemplateShell.js +10 -10
- package/dist/node/hooks/index.js +29 -29
- package/dist/node/index.js +193 -286
- package/dist/node/lib/component-registry.js +1 -1
- package/dist/node/markdown/formatPresentationName.js +9 -0
- package/dist/node/markdown/useMarkdownPresentation.js +65 -0
- package/dist/utils/index.d.ts +1 -1
- package/package.json +38 -11
- package/src/EvolutionDashboard.tsx +415 -415
- package/src/EvolutionSidebar.tsx +245 -245
- package/src/LocalDataIndicator.tsx +28 -28
- package/src/MarkdownView.tsx +119 -372
- package/src/OverlayContextProvider.tsx +272 -272
- package/src/PersonalizationInsights.tsx +232 -232
- package/src/SaveToStudioButton.tsx +51 -51
- package/src/SpecDrivenTemplateShell.tsx +59 -59
- package/src/SpecEditorPanel.tsx +138 -138
- package/src/TemplateShell.tsx +50 -50
- package/src/bundles/ExampleTemplateBundle.ts +78 -78
- package/src/hooks/index.ts +3 -3
- package/src/hooks/useBehaviorTracking.ts +252 -252
- package/src/hooks/useEvolution.ts +437 -437
- package/src/hooks/useRegistryTemplates.ts +42 -42
- package/src/hooks/useSpecContent.ts +214 -214
- package/src/hooks/useWorkflowComposer.ts +567 -567
- package/src/index.ts +12 -11
- package/src/lib/component-registry.tsx +40 -40
- package/src/lib/runtime-context.tsx +31 -31
- package/src/lib/types.ts +57 -57
- package/src/markdown/formatPresentationName.ts +9 -0
- package/src/markdown/useMarkdownPresentation.ts +107 -0
- package/src/overlay-types.ts +15 -15
- package/src/utils/fetchPresentationData.ts +13 -13
- package/src/utils/generateSpecFromTemplate.ts +29 -29
- package/src/utils/index.ts +1 -1
- package/tsconfig.json +8 -8
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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: "
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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: "
|
|
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-
|
|
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
|
|
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-
|
|
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-
|
|
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: "
|
|
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
|
|
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: "
|
|
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/
|
|
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
|
|
25
|
-
|
|
23
|
+
function useMarkdownPresentation({
|
|
24
|
+
engine,
|
|
25
|
+
fetchData,
|
|
26
26
|
presentationId,
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 =
|
|
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
|
|
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
|
};
|