reachat 2.1.0-alpha.21 → 2.1.0-alpha.23
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/{CSVFileRenderer-GYEEFRXD.js → CSVFileRenderer-CnRHD92k.js} +2 -2
- package/dist/{CSVFileRenderer-GYEEFRXD.js.map → CSVFileRenderer-CnRHD92k.js.map} +1 -1
- package/dist/ChatInput/ChatInput.d.ts +9 -1
- package/dist/ChatInput/FileDropzone.d.ts +33 -0
- package/dist/ChatInput/FileInput.d.ts +0 -4
- package/dist/ChatInput/index.d.ts +1 -0
- package/dist/ChatSuggestions/ChatSuggestion.d.ts +9 -0
- package/dist/ChatSuggestions/ChatSuggestions.d.ts +22 -0
- package/dist/ChatSuggestions/index.d.ts +2 -0
- package/dist/{DefaultFileRenderer-CUcl0kc2.js → DefaultFileRenderer-Du1R14oj.js} +2 -2
- package/dist/{DefaultFileRenderer-CUcl0kc2.js.map → DefaultFileRenderer-Du1R14oj.js.map} +1 -1
- package/dist/MessageStatus/MessageStatus.d.ts +44 -0
- package/dist/MessageStatus/MessageStatusItem.d.ts +9 -0
- package/dist/MessageStatus/StatusIcon.d.ts +17 -0
- package/dist/MessageStatus/index.d.ts +3 -0
- package/dist/SessionMessages/SessionMessages.d.ts +16 -0
- package/dist/docs.json +612 -16
- package/dist/{index-CwH75cwk.js → index-tgcYBaMs.js} +476 -123
- package/dist/index-tgcYBaMs.js.map +1 -0
- package/dist/index.css +186 -55
- package/dist/index.d.ts +2 -0
- package/dist/index.js +30 -24
- package/dist/index.umd.cjs +449 -98
- package/dist/index.umd.cjs.map +1 -1
- package/dist/stories/ChatSuggestions.stories.tsx +542 -0
- package/dist/stories/Console.stories.tsx +101 -623
- package/dist/stories/Files.stories.tsx +348 -0
- package/dist/stories/Markdown.stories.tsx +108 -1
- package/dist/stories/MessageStatus.stories.tsx +326 -0
- package/dist/stories/SessionsList.stories.tsx +276 -0
- package/dist/stories/assets/sparkles.svg +7 -0
- package/dist/stories/examples.ts +34 -0
- package/dist/theme.d.ts +46 -0
- package/dist/types.d.ts +10 -0
- package/package.json +7 -4
- package/dist/index-CwH75cwk.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { AnimatePresence, motion } from "motion/react";
|
|
|
3
3
|
import { IconButton } from "reablocks";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { useContext, useState, useRef, useEffect } from "react";
|
|
6
|
-
import { C as ChatContext, a as SvgCopy } from "./index-
|
|
6
|
+
import { C as ChatContext, a as SvgCopy } from "./index-tgcYBaMs.js";
|
|
7
7
|
const SvgDownload = (props) => /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "24px", height: "24px", ...props }, /* @__PURE__ */ React.createElement("path", { d: "M 11 2 C 10.448 2 10 2.448 10 3 L 10 11 L 6.5 11 A 0.5 0.5 0 0 0 6 11.5 A 0.5 0.5 0 0 0 6.1464844 11.853516 A 0.5 0.5 0 0 0 6.1777344 11.882812 L 11.283203 16.697266 L 11.316406 16.728516 A 1 1 0 0 0 12 17 A 1 1 0 0 0 12.683594 16.728516 L 12.697266 16.716797 A 1 1 0 0 0 12.707031 16.705078 L 17.810547 11.892578 A 0.5 0.5 0 0 0 17.839844 11.865234 L 17.847656 11.859375 A 0.5 0.5 0 0 0 17.853516 11.853516 A 0.5 0.5 0 0 0 18 11.5 A 0.5 0.5 0 0 0 17.5 11 L 14 11 L 14 3 C 14 2.448 13.552 2 13 2 L 12 2 L 11 2 z M 3 20 A 1.0001 1.0001 0 1 0 3 22 L 21 22 A 1.0001 1.0001 0 1 0 21 20 L 3 20 z", fill: "currentColor" }));
|
|
8
8
|
const sanitizeSVGCell = (cell) => {
|
|
9
9
|
const trimmed = cell.trim();
|
|
@@ -139,4 +139,4 @@ const CSVFileRenderer = ({ name, url, fileIcon }) => {
|
|
|
139
139
|
export {
|
|
140
140
|
CSVFileRenderer as default
|
|
141
141
|
};
|
|
142
|
-
//# sourceMappingURL=CSVFileRenderer-
|
|
142
|
+
//# sourceMappingURL=CSVFileRenderer-CnRHD92k.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CSVFileRenderer-GYEEFRXD.js","sources":["../src/assets/download.svg?react","../src/utils/sanitize.ts","../src/utils/parseCSV.ts","../src/SessionMessages/SessionMessage/MessageFile/renderers/CSVFileRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nconst SvgDownload = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", viewBox: \"0 0 24 24\", width: \"24px\", height: \"24px\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M 11 2 C 10.448 2 10 2.448 10 3 L 10 11 L 6.5 11 A 0.5 0.5 0 0 0 6 11.5 A 0.5 0.5 0 0 0 6.1464844 11.853516 A 0.5 0.5 0 0 0 6.1777344 11.882812 L 11.283203 16.697266 L 11.316406 16.728516 A 1 1 0 0 0 12 17 A 1 1 0 0 0 12.683594 16.728516 L 12.697266 16.716797 A 1 1 0 0 0 12.707031 16.705078 L 17.810547 11.892578 A 0.5 0.5 0 0 0 17.839844 11.865234 L 17.847656 11.859375 A 0.5 0.5 0 0 0 17.853516 11.853516 A 0.5 0.5 0 0 0 18 11.5 A 0.5 0.5 0 0 0 17.5 11 L 14 11 L 14 3 C 14 2.448 13.552 2 13 2 L 12 2 L 11 2 z M 3 20 A 1.0001 1.0001 0 1 0 3 22 L 21 22 A 1.0001 1.0001 0 1 0 21 20 L 3 20 z\", fill: \"currentColor\" }));\nexport default SvgDownload;\n","/**\n * Sanitizes cell content to prevent CSV injection and other potential vulnerabilities.\n * Based on the documentation of OWASP for CSV Injection\n * https://owasp.org/www-community/attacks/CSV_Injection\n * @param cell The cell content to sanitize.\n * @returns The sanitized cell content.\n */\nexport const sanitizeSVGCell = (cell: string): string => {\n const trimmed = cell.trim();\n // Escape double quotes by doubling them\n const escaped = trimmed.replace(/\"/g, '\"\"');\n // Add single quote prefix only for potentially dangerous content\n const prefix = /^[=+\\-@]/.test(trimmed) ? \"'\" : '';\n // Only wrap in quotes if the content contains special characters\n const needsQuotes = /[\",\\n\\r]/.test(escaped) || prefix;\n\n return needsQuotes ? `\"${prefix}${escaped}\"` : escaped;\n};\n","import { sanitizeSVGCell } from './sanitize';\n\n/**\n * Parses a CSV string from a local file and returns an array of rows.\n * Sanitizes cell data to prevent injection attacks.\n * @param csvString The raw CSV string content to parse.\n * @returns The parsed CSV data as a 2D array of strings.\n */\nexport const parseCSV = (csvString: string): string[][] => {\n try {\n const rows = csvString.split('\\n');\n return rows.map(row => row.split(',').map(cell => sanitizeSVGCell(cell)));\n } catch (error) {\n console.error('Error parsing CSV:', error);\n throw new Error('Failed to parse CSV file.');\n }\n};\n","import { AnimatePresence, motion } from 'motion/react';\nimport { IconButton } from 'reablocks';\nimport type { FC, ReactElement } from 'react';\nimport { useContext, useEffect, useRef, useState } from 'react';\n\nimport PlaceholderIcon from '@/assets/copy.svg?react';\nimport DownloadIcon from '@/assets/download.svg?react';\nimport { ChatContext } from '@/ChatContext';\nimport { parseCSV } from '@/utils/parseCSV';\n\ninterface CSVFileRendererProps {\n /**\n * Name of the file.\n */\n name?: string;\n\n /**\n * URL of the file.\n */\n url: string;\n\n /**\n * Icon to for file type.\n */\n fileIcon?: ReactElement;\n}\n\n/**\n * Renderer for CSV files that fetches and displays a snippet of the file data.\n */\nconst CSVFileRenderer: FC<CSVFileRendererProps> = ({ name, url, fileIcon }) => {\n const { theme } = useContext(ChatContext);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [csvData, setCsvData] = useState<string[][]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isModalOpen, setIsModalOpen] = useState(false);\n const modalRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const fetchCsvData = async () => {\n try {\n setIsLoading(true);\n const response = await fetch(url);\n const data = parseCSV(await response.text());\n setCsvData(data);\n } catch {\n setError('Failed to load CSV file.');\n } finally {\n setIsLoading(false);\n }\n };\n\n fetchCsvData();\n }, [url]);\n\n const toggleModal = () => {\n setIsModalOpen(prev => !prev);\n };\n\n const handleClickOutside = (event: MouseEvent) => {\n if (modalRef.current && !modalRef.current.contains(event.target as Node)) {\n setIsModalOpen(false);\n }\n };\n\n useEffect(() => {\n if (isModalOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isModalOpen]);\n\n const downloadCSV = () => {\n if (csvData.length === 0) return;\n\n const csvContent = csvData.map(row => row.join(',')).join('\\n');\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `${name || 'data'}`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n };\n\n const renderTable = (data: string[][], maxRows?: number) => (\n <motion.table\n layout\n className=\"w-full\"\n transition={{ type: 'spring', stiffness: 100, damping: 20 }}\n >\n <thead className=\"sticky top-0 bg-gray-200 dark:bg-gray-800 z-10\">\n <tr>\n <th className=\"py-4 px-6\">#</th>\n {data[0].map((header, index) => (\n <th key={`header-${index}`} className=\"py-4 px-6\">\n {header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.slice(1, maxRows).map((row, rowIndex) => (\n <tr\n key={`row-${rowIndex}`}\n className=\"border-b border-panel-accent light:border-gray-700 hover:bg-panel-accent hover:light:bg-gray-700/40 transition-colors text-base\"\n >\n <td className=\"py-4 px-6\">{rowIndex + 1}</td>\n {row.map((cell, cellIndex) => (\n <td key={`cell-${rowIndex}-${cellIndex}`} className=\"py-4 px-6\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </motion.table>\n );\n\n return (\n <div className={theme.messages.message.csvPreview.base}>\n <div className={theme.messages.message.csvPreview.header.base}>\n <div className={theme.messages.message.csvPreview.header.icon}>\n {fileIcon}\n {name && <figcaption className=\"ml-1\">{name}</figcaption>}\n </div>\n <div className={theme.messages.message.csvPreview.header.actions}>\n <IconButton size=\"medium\" variant=\"text\" onClick={downloadCSV}>\n <DownloadIcon />\n </IconButton>\n <IconButton size=\"medium\" variant=\"text\" onClick={toggleModal}>\n <PlaceholderIcon />\n </IconButton>\n </div>\n </div>\n\n {error && <div className=\"error-message\">{error}</div>}\n\n {isLoading && !csvData && (\n <div className=\"text-text-secondary\">Loading...</div>\n )}\n\n <div className={theme.messages.message.csvPreview.tableContainer}>\n {!error && csvData.length > 0 && renderTable(csvData, 6)}\n </div>\n\n <AnimatePresence>\n {isModalOpen && (\n <motion.div\n className={theme.messages.message.csvPreview.dialog.base}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.3 }}\n >\n <motion.div\n ref={modalRef}\n className={theme.messages.message.csvPreview.dialog.container}\n initial={{ scale: 0.8 }}\n animate={{ scale: 1 }}\n exit={{ scale: 0.8 }}\n transition={{ duration: 0.3 }}\n >\n {!error && csvData.length > 0 && renderTable(csvData)}\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n};\n\nexport default CSVFileRenderer;\n"],"names":["url","DownloadIcon","PlaceholderIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CSVFileRenderer-CnRHD92k.js","sources":["../src/assets/download.svg?react","../src/utils/sanitize.ts","../src/utils/parseCSV.ts","../src/SessionMessages/SessionMessage/MessageFile/renderers/CSVFileRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nconst SvgDownload = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", viewBox: \"0 0 24 24\", width: \"24px\", height: \"24px\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M 11 2 C 10.448 2 10 2.448 10 3 L 10 11 L 6.5 11 A 0.5 0.5 0 0 0 6 11.5 A 0.5 0.5 0 0 0 6.1464844 11.853516 A 0.5 0.5 0 0 0 6.1777344 11.882812 L 11.283203 16.697266 L 11.316406 16.728516 A 1 1 0 0 0 12 17 A 1 1 0 0 0 12.683594 16.728516 L 12.697266 16.716797 A 1 1 0 0 0 12.707031 16.705078 L 17.810547 11.892578 A 0.5 0.5 0 0 0 17.839844 11.865234 L 17.847656 11.859375 A 0.5 0.5 0 0 0 17.853516 11.853516 A 0.5 0.5 0 0 0 18 11.5 A 0.5 0.5 0 0 0 17.5 11 L 14 11 L 14 3 C 14 2.448 13.552 2 13 2 L 12 2 L 11 2 z M 3 20 A 1.0001 1.0001 0 1 0 3 22 L 21 22 A 1.0001 1.0001 0 1 0 21 20 L 3 20 z\", fill: \"currentColor\" }));\nexport default SvgDownload;\n","/**\n * Sanitizes cell content to prevent CSV injection and other potential vulnerabilities.\n * Based on the documentation of OWASP for CSV Injection\n * https://owasp.org/www-community/attacks/CSV_Injection\n * @param cell The cell content to sanitize.\n * @returns The sanitized cell content.\n */\nexport const sanitizeSVGCell = (cell: string): string => {\n const trimmed = cell.trim();\n // Escape double quotes by doubling them\n const escaped = trimmed.replace(/\"/g, '\"\"');\n // Add single quote prefix only for potentially dangerous content\n const prefix = /^[=+\\-@]/.test(trimmed) ? \"'\" : '';\n // Only wrap in quotes if the content contains special characters\n const needsQuotes = /[\",\\n\\r]/.test(escaped) || prefix;\n\n return needsQuotes ? `\"${prefix}${escaped}\"` : escaped;\n};\n","import { sanitizeSVGCell } from './sanitize';\n\n/**\n * Parses a CSV string from a local file and returns an array of rows.\n * Sanitizes cell data to prevent injection attacks.\n * @param csvString The raw CSV string content to parse.\n * @returns The parsed CSV data as a 2D array of strings.\n */\nexport const parseCSV = (csvString: string): string[][] => {\n try {\n const rows = csvString.split('\\n');\n return rows.map(row => row.split(',').map(cell => sanitizeSVGCell(cell)));\n } catch (error) {\n console.error('Error parsing CSV:', error);\n throw new Error('Failed to parse CSV file.');\n }\n};\n","import { AnimatePresence, motion } from 'motion/react';\nimport { IconButton } from 'reablocks';\nimport type { FC, ReactElement } from 'react';\nimport { useContext, useEffect, useRef, useState } from 'react';\n\nimport PlaceholderIcon from '@/assets/copy.svg?react';\nimport DownloadIcon from '@/assets/download.svg?react';\nimport { ChatContext } from '@/ChatContext';\nimport { parseCSV } from '@/utils/parseCSV';\n\ninterface CSVFileRendererProps {\n /**\n * Name of the file.\n */\n name?: string;\n\n /**\n * URL of the file.\n */\n url: string;\n\n /**\n * Icon to for file type.\n */\n fileIcon?: ReactElement;\n}\n\n/**\n * Renderer for CSV files that fetches and displays a snippet of the file data.\n */\nconst CSVFileRenderer: FC<CSVFileRendererProps> = ({ name, url, fileIcon }) => {\n const { theme } = useContext(ChatContext);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [csvData, setCsvData] = useState<string[][]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isModalOpen, setIsModalOpen] = useState(false);\n const modalRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const fetchCsvData = async () => {\n try {\n setIsLoading(true);\n const response = await fetch(url);\n const data = parseCSV(await response.text());\n setCsvData(data);\n } catch {\n setError('Failed to load CSV file.');\n } finally {\n setIsLoading(false);\n }\n };\n\n fetchCsvData();\n }, [url]);\n\n const toggleModal = () => {\n setIsModalOpen(prev => !prev);\n };\n\n const handleClickOutside = (event: MouseEvent) => {\n if (modalRef.current && !modalRef.current.contains(event.target as Node)) {\n setIsModalOpen(false);\n }\n };\n\n useEffect(() => {\n if (isModalOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isModalOpen]);\n\n const downloadCSV = () => {\n if (csvData.length === 0) return;\n\n const csvContent = csvData.map(row => row.join(',')).join('\\n');\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `${name || 'data'}`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n };\n\n const renderTable = (data: string[][], maxRows?: number) => (\n <motion.table\n layout\n className=\"w-full\"\n transition={{ type: 'spring', stiffness: 100, damping: 20 }}\n >\n <thead className=\"sticky top-0 bg-gray-200 dark:bg-gray-800 z-10\">\n <tr>\n <th className=\"py-4 px-6\">#</th>\n {data[0].map((header, index) => (\n <th key={`header-${index}`} className=\"py-4 px-6\">\n {header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.slice(1, maxRows).map((row, rowIndex) => (\n <tr\n key={`row-${rowIndex}`}\n className=\"border-b border-panel-accent light:border-gray-700 hover:bg-panel-accent hover:light:bg-gray-700/40 transition-colors text-base\"\n >\n <td className=\"py-4 px-6\">{rowIndex + 1}</td>\n {row.map((cell, cellIndex) => (\n <td key={`cell-${rowIndex}-${cellIndex}`} className=\"py-4 px-6\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </motion.table>\n );\n\n return (\n <div className={theme.messages.message.csvPreview.base}>\n <div className={theme.messages.message.csvPreview.header.base}>\n <div className={theme.messages.message.csvPreview.header.icon}>\n {fileIcon}\n {name && <figcaption className=\"ml-1\">{name}</figcaption>}\n </div>\n <div className={theme.messages.message.csvPreview.header.actions}>\n <IconButton size=\"medium\" variant=\"text\" onClick={downloadCSV}>\n <DownloadIcon />\n </IconButton>\n <IconButton size=\"medium\" variant=\"text\" onClick={toggleModal}>\n <PlaceholderIcon />\n </IconButton>\n </div>\n </div>\n\n {error && <div className=\"error-message\">{error}</div>}\n\n {isLoading && !csvData && (\n <div className=\"text-text-secondary\">Loading...</div>\n )}\n\n <div className={theme.messages.message.csvPreview.tableContainer}>\n {!error && csvData.length > 0 && renderTable(csvData, 6)}\n </div>\n\n <AnimatePresence>\n {isModalOpen && (\n <motion.div\n className={theme.messages.message.csvPreview.dialog.base}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.3 }}\n >\n <motion.div\n ref={modalRef}\n className={theme.messages.message.csvPreview.dialog.container}\n initial={{ scale: 0.8 }}\n animate={{ scale: 1 }}\n exit={{ scale: 0.8 }}\n transition={{ duration: 0.3 }}\n >\n {!error && csvData.length > 0 && renderTable(csvData)}\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n};\n\nexport default CSVFileRenderer;\n"],"names":["url","DownloadIcon","PlaceholderIcon"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ interface ChatInputProps {
|
|
|
5
5
|
*/
|
|
6
6
|
defaultValue?: string;
|
|
7
7
|
/**
|
|
8
|
-
* Allowed file
|
|
8
|
+
* Allowed file extensions for upload (e.g., ['.pdf', '.docx']).
|
|
9
9
|
*/
|
|
10
10
|
allowedFiles?: string[];
|
|
11
11
|
/**
|
|
@@ -28,6 +28,14 @@ interface ChatInputProps {
|
|
|
28
28
|
* Icon to show for attach.
|
|
29
29
|
*/
|
|
30
30
|
attachIcon?: ReactElement;
|
|
31
|
+
/**
|
|
32
|
+
* Icon to show for the dropzone overlay.
|
|
33
|
+
*/
|
|
34
|
+
dropIcon?: ReactElement;
|
|
35
|
+
/**
|
|
36
|
+
* Text to show on the dropzone overlay.
|
|
37
|
+
*/
|
|
38
|
+
dropText?: string;
|
|
31
39
|
/**
|
|
32
40
|
* Message to be displayed in the input field.
|
|
33
41
|
*/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
interface FileDropzoneProps {
|
|
3
|
+
/**
|
|
4
|
+
* Array of allowed file extensions (e.g., ['.pdf', '.docx', '.png']).
|
|
5
|
+
*/
|
|
6
|
+
allowedFiles?: string[];
|
|
7
|
+
/**
|
|
8
|
+
* Allow multiple file uploads.
|
|
9
|
+
*/
|
|
10
|
+
multiple?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Disables the dropzone when true.
|
|
13
|
+
*/
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Icon to show for the dropzone overlay.
|
|
17
|
+
*/
|
|
18
|
+
dropIcon?: ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Text to show on the dropzone overlay.
|
|
21
|
+
*/
|
|
22
|
+
dropText?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Children to render inside the dropzone.
|
|
25
|
+
*/
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* Callback function triggered when files are dropped.
|
|
29
|
+
*/
|
|
30
|
+
onFileDrop?: (file: File) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare const FileDropzone: FC<FileDropzoneProps>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Suggestion } from '../types';
|
|
3
|
+
export interface ChatSuggestionProps extends Suggestion {
|
|
4
|
+
/**
|
|
5
|
+
* Callback when the suggestion is clicked.
|
|
6
|
+
*/
|
|
7
|
+
onClick?: (suggestion: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const ChatSuggestion: FC<ChatSuggestionProps>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FC, ReactElement } from 'react';
|
|
2
|
+
import { Suggestion } from '../types';
|
|
3
|
+
export interface ChatSuggestionsProps {
|
|
4
|
+
/**
|
|
5
|
+
* Array of suggestions to display.
|
|
6
|
+
*/
|
|
7
|
+
suggestions: Suggestion[];
|
|
8
|
+
/**
|
|
9
|
+
* Custom class name to apply to the container.
|
|
10
|
+
*/
|
|
11
|
+
className?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Callback when a suggestion is clicked.
|
|
14
|
+
*/
|
|
15
|
+
onSuggestionClick?: (suggestion: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Custom render function for each suggestion item.
|
|
18
|
+
* Receives the suggestion data and onClick handler.
|
|
19
|
+
*/
|
|
20
|
+
children?: ReactElement;
|
|
21
|
+
}
|
|
22
|
+
export declare const ChatSuggestions: FC<ChatSuggestionsProps>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn, Ellipsis } from "reablocks";
|
|
3
|
-
import { S as SvgFile } from "./index-
|
|
3
|
+
import { S as SvgFile } from "./index-tgcYBaMs.js";
|
|
4
4
|
const DefaultFileRenderer = ({
|
|
5
5
|
name,
|
|
6
6
|
limit = 100,
|
|
@@ -12,4 +12,4 @@ const DefaultFileRenderer = ({
|
|
|
12
12
|
export {
|
|
13
13
|
DefaultFileRenderer as default
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=DefaultFileRenderer-
|
|
15
|
+
//# sourceMappingURL=DefaultFileRenderer-Du1R14oj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultFileRenderer-
|
|
1
|
+
{"version":3,"file":"DefaultFileRenderer-Du1R14oj.js","sources":["../src/SessionMessages/SessionMessage/MessageFile/renderers/DefaultFileRenderer.tsx"],"sourcesContent":["import { cn, Ellipsis } from 'reablocks';\nimport type { FC, ReactElement } from 'react';\n\nimport FileIcon from '@/assets/file.svg?react';\n\ninterface DefaultFileRendererProps {\n /**\n * Limit for the name.\n */\n limit?: number;\n\n /**\n * Name of the file.\n */\n name?: string;\n\n /**\n * URL of the file.\n */\n url: string;\n\n /**\n * Icon to for file type.\n */\n fileIcon?: ReactElement;\n}\n\n/**\n * Default renderer for unspecified file types.\n */\nconst DefaultFileRenderer: FC<DefaultFileRendererProps> = ({\n name,\n limit = 100,\n fileIcon = <FileIcon />\n}) => (\n <figure className=\"flex items-center gap-2\">\n {fileIcon}\n {name && (\n <figcaption className={cn('file-name-class')}>\n <Ellipsis value={name} limit={limit} />\n </figcaption>\n )}\n </figure>\n);\n\nexport default DefaultFileRenderer;\n"],"names":["FileIcon"],"mappings":";;;AA8BA,MAAM,sBAAoD,CAAC;AAAA,EACzD;AAAA,EACA,QAAQ;AAAA,EACR,+BAAYA,SAAA,CAAA,CAAS;AACvB,MACE,qBAAC,UAAA,EAAO,WAAU,2BACf,UAAA;AAAA,EAAA;AAAA,EACA,QACC,oBAAC,cAAA,EAAW,WAAW,GAAG,iBAAiB,GACzC,UAAA,oBAAC,UAAA,EAAS,OAAO,MAAM,MAAA,CAAc,EAAA,CACvC;AAAA,EAAA,CAEJ;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { FC, PropsWithChildren, ReactNode } from 'react';
|
|
2
|
+
export type MessageStatusState = 'loading' | 'complete' | 'error';
|
|
3
|
+
export interface MessageStatusStep {
|
|
4
|
+
/**
|
|
5
|
+
* Unique identifier for the step.
|
|
6
|
+
*/
|
|
7
|
+
id: string;
|
|
8
|
+
/**
|
|
9
|
+
* Text to display for the step.
|
|
10
|
+
*/
|
|
11
|
+
text: string;
|
|
12
|
+
/**
|
|
13
|
+
* Current state of the step.
|
|
14
|
+
* @default 'loading'
|
|
15
|
+
*/
|
|
16
|
+
status?: MessageStatusState;
|
|
17
|
+
}
|
|
18
|
+
export interface MessageStatusProps extends PropsWithChildren {
|
|
19
|
+
/**
|
|
20
|
+
* Current status state.
|
|
21
|
+
* @default 'loading'
|
|
22
|
+
*/
|
|
23
|
+
status?: MessageStatusState;
|
|
24
|
+
/**
|
|
25
|
+
* Main status text to display.
|
|
26
|
+
*/
|
|
27
|
+
text: string;
|
|
28
|
+
/**
|
|
29
|
+
* Optional sub-steps to display.
|
|
30
|
+
*/
|
|
31
|
+
steps?: MessageStatusStep[];
|
|
32
|
+
/**
|
|
33
|
+
* Custom icon to display. If not provided, uses default icons based on status.
|
|
34
|
+
*/
|
|
35
|
+
icon?: ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Additional CSS class name.
|
|
38
|
+
*/
|
|
39
|
+
className?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Displays status information with optional sub-steps, similar to Claude's tool status UI.
|
|
43
|
+
*/
|
|
44
|
+
export declare const MessageStatus: FC<MessageStatusProps>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { MessageStatusState } from './MessageStatus';
|
|
3
|
+
export interface StatusIconProps {
|
|
4
|
+
/**
|
|
5
|
+
* Current state of the status icon.
|
|
6
|
+
*/
|
|
7
|
+
state: MessageStatusState;
|
|
8
|
+
/**
|
|
9
|
+
* Additional CSS class name for the icon container.
|
|
10
|
+
*/
|
|
11
|
+
className?: string;
|
|
12
|
+
/**
|
|
13
|
+
* CSS class name for the icon color based on state.
|
|
14
|
+
*/
|
|
15
|
+
colorClassName?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const StatusIcon: FC<StatusIconProps>;
|
|
@@ -21,15 +21,31 @@ interface SessionMessagesProps {
|
|
|
21
21
|
* Whether to automatically scroll to the bottom of the content.
|
|
22
22
|
*/
|
|
23
23
|
autoScroll?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to display the scroll to bottom button.
|
|
26
|
+
*/
|
|
27
|
+
showScrollBottomButton?: boolean;
|
|
24
28
|
/**
|
|
25
29
|
* Render function for the session messages.
|
|
26
30
|
*/
|
|
27
31
|
children?: (conversations: Conversation[]) => ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to show the load more button.
|
|
34
|
+
*/
|
|
35
|
+
showLoadMoreButton?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to disable the load more button.
|
|
38
|
+
*/
|
|
39
|
+
loadMoreButtonDisabled?: boolean;
|
|
28
40
|
/**
|
|
29
41
|
* Scroll event handler.
|
|
30
42
|
* @param e
|
|
31
43
|
*/
|
|
32
44
|
onScroll?: UIEventHandler<HTMLDivElement>;
|
|
45
|
+
/**
|
|
46
|
+
* Load more event handler.
|
|
47
|
+
*/
|
|
48
|
+
onLoadMore?: () => void;
|
|
33
49
|
}
|
|
34
50
|
export declare const SessionMessages: React.FC<SessionMessagesProps>;
|
|
35
51
|
export {};
|