@codrstudio/openclaude-chat 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/StreamingIndicator.js +5 -5
- package/dist/display/DisplayReactRenderer.js +12 -12
- package/dist/display/react-sandbox/bootstrap.js +150 -150
- package/dist/styles.css +1 -2
- package/package.json +64 -61
- package/src/components/Chat.tsx +107 -107
- package/src/components/ErrorNote.tsx +35 -35
- package/src/components/LazyRender.tsx +42 -42
- package/src/components/Markdown.tsx +114 -114
- package/src/components/MessageBubble.tsx +107 -107
- package/src/components/MessageInput.tsx +421 -421
- package/src/components/MessageList.tsx +153 -153
- package/src/components/StreamingIndicator.tsx +19 -19
- package/src/display/AlertRenderer.tsx +23 -23
- package/src/display/CarouselRenderer.tsx +141 -141
- package/src/display/ChartRenderer.tsx +195 -195
- package/src/display/ChoiceButtonsRenderer.tsx +114 -114
- package/src/display/CodeBlockRenderer.tsx +49 -49
- package/src/display/ComparisonTableRenderer.tsx +132 -132
- package/src/display/DataTableRenderer.tsx +144 -144
- package/src/display/DisplayReactRenderer.tsx +269 -269
- package/src/display/FileCardRenderer.tsx +55 -55
- package/src/display/GalleryRenderer.tsx +65 -65
- package/src/display/ImageViewerRenderer.tsx +114 -114
- package/src/display/LinkPreviewRenderer.tsx +74 -74
- package/src/display/MapViewRenderer.tsx +75 -75
- package/src/display/MetricCardRenderer.tsx +29 -29
- package/src/display/PriceHighlightRenderer.tsx +62 -62
- package/src/display/ProductCardRenderer.tsx +112 -112
- package/src/display/ProgressStepsRenderer.tsx +59 -59
- package/src/display/SourcesListRenderer.tsx +47 -47
- package/src/display/SpreadsheetRenderer.tsx +86 -86
- package/src/display/StepTimelineRenderer.tsx +75 -75
- package/src/display/index.ts +21 -21
- package/src/display/react-sandbox/bootstrap.ts +155 -155
- package/src/display/registry.ts +84 -84
- package/src/display/sdk-types.ts +217 -217
- package/src/hooks/ChatProvider.tsx +21 -21
- package/src/hooks/useIsMobile.ts +15 -15
- package/src/hooks/useOpenClaudeChat.ts +476 -476
- package/src/index.ts +76 -76
- package/src/lib/utils.ts +6 -6
- package/src/parts/PartErrorBoundary.tsx +51 -51
- package/src/parts/PartRenderer.tsx +145 -145
- package/src/parts/ReasoningBlock.tsx +41 -41
- package/src/parts/ToolActivity.tsx +78 -78
- package/src/parts/ToolResult.tsx +79 -79
- package/src/styles.css +2 -2
- package/src/types.ts +41 -41
- package/src/ui/alert.tsx +77 -77
- package/src/ui/badge.tsx +36 -36
- package/src/ui/button.tsx +54 -54
- package/src/ui/card.tsx +68 -68
- package/src/ui/collapsible.tsx +7 -7
- package/src/ui/dialog.tsx +122 -122
- package/src/ui/dropdown-menu.tsx +76 -76
- package/src/ui/input.tsx +24 -24
- package/src/ui/progress.tsx +36 -36
- package/src/ui/scroll-area.tsx +48 -48
- package/src/ui/separator.tsx +31 -31
- package/src/ui/skeleton.tsx +9 -9
- package/src/ui/table.tsx +114 -114
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
import type { DisplaySpreadsheet } from "./sdk-types.js";
|
|
2
|
-
import { ScrollArea, ScrollBar } from "../ui/scroll-area.js";
|
|
3
|
-
import {
|
|
4
|
-
Table,
|
|
5
|
-
TableBody,
|
|
6
|
-
TableCell,
|
|
7
|
-
TableHead,
|
|
8
|
-
TableHeader,
|
|
9
|
-
TableRow,
|
|
10
|
-
} from "../ui/table.js";
|
|
11
|
-
import { cn } from "../lib/utils.js";
|
|
12
|
-
|
|
13
|
-
function formatCell(
|
|
14
|
-
value: string | number | null,
|
|
15
|
-
colIndex: number,
|
|
16
|
-
moneyColumns: number[] = [],
|
|
17
|
-
percentColumns: number[] = [],
|
|
18
|
-
): string {
|
|
19
|
-
if (value === null || value === undefined) return "";
|
|
20
|
-
if (typeof value === "number") {
|
|
21
|
-
if (moneyColumns.includes(colIndex)) {
|
|
22
|
-
return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value);
|
|
23
|
-
}
|
|
24
|
-
if (percentColumns.includes(colIndex)) {
|
|
25
|
-
return new Intl.NumberFormat("pt-BR", {
|
|
26
|
-
style: "percent",
|
|
27
|
-
minimumFractionDigits: 1,
|
|
28
|
-
maximumFractionDigits: 2,
|
|
29
|
-
}).format(value / 100);
|
|
30
|
-
}
|
|
31
|
-
return new Intl.NumberFormat("pt-BR").format(value);
|
|
32
|
-
}
|
|
33
|
-
return String(value);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function SpreadsheetRenderer({ title, headers, rows, format }: DisplaySpreadsheet) {
|
|
37
|
-
const moneyColumns = format?.moneyColumns ?? [];
|
|
38
|
-
const percentColumns = format?.percentColumns ?? [];
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<div className="space-y-2">
|
|
42
|
-
{title && <h3 className="text-sm font-semibold text-foreground">{title}</h3>}
|
|
43
|
-
|
|
44
|
-
<ScrollArea className="w-full">
|
|
45
|
-
<Table aria-readonly="true">
|
|
46
|
-
<TableHeader>
|
|
47
|
-
<TableRow>
|
|
48
|
-
<TableHead className="text-muted-foreground font-normal text-center w-10" aria-label="Linha" />
|
|
49
|
-
{headers.map((h, i) => (
|
|
50
|
-
<TableHead key={i} className="font-semibold">
|
|
51
|
-
{h}
|
|
52
|
-
</TableHead>
|
|
53
|
-
))}
|
|
54
|
-
</TableRow>
|
|
55
|
-
</TableHeader>
|
|
56
|
-
|
|
57
|
-
<TableBody>
|
|
58
|
-
{rows.map((row, ri) => (
|
|
59
|
-
<TableRow key={ri}>
|
|
60
|
-
<TableCell className="text-center text-xs text-muted-foreground select-none">
|
|
61
|
-
{ri + 1}
|
|
62
|
-
</TableCell>
|
|
63
|
-
{row.map((cell, ci) => {
|
|
64
|
-
const isMoney = moneyColumns.includes(ci);
|
|
65
|
-
const isPercent = percentColumns.includes(ci);
|
|
66
|
-
const isNumber = typeof cell === "number";
|
|
67
|
-
return (
|
|
68
|
-
<TableCell
|
|
69
|
-
key={ci}
|
|
70
|
-
className={cn(
|
|
71
|
-
(isMoney || isPercent || isNumber) && "text-right font-mono text-sm"
|
|
72
|
-
)}
|
|
73
|
-
>
|
|
74
|
-
{formatCell(cell, ci, moneyColumns, percentColumns)}
|
|
75
|
-
</TableCell>
|
|
76
|
-
);
|
|
77
|
-
})}
|
|
78
|
-
</TableRow>
|
|
79
|
-
))}
|
|
80
|
-
</TableBody>
|
|
81
|
-
</Table>
|
|
82
|
-
<ScrollBar orientation="horizontal" />
|
|
83
|
-
</ScrollArea>
|
|
84
|
-
</div>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
1
|
+
import type { DisplaySpreadsheet } from "./sdk-types.js";
|
|
2
|
+
import { ScrollArea, ScrollBar } from "../ui/scroll-area.js";
|
|
3
|
+
import {
|
|
4
|
+
Table,
|
|
5
|
+
TableBody,
|
|
6
|
+
TableCell,
|
|
7
|
+
TableHead,
|
|
8
|
+
TableHeader,
|
|
9
|
+
TableRow,
|
|
10
|
+
} from "../ui/table.js";
|
|
11
|
+
import { cn } from "../lib/utils.js";
|
|
12
|
+
|
|
13
|
+
function formatCell(
|
|
14
|
+
value: string | number | null,
|
|
15
|
+
colIndex: number,
|
|
16
|
+
moneyColumns: number[] = [],
|
|
17
|
+
percentColumns: number[] = [],
|
|
18
|
+
): string {
|
|
19
|
+
if (value === null || value === undefined) return "";
|
|
20
|
+
if (typeof value === "number") {
|
|
21
|
+
if (moneyColumns.includes(colIndex)) {
|
|
22
|
+
return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value);
|
|
23
|
+
}
|
|
24
|
+
if (percentColumns.includes(colIndex)) {
|
|
25
|
+
return new Intl.NumberFormat("pt-BR", {
|
|
26
|
+
style: "percent",
|
|
27
|
+
minimumFractionDigits: 1,
|
|
28
|
+
maximumFractionDigits: 2,
|
|
29
|
+
}).format(value / 100);
|
|
30
|
+
}
|
|
31
|
+
return new Intl.NumberFormat("pt-BR").format(value);
|
|
32
|
+
}
|
|
33
|
+
return String(value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function SpreadsheetRenderer({ title, headers, rows, format }: DisplaySpreadsheet) {
|
|
37
|
+
const moneyColumns = format?.moneyColumns ?? [];
|
|
38
|
+
const percentColumns = format?.percentColumns ?? [];
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className="space-y-2">
|
|
42
|
+
{title && <h3 className="text-sm font-semibold text-foreground">{title}</h3>}
|
|
43
|
+
|
|
44
|
+
<ScrollArea className="w-full">
|
|
45
|
+
<Table aria-readonly="true">
|
|
46
|
+
<TableHeader>
|
|
47
|
+
<TableRow>
|
|
48
|
+
<TableHead className="text-muted-foreground font-normal text-center w-10" aria-label="Linha" />
|
|
49
|
+
{headers.map((h, i) => (
|
|
50
|
+
<TableHead key={i} className="font-semibold">
|
|
51
|
+
{h}
|
|
52
|
+
</TableHead>
|
|
53
|
+
))}
|
|
54
|
+
</TableRow>
|
|
55
|
+
</TableHeader>
|
|
56
|
+
|
|
57
|
+
<TableBody>
|
|
58
|
+
{rows.map((row, ri) => (
|
|
59
|
+
<TableRow key={ri}>
|
|
60
|
+
<TableCell className="text-center text-xs text-muted-foreground select-none">
|
|
61
|
+
{ri + 1}
|
|
62
|
+
</TableCell>
|
|
63
|
+
{row.map((cell, ci) => {
|
|
64
|
+
const isMoney = moneyColumns.includes(ci);
|
|
65
|
+
const isPercent = percentColumns.includes(ci);
|
|
66
|
+
const isNumber = typeof cell === "number";
|
|
67
|
+
return (
|
|
68
|
+
<TableCell
|
|
69
|
+
key={ci}
|
|
70
|
+
className={cn(
|
|
71
|
+
(isMoney || isPercent || isNumber) && "text-right font-mono text-sm"
|
|
72
|
+
)}
|
|
73
|
+
>
|
|
74
|
+
{formatCell(cell, ci, moneyColumns, percentColumns)}
|
|
75
|
+
</TableCell>
|
|
76
|
+
);
|
|
77
|
+
})}
|
|
78
|
+
</TableRow>
|
|
79
|
+
))}
|
|
80
|
+
</TableBody>
|
|
81
|
+
</Table>
|
|
82
|
+
<ScrollBar orientation="horizontal" />
|
|
83
|
+
</ScrollArea>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
import type { DisplaySteps } from "./sdk-types.js";
|
|
2
|
-
import { cn } from "../lib/utils";
|
|
3
|
-
import { Badge } from "../ui/badge";
|
|
4
|
-
|
|
5
|
-
const STATUS_CIRCLE: Record<"completed" | "current" | "pending", string> = {
|
|
6
|
-
completed: "bg-primary text-primary-foreground",
|
|
7
|
-
current: "bg-primary/20 border border-primary",
|
|
8
|
-
pending: "bg-muted text-muted-foreground",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const STATUS_TITLE: Record<"completed" | "current" | "pending", string> = {
|
|
12
|
-
completed: "text-foreground",
|
|
13
|
-
current: "text-primary",
|
|
14
|
-
pending: "text-muted-foreground",
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export function StepTimelineRenderer({ title, steps, orientation }: DisplaySteps) {
|
|
18
|
-
const isVertical = orientation !== "horizontal";
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<div className={cn("flex", isVertical ? "flex-col gap-0" : "flex-row items-start gap-0")}>
|
|
22
|
-
{title && (
|
|
23
|
-
<p className="text-sm font-medium text-foreground mb-3">{title}</p>
|
|
24
|
-
)}
|
|
25
|
-
{steps.map((step, index) => {
|
|
26
|
-
const isLast = index === steps.length - 1;
|
|
27
|
-
const { status } = step;
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div
|
|
31
|
-
key={index}
|
|
32
|
-
className={cn(
|
|
33
|
-
"flex",
|
|
34
|
-
isVertical ? "flex-row gap-3" : "flex-col items-center gap-2 flex-1"
|
|
35
|
-
)}
|
|
36
|
-
>
|
|
37
|
-
{/* Circle + connector column */}
|
|
38
|
-
<div className={cn("flex", isVertical ? "flex-col items-center" : "flex-row items-center")}>
|
|
39
|
-
<div
|
|
40
|
-
className={cn(
|
|
41
|
-
"w-6 h-6 rounded-full flex items-center justify-center shrink-0",
|
|
42
|
-
STATUS_CIRCLE[status]
|
|
43
|
-
)}
|
|
44
|
-
>
|
|
45
|
-
<Badge
|
|
46
|
-
variant="secondary"
|
|
47
|
-
className="w-5 h-5 flex items-center justify-center rounded-full p-0 text-[10px] font-semibold border-0 bg-transparent text-inherit"
|
|
48
|
-
>
|
|
49
|
-
{index + 1}
|
|
50
|
-
</Badge>
|
|
51
|
-
</div>
|
|
52
|
-
{!isLast && (
|
|
53
|
-
<div
|
|
54
|
-
className={cn(
|
|
55
|
-
isVertical ? "w-px h-6 bg-border" : "h-px w-full bg-border flex-1"
|
|
56
|
-
)}
|
|
57
|
-
/>
|
|
58
|
-
)}
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
{/* Content */}
|
|
62
|
-
<div className={cn("pb-4 flex-1 min-w-0", isLast && "pb-0", !isVertical && "text-center")}>
|
|
63
|
-
<p className={cn("text-sm font-medium leading-none", STATUS_TITLE[status])}>
|
|
64
|
-
{step.title}
|
|
65
|
-
</p>
|
|
66
|
-
{step.description && (
|
|
67
|
-
<p className="text-xs text-muted-foreground mt-1">{step.description}</p>
|
|
68
|
-
)}
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
})}
|
|
73
|
-
</div>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
1
|
+
import type { DisplaySteps } from "./sdk-types.js";
|
|
2
|
+
import { cn } from "../lib/utils";
|
|
3
|
+
import { Badge } from "../ui/badge";
|
|
4
|
+
|
|
5
|
+
const STATUS_CIRCLE: Record<"completed" | "current" | "pending", string> = {
|
|
6
|
+
completed: "bg-primary text-primary-foreground",
|
|
7
|
+
current: "bg-primary/20 border border-primary",
|
|
8
|
+
pending: "bg-muted text-muted-foreground",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const STATUS_TITLE: Record<"completed" | "current" | "pending", string> = {
|
|
12
|
+
completed: "text-foreground",
|
|
13
|
+
current: "text-primary",
|
|
14
|
+
pending: "text-muted-foreground",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function StepTimelineRenderer({ title, steps, orientation }: DisplaySteps) {
|
|
18
|
+
const isVertical = orientation !== "horizontal";
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className={cn("flex", isVertical ? "flex-col gap-0" : "flex-row items-start gap-0")}>
|
|
22
|
+
{title && (
|
|
23
|
+
<p className="text-sm font-medium text-foreground mb-3">{title}</p>
|
|
24
|
+
)}
|
|
25
|
+
{steps.map((step, index) => {
|
|
26
|
+
const isLast = index === steps.length - 1;
|
|
27
|
+
const { status } = step;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
key={index}
|
|
32
|
+
className={cn(
|
|
33
|
+
"flex",
|
|
34
|
+
isVertical ? "flex-row gap-3" : "flex-col items-center gap-2 flex-1"
|
|
35
|
+
)}
|
|
36
|
+
>
|
|
37
|
+
{/* Circle + connector column */}
|
|
38
|
+
<div className={cn("flex", isVertical ? "flex-col items-center" : "flex-row items-center")}>
|
|
39
|
+
<div
|
|
40
|
+
className={cn(
|
|
41
|
+
"w-6 h-6 rounded-full flex items-center justify-center shrink-0",
|
|
42
|
+
STATUS_CIRCLE[status]
|
|
43
|
+
)}
|
|
44
|
+
>
|
|
45
|
+
<Badge
|
|
46
|
+
variant="secondary"
|
|
47
|
+
className="w-5 h-5 flex items-center justify-center rounded-full p-0 text-[10px] font-semibold border-0 bg-transparent text-inherit"
|
|
48
|
+
>
|
|
49
|
+
{index + 1}
|
|
50
|
+
</Badge>
|
|
51
|
+
</div>
|
|
52
|
+
{!isLast && (
|
|
53
|
+
<div
|
|
54
|
+
className={cn(
|
|
55
|
+
isVertical ? "w-px h-6 bg-border" : "h-px w-full bg-border flex-1"
|
|
56
|
+
)}
|
|
57
|
+
/>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
{/* Content */}
|
|
62
|
+
<div className={cn("pb-4 flex-1 min-w-0", isLast && "pb-0", !isVertical && "text-center")}>
|
|
63
|
+
<p className={cn("text-sm font-medium leading-none", STATUS_TITLE[status])}>
|
|
64
|
+
{step.title}
|
|
65
|
+
</p>
|
|
66
|
+
{step.description && (
|
|
67
|
+
<p className="text-xs text-muted-foreground mt-1">{step.description}</p>
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
})}
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
package/src/display/index.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
export { AlertRenderer } from "./AlertRenderer.js";
|
|
2
|
-
export { MetricCardRenderer } from "./MetricCardRenderer.js";
|
|
3
|
-
export { PriceHighlightRenderer } from "./PriceHighlightRenderer.js";
|
|
4
|
-
export { FileCardRenderer } from "./FileCardRenderer.js";
|
|
5
|
-
export { CodeBlockRenderer } from "./CodeBlockRenderer.js";
|
|
6
|
-
export { SourcesListRenderer } from "./SourcesListRenderer.js";
|
|
7
|
-
export { StepTimelineRenderer } from "./StepTimelineRenderer.js";
|
|
8
|
-
export { ProgressStepsRenderer } from "./ProgressStepsRenderer.js";
|
|
9
|
-
export { ChartRenderer } from "./ChartRenderer.js";
|
|
10
|
-
export { CarouselRenderer } from "./CarouselRenderer.js";
|
|
11
|
-
export { ProductCardRenderer } from "./ProductCardRenderer.js";
|
|
12
|
-
export { ComparisonTableRenderer } from "./ComparisonTableRenderer.js";
|
|
13
|
-
export { DataTableRenderer } from "./DataTableRenderer.js";
|
|
14
|
-
export { SpreadsheetRenderer } from "./SpreadsheetRenderer.js";
|
|
15
|
-
export { GalleryRenderer } from "./GalleryRenderer.js";
|
|
16
|
-
export { ImageViewerRenderer } from "./ImageViewerRenderer.js";
|
|
17
|
-
export { LinkPreviewRenderer } from "./LinkPreviewRenderer.js";
|
|
18
|
-
export { MapViewRenderer } from "./MapViewRenderer.js";
|
|
19
|
-
export { ChoiceButtonsRenderer } from "./ChoiceButtonsRenderer.js";
|
|
20
|
-
export { defaultDisplayRenderers, resolveDisplayRenderer } from "./registry.js";
|
|
21
|
-
export type { DisplayRendererMap, DisplayActionName } from "./registry.js";
|
|
1
|
+
export { AlertRenderer } from "./AlertRenderer.js";
|
|
2
|
+
export { MetricCardRenderer } from "./MetricCardRenderer.js";
|
|
3
|
+
export { PriceHighlightRenderer } from "./PriceHighlightRenderer.js";
|
|
4
|
+
export { FileCardRenderer } from "./FileCardRenderer.js";
|
|
5
|
+
export { CodeBlockRenderer } from "./CodeBlockRenderer.js";
|
|
6
|
+
export { SourcesListRenderer } from "./SourcesListRenderer.js";
|
|
7
|
+
export { StepTimelineRenderer } from "./StepTimelineRenderer.js";
|
|
8
|
+
export { ProgressStepsRenderer } from "./ProgressStepsRenderer.js";
|
|
9
|
+
export { ChartRenderer } from "./ChartRenderer.js";
|
|
10
|
+
export { CarouselRenderer } from "./CarouselRenderer.js";
|
|
11
|
+
export { ProductCardRenderer } from "./ProductCardRenderer.js";
|
|
12
|
+
export { ComparisonTableRenderer } from "./ComparisonTableRenderer.js";
|
|
13
|
+
export { DataTableRenderer } from "./DataTableRenderer.js";
|
|
14
|
+
export { SpreadsheetRenderer } from "./SpreadsheetRenderer.js";
|
|
15
|
+
export { GalleryRenderer } from "./GalleryRenderer.js";
|
|
16
|
+
export { ImageViewerRenderer } from "./ImageViewerRenderer.js";
|
|
17
|
+
export { LinkPreviewRenderer } from "./LinkPreviewRenderer.js";
|
|
18
|
+
export { MapViewRenderer } from "./MapViewRenderer.js";
|
|
19
|
+
export { ChoiceButtonsRenderer } from "./ChoiceButtonsRenderer.js";
|
|
20
|
+
export { defaultDisplayRenderers, resolveDisplayRenderer } from "./registry.js";
|
|
21
|
+
export type { DisplayRendererMap, DisplayActionName } from "./registry.js";
|