reachat 2.1.0-alpha.9 → 2.1.1

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 (82) hide show
  1. package/README.md +4 -2
  2. package/dist/AppBar/AppBar.d.ts +1 -1
  3. package/dist/{CSVFileRenderer-CkRKGiCl.js → CSVFileRenderer-DXI8PDqR.js} +14 -15
  4. package/dist/CSVFileRenderer-DXI8PDqR.js.map +1 -0
  5. package/dist/Chat.d.ts +9 -3
  6. package/dist/ChatBubble/ChatBubble.d.ts +1 -1
  7. package/dist/ChatContext.d.ts +4 -2
  8. package/dist/ChatInput/ChatInput.d.ts +23 -13
  9. package/dist/ChatInput/FileInput.d.ts +1 -1
  10. package/dist/ChatInput/MentionList.d.ts +32 -0
  11. package/dist/ChatInput/RichTextInput.d.ts +55 -0
  12. package/dist/ChatInput/index.d.ts +3 -0
  13. package/dist/ChatInput/types.d.ts +104 -0
  14. package/dist/ChatSuggestions/ChatSuggestion.d.ts +9 -0
  15. package/dist/ChatSuggestions/ChatSuggestions.d.ts +22 -0
  16. package/dist/ChatSuggestions/index.d.ts +2 -0
  17. package/dist/{DefaultFileRenderer-C1qZ57tG.js → DefaultFileRenderer-Bi8LNDio.js} +2 -2
  18. package/dist/DefaultFileRenderer-Bi8LNDio.js.map +1 -0
  19. package/dist/ImageFileRenderer-C8tVW3I8.js.map +1 -1
  20. package/dist/Markdown/Markdown.d.ts +4 -3
  21. package/dist/Markdown/Table.d.ts +1 -1
  22. package/dist/Markdown/charts/ChartError.d.ts +21 -0
  23. package/dist/Markdown/charts/ChartPre.d.ts +6 -0
  24. package/dist/Markdown/charts/ChartRenderer.d.ts +13 -0
  25. package/dist/Markdown/charts/chartHelpers.d.ts +40 -0
  26. package/dist/Markdown/charts/chartHelpers.spec.d.ts +1 -0
  27. package/dist/Markdown/charts/index.d.ts +7 -0
  28. package/dist/Markdown/index.d.ts +3 -2
  29. package/dist/Markdown/plugins/index.d.ts +1 -0
  30. package/dist/Markdown/plugins/remarkChart.d.ts +59 -0
  31. package/dist/Markdown/plugins/remarkCve.d.ts +1 -1
  32. package/dist/MessageStatus/MessageStatus.d.ts +44 -0
  33. package/dist/MessageStatus/MessageStatusItem.d.ts +9 -0
  34. package/dist/MessageStatus/StatusIcon.d.ts +17 -0
  35. package/dist/MessageStatus/index.d.ts +3 -0
  36. package/dist/PDFFileRenderer-DQdFS2l6.js +9 -0
  37. package/dist/PDFFileRenderer-DQdFS2l6.js.map +1 -0
  38. package/dist/SessionMessages/SessionEmpty.d.ts +4 -1
  39. package/dist/SessionMessages/SessionMessage/MessageFile/renderers/index.d.ts +1 -1
  40. package/dist/SessionMessages/SessionMessage/MessageFiles.d.ts +1 -1
  41. package/dist/SessionMessages/SessionMessage/MessageSources.d.ts +1 -1
  42. package/dist/SessionMessages/SessionMessage/SessionMessage.d.ts +0 -4
  43. package/dist/SessionMessages/SessionMessage/index.d.ts +2 -2
  44. package/dist/SessionMessages/SessionMessages.d.ts +3 -7
  45. package/dist/SessionMessages/index.d.ts +2 -2
  46. package/dist/SessionsList/index.d.ts +2 -2
  47. package/dist/docs.json +1037 -183
  48. package/dist/index-CBHNcMyR.js +4369 -0
  49. package/dist/index-CBHNcMyR.js.map +1 -0
  50. package/dist/index.css +2129 -6532
  51. package/dist/index.d.ts +8 -7
  52. package/dist/index.js +49 -34
  53. package/dist/index.umd.cjs +3414 -1320
  54. package/dist/index.umd.cjs.map +1 -1
  55. package/dist/stories/Changelog.mdx +1 -1
  56. package/dist/stories/ChartError.stories.tsx +85 -0
  57. package/dist/stories/Charts.stories.tsx +371 -0
  58. package/dist/stories/Chat.stories.tsx +5 -5
  59. package/dist/stories/ChatBubble.stories.tsx +3 -3
  60. package/dist/stories/ChatSuggestions.stories.tsx +541 -0
  61. package/dist/stories/Companion.stories.tsx +6 -6
  62. package/dist/stories/Console.stories.tsx +165 -25
  63. package/dist/stories/EnhancedInput.stories.tsx +322 -0
  64. package/dist/stories/Integration.stories.tsx +2 -2
  65. package/dist/stories/Intro.mdx +1 -1
  66. package/dist/stories/MessageStatus.stories.tsx +314 -0
  67. package/dist/stories/RichTextInput.stories.tsx +198 -0
  68. package/dist/stories/assets/logo.svg +19 -38
  69. package/dist/stories/assets/paperclip.svg +1 -4
  70. package/dist/stories/assets/search.svg +1 -5
  71. package/dist/stories/assets/sparkles.svg +7 -0
  72. package/dist/stories/examples.ts +47 -20
  73. package/dist/theme.d.ts +76 -13
  74. package/dist/types.d.ts +10 -0
  75. package/package.json +69 -66
  76. package/dist/CSVFileRenderer-CkRKGiCl.js.map +0 -1
  77. package/dist/DefaultFileRenderer-C1qZ57tG.js.map +0 -1
  78. package/dist/PDFFileRenderer-BBn2EVrV.js +0 -16
  79. package/dist/PDFFileRenderer-BBn2EVrV.js.map +0 -1
  80. package/dist/index-6CsqxEMx.js +0 -2257
  81. package/dist/index-6CsqxEMx.js.map +0 -1
  82. package/dist/utils/index.d.ts +0 -1
@@ -1,7 +1,6 @@
1
+ import { Session } from '@/types';
1
2
  import { subHours } from 'date-fns';
2
3
 
3
- import type { Session } from '@/types';
4
-
5
4
  export const fakeSessions: Session[] = [
6
5
  {
7
6
  id: '1',
@@ -188,11 +187,12 @@ export const sessionWithDataDocs: Session[] = [
188
187
  {
189
188
  id: '1',
190
189
  question: 'Summarize the contents of the CSV.',
191
- response:
192
- 'The CSV file contains a dataset with the following columns: Name, Age, Occupation, and City.',
190
+ response: 'The CSV file contains a dataset with the following columns: Name, Age, Occupation, and City.',
193
191
  createdAt: new Date(),
194
192
  updatedAt: new Date(),
195
- files: [{ name: 'sample.csv', size: 1024000, type: 'text/csv' }]
193
+ files: [
194
+ { name: 'sample.csv', size: 1024000, type: 'text/csv' }
195
+ ]
196
196
  },
197
197
  {
198
198
  id: '2',
@@ -201,7 +201,7 @@ export const sessionWithDataDocs: Session[] = [
201
201
  createdAt: new Date(),
202
202
  updatedAt: new Date(),
203
203
  files: [
204
- { name: 'document.pdf', size: 1024000, type: 'application/pdf' }
204
+ { name: 'document.pdf', size: 1024000, type: 'application/pdf' },
205
205
  ]
206
206
  }
207
207
  ]
@@ -218,17 +218,11 @@ export const sessionWithCSVFiles: Session[] = [
218
218
  {
219
219
  id: '1',
220
220
  question: 'Summarize the contents of the CSV.',
221
- response:
222
- 'The CSV file contains a dataset with the following columns: Name, HEX, RGB.',
221
+ response: 'The CSV file contains a dataset with the following columns: Name, HEX, RGB.',
223
222
  createdAt: new Date(),
224
223
  updatedAt: new Date(),
225
224
  files: [
226
- {
227
- name: 'sample.csv',
228
- size: 500,
229
- type: 'text/csv',
230
- url: 'https://gist.githubusercontent.com/RobVanGroenewoud/ba89ad7684df8cefe5c183adb498cc65/raw/f2eec6d2cb89f5d779e16b28ed0dab89d738ba96/sample.csv'
231
- }
225
+ { name: 'sample.csv', size: 500, type: 'text/csv', url: 'https://gist.githubusercontent.com/RobVanGroenewoud/ba89ad7684df8cefe5c183adb498cc65/raw/f2eec6d2cb89f5d779e16b28ed0dab89d738ba96/sample.csv' }
232
226
  ]
233
227
  },
234
228
  {
@@ -238,7 +232,7 @@ export const sessionWithCSVFiles: Session[] = [
238
232
  createdAt: new Date(),
239
233
  updatedAt: new Date(),
240
234
  files: [
241
- { name: 'document.pdf', size: 1024000, type: 'application/pdf' }
235
+ { name: 'document.pdf', size: 1024000, type: 'application/pdf' },
242
236
  ]
243
237
  }
244
238
  ]
@@ -249,26 +243,59 @@ export const chatTemplates = [
249
243
  {
250
244
  id: '1',
251
245
  title: 'Explore Components',
252
- message: 'Can you show me the main components available in Reachat?',
246
+ message: "Can you show me the main components available in Reachat?",
253
247
  icon: 'SendPlane'
254
248
  },
255
249
  {
256
250
  id: '2',
257
251
  title: 'Customize Chat UI',
258
- message: 'How can I customize the appearance of my Reachat interface?',
252
+ message: "How can I customize the appearance of my Reachat interface?",
259
253
  icon: 'SendPlane'
260
254
  },
261
255
  {
262
256
  id: '3',
263
257
  title: 'Manage Sessions',
264
- message:
265
- 'What are the best practices for managing chat sessions in Reachat?',
258
+ message: "What are the best practices for managing chat sessions in Reachat?",
266
259
  icon: 'SendPlane'
267
260
  },
268
261
  {
269
262
  id: '4',
270
263
  title: 'Tailwind Setup',
271
- message: 'How do I properly set up Tailwind CSS with Reachat?',
264
+ message: "How do I properly set up Tailwind CSS with Reachat?",
272
265
  icon: 'SendPlane'
273
266
  }
274
267
  ];
268
+
269
+ export const defaultSuggestions = [
270
+ {
271
+ id: '1',
272
+ content: 'Tell me more about this topic'
273
+ },
274
+ {
275
+ id: '2',
276
+ content: 'Can you provide an example?'
277
+ },
278
+ {
279
+ id: '3',
280
+ content: 'What are the best practices?'
281
+ }
282
+ ];
283
+
284
+ export const sessionWithSuggestions = [
285
+ {
286
+ id: 'session-suggestions',
287
+ title: 'Session with Suggestions',
288
+ createdAt: new Date(),
289
+ updatedAt: new Date(),
290
+ conversations: [
291
+ {
292
+ id: '1',
293
+ question: 'What is React?',
294
+ response:
295
+ 'React is a JavaScript library for building user interfaces. It was developed by Facebook and is now maintained by Meta and a community of developers.',
296
+ createdAt: new Date(),
297
+ updatedAt: new Date()
298
+ }
299
+ ]
300
+ }
301
+ ];
package/dist/theme.d.ts CHANGED
@@ -4,6 +4,33 @@ export interface ChatTheme {
4
4
  companion: string;
5
5
  empty: string;
6
6
  appbar: string;
7
+ status: {
8
+ base: string;
9
+ header: string;
10
+ icon: {
11
+ base: string;
12
+ loading: string;
13
+ complete: string;
14
+ error: string;
15
+ };
16
+ text: {
17
+ base: string;
18
+ loading: string;
19
+ complete: string;
20
+ error: string;
21
+ };
22
+ steps: {
23
+ base: string;
24
+ step: {
25
+ base: string;
26
+ icon: string;
27
+ text: string;
28
+ loading: string;
29
+ complete: string;
30
+ error: string;
31
+ };
32
+ };
33
+ };
7
34
  sessions: {
8
35
  base: string;
9
36
  console: string;
@@ -34,6 +61,10 @@ export interface ChatTheme {
34
61
  cursor: string;
35
62
  overlay: string;
36
63
  expand: string;
64
+ scrollToBottom: {
65
+ container: string;
66
+ button: string;
67
+ };
37
68
  files: {
38
69
  base: string;
39
70
  file: {
@@ -64,19 +95,6 @@ export interface ChatTheme {
64
95
  ol: string;
65
96
  copy: string;
66
97
  };
67
- csvPreview: {
68
- base: string;
69
- header: {
70
- base: string;
71
- icon: string;
72
- actions: string;
73
- };
74
- tableContainer: string;
75
- dialog: {
76
- base: string;
77
- container: string;
78
- };
79
- };
80
98
  footer: {
81
99
  base: string;
82
100
  copy: string;
@@ -95,6 +113,51 @@ export interface ChatTheme {
95
113
  send: string;
96
114
  stop: string;
97
115
  };
116
+ popup: {
117
+ base: string;
118
+ content: string;
119
+ item: string;
120
+ itemHighlighted: string;
121
+ itemIcon: string;
122
+ itemContent: string;
123
+ itemLabel: string;
124
+ itemDescription: string;
125
+ itemShortcut: string;
126
+ empty: string;
127
+ loading: string;
128
+ };
129
+ tag: {
130
+ base: string;
131
+ mention: string;
132
+ command: string;
133
+ };
134
+ editor: {
135
+ base: string;
136
+ container: string;
137
+ placeholder: string;
138
+ };
139
+ };
140
+ suggestions: {
141
+ base: string;
142
+ item: {
143
+ base: string;
144
+ icon: string;
145
+ text: string;
146
+ };
147
+ };
148
+ chart: {
149
+ base: string;
150
+ title: string;
151
+ content: string;
152
+ error: {
153
+ base: string;
154
+ title: string;
155
+ code: string;
156
+ };
157
+ warning: {
158
+ base: string;
159
+ title: string;
160
+ };
98
161
  };
99
162
  }
100
163
  export declare const chatTheme: ChatTheme;
package/dist/types.d.ts CHANGED
@@ -49,6 +49,16 @@ export interface Template {
49
49
  */
50
50
  icon?: ReactElement;
51
51
  }
52
+ export interface Suggestion {
53
+ /**
54
+ * Unique identifier for the suggestion
55
+ */
56
+ id: string;
57
+ /**
58
+ * The display text for the suggestion
59
+ */
60
+ content: string;
61
+ }
52
62
  export interface Conversation {
53
63
  /**
54
64
  * Unique identifier for the conversation
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "reachat",
3
- "version": "2.1.0-alpha.9",
3
+ "version": "2.1.1",
4
4
  "description": "Chat UI for Building LLMs",
5
5
  "scripts": {
6
6
  "build-storybook": "storybook build",
7
7
  "build": "npm run build:js && npm run build:styles && npm run build:docs && npm run rewrite:stories",
8
8
  "build:js": "vite build --mode library",
9
9
  "build:docs": "node scripts/docs.js",
10
- "build:styles": "npx @tailwindcss/cli -i ./src/styles/index.css -o ./dist/index.css",
10
+ "build:styles": "npx @tailwindcss/cli -i ./src/index.css -o ./dist/index.css",
11
11
  "lint": "eslint --ext js,ts,tsx",
12
12
  "lint:fix": "eslint --ext js,ts,tsx --fix src",
13
13
  "lint:prettier": "prettier --loglevel warn --write 'src/**/*.{ts,tsx,js,jsx}'",
@@ -40,14 +40,23 @@
40
40
  "browser": "dist/index.js",
41
41
  "typings": "dist/index.d.ts",
42
42
  "dependencies": {
43
- "@ai-sdk/openai": "^1.1.9",
44
43
  "@floating-ui/react": "^0.27.6",
45
44
  "@radix-ui/react-slot": "^1.1.0",
45
+ "@tiptap/core": "^3.15.3",
46
+ "@tiptap/extension-document": "^3.15.3",
47
+ "@tiptap/extension-hard-break": "^3.15.3",
48
+ "@tiptap/extension-mention": "^3.15.3",
49
+ "@tiptap/extension-paragraph": "^3.15.3",
50
+ "@tiptap/extension-placeholder": "^3.15.3",
51
+ "@tiptap/extension-text": "^3.15.3",
52
+ "@tiptap/pm": "^3.15.3",
53
+ "@tiptap/react": "^3.15.3",
46
54
  "date-fns": "^4.1.0",
47
55
  "katex": "^0.16.11",
56
+ "lodash": "^4.17.21",
48
57
  "mdast-util-find-and-replace": "^3.0.1",
49
58
  "motion": "^12.4.2",
50
- "reablocks": "10.0.0-alpha.4",
59
+ "reablocks": "^9.0.0",
51
60
  "react-markdown": "^9.0.3",
52
61
  "react-syntax-highlighter": "^15.6.1",
53
62
  "reakeys": "^2.0.3",
@@ -55,79 +64,78 @@
55
64
  "remark-gfm": "^4.0.0",
56
65
  "remark-math": "^6.0.0",
57
66
  "remark-youtube": "^1.3.2",
58
- "unified": "^11.0.5"
67
+ "unified": "^11.0.5",
68
+ "unist-util-visit": "^5.0.0"
59
69
  },
60
70
  "peerDependencies": {
61
71
  "react": ">=18",
62
- "react-dom": ">=18"
72
+ "react-dom": ">=18",
73
+ "reaviz": ">=16"
74
+ },
75
+ "peerDependenciesMeta": {
76
+ "reaviz": {
77
+ "optional": true
78
+ }
63
79
  },
64
80
  "devDependencies": {
65
- "@eslint/compat": "^1.3.2",
66
- "@eslint/eslintrc": "^3.3.1",
67
- "@eslint/js": "^9.35.0",
68
- "@storybook/addon-docs": "^9.1.8",
69
- "@storybook/addon-essentials": "^9.0.0-alpha.12",
70
- "@storybook/addon-interactions": "^9.0.0-alpha.10",
71
- "@storybook/addon-mdx-gfm": "^9.0.0-alpha.13",
72
- "@storybook/addon-storysource": "^9.0.0-alpha.14",
73
- "@storybook/addon-themes": "^9.1.5",
74
- "@storybook/manager-api": "^9.0.0-alpha.1",
75
- "@storybook/preview-api": "^9.0.0-alpha.1",
76
- "@storybook/react": "^9.1.5",
77
- "@storybook/react-vite": "^9.1.5",
78
- "@storybook/theming": "^9.0.0-alpha.1",
79
- "@tailwindcss/cli": "^4.1.13",
80
- "@tailwindcss/postcss": "^4.1.13",
81
- "@tailwindcss/vite": "^4.1.13",
82
- "@types/classnames": "^2.3.4",
83
- "@types/node": "^22.18.1",
84
- "@types/react": "^18.3.24",
85
- "@types/react-dom": "^18.3.7",
86
- "@typescript-eslint/eslint-plugin": "^8.43.0",
87
- "@typescript-eslint/parser": "^8.43.0",
88
- "@vitejs/plugin-react": "^5.0.2",
89
- "@vitest/coverage-v8": "^3.2.4",
81
+ "@ai-sdk/openai": "^1.1.9",
82
+ "@storybook/addon-docs": "^8.2.6",
83
+ "@storybook/addon-essentials": "^8.2.6",
84
+ "@storybook/addon-mdx-gfm": "^8.2.6",
85
+ "@storybook/addon-storysource": "^8.2.6",
86
+ "@storybook/addon-themes": "^8.2.6",
87
+ "@storybook/manager-api": "^8.2.6",
88
+ "@storybook/preview-api": "^8.2.6",
89
+ "@storybook/react": "^8.2.6",
90
+ "@storybook/react-vite": "^8.2.6",
91
+ "@storybook/theming": "^8.2.6",
92
+ "@tailwindcss/cli": "^4.0.3",
93
+ "@tailwindcss/postcss": "^4.0.1",
94
+ "@tailwindcss/vite": "^4.0.6",
95
+ "@types/classnames": "^2.3.1",
96
+ "@types/lodash": "^4.17.21",
97
+ "@types/mdast": "^4.0.4",
98
+ "@types/react": "^18.2.61",
99
+ "@types/react-dom": "^18.2.19",
100
+ "@typescript-eslint/eslint-plugin": "^7.6.0",
101
+ "@typescript-eslint/parser": "^7.6.0",
102
+ "@vitejs/plugin-react": "^4.2.1",
103
+ "@vitest/coverage-v8": "^1.4.0",
90
104
  "ai": "^4.1.35",
91
105
  "autoprefixer": "^10.4.19",
92
- "eslint": "^9.35.0",
93
- "eslint-config-prettier": "^10.1.8",
94
- "eslint-plugin-import": "^2.32.0",
95
- "eslint-plugin-prettier": "^5.5.4",
96
- "eslint-plugin-react-refresh": "^0.4.22",
97
- "eslint-plugin-no-relative-import-paths": "^1.6.1",
98
- "eslint-plugin-react": "^7.37.5",
99
- "eslint-plugin-react-hooks": "^5.2.0",
100
- "eslint-plugin-simple-import-sort": "^12.1.1",
101
- "eslint-plugin-storybook": "^9.1.5",
102
- "eslint-plugin-unused-imports": "^4.2.0",
106
+ "eslint": "^8.57.0",
107
+ "eslint-config-prettier": "^9.1.0",
108
+ "eslint-plugin-no-relative-import-paths": "^1.5.4",
109
+ "eslint-plugin-react": "^7.34.1",
110
+ "eslint-plugin-react-hooks": "^4.3.0",
111
+ "eslint-plugin-storybook": "^0.8.0",
103
112
  "fast-glob": "^3.3.2",
104
- "husky": "^9.1.7",
105
- "jsdom": "^26.1.0",
106
- "lint-staged": "^16.1.6",
113
+ "husky": "^9.0.11",
114
+ "jsdom": "^24.0.0",
115
+ "lint-staged": "^15.2.2",
107
116
  "openai": "^4.84.0",
108
117
  "postcss": "^8.4.39",
109
- "postcss-nested": "^7.0.2",
110
- "postcss-preset-env": "^10.3.1",
111
- "prettier": "^3.6.2",
118
+ "postcss-nested": "^6.0.1",
119
+ "postcss-preset-env": "^9.5.2",
120
+ "prettier": "^3.2.5",
121
+ "reaviz": "^16.1.1",
112
122
  "react": "^18.3.1",
113
123
  "react-docgen-typescript": "^2.2.2",
114
124
  "react-dom": "^18.3.1",
115
- "reaviz-lint-rules": "^1.0.3",
116
125
  "rollup-plugin-peer-deps-external": "2.2.4",
117
- "storybook": "^9.1.5",
118
- "tailwindcss": "^4.1.13",
126
+ "storybook": "^8.2.6",
127
+ "tailwindcss": "^4.0.0",
119
128
  "tw-colors": "^3.3.1",
120
- "typescript": "^5.9.2",
121
- "typescript-eslint": "^8.44.1",
129
+ "typescript": "^4.9.5",
122
130
  "typescript-rewrite-paths": "^1.3.1",
123
- "vite": "^7.1.5",
124
- "vite-plugin-checker": "^0.10.3",
125
- "vite-plugin-css-injected-by-js": "^3.5.2",
126
- "vite-plugin-dts": "^4.5.4",
127
- "vite-plugin-static-copy": "^3.1.2",
128
- "vite-plugin-svgr": "^4.5.0",
129
- "vite-tsconfig-paths": "^5.1.4",
130
- "vitest": "^3.2.4"
131
+ "vite": "^5.2.2",
132
+ "vite-plugin-checker": "^0.8.0",
133
+ "vite-plugin-css-injected-by-js": "^3.5.0",
134
+ "vite-plugin-dts": "^4.5.0",
135
+ "vite-plugin-static-copy": "^3.1.1",
136
+ "vite-plugin-svgr": "^4.2.0",
137
+ "vite-tsconfig-paths": "^4.3.2",
138
+ "vitest": "^1.4.0"
131
139
  },
132
140
  "prettier": {
133
141
  "semi": true,
@@ -147,10 +155,5 @@
147
155
  "hooks": {
148
156
  "pre-commit": "lint-staged"
149
157
  }
150
- },
151
- "packageManager": "npm@10.8.2",
152
- "engines": {
153
- "node": ">=22",
154
- "npm": ">=10.8.2"
155
158
  }
156
159
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"CSVFileRenderer-CkRKGiCl.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 +0,0 @@
1
- {"version":3,"file":"DefaultFileRenderer-C1qZ57tG.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;"}
@@ -1,16 +0,0 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- const PDFFileRenderer = ({ name, url, fileIcon }) => /* @__PURE__ */ jsxs(
3
- "figure",
4
- {
5
- className: "csv-icon flex items-center gap-2",
6
- onClick: () => window.open(url, "_blank"),
7
- children: [
8
- fileIcon,
9
- name && /* @__PURE__ */ jsx("figcaption", { className: "file-name", children: name })
10
- ]
11
- }
12
- );
13
- export {
14
- PDFFileRenderer as default
15
- };
16
- //# sourceMappingURL=PDFFileRenderer-BBn2EVrV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PDFFileRenderer-BBn2EVrV.js","sources":["../src/SessionMessages/SessionMessage/MessageFile/renderers/PDFFileRenderer.tsx"],"sourcesContent":["import type { FC, ReactElement } from 'react';\n\ninterface PDFFileRendererProps {\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 PDF files.\n */\nconst PDFFileRenderer: FC<PDFFileRendererProps> = ({ name, url, fileIcon }) => (\n <figure\n className=\"csv-icon flex items-center gap-2\"\n onClick={() => window.open(url, '_blank')}\n >\n {fileIcon}\n {name && <figcaption className=\"file-name\">{name}</figcaption>}\n </figure>\n);\n\nexport default PDFFileRenderer;\n"],"names":[],"mappings":";AAsBA,MAAM,kBAA4C,CAAC,EAAE,MAAM,KAAK,eAC9D;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,SAAS,MAAM,OAAO,KAAK,KAAK,QAAQ;AAAA,IAEvC,UAAA;AAAA,MAAA;AAAA,MACA,QAAQ,oBAAC,cAAA,EAAW,WAAU,aAAa,UAAA,KAAA,CAAK;AAAA,IAAA;AAAA,EAAA;AACnD;"}