@codrstudio/openclaude-chat 0.1.0 → 0.1.9

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 (62) hide show
  1. package/dist/components/StreamingIndicator.js +5 -5
  2. package/dist/display/DisplayReactRenderer.js +12 -12
  3. package/dist/display/react-sandbox/bootstrap.js +150 -150
  4. package/dist/styles.css +1 -2
  5. package/package.json +64 -61
  6. package/src/components/Chat.tsx +107 -107
  7. package/src/components/ErrorNote.tsx +35 -35
  8. package/src/components/LazyRender.tsx +42 -42
  9. package/src/components/Markdown.tsx +114 -114
  10. package/src/components/MessageBubble.tsx +107 -107
  11. package/src/components/MessageInput.tsx +421 -421
  12. package/src/components/MessageList.tsx +153 -153
  13. package/src/components/StreamingIndicator.tsx +19 -19
  14. package/src/display/AlertRenderer.tsx +23 -23
  15. package/src/display/CarouselRenderer.tsx +141 -141
  16. package/src/display/ChartRenderer.tsx +195 -195
  17. package/src/display/ChoiceButtonsRenderer.tsx +114 -114
  18. package/src/display/CodeBlockRenderer.tsx +49 -49
  19. package/src/display/ComparisonTableRenderer.tsx +132 -132
  20. package/src/display/DataTableRenderer.tsx +144 -144
  21. package/src/display/DisplayReactRenderer.tsx +269 -269
  22. package/src/display/FileCardRenderer.tsx +55 -55
  23. package/src/display/GalleryRenderer.tsx +65 -65
  24. package/src/display/ImageViewerRenderer.tsx +114 -114
  25. package/src/display/LinkPreviewRenderer.tsx +74 -74
  26. package/src/display/MapViewRenderer.tsx +75 -75
  27. package/src/display/MetricCardRenderer.tsx +29 -29
  28. package/src/display/PriceHighlightRenderer.tsx +62 -62
  29. package/src/display/ProductCardRenderer.tsx +112 -112
  30. package/src/display/ProgressStepsRenderer.tsx +59 -59
  31. package/src/display/SourcesListRenderer.tsx +47 -47
  32. package/src/display/SpreadsheetRenderer.tsx +86 -86
  33. package/src/display/StepTimelineRenderer.tsx +75 -75
  34. package/src/display/index.ts +21 -21
  35. package/src/display/react-sandbox/bootstrap.ts +155 -155
  36. package/src/display/registry.ts +84 -84
  37. package/src/display/sdk-types.ts +217 -217
  38. package/src/hooks/ChatProvider.tsx +21 -21
  39. package/src/hooks/useIsMobile.ts +15 -15
  40. package/src/hooks/useOpenClaudeChat.ts +476 -476
  41. package/src/index.ts +76 -76
  42. package/src/lib/utils.ts +6 -6
  43. package/src/parts/PartErrorBoundary.tsx +51 -51
  44. package/src/parts/PartRenderer.tsx +145 -145
  45. package/src/parts/ReasoningBlock.tsx +41 -41
  46. package/src/parts/ToolActivity.tsx +78 -78
  47. package/src/parts/ToolResult.tsx +79 -79
  48. package/src/styles.css +2 -2
  49. package/src/types.ts +41 -41
  50. package/src/ui/alert.tsx +77 -77
  51. package/src/ui/badge.tsx +36 -36
  52. package/src/ui/button.tsx +54 -54
  53. package/src/ui/card.tsx +68 -68
  54. package/src/ui/collapsible.tsx +7 -7
  55. package/src/ui/dialog.tsx +122 -122
  56. package/src/ui/dropdown-menu.tsx +76 -76
  57. package/src/ui/input.tsx +24 -24
  58. package/src/ui/progress.tsx +36 -36
  59. package/src/ui/scroll-area.tsx +48 -48
  60. package/src/ui/separator.tsx +31 -31
  61. package/src/ui/skeleton.tsx +9 -9
  62. package/src/ui/table.tsx +114 -114
@@ -1,141 +1,141 @@
1
- import type { DisplayCarousel } from "./sdk-types.js";
2
- import useEmblaCarousel from "embla-carousel-react";
3
- import { ChevronLeft, ChevronRight } from "lucide-react";
4
- import { useCallback, useEffect, useState } from "react";
5
- import { Badge } from "../ui/badge";
6
- import { Button } from "../ui/button";
7
- import { Card, CardContent } from "../ui/card";
8
- import { cn } from "../lib/utils";
9
-
10
- function formatPrice(value: number, currency: string): string {
11
- return new Intl.NumberFormat("pt-BR", { style: "currency", currency }).format(value);
12
- }
13
-
14
- export function CarouselRenderer({ title, items }: DisplayCarousel) {
15
- const [emblaRef, emblaApi] = useEmblaCarousel({ loop: false, dragFree: false });
16
- const [selectedIndex, setSelectedIndex] = useState(0);
17
- const [canScrollPrev, setCanScrollPrev] = useState(false);
18
- const [canScrollNext, setCanScrollNext] = useState(false);
19
-
20
- const onSelect = useCallback(() => {
21
- if (!emblaApi) return;
22
- setSelectedIndex(emblaApi.selectedScrollSnap());
23
- setCanScrollPrev(emblaApi.canScrollPrev());
24
- setCanScrollNext(emblaApi.canScrollNext());
25
- }, [emblaApi]);
26
-
27
- useEffect(() => {
28
- if (!emblaApi) return;
29
- onSelect();
30
- emblaApi.on("select", onSelect);
31
- emblaApi.on("reInit", onSelect);
32
- return () => {
33
- emblaApi.off("select", onSelect);
34
- emblaApi.off("reInit", onSelect);
35
- };
36
- }, [emblaApi, onSelect]);
37
-
38
- const scrollPrev = useCallback(() => emblaApi?.scrollPrev(), [emblaApi]);
39
- const scrollNext = useCallback(() => emblaApi?.scrollNext(), [emblaApi]);
40
-
41
- return (
42
- <div className="flex flex-col gap-3">
43
- {title && <p className="text-sm font-medium text-foreground">{title}</p>}
44
-
45
- <div className="flex items-center gap-2">
46
- <Button
47
- variant="outline"
48
- size="icon"
49
- className="rounded-full shrink-0"
50
- onClick={scrollPrev}
51
- disabled={!canScrollPrev}
52
- aria-label="Anterior"
53
- type="button"
54
- >
55
- <ChevronLeft className="h-4 w-4" />
56
- </Button>
57
-
58
- <div className="overflow-hidden flex-1" ref={emblaRef}>
59
- <div className="flex">
60
- {items.map((item, index) => (
61
- <div key={index} className="flex-[0_0_80%] min-w-0 pl-3 first:pl-0">
62
- {item.url ? (
63
- <a href={item.url} target="_blank" rel="noopener noreferrer" className="block">
64
- <CarouselCard item={item} />
65
- </a>
66
- ) : (
67
- <CarouselCard item={item} />
68
- )}
69
- </div>
70
- ))}
71
- </div>
72
- </div>
73
-
74
- <Button
75
- variant="outline"
76
- size="icon"
77
- className="rounded-full shrink-0"
78
- onClick={scrollNext}
79
- disabled={!canScrollNext}
80
- aria-label="Próximo"
81
- type="button"
82
- >
83
- <ChevronRight className="h-4 w-4" />
84
- </Button>
85
- </div>
86
-
87
- {items.length > 1 && (
88
- <div className="flex items-center justify-center gap-1.5" role="tablist" aria-label="Slides">
89
- {items.map((_, index) => (
90
- <button
91
- key={index}
92
- className={cn(
93
- "w-2 h-2 rounded-full transition-colors",
94
- index === selectedIndex ? "bg-primary" : "bg-muted"
95
- )}
96
- onClick={() => emblaApi?.scrollTo(index)}
97
- role="tab"
98
- aria-selected={index === selectedIndex}
99
- aria-label={`Slide ${index + 1}`}
100
- type="button"
101
- />
102
- ))}
103
- </div>
104
- )}
105
- </div>
106
- );
107
- }
108
-
109
- type CarouselItem = DisplayCarousel["items"][number];
110
-
111
- function CarouselCard({ item }: { item: CarouselItem }) {
112
- return (
113
- <Card className="overflow-hidden">
114
- {item.image && (
115
- <div className="aspect-video overflow-hidden">
116
- <img src={item.image} alt={item.title} loading="lazy" className="w-full h-full object-cover" />
117
- </div>
118
- )}
119
- <CardContent className="p-3 space-y-1">
120
- <p className="font-medium text-sm text-foreground">{item.title}</p>
121
- {item.subtitle && (
122
- <p className="text-xs text-muted-foreground">{item.subtitle}</p>
123
- )}
124
- {item.price && (
125
- <p className="text-sm font-bold text-foreground">
126
- {formatPrice(item.price.value, item.price.currency)}
127
- </p>
128
- )}
129
- {item.badges && item.badges.length > 0 && (
130
- <div className="flex flex-wrap gap-1 pt-1">
131
- {item.badges.map((badge, i) => (
132
- <Badge key={i} variant={(badge.variant as string) === "destructive" ? "destructive" : (badge.variant as string) === "secondary" ? "secondary" : "default"}>
133
- {badge.label}
134
- </Badge>
135
- ))}
136
- </div>
137
- )}
138
- </CardContent>
139
- </Card>
140
- );
141
- }
1
+ import type { DisplayCarousel } from "./sdk-types.js";
2
+ import useEmblaCarousel from "embla-carousel-react";
3
+ import { ChevronLeft, ChevronRight } from "lucide-react";
4
+ import { useCallback, useEffect, useState } from "react";
5
+ import { Badge } from "../ui/badge";
6
+ import { Button } from "../ui/button";
7
+ import { Card, CardContent } from "../ui/card";
8
+ import { cn } from "../lib/utils";
9
+
10
+ function formatPrice(value: number, currency: string): string {
11
+ return new Intl.NumberFormat("pt-BR", { style: "currency", currency }).format(value);
12
+ }
13
+
14
+ export function CarouselRenderer({ title, items }: DisplayCarousel) {
15
+ const [emblaRef, emblaApi] = useEmblaCarousel({ loop: false, dragFree: false });
16
+ const [selectedIndex, setSelectedIndex] = useState(0);
17
+ const [canScrollPrev, setCanScrollPrev] = useState(false);
18
+ const [canScrollNext, setCanScrollNext] = useState(false);
19
+
20
+ const onSelect = useCallback(() => {
21
+ if (!emblaApi) return;
22
+ setSelectedIndex(emblaApi.selectedScrollSnap());
23
+ setCanScrollPrev(emblaApi.canScrollPrev());
24
+ setCanScrollNext(emblaApi.canScrollNext());
25
+ }, [emblaApi]);
26
+
27
+ useEffect(() => {
28
+ if (!emblaApi) return;
29
+ onSelect();
30
+ emblaApi.on("select", onSelect);
31
+ emblaApi.on("reInit", onSelect);
32
+ return () => {
33
+ emblaApi.off("select", onSelect);
34
+ emblaApi.off("reInit", onSelect);
35
+ };
36
+ }, [emblaApi, onSelect]);
37
+
38
+ const scrollPrev = useCallback(() => emblaApi?.scrollPrev(), [emblaApi]);
39
+ const scrollNext = useCallback(() => emblaApi?.scrollNext(), [emblaApi]);
40
+
41
+ return (
42
+ <div className="flex flex-col gap-3">
43
+ {title && <p className="text-sm font-medium text-foreground">{title}</p>}
44
+
45
+ <div className="flex items-center gap-2">
46
+ <Button
47
+ variant="outline"
48
+ size="icon"
49
+ className="rounded-full shrink-0"
50
+ onClick={scrollPrev}
51
+ disabled={!canScrollPrev}
52
+ aria-label="Anterior"
53
+ type="button"
54
+ >
55
+ <ChevronLeft className="h-4 w-4" />
56
+ </Button>
57
+
58
+ <div className="overflow-hidden flex-1" ref={emblaRef}>
59
+ <div className="flex">
60
+ {items.map((item, index) => (
61
+ <div key={index} className="flex-[0_0_80%] min-w-0 pl-3 first:pl-0">
62
+ {item.url ? (
63
+ <a href={item.url} target="_blank" rel="noopener noreferrer" className="block">
64
+ <CarouselCard item={item} />
65
+ </a>
66
+ ) : (
67
+ <CarouselCard item={item} />
68
+ )}
69
+ </div>
70
+ ))}
71
+ </div>
72
+ </div>
73
+
74
+ <Button
75
+ variant="outline"
76
+ size="icon"
77
+ className="rounded-full shrink-0"
78
+ onClick={scrollNext}
79
+ disabled={!canScrollNext}
80
+ aria-label="Próximo"
81
+ type="button"
82
+ >
83
+ <ChevronRight className="h-4 w-4" />
84
+ </Button>
85
+ </div>
86
+
87
+ {items.length > 1 && (
88
+ <div className="flex items-center justify-center gap-1.5" role="tablist" aria-label="Slides">
89
+ {items.map((_, index) => (
90
+ <button
91
+ key={index}
92
+ className={cn(
93
+ "w-2 h-2 rounded-full transition-colors",
94
+ index === selectedIndex ? "bg-primary" : "bg-muted"
95
+ )}
96
+ onClick={() => emblaApi?.scrollTo(index)}
97
+ role="tab"
98
+ aria-selected={index === selectedIndex}
99
+ aria-label={`Slide ${index + 1}`}
100
+ type="button"
101
+ />
102
+ ))}
103
+ </div>
104
+ )}
105
+ </div>
106
+ );
107
+ }
108
+
109
+ type CarouselItem = DisplayCarousel["items"][number];
110
+
111
+ function CarouselCard({ item }: { item: CarouselItem }) {
112
+ return (
113
+ <Card className="overflow-hidden">
114
+ {item.image && (
115
+ <div className="aspect-video overflow-hidden">
116
+ <img src={item.image} alt={item.title} loading="lazy" className="w-full h-full object-cover" />
117
+ </div>
118
+ )}
119
+ <CardContent className="p-3 space-y-1">
120
+ <p className="font-medium text-sm text-foreground">{item.title}</p>
121
+ {item.subtitle && (
122
+ <p className="text-xs text-muted-foreground">{item.subtitle}</p>
123
+ )}
124
+ {item.price && (
125
+ <p className="text-sm font-bold text-foreground">
126
+ {formatPrice(item.price.value, item.price.currency)}
127
+ </p>
128
+ )}
129
+ {item.badges && item.badges.length > 0 && (
130
+ <div className="flex flex-wrap gap-1 pt-1">
131
+ {item.badges.map((badge, i) => (
132
+ <Badge key={i} variant={(badge.variant as string) === "destructive" ? "destructive" : (badge.variant as string) === "secondary" ? "secondary" : "default"}>
133
+ {badge.label}
134
+ </Badge>
135
+ ))}
136
+ </div>
137
+ )}
138
+ </CardContent>
139
+ </Card>
140
+ );
141
+ }