@alquimia-ai/ui 1.2.1 → 1.2.4
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/hooks/index.js +41 -32
- package/dist/components/hooks/index.js.map +1 -1
- package/dist/components/hooks/index.mjs +42 -33
- package/dist/components/hooks/index.mjs.map +1 -1
- package/dist/components/molecules/index.js +41 -32
- package/dist/components/molecules/index.js.map +1 -1
- package/dist/components/molecules/index.mjs +42 -33
- package/dist/components/molecules/index.mjs.map +1 -1
- package/dist/components/organisms/index.js +41 -32
- package/dist/components/organisms/index.js.map +1 -1
- package/dist/components/organisms/index.mjs +42 -33
- package/dist/components/organisms/index.mjs.map +1 -1
- package/dist/index.js +41 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -33
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +136 -0
- package/package.json +50 -53
- package/src/components/atoms/index.ts +0 -32
- package/src/components/atoms/ui/alert.tsx +0 -59
- package/src/components/atoms/ui/aspect-ratio.tsx +0 -7
- package/src/components/atoms/ui/avatar.tsx +0 -50
- package/src/components/atoms/ui/badge.tsx +0 -36
- package/src/components/atoms/ui/breadcrumb.tsx +0 -120
- package/src/components/atoms/ui/button.tsx +0 -56
- package/src/components/atoms/ui/card.tsx +0 -87
- package/src/components/atoms/ui/checkbox.tsx +0 -31
- package/src/components/atoms/ui/command.tsx +0 -155
- package/src/components/atoms/ui/dialog.tsx +0 -125
- package/src/components/atoms/ui/drawer.tsx +0 -119
- package/src/components/atoms/ui/input.tsx +0 -26
- package/src/components/atoms/ui/label.tsx +0 -26
- package/src/components/atoms/ui/loader.tsx +0 -52
- package/src/components/atoms/ui/popover.tsx +0 -31
- package/src/components/atoms/ui/rich-text.tsx +0 -19
- package/src/components/atoms/ui/scroll-area.tsx +0 -48
- package/src/components/atoms/ui/select.tsx +0 -160
- package/src/components/atoms/ui/skeleton.tsx +0 -15
- package/src/components/atoms/ui/slider.tsx +0 -29
- package/src/components/atoms/ui/switch.tsx +0 -30
- package/src/components/atoms/ui/table.tsx +0 -118
- package/src/components/atoms/ui/tabs.tsx +0 -56
- package/src/components/atoms/ui/text-area/index.tsx +0 -24
- package/src/components/atoms/ui/textarea.tsx +0 -25
- package/src/components/atoms/ui/think-indicator.tsx +0 -103
- package/src/components/atoms/ui/toast.tsx +0 -129
- package/src/components/atoms/ui/toaster.tsx +0 -38
- package/src/components/atoms/ui/toggle.tsx +0 -45
- package/src/components/atoms/ui/typography/index.tsx +0 -30
- package/src/components/hooks/index.ts +0 -4
- package/src/components/hooks/use-document.tsx +0 -44
- package/src/components/hooks/use-resize-observer.ts +0 -28
- package/src/components/hooks/use-text-streaming.ts +0 -63
- package/src/components/hooks/use-toast.ts +0 -194
- package/src/components/index.ts +0 -1
- package/src/components/molecules/alert-dialog.tsx +0 -141
- package/src/components/molecules/assistant-button.tsx +0 -148
- package/src/components/molecules/call-out.tsx +0 -163
- package/src/components/molecules/carousel.tsx +0 -262
- package/src/components/molecules/documents/document-selector.tsx +0 -79
- package/src/components/molecules/documents/document-viewer.tsx +0 -85
- package/src/components/molecules/documents/index.ts +0 -2
- package/src/components/molecules/index.ts +0 -11
- package/src/components/molecules/navigation-menu.tsx +0 -128
- package/src/components/molecules/page-container.tsx +0 -17
- package/src/components/molecules/rating-comment.tsx +0 -93
- package/src/components/molecules/rating-stars.tsx +0 -136
- package/src/components/molecules/rating-thumbs.tsx +0 -90
- package/src/components/molecules/sidebar.tsx +0 -107
- package/src/components/molecules/sonner.tsx +0 -30
- package/src/components/molecules/viewers/index.ts +0 -2
- package/src/components/molecules/viewers/pdf-viewer.tsx +0 -138
- package/src/components/molecules/viewers/plain-text-viewer.tsx +0 -40
- package/src/components/organisms/assistant.tsx +0 -271
- package/src/components/organisms/index.ts +0 -6
- package/src/components/organisms/rating-dialog.tsx +0 -104
- package/src/components/organisms/speechToText.tsx +0 -92
- package/src/components/organisms/whisper.tsx +0 -106
- package/src/components/templates/cards/index.ts +0 -2
- package/src/components/templates/cards/with-image-heading-description-avatar.tsx +0 -94
- package/src/components/templates/cards/with-image-heading-description.tsx +0 -63
- package/src/components/templates/hero/index.tsx +0 -39
- package/src/components/templates/index.ts +0 -4
- package/src/components/templates/messages-window.tsx +0 -15
- package/src/components/templates/query-box.tsx +0 -13
- package/src/components/ui/input.tsx +0 -25
- package/src/components/ui/select.tsx +0 -163
- package/src/index.ts +0 -7
- package/src/lib/index.ts +0 -1
- package/src/lib/utils.ts +0 -34
- package/src/styles/call-out.css +0 -153
- package/src/styles/drawer.css +0 -28
- package/src/styles/globals.css +0 -69
- package/src/styles/prose.css +0 -51
- package/src/styles/ratings.css +0 -27
- package/src/styles/themes/base-alquimia.css +0 -95
- package/src/styles/themes/base-nordic.css +0 -83
- package/src/styles/themes/base-primary.css +0 -85
- package/src/styles/themes/base.css +0 -8
- package/src/types/index.ts +0 -1
- package/src/types/type.ts +0 -76
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { LucideIcon } from "lucide-react";
|
|
3
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../lib/utils";
|
|
6
|
-
import { ScrollArea, Button } from "../atoms";
|
|
7
|
-
|
|
8
|
-
const sidebarVariants = cva(
|
|
9
|
-
"flex flex-col border-r",
|
|
10
|
-
{
|
|
11
|
-
variants: {
|
|
12
|
-
size: {
|
|
13
|
-
sm: "w-48",
|
|
14
|
-
default: "w-64",
|
|
15
|
-
lg: "w-72"
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
defaultVariants: {
|
|
19
|
-
size: "default",
|
|
20
|
-
},
|
|
21
|
-
}
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
export interface SidebarItem {
|
|
25
|
-
name: string;
|
|
26
|
-
icon?: LucideIcon;
|
|
27
|
-
disabled?: boolean;
|
|
28
|
-
isLink?: boolean;
|
|
29
|
-
link?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
type SidebarBaseProps = {
|
|
33
|
-
items: SidebarItem[];
|
|
34
|
-
selectedSection?: SidebarItem;
|
|
35
|
-
onSelect?: (item: SidebarItem) => void;
|
|
36
|
-
footerContent?: React.ReactNode;
|
|
37
|
-
selectedVariant?: "default" | "secondary" | "ghost" | "link";
|
|
38
|
-
defaultVariant?: "default" | "secondary" | "ghost" | "link";
|
|
39
|
-
buttonClassName?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface SidebarProps
|
|
43
|
-
extends SidebarBaseProps,
|
|
44
|
-
Omit<React.HTMLAttributes<HTMLDivElement>, keyof SidebarBaseProps>,
|
|
45
|
-
VariantProps<typeof sidebarVariants> {}
|
|
46
|
-
|
|
47
|
-
export const SidebarFooter = React.forwardRef<
|
|
48
|
-
HTMLDivElement,
|
|
49
|
-
React.HTMLAttributes<HTMLDivElement>
|
|
50
|
-
>(({ className, children, ...props }, ref) => (
|
|
51
|
-
<div
|
|
52
|
-
ref={ref}
|
|
53
|
-
className={cn("p-4", className)}
|
|
54
|
-
{...props}
|
|
55
|
-
>
|
|
56
|
-
{children}
|
|
57
|
-
</div>
|
|
58
|
-
));
|
|
59
|
-
SidebarFooter.displayName = "SidebarFooter";
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
export const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
|
|
63
|
-
({
|
|
64
|
-
className,
|
|
65
|
-
items,
|
|
66
|
-
selectedSection,
|
|
67
|
-
onSelect,
|
|
68
|
-
footerContent,
|
|
69
|
-
size = "default",
|
|
70
|
-
selectedVariant = "secondary",
|
|
71
|
-
defaultVariant = "ghost",
|
|
72
|
-
buttonClassName,
|
|
73
|
-
...props
|
|
74
|
-
}, ref) => {
|
|
75
|
-
return (
|
|
76
|
-
<div className={cn(className, "alq--navigation-sidebar h-full")} ref={ref} {...props}>
|
|
77
|
-
<aside className={cn(sidebarVariants({ size }), "h-full")}>
|
|
78
|
-
<ScrollArea className="flex-grow justify-between">
|
|
79
|
-
<div className="flex flex-col gap-2 p-4">
|
|
80
|
-
{items.map((item) => (
|
|
81
|
-
<Button
|
|
82
|
-
key={item.name}
|
|
83
|
-
variant={selectedSection?.name === item.name ? selectedVariant : defaultVariant}
|
|
84
|
-
className={cn("justify-start", buttonClassName)}
|
|
85
|
-
disabled={item.disabled}
|
|
86
|
-
onClick={() => {
|
|
87
|
-
if (onSelect) {
|
|
88
|
-
onSelect(item);
|
|
89
|
-
}
|
|
90
|
-
}}
|
|
91
|
-
>
|
|
92
|
-
{item.icon && <item.icon className="mr-2 h-4 w-4" />}
|
|
93
|
-
{item.name}
|
|
94
|
-
</Button>
|
|
95
|
-
))}
|
|
96
|
-
</div>
|
|
97
|
-
</ScrollArea>
|
|
98
|
-
{footerContent && (
|
|
99
|
-
<SidebarFooter>
|
|
100
|
-
{footerContent}
|
|
101
|
-
</SidebarFooter>
|
|
102
|
-
)}
|
|
103
|
-
</aside>
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
);
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { useTheme } from "next-themes";
|
|
4
|
-
import { Toaster as Sonner } from "sonner";
|
|
5
|
-
|
|
6
|
-
type ToasterProps = React.ComponentProps<typeof Sonner>;
|
|
7
|
-
|
|
8
|
-
const Toaster = ({ ...props }: ToasterProps) => {
|
|
9
|
-
const { theme = "system" } = useTheme();
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Sonner
|
|
13
|
-
theme={theme as ToasterProps["theme"]}
|
|
14
|
-
className="toaster group"
|
|
15
|
-
toastOptions={{
|
|
16
|
-
classNames: {
|
|
17
|
-
toast:
|
|
18
|
-
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
|
19
|
-
description: "group-[.toast]:text-muted-foreground",
|
|
20
|
-
actionButton:
|
|
21
|
-
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
|
22
|
-
cancelButton:
|
|
23
|
-
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
|
24
|
-
},
|
|
25
|
-
}}
|
|
26
|
-
{...props}
|
|
27
|
-
/>
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
export { Toaster as SonnerToaster };
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React, { useState, useCallback, useEffect } from 'react'
|
|
4
|
-
import { Button, Loader } from '../../atoms';
|
|
5
|
-
import { ChevronLeft, ChevronRight, ZoomIn, ZoomOut, Download } from 'lucide-react'
|
|
6
|
-
import useResizeObserver from '../../hooks/use-resize-observer';
|
|
7
|
-
import { pdfjs, Document, Page } from 'react-pdf';
|
|
8
|
-
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
|
|
9
|
-
import 'react-pdf/dist/esm/Page/TextLayer.css';
|
|
10
|
-
|
|
11
|
-
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
12
|
-
|
|
13
|
-
const options = {
|
|
14
|
-
cMapUrl: '/cmaps/',
|
|
15
|
-
standardFontDataUrl: '/standard_fonts/',
|
|
16
|
-
cMapPacked: true,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const resizeObserverOptions = {};
|
|
20
|
-
|
|
21
|
-
type PdfViewerProps = {
|
|
22
|
-
doc: Blob | null;
|
|
23
|
-
loading?: boolean;
|
|
24
|
-
docId: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default function PdfViewer({ doc, docId }: PdfViewerProps) {
|
|
28
|
-
const [numPages, setNumPages] = useState<number>(0);
|
|
29
|
-
const [pageNumber, setPageNumber] = useState<number>(1);
|
|
30
|
-
const [scale, setScale] = useState<number>(1);
|
|
31
|
-
const [containerRef, setContainerRef] = useState<HTMLElement | null>(null);
|
|
32
|
-
const [containerWidth, setContainerWidth] = useState<number>();
|
|
33
|
-
|
|
34
|
-
const onResize = useCallback<ResizeObserverCallback>((entries) => {
|
|
35
|
-
const [entry] = entries;
|
|
36
|
-
if (entry) {
|
|
37
|
-
setContainerWidth(entry.contentRect.width);
|
|
38
|
-
}
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
useResizeObserver(containerRef, resizeObserverOptions, onResize);
|
|
42
|
-
|
|
43
|
-
function onDocumentLoadSuccess({ numPages: nextNumPages }: pdfjs.PDFDocumentProxy): void {
|
|
44
|
-
setNumPages(nextNumPages);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const resetDocument = () => {
|
|
48
|
-
setPageNumber(1);
|
|
49
|
-
setScale(1);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
resetDocument()
|
|
54
|
-
}, []);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const handlePrevPage = () => setPageNumber((prev) => Math.max(prev - 1, 1));
|
|
58
|
-
const handleNextPage = () => setPageNumber((prev) => Math.min(prev + 1, numPages));
|
|
59
|
-
const handleZoomIn = () => setScale((prev) => Math.min(prev + 0.1, 2));
|
|
60
|
-
const handleZoomOut = () => setScale((prev) => Math.max(prev - 0.1, 0.5));
|
|
61
|
-
|
|
62
|
-
const handleKeyDown = useCallback((e: KeyboardEvent) => {
|
|
63
|
-
if (e.key === 'ArrowLeft') {
|
|
64
|
-
handlePrevPage();
|
|
65
|
-
} else if (e.key === 'ArrowRight') {
|
|
66
|
-
handleNextPage();
|
|
67
|
-
}
|
|
68
|
-
}, [handlePrevPage, handleNextPage]);
|
|
69
|
-
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
window.addEventListener('keydown', handleKeyDown);
|
|
72
|
-
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
73
|
-
}, [handleKeyDown]);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const handleDownloadFile = () => {
|
|
77
|
-
const docUrl = doc && URL.createObjectURL(doc);
|
|
78
|
-
const a = document.createElement('a');
|
|
79
|
-
a.href = docUrl || '';
|
|
80
|
-
a.download = docId;
|
|
81
|
-
a.click();
|
|
82
|
-
URL.revokeObjectURL(docUrl || '');
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<>
|
|
87
|
-
<div className="flex justify-between items-center p-4 border-b border-border">
|
|
88
|
-
<div>
|
|
89
|
-
<Button
|
|
90
|
-
onClick={handlePrevPage}
|
|
91
|
-
disabled={pageNumber <= 1}
|
|
92
|
-
>
|
|
93
|
-
<ChevronLeft className="h-4 w-4" />
|
|
94
|
-
</Button>
|
|
95
|
-
<span className="mx-2">
|
|
96
|
-
Page {pageNumber} of {numPages}
|
|
97
|
-
</span>
|
|
98
|
-
<Button
|
|
99
|
-
onClick={handleNextPage}
|
|
100
|
-
disabled={pageNumber >= numPages}
|
|
101
|
-
>
|
|
102
|
-
<ChevronRight className="h-4 w-4" />
|
|
103
|
-
</Button>
|
|
104
|
-
</div>
|
|
105
|
-
{/* <div>
|
|
106
|
-
<Button onClick={handleDownloadFile}>
|
|
107
|
-
<Download className="h-4 w-4" />
|
|
108
|
-
</Button>
|
|
109
|
-
</div> */}
|
|
110
|
-
<div>
|
|
111
|
-
<Button onClick={handleZoomOut}>
|
|
112
|
-
<ZoomOut className="h-4 w-4" />
|
|
113
|
-
</Button>
|
|
114
|
-
<span className="mx-2">{(scale * 100).toFixed(0)}%</span>
|
|
115
|
-
<Button onClick={handleZoomIn}>
|
|
116
|
-
<ZoomIn className="h-4 w-4" />
|
|
117
|
-
</Button>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
<div ref={setContainerRef} className="overflow-auto">
|
|
121
|
-
<Document
|
|
122
|
-
file={doc}
|
|
123
|
-
// file={`/docs/${docId}`}
|
|
124
|
-
onLoadSuccess={onDocumentLoadSuccess}
|
|
125
|
-
options={options}
|
|
126
|
-
loading={<Loader size="xl" colorVariant="destructive" />}
|
|
127
|
-
>
|
|
128
|
-
<Page
|
|
129
|
-
pageNumber={pageNumber}
|
|
130
|
-
scale={scale}
|
|
131
|
-
width={containerWidth}
|
|
132
|
-
className="w-full"
|
|
133
|
-
/>
|
|
134
|
-
</Document>
|
|
135
|
-
</div>
|
|
136
|
-
</>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React, { useState, useEffect } from "react";
|
|
4
|
-
import { Loader, RichText } from "../../atoms";
|
|
5
|
-
|
|
6
|
-
type PlainTextViewerProps = {
|
|
7
|
-
doc: Blob | null;
|
|
8
|
-
docId?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export default function PlainTextViewer({ doc }: PlainTextViewerProps) {
|
|
12
|
-
const [content, setContent] = useState<string | null>(null);
|
|
13
|
-
const [loading, setLoading] = useState(true);
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
async function parseDocument() {
|
|
17
|
-
try {
|
|
18
|
-
if (doc && doc.type === "text/plain") {
|
|
19
|
-
const text = await doc.text();
|
|
20
|
-
setContent(text);
|
|
21
|
-
}
|
|
22
|
-
} catch (err) {
|
|
23
|
-
console.error("Error parsing Document:", err);
|
|
24
|
-
} finally {
|
|
25
|
-
setLoading(false);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
parseDocument();
|
|
30
|
-
}, [doc]);
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<>
|
|
34
|
-
<div className="relative w-full h-full max-h-[80vh] overflow-y-auto p-8 alq--prose">
|
|
35
|
-
{loading && <Loader />}
|
|
36
|
-
{!loading && <RichText content={content || ""} />}
|
|
37
|
-
</div>
|
|
38
|
-
</>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { useEffect } from "react";
|
|
5
|
-
import { AlquimiaSDK } from "@alquimia-ai/tools/sdk";
|
|
6
|
-
import { Typography } from "../atoms";
|
|
7
|
-
import { CallOut, CallOutResponse, CallOutActions } from "../molecules";
|
|
8
|
-
import { ThinkIndicator } from "../atoms";
|
|
9
|
-
import { cn } from "../../lib/utils";
|
|
10
|
-
import { Message } from "ai";
|
|
11
|
-
import { Send } from "lucide-react";
|
|
12
|
-
|
|
13
|
-
interface AssistantProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
14
|
-
sdk: AlquimiaSDK;
|
|
15
|
-
title?: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const Assistant = React.forwardRef<HTMLDivElement, AssistantProps>(
|
|
20
|
-
({ className, sdk, title, description, children, ...props }, ref) => {
|
|
21
|
-
return (
|
|
22
|
-
<div
|
|
23
|
-
ref={ref}
|
|
24
|
-
className={cn("flex flex-col h-full bg-background text-foreground", className)}
|
|
25
|
-
{...props}
|
|
26
|
-
>
|
|
27
|
-
{(title || description) && (
|
|
28
|
-
<AssistantHeader>
|
|
29
|
-
{title && <AssistantTitle title={title} />}
|
|
30
|
-
{description && <AssistantDescription description={description} />}
|
|
31
|
-
</AssistantHeader>
|
|
32
|
-
)}
|
|
33
|
-
{children}
|
|
34
|
-
</div>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
);
|
|
38
|
-
Assistant.displayName = "Assistant";
|
|
39
|
-
|
|
40
|
-
interface AssistantTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
41
|
-
title: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const AssistantTitle = React.forwardRef<HTMLHeadingElement, AssistantTitleProps>(
|
|
45
|
-
({ className, title, ...props }, ref) => (
|
|
46
|
-
<div ref={ref} className={cn("text-foreground", className)} {...props}>
|
|
47
|
-
<Typography typeStyle="heading1" as="h1">
|
|
48
|
-
{title}
|
|
49
|
-
</Typography>
|
|
50
|
-
</div>
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
AssistantTitle.displayName = "AssistantTitle";
|
|
54
|
-
|
|
55
|
-
interface AssistantDescriptionProps
|
|
56
|
-
extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
57
|
-
description: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const AssistantDescription = React.forwardRef<
|
|
61
|
-
HTMLParagraphElement,
|
|
62
|
-
AssistantDescriptionProps
|
|
63
|
-
>(({ className, description, ...props }, ref) => (
|
|
64
|
-
<div ref={ref} className={cn("text-foreground", className)} {...props}>
|
|
65
|
-
<Typography typeStyle="display" as="p">
|
|
66
|
-
{description}
|
|
67
|
-
</Typography>
|
|
68
|
-
</div>
|
|
69
|
-
));
|
|
70
|
-
AssistantDescription.displayName = "AssistantDescription";
|
|
71
|
-
|
|
72
|
-
interface AssistantHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
73
|
-
|
|
74
|
-
const AssistantHeader = React.forwardRef<HTMLDivElement, AssistantHeaderProps>(
|
|
75
|
-
({ className, children, ...props }, ref) => (
|
|
76
|
-
<div
|
|
77
|
-
ref={ref}
|
|
78
|
-
className={cn("bg-background text-foreground", className)}
|
|
79
|
-
{...props}
|
|
80
|
-
>
|
|
81
|
-
{children}
|
|
82
|
-
</div>
|
|
83
|
-
)
|
|
84
|
-
);
|
|
85
|
-
AssistantHeader.displayName = "AssistantHeader";
|
|
86
|
-
|
|
87
|
-
interface MessageAction {
|
|
88
|
-
label: string;
|
|
89
|
-
icon: React.ReactNode;
|
|
90
|
-
onClick: (message?: Message) => Promise<void>;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
interface AssistantMessageAreaProps
|
|
94
|
-
extends React.HTMLAttributes<HTMLDivElement> {
|
|
95
|
-
messages: (Message & {
|
|
96
|
-
error_code?: string;
|
|
97
|
-
created_at?: string;
|
|
98
|
-
error_detail?: string;
|
|
99
|
-
additionalInfo?: string;
|
|
100
|
-
loading?: boolean;
|
|
101
|
-
})[];
|
|
102
|
-
actions?: MessageAction[];
|
|
103
|
-
messagesEndRef: any;
|
|
104
|
-
thinkIndicator?: React.ReactNode;
|
|
105
|
-
isMessageStreaming?: boolean;
|
|
106
|
-
streamingMessageId: string | null;
|
|
107
|
-
handleIsTextStreaming?: (isStreaming: boolean) => void;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const AssistantMessageArea = React.forwardRef<
|
|
111
|
-
HTMLDivElement,
|
|
112
|
-
AssistantMessageAreaProps
|
|
113
|
-
>(
|
|
114
|
-
(
|
|
115
|
-
{
|
|
116
|
-
className,
|
|
117
|
-
messages,
|
|
118
|
-
messagesEndRef,
|
|
119
|
-
actions,
|
|
120
|
-
streamingMessageId,
|
|
121
|
-
thinkIndicator,
|
|
122
|
-
handleIsTextStreaming,
|
|
123
|
-
...props
|
|
124
|
-
},
|
|
125
|
-
ref
|
|
126
|
-
) => {
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
messagesEndRef.current?.scrollIntoView({ behavior: "instant" });
|
|
129
|
-
}, []);
|
|
130
|
-
return(
|
|
131
|
-
<div
|
|
132
|
-
ref={ref}
|
|
133
|
-
className={cn("p-6 overflow-y-auto flex-grow bg-background", className)}
|
|
134
|
-
{...props}
|
|
135
|
-
>
|
|
136
|
-
{messages.map((message) => (
|
|
137
|
-
<div key={message.id}>
|
|
138
|
-
<CallOut
|
|
139
|
-
key={message.id}
|
|
140
|
-
role={message.role as "user" | "assistant"}
|
|
141
|
-
message={message}
|
|
142
|
-
>
|
|
143
|
-
{message.created_at && (
|
|
144
|
-
<div className="text-xs text-muted-foreground/80 pb-1">
|
|
145
|
-
{new Date(Number(message.created_at)).toLocaleString("es-ES", {
|
|
146
|
-
day: "2-digit",
|
|
147
|
-
month: "2-digit",
|
|
148
|
-
year: "numeric",
|
|
149
|
-
hour: "2-digit",
|
|
150
|
-
minute: "2-digit",
|
|
151
|
-
second: "2-digit",
|
|
152
|
-
hour12: false,
|
|
153
|
-
})}
|
|
154
|
-
</div>
|
|
155
|
-
)}
|
|
156
|
-
{message.loading && (
|
|
157
|
-
<div>
|
|
158
|
-
{thinkIndicator ?? <ThinkIndicator />}
|
|
159
|
-
</div>
|
|
160
|
-
)}
|
|
161
|
-
{message.error_code && (
|
|
162
|
-
<CallOutResponse
|
|
163
|
-
role="assistant"
|
|
164
|
-
data-error-code={message.error_code}
|
|
165
|
-
>
|
|
166
|
-
We have an internal error, please try again later.
|
|
167
|
-
</CallOutResponse>
|
|
168
|
-
)}
|
|
169
|
-
{message.content && (
|
|
170
|
-
<CallOutResponse
|
|
171
|
-
role={message.role}
|
|
172
|
-
isStreaming={streamingMessageId === message.id}
|
|
173
|
-
handleIsTextStreaming={handleIsTextStreaming}
|
|
174
|
-
additionalInfo={
|
|
175
|
-
streamingMessageId !== message.id
|
|
176
|
-
? message?.additionalInfo
|
|
177
|
-
: undefined
|
|
178
|
-
}
|
|
179
|
-
>
|
|
180
|
-
{message.content}
|
|
181
|
-
</CallOutResponse>
|
|
182
|
-
)}
|
|
183
|
-
{actions && streamingMessageId !== message.id &&
|
|
184
|
-
<CallOutActions
|
|
185
|
-
key={message.id}
|
|
186
|
-
actions={actions}
|
|
187
|
-
message={message}
|
|
188
|
-
role={message.role as "user" | "assistant"}
|
|
189
|
-
/>
|
|
190
|
-
}
|
|
191
|
-
</CallOut>
|
|
192
|
-
</div>
|
|
193
|
-
))}
|
|
194
|
-
<div ref={messagesEndRef} />
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
AssistantMessageArea.displayName = "AssistantMessageArea";
|
|
200
|
-
|
|
201
|
-
interface AssistantInputProps
|
|
202
|
-
extends React.FormHTMLAttributes<HTMLFormElement> {
|
|
203
|
-
sendMessageFunc: (event: React.FormEvent<HTMLFormElement>) => Promise<void>;
|
|
204
|
-
isButtonDisabled: boolean;
|
|
205
|
-
input: string;
|
|
206
|
-
handleInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
207
|
-
isMessageStreaming: boolean;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const AssistantInput = React.forwardRef<HTMLFormElement, AssistantInputProps>(
|
|
211
|
-
(
|
|
212
|
-
{
|
|
213
|
-
className,
|
|
214
|
-
sendMessageFunc,
|
|
215
|
-
isButtonDisabled,
|
|
216
|
-
input,
|
|
217
|
-
handleInputChange,
|
|
218
|
-
isMessageStreaming,
|
|
219
|
-
...props
|
|
220
|
-
},
|
|
221
|
-
ref
|
|
222
|
-
) => {
|
|
223
|
-
return (
|
|
224
|
-
<form
|
|
225
|
-
onSubmit={sendMessageFunc}
|
|
226
|
-
className={cn("flex items-center space-x-4", className)}
|
|
227
|
-
ref={ref}
|
|
228
|
-
{...props}
|
|
229
|
-
>
|
|
230
|
-
<input
|
|
231
|
-
type="text"
|
|
232
|
-
disabled={isButtonDisabled}
|
|
233
|
-
value={input}
|
|
234
|
-
onChange={handleInputChange}
|
|
235
|
-
placeholder={
|
|
236
|
-
isMessageStreaming ? "Procesando..." : "Escribe tu mensaje aquí..."
|
|
237
|
-
}
|
|
238
|
-
className={cn(
|
|
239
|
-
"flex-1 text-sm p-3 rounded-lg focus:outline-none w-full",
|
|
240
|
-
"border border-input bg-background text-foreground",
|
|
241
|
-
"placeholder:text-muted-foreground",
|
|
242
|
-
"focus:ring-2 focus:ring-ring",
|
|
243
|
-
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
244
|
-
)}
|
|
245
|
-
/>
|
|
246
|
-
<button
|
|
247
|
-
type="submit"
|
|
248
|
-
disabled={isButtonDisabled}
|
|
249
|
-
className={cn(
|
|
250
|
-
"w-10 h-10 rounded-full flex items-center justify-center alq--assistant-button-send",
|
|
251
|
-
isButtonDisabled
|
|
252
|
-
? "bg-muted text-muted-foreground"
|
|
253
|
-
: "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
254
|
-
)}
|
|
255
|
-
>
|
|
256
|
-
<Send className="w-5 h-5" />
|
|
257
|
-
</button>
|
|
258
|
-
</form>
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
);
|
|
262
|
-
AssistantInput.displayName = "AssistantInput";
|
|
263
|
-
|
|
264
|
-
export {
|
|
265
|
-
Assistant,
|
|
266
|
-
AssistantTitle,
|
|
267
|
-
AssistantDescription,
|
|
268
|
-
AssistantHeader,
|
|
269
|
-
AssistantMessageArea,
|
|
270
|
-
AssistantInput,
|
|
271
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { Whisper } from "./whisper";
|
|
2
|
-
export { SpeechToText } from "./speechToText";
|
|
3
|
-
export { Assistant } from "./assistant";
|
|
4
|
-
export { RatingDialog } from "./rating-dialog";
|
|
5
|
-
export { AssistantMessageArea } from "./assistant";
|
|
6
|
-
export { AssistantInput } from "./assistant";
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Message } from "ai";
|
|
4
|
-
|
|
5
|
-
import { RatingData } from "../../types/type";
|
|
6
|
-
import { useRatings } from "@alquimia-ai/tools/hooks";
|
|
7
|
-
import { useToast } from "../hooks";
|
|
8
|
-
import { RatingThumbs, RatingStars, RatingComment } from "../molecules";
|
|
9
|
-
import {
|
|
10
|
-
Dialog,
|
|
11
|
-
DialogDescription,
|
|
12
|
-
DialogTitle,
|
|
13
|
-
DialogContent,
|
|
14
|
-
DialogHeader,
|
|
15
|
-
Typography,
|
|
16
|
-
Button,
|
|
17
|
-
ToastAction,
|
|
18
|
-
} from "../atoms";
|
|
19
|
-
|
|
20
|
-
interface RatingDialogProps {
|
|
21
|
-
topicId: string;
|
|
22
|
-
assistantId: string;
|
|
23
|
-
sendRating: (ratingData: RatingData) => Promise<any>;
|
|
24
|
-
isOpen: boolean;
|
|
25
|
-
onOpenChange: (open: boolean) => void;
|
|
26
|
-
setHasRatedTopic: (hasRated: boolean) => void;
|
|
27
|
-
onError?: (componentName: string, error: Error) => void;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function RatingDialog({
|
|
31
|
-
sendRating,
|
|
32
|
-
topicId,
|
|
33
|
-
assistantId,
|
|
34
|
-
isOpen,
|
|
35
|
-
onOpenChange,
|
|
36
|
-
setHasRatedTopic,
|
|
37
|
-
}: RatingDialogProps) {
|
|
38
|
-
const { toast } = useToast();
|
|
39
|
-
const { handleRate, ratingStars, ratingThumbs, ratingComment, isLoading } =
|
|
40
|
-
useRatings({ assistantId, sendRating, topicId });
|
|
41
|
-
|
|
42
|
-
const onHandleRateSuccess = (success: boolean, err?: string) => {
|
|
43
|
-
setTimeout(() => onOpenChange(false), 1000);
|
|
44
|
-
success
|
|
45
|
-
? setHasRatedTopic(true)
|
|
46
|
-
: toast({
|
|
47
|
-
title: "Error",
|
|
48
|
-
description: `Hubo un error al enviar la calificación`,
|
|
49
|
-
action: (
|
|
50
|
-
<ToastAction altText="Goto schedule to undo">Cerrar</ToastAction>
|
|
51
|
-
),
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const handleCancelRate = () => {
|
|
56
|
-
setHasRatedTopic(true);
|
|
57
|
-
onOpenChange(false);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
|
62
|
-
<DialogContent className="sm:max-w-md">
|
|
63
|
-
<DialogHeader>
|
|
64
|
-
<DialogTitle>Calificá esta conversación</DialogTitle>
|
|
65
|
-
<DialogDescription>
|
|
66
|
-
Por favor, compartí tu opinión sobre el asistente.
|
|
67
|
-
</DialogDescription>
|
|
68
|
-
</DialogHeader>
|
|
69
|
-
<div className="flex flex-row justify-center gap-4 py-4">
|
|
70
|
-
<RatingStars
|
|
71
|
-
currentRating={ratingStars}
|
|
72
|
-
onRate={(newRating) =>
|
|
73
|
-
handleRate("score", newRating, onHandleRateSuccess)
|
|
74
|
-
}
|
|
75
|
-
isLoading={isLoading}
|
|
76
|
-
className="p-2 rounded"
|
|
77
|
-
/>
|
|
78
|
-
<RatingThumbs
|
|
79
|
-
currentRating={ratingComment}
|
|
80
|
-
onRate={(newRating) =>
|
|
81
|
-
handleRate("description", newRating, onHandleRateSuccess)
|
|
82
|
-
}
|
|
83
|
-
direction="row"
|
|
84
|
-
isLoading={isLoading}
|
|
85
|
-
/>
|
|
86
|
-
<RatingComment
|
|
87
|
-
currentRating={ratingComment}
|
|
88
|
-
onRate={(newRating) =>
|
|
89
|
-
handleRate("description", newRating, onHandleRateSuccess)
|
|
90
|
-
}
|
|
91
|
-
isLoading={isLoading}
|
|
92
|
-
/>
|
|
93
|
-
</div>
|
|
94
|
-
<div className="flex flex-row justify-center gap-4">
|
|
95
|
-
<Button onClick={handleCancelRate} variant="secondary">
|
|
96
|
-
<Typography as="p" typeStyle="tiny">
|
|
97
|
-
No, gracias.
|
|
98
|
-
</Typography>
|
|
99
|
-
</Button>
|
|
100
|
-
</div>
|
|
101
|
-
</DialogContent>
|
|
102
|
-
</Dialog>
|
|
103
|
-
);
|
|
104
|
-
}
|