@memori.ai/memori-react 7.23.1 → 7.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/components/ChatBubble/ChatBubble.css +4 -0
  3. package/dist/components/ChatBubble/ChatBubble.js +5 -75
  4. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  5. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +1 -1
  6. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  7. package/dist/components/MemoriWidget/MemoriWidget.js +22 -18
  8. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  9. package/dist/components/StartPanel/StartPanel.css +1 -0
  10. package/dist/components/StartPanel/StartPanel.d.ts +4 -1
  11. package/dist/components/StartPanel/StartPanel.js +7 -2
  12. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  13. package/dist/components/UploadButton/UploadButton.js +53 -22
  14. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  15. package/dist/components/WhyThisAnswer/WhyThisAnswer.js +1 -1
  16. package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  17. package/dist/components/ui/Expandable.d.ts +3 -2
  18. package/dist/components/ui/Expandable.js +35 -20
  19. package/dist/components/ui/Expandable.js.map +1 -1
  20. package/dist/helpers/constants.d.ts +2 -0
  21. package/dist/helpers/constants.js +3 -1
  22. package/dist/helpers/constants.js.map +1 -1
  23. package/dist/helpers/message.d.ts +5 -0
  24. package/dist/helpers/message.js +96 -0
  25. package/dist/helpers/message.js.map +1 -0
  26. package/esm/components/ChatBubble/ChatBubble.css +4 -0
  27. package/esm/components/ChatBubble/ChatBubble.js +6 -76
  28. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  29. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +1 -1
  30. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  31. package/esm/components/MemoriWidget/MemoriWidget.js +22 -18
  32. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  33. package/esm/components/StartPanel/StartPanel.css +1 -0
  34. package/esm/components/StartPanel/StartPanel.d.ts +4 -1
  35. package/esm/components/StartPanel/StartPanel.js +7 -2
  36. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  37. package/esm/components/UploadButton/UploadButton.js +53 -22
  38. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  39. package/esm/components/WhyThisAnswer/WhyThisAnswer.js +1 -1
  40. package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  41. package/esm/components/ui/Expandable.d.ts +3 -2
  42. package/esm/components/ui/Expandable.js +35 -20
  43. package/esm/components/ui/Expandable.js.map +1 -1
  44. package/esm/helpers/constants.d.ts +2 -0
  45. package/esm/helpers/constants.js +2 -0
  46. package/esm/helpers/constants.js.map +1 -1
  47. package/esm/helpers/message.d.ts +5 -0
  48. package/esm/helpers/message.js +89 -0
  49. package/esm/helpers/message.js.map +1 -0
  50. package/package.json +2 -2
  51. package/src/components/Chat/Chat.stories.tsx +16 -0
  52. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +378 -135
  53. package/src/components/ChatBubble/ChatBubble.css +4 -0
  54. package/src/components/ChatBubble/ChatBubble.tsx +23 -123
  55. package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +84 -30
  56. package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +1 -1
  57. package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +2 -2
  58. package/src/components/MemoriWidget/MemoriWidget.stories.tsx +9 -0
  59. package/src/components/MemoriWidget/MemoriWidget.tsx +15 -9
  60. package/src/components/StartPanel/StartPanel.css +1 -0
  61. package/src/components/StartPanel/StartPanel.stories.tsx +35 -0
  62. package/src/components/StartPanel/StartPanel.test.tsx +22 -0
  63. package/src/components/StartPanel/StartPanel.tsx +194 -170
  64. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +108 -1
  65. package/src/components/UploadButton/UploadButton.tsx +71 -31
  66. package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +1 -1
  67. package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +2 -1
  68. package/src/components/ui/Expandable.stories.tsx +128 -1
  69. package/src/components/ui/Expandable.tsx +44 -22
  70. package/src/helpers/constants.ts +3 -0
  71. package/src/helpers/message.ts +139 -0
  72. package/src/mocks/data.ts +11 -0
  73. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.d.ts +0 -34
  74. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +0 -147
  75. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +0 -1
  76. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.d.ts +0 -17
  77. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js +0 -73
  78. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js.map +0 -1
  79. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.d.ts +0 -17
  80. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js +0 -25
  81. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js.map +0 -1
  82. package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.d.ts +0 -17
  83. package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js +0 -76
  84. package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js.map +0 -1
  85. package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.d.ts +0 -19
  86. package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js +0 -60
  87. package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js.map +0 -1
  88. package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.d.ts +0 -18
  89. package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.js +0 -26
  90. package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.js.map +0 -1
  91. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.d.ts +0 -38
  92. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.js +0 -181
  93. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.js.map +0 -1
  94. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +0 -26
  95. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +0 -166
  96. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +0 -1
  97. package/dist/helpers/tenant.d.ts +0 -2
  98. package/dist/helpers/tenant.js +0 -40
  99. package/dist/helpers/tenant.js.map +0 -1
  100. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.d.ts +0 -34
  101. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +0 -143
  102. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +0 -1
  103. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.d.ts +0 -17
  104. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js +0 -69
  105. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js.map +0 -1
  106. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.d.ts +0 -17
  107. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js +0 -22
  108. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js.map +0 -1
  109. package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.d.ts +0 -17
  110. package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js +0 -72
  111. package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js.map +0 -1
  112. package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.d.ts +0 -19
  113. package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js +0 -56
  114. package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js.map +0 -1
  115. package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.d.ts +0 -18
  116. package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.js +0 -23
  117. package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.js.map +0 -1
  118. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.d.ts +0 -38
  119. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.js +0 -177
  120. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.js.map +0 -1
  121. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +0 -26
  122. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +0 -163
  123. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +0 -1
  124. package/esm/helpers/tenant.d.ts +0 -2
  125. package/esm/helpers/tenant.js +0 -36
  126. package/esm/helpers/tenant.js.map +0 -1
@@ -159,15 +159,15 @@ const FileUploadButton = ({
159
159
  // Try parsing with full options first
160
160
  workbook = window.XLSX.read(arrayBuffer, {
161
161
  type: 'array',
162
- cellFormula: false, // Disable formula parsing to avoid potential issues
163
- cellNF: false, // Disable number format parsing
164
- cellHTML: false, // Disable HTML parsing
165
- cellText: true, // Force text output
166
- cellDates: false, // Disable date parsing to avoid errors
162
+ cellFormula: true,
163
+ cellNF: true,
164
+ cellHTML: true,
165
+ cellText: true,
166
+ cellDates: true,
167
167
  error: (e: any) => {
168
168
  console.warn('Non-fatal XLSX error:', e);
169
- }, // Log non-fatal errors
170
- cellStyles: false, // Disable style parsing
169
+ },
170
+ cellStyles: true,
171
171
  });
172
172
  } catch (initialError) {
173
173
  console.warn(
@@ -179,15 +179,15 @@ const FileUploadButton = ({
179
179
  try {
180
180
  workbook = window.XLSX.read(arrayBuffer, {
181
181
  type: 'array',
182
- sheetRows: 1000, // Limit number of rows to parse
183
- cellFormula: false,
184
- cellStyles: false,
185
- bookDeps: false, // Don't parse external dependencies
186
- bookFiles: false, // Don't parse embedded files
187
- bookProps: false, // Don't parse document properties
188
- bookSheets: false, // Don't parse sheet properties
189
- bookVBA: false, // Don't parse VBA
190
- WTF: true, // "What the Formula" mode - ignores errors when possible
182
+ sheetRows: 1000,
183
+ cellFormula: true,
184
+ cellStyles: true,
185
+ bookDeps: true,
186
+ bookFiles: true,
187
+ bookProps: true,
188
+ bookSheets: true,
189
+ bookVBA: true,
190
+ WTF: true,
191
191
  });
192
192
  } catch (recoveryError) {
193
193
  setErrors(prev => [
@@ -247,27 +247,63 @@ const FileUploadButton = ({
247
247
  );
248
248
  }
249
249
 
250
- // Try to convert sheet to CSV
251
- let csv;
250
+ // Try to convert sheet to formatted text with columns
251
+ let formattedText;
252
252
  try {
253
- csv = window.XLSX.utils.sheet_to_csv(worksheet);
254
- } catch (csvError) {
255
- // If CSV conversion fails, try a more basic cell-by-cell approach
256
- csv = '';
253
+ // Get array of arrays representation
254
+ const data = window.XLSX.utils.sheet_to_json(worksheet, {
255
+ header: 1,
256
+ raw: false,
257
+ });
258
+
259
+ // Find the maximum width for each column
260
+ const colWidths = data.reduce((widths: number[], row: any[]) => {
261
+ row.forEach((cell, i) => {
262
+ const cellWidth = (cell || '').toString().length;
263
+ widths[i] = Math.max(widths[i] || 0, cellWidth);
264
+ });
265
+ return widths;
266
+ }, []);
267
+
268
+ // Format each row with proper column spacing
269
+ formattedText = data.map((row: any[]) => {
270
+ return row
271
+ .map((cell, i) => {
272
+ const cellStr = (cell || '').toString();
273
+ return cellStr.padEnd(colWidths[i] + 2); // Add 2 spaces padding
274
+ })
275
+ .join('|')
276
+ .trim();
277
+ });
278
+
279
+ // Add separator line after header
280
+ if (formattedText.length > 0) {
281
+ const separator = colWidths
282
+ .map((w: number) => '-'.repeat(w + 2))
283
+ .join('+');
284
+ formattedText.splice(1, 0, separator);
285
+ }
286
+
287
+ formattedText = formattedText.join('\n');
288
+ } catch (formatError) {
289
+ // Fallback to basic formatting if advanced fails
290
+ formattedText = '';
257
291
  for (let r = range.s.r; r <= Math.min(range.e.r, 1000); ++r) {
258
292
  let row = '';
259
293
  for (let c = range.s.c; c <= Math.min(range.e.c, 100); ++c) {
260
294
  const cell =
261
295
  worksheet[window.XLSX.utils.encode_cell({ r: r, c: c })];
262
- row += (cell ? String(cell.v || '') : '') + ',';
296
+ row +=
297
+ (cell ? String(cell.v || '').padEnd(15) : ' '.repeat(15)) +
298
+ '|';
263
299
  }
264
- csv += row + '\n';
300
+ formattedText += row + '\n';
265
301
  }
266
- csv += '...(truncated due to potential corruption)';
302
+ formattedText += '...(truncated due to potential corruption)';
267
303
  }
268
304
 
269
- // Add sheet name and content to final text
270
- text += `Sheet: ${sheetName}\n${csv}\n\n`;
305
+ // Add sheet name and formatted content to final text
306
+ text += `Sheet: ${sheetName}\n${formattedText}\n\n`;
271
307
  successfulSheets++;
272
308
  } catch (sheetError) {
273
309
  // Log sheet-specific error but continue with other sheets
@@ -291,7 +327,7 @@ const FileUploadButton = ({
291
327
  text;
292
328
  }
293
329
 
294
- return text; // Return the extracted text from all sheets
330
+ return text;
295
331
  } catch (error) {
296
332
  setErrors(prev => [
297
333
  ...prev,
@@ -303,7 +339,6 @@ const FileUploadButton = ({
303
339
  fileId: file.name,
304
340
  },
305
341
  ]);
306
- // If any error occurs during processing, throw with descriptive message
307
342
  throw new Error(
308
343
  `XLSX extraction failed: ${
309
344
  error instanceof Error ? error.message : 'Unknown error'
@@ -360,7 +395,12 @@ const FileUploadButton = ({
360
395
 
361
396
  if (fileExt === 'pdf') {
362
397
  text = await extractTextFromPDF(file);
363
- } else if (fileExt === 'txt' || fileExt === 'json' || fileExt === 'csv') {
398
+ } else if (
399
+ fileExt === 'txt' ||
400
+ fileExt === 'md' ||
401
+ fileExt === 'json' ||
402
+ fileExt === 'csv'
403
+ ) {
364
404
  text = await file.text();
365
405
  } else if (fileExt === 'xlsx') {
366
406
  text = await extractTextFromXLSX(file);
@@ -442,7 +482,7 @@ const FileUploadButton = ({
442
482
  <input
443
483
  ref={fileInputRef}
444
484
  type="file"
445
- accept=".pdf,.txt,.json,.xlsx,.csv"
485
+ accept=".pdf,.txt,.md,.json,.xlsx,.csv"
446
486
  className="memori--upload-file-input"
447
487
  onChange={handleFileSelect}
448
488
  multiple
@@ -6,7 +6,7 @@ exports[`renders UploadButton unchanged 1`] = `
6
6
  class="relative file-upload-wrapper"
7
7
  >
8
8
  <input
9
- accept=".pdf,.txt,.json,.xlsx,.csv"
9
+ accept=".pdf,.txt,.md,.json,.xlsx,.csv"
10
10
  class="memori--upload-file-input"
11
11
  multiple=""
12
12
  type="file"
@@ -189,7 +189,7 @@ const WhyThisAnswer = ({
189
189
  )}
190
190
  {m.memory.answers?.map((a, i) => (
191
191
  <p key={i} className="memori--whythisanswer-answer">
192
- <Expandable rows={3}>{a.text}</Expandable>
192
+ <Expandable mode="rows" rows={3}>{a.text}</Expandable>
193
193
  </p>
194
194
  ))}
195
195
 
@@ -203,6 +203,7 @@ const WhyThisAnswer = ({
203
203
  ?.filter(m => m.mimeType === 'text/plain')
204
204
  ?.map(m => (
205
205
  <Expandable
206
+ mode="rows"
206
207
  rows={2}
207
208
  key={m.mediumID}
208
209
  lineHeightMultiplier={2}
@@ -26,7 +26,116 @@ const Template: Story<Props> = args => (
26
26
  Suspendisse a sodales nulla, sed semper nisi. Suspendisse a sodales nulla,
27
27
  sed semper nisi. Suspendisse a sodales nulla, sed semper nisi. Suspendisse a
28
28
  sodales nulla, sed semper nisi. Suspendisse a sodales nulla, sed semper
29
- nisi.
29
+ nisi. Lorem Ipsum is simply dummy text of the printing and typesetting
30
+ industry. Lorem Ipsum has been the industry&apos;s standard dummy text ever
31
+ since the 1500s, when an unknown printer took a galley of type and scrambled
32
+ it to make a type specimen book. It has survived not only five centuries,
33
+ but also the leap into electronic typesetting, remaining essentially
34
+ unchanged. It was popularised in the 1960s with the release of Letraset
35
+ sheets containing Lorem Ipsum passages, and more recently with desktop
36
+ publishing software like Aldus PageMaker including versions of Lorem Ipsum.
37
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry.
38
+ Lorem Ipsum has been the industry&apos;s standard dummy text ever since the
39
+ 1500s, when an unknown printer took a galley of type and scrambled it to
40
+ make a type specimen book. It has survived not only five centuries, but also
41
+ the leap into electronic typesetting, remaining essentially unchanged. It
42
+ was popularised in the 1960s with the release of Letraset sheets containing
43
+ Lorem Ipsum passages, and more recently with desktop publishing software
44
+ like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is
45
+ simply dummy text of the printing and typesetting industry. Lorem Ipsum has
46
+ been the industry&apos;s standard dummy text ever since the 1500s, when an
47
+ unknown printer took a galley of type and scrambled it to make a type
48
+ specimen book. It has survived not only five centuries, but also the leap
49
+ into electronic typesetting, remaining essentially unchanged. It was
50
+ popularised in the 1960s with the release of Letraset sheets containing
51
+ Lorem Ipsum passages, and more recently with desktop publishing software
52
+ like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is
53
+ simply dummy text of the printing and typesetting industry. Lorem Ipsum has
54
+ been the industry&apos;s standard dummy text ever since the 1500s, when an
55
+ unknown printer took a galley of type and scrambled it to make a type
56
+ specimen book. It has survived not only five centuries, but also the leap
57
+ into electronic typesetting, remaining essentially unchanged. It was
58
+ popularised in the 1960s with the release of Letraset sheets containing
59
+ Lorem Ipsum passages, and more recently with desktop publishing software
60
+ like Aldus PageMaker including versions of Lorem Ipsum.
61
+ </Expandable>
62
+ );
63
+
64
+ const TemplateWithHTML: Story<Props> = args => (
65
+ <Expandable {...args}>
66
+ <p>
67
+ Ah, ottima domanda! Stavo giusto riflettendo su come spiegare al meglio le
68
+ funzionalità di questo sistema.{' '}
69
+ </p>
70
+ <p>Da qui puoi fare diverse cose interessanti:</p>
71
+ <ol>
72
+ <li>
73
+ <p>
74
+ Puoi conversare con me, Nunzio Fiore, e io risponderò basandomi sulle
75
+ mie conoscenze ed esperienze.
76
+ </p>
77
+ </li>
78
+ <li>
79
+ <p>
80
+ Puoi aggiungere nuove memorie o informazioni al mio database. Questo
81
+ significa che puoi insegnarmi cose nuove o aggiornare le mie
82
+ conoscenze esistenti.
83
+ </p>
84
+ </li>
85
+ <li>
86
+ <p>
87
+ Puoi creare, modificare o eliminare ricevitori. Questi sono come
88
+ utenti specifici che possono interagire con me in modo personalizzato.
89
+ </p>
90
+ </li>
91
+ <li>
92
+ <p>
93
+ Puoi associare determinate memorie a ricevitori specifici, creando
94
+ così contenuti personalizzati per diverse persone.
95
+ </p>
96
+ </li>
97
+ <li>
98
+ <p>
99
+ Puoi cercare tra le memorie esistenti, visualizzare le ultime
100
+ aggiunte, o modificare quelle già presenti.
101
+ </p>
102
+ </li>
103
+ </ol>
104
+ <p>
105
+ In pratica, stai interagendo con un sistema che permette di creare e
106
+ gestire un &quot;gemello digitale&quot; - in questo caso, me stesso. È un
107
+ po&apos; come scrivere un libro interattivo sulla mia vita e le mie
108
+ conoscenze.
109
+ </p>
110
+ <p>
111
+ C&apos;è qualcosa in particolare che ti interessa esplorare o su cui
112
+ vorresti saperne di più?
113
+ </p>
114
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
115
+ <div className="memori--responsive-table-wrapper">
116
+ <table className="memori--table memori--table--compact">
117
+ <thead>
118
+ <tr>
119
+ <th>Header 1</th>
120
+ <th>Header 2</th>
121
+ <th>Header 3</th>
122
+ </tr>
123
+ </thead>
124
+ <tbody>
125
+ <tr>
126
+ <td>Cell 1</td>
127
+ <td>Cell 2</td>
128
+ <td>Cell 3</td>
129
+ </tr>
130
+ <tr>
131
+ <td>Cell 4</td>
132
+ <td>Cell 5</td>
133
+ <td>Cell 6</td>
134
+ </tr>
135
+ </tbody>
136
+ </table>
137
+ </div>
138
+ <p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
30
139
  </Expandable>
31
140
  );
32
141
 
@@ -35,11 +144,13 @@ const Template: Story<Props> = args => (
35
144
  export const Default = Template.bind({});
36
145
  Default.args = {
37
146
  rows: 2,
147
+ mode: 'rows',
38
148
  };
39
149
 
40
150
  export const DefaultExpanded = Template.bind({});
41
151
  DefaultExpanded.args = {
42
152
  rows: 3,
153
+ mode: 'rows',
43
154
  defaultExpanded: true,
44
155
  };
45
156
 
@@ -51,3 +162,19 @@ WithCustomProps.args = {
51
162
  expandSymbol: () => '🔽',
52
163
  collapseSymbol: () => '🔼',
53
164
  };
165
+
166
+ export const WithHTML = TemplateWithHTML.bind({});
167
+ WithHTML.args = {
168
+ rows: 3,
169
+ mode: 'rows',
170
+ };
171
+
172
+ export const ModeChar = Template.bind({});
173
+ ModeChar.args = {
174
+ mode: 'characters',
175
+ };
176
+
177
+ export const ModeCharWithHTML = TemplateWithHTML.bind({});
178
+ ModeCharWithHTML.args = {
179
+ mode: 'characters',
180
+ };
@@ -2,9 +2,11 @@ import React, { useEffect, useRef, useState } from 'react';
2
2
  import Button from './Button';
3
3
  import cx from 'classnames';
4
4
  import { useTranslation } from 'react-i18next';
5
+ import { truncateMessage } from '../../helpers/message';
6
+ import { MAX_MSG_CHARS, MAX_MSG_WORDS } from '../../helpers/constants';
5
7
 
6
8
  export interface Props {
7
- rows: number;
9
+ rows?: number;
8
10
  className?: string;
9
11
  innerClassName?: string;
10
12
  btnClassName?: string;
@@ -13,6 +15,7 @@ export interface Props {
13
15
  expandSymbol?: (lang: string) => React.ReactNode;
14
16
  collapseSymbol?: (lang: string) => React.ReactNode;
15
17
  children: React.ReactNode;
18
+ mode?: 'rows' | 'characters';
16
19
  }
17
20
 
18
21
  const Expandable = ({
@@ -26,6 +29,7 @@ const Expandable = ({
26
29
  collapseSymbol = (lang: string) =>
27
30
  lang === 'it' ? 'Mostra meno' : 'Show less',
28
31
  children,
32
+ mode = 'rows',
29
33
  }: Props) => {
30
34
  const { i18n } = useTranslation();
31
35
  const lang = i18n.language;
@@ -34,31 +38,47 @@ const Expandable = ({
34
38
  const [expanded, setExpanded] = useState(defaultExpanded);
35
39
  const [needsExpanding, setNeedsExpanding] = useState(false);
36
40
  const [rowHeight, setRowHeight] = useState(16);
37
- const ref = useRef(null);
41
+ const ref = useRef<HTMLDivElement>(null);
38
42
 
39
43
  useEffect(() => {
40
44
  if (ref.current) {
41
- let height = (ref.current as HTMLElement).getBoundingClientRect().height;
42
- let computedStyle = getComputedStyle(ref.current as HTMLElement);
43
- let elLineHeight = computedStyle.lineHeight;
44
- let lineHeight =
45
- elLineHeight === 'normal' || !elLineHeight?.length
46
- ? lineHeightMultiplier * parseInt(computedStyle.fontSize, 10)
47
- : parseInt(elLineHeight, 10);
45
+ if (mode === 'rows') {
46
+ let height = ref.current.getBoundingClientRect().height;
47
+ let computedStyle = getComputedStyle(ref.current);
48
+ let elLineHeight = computedStyle.lineHeight;
49
+ let lineHeight =
50
+ elLineHeight === 'normal' || !elLineHeight?.length
51
+ ? lineHeightMultiplier * parseInt(computedStyle.fontSize, 10)
52
+ : parseInt(elLineHeight, 10);
48
53
 
49
- console.table({
50
- rows,
51
- lineHeight,
52
- height,
53
- maxHeight: rows * lineHeight,
54
- needsExpanding: height > rows * lineHeight,
55
- });
56
- setRowHeight(lineHeight);
57
- if (height && height > rows * lineHeight) {
58
- setNeedsExpanding(true);
54
+ setRowHeight(lineHeight);
55
+ if (height && rows && height > rows * lineHeight) {
56
+ setNeedsExpanding(true);
57
+ }
58
+ } else if (mode === 'characters') {
59
+ // Get text content length
60
+ const textContent = ref.current.textContent || '';
61
+
62
+ if (
63
+ textContent.length > MAX_MSG_CHARS ||
64
+ textContent.split(' ').length > MAX_MSG_WORDS
65
+ ) {
66
+ setNeedsExpanding(true);
67
+ }
59
68
  }
60
69
  }
61
- }, [rows, ref.current]);
70
+ }, [rows, mode, ref.current]);
71
+
72
+ const renderContent = () => {
73
+ if (mode === 'characters' && !expanded && needsExpanding) {
74
+ const content = ref.current?.textContent || '';
75
+ let truncatedContent = truncateMessage(content);
76
+
77
+ return truncatedContent;
78
+ }
79
+
80
+ return children;
81
+ };
62
82
 
63
83
  return (
64
84
  <div className={cx('memori-expandable', className)}>
@@ -67,10 +87,12 @@ const Expandable = ({
67
87
  className={cx('memori-expandable--inner', innerClassName)}
68
88
  style={{
69
89
  maxHeight:
70
- expanded || !needsExpanding ? '9999px' : `${rowHeight * rows}px`,
90
+ expanded || !needsExpanding || mode === 'characters'
91
+ ? '9999px'
92
+ : `${rowHeight * (rows || 1)}px`,
71
93
  }}
72
94
  >
73
- {children}
95
+ {renderContent()}
74
96
  </div>
75
97
  {needsExpanding && !expanded && (
76
98
  <Button
@@ -183,3 +183,6 @@ export const boardOfExpertsLoadingSentences: {
183
183
  },
184
184
  ],
185
185
  };
186
+
187
+ export const MAX_MSG_CHARS = 4000;
188
+ export const MAX_MSG_WORDS = 300;
@@ -0,0 +1,139 @@
1
+ import { marked } from 'marked';
2
+ import DOMPurify from 'dompurify';
3
+ import { MAX_MSG_CHARS, MAX_MSG_WORDS } from './constants';
4
+ import { cleanUrl } from './utils';
5
+ import markedLinkifyIt from 'marked-linkify-it';
6
+ import markedKatex from 'marked-katex-extension';
7
+ import markedExtendedTables from './markedExtendedTables';
8
+
9
+ // Always configure marked with necessary extensions
10
+ marked.use({
11
+ async: false,
12
+ gfm: true,
13
+ pedantic: false,
14
+ renderer: {
15
+ link: ({
16
+ href,
17
+ title,
18
+ text,
19
+ }: {
20
+ href: string | null;
21
+ title?: string | null;
22
+ text: string;
23
+ }) => {
24
+ const cleanHref = href ? cleanUrl(href) : null;
25
+
26
+ if (cleanHref === null) {
27
+ return text;
28
+ }
29
+ href = cleanHref;
30
+ let out = '<a href="' + href + '"';
31
+ if (title) {
32
+ out += ' title="' + title + '"';
33
+ }
34
+ out += ' target="_blank" rel="noopener noreferrer">' + text + '</a>';
35
+ return out;
36
+ },
37
+ },
38
+ });
39
+
40
+ marked.use(markedLinkifyIt());
41
+ marked.use(markedExtendedTables());
42
+
43
+ export const needsTruncation = (message: string) => {
44
+ return (
45
+ message.length > MAX_MSG_CHARS || message.split(' ').length > MAX_MSG_WORDS
46
+ );
47
+ };
48
+
49
+ export const truncateMessage = (message: string) => {
50
+ let truncatedMessage = message;
51
+ if (message.length > MAX_MSG_CHARS) {
52
+ truncatedMessage = `${message.slice(0, MAX_MSG_CHARS)}\n<br />...`;
53
+ }
54
+ if (truncatedMessage.split(' ').length > MAX_MSG_WORDS) {
55
+ truncatedMessage = truncatedMessage
56
+ .split(' ')
57
+ .slice(0, MAX_MSG_WORDS)
58
+ .join(' ');
59
+ }
60
+ return truncatedMessage;
61
+ };
62
+
63
+ export const renderMsg = (
64
+ text: string,
65
+ useMathFormatting = false
66
+ ): {
67
+ text: string;
68
+ } => {
69
+ try {
70
+ // Preprocessing del testo per gestire i delimitatori LaTeX
71
+ let preprocessedText = text
72
+ .trim()
73
+ .replaceAll(
74
+ /\[([^\]]+)\]\(([^\)]+)\)/g,
75
+ '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
76
+ )
77
+ .replaceAll(/```markdown([^```]+)```/g, '$1')
78
+ .replaceAll('($', '( $')
79
+ .replaceAll(':$', ': $')
80
+ .replaceAll('\frac', '\\frac')
81
+ .replaceAll('\beta', '\\beta')
82
+ .replaceAll('cdot', '\\cdot');
83
+
84
+ // Correzione dei delimitatori LaTeX inconsistenti
85
+ if (useMathFormatting) {
86
+ // Abilita il supporto per KaTeX
87
+ marked.use(
88
+ markedKatex({
89
+ throwOnError: false,
90
+ output: 'htmlAndMathml',
91
+ })
92
+ );
93
+
94
+ // Normalizza tutti i delimitatori LaTeX per equazioni su linea separata
95
+ // Da \\[ ... \\] o \\[ ... ] a $$ ... $$
96
+ preprocessedText = preprocessedText.replace(
97
+ /\\+\[(.*?)\\*\]/gs,
98
+ (_, content) => {
99
+ return `$$${content}$$`;
100
+ }
101
+ );
102
+
103
+ // Gestione dei delimitatori [ ... ] che dovrebbero essere equazioni
104
+ preprocessedText = preprocessedText.replace(
105
+ /\[([^[\]]+?)\]/g,
106
+ (match, content) => {
107
+ // Verifica se sembra una formula matematica
108
+ if (
109
+ /[\\+a-z0-9_{}^=\-\+\*\/]+/i.test(content) &&
110
+ !match.startsWith('[http') &&
111
+ !match.includes('](')
112
+ ) {
113
+ return `$$${content}$$`;
114
+ }
115
+ return match; // Mantieni invariati i link e altre strutture
116
+ }
117
+ );
118
+ }
119
+
120
+ // Ora procedi con il parsing markdown
121
+ let parsedText = marked.parse(preprocessedText).toString().trim();
122
+
123
+ // Sanitize HTML
124
+ parsedText = DOMPurify.sanitize(parsedText, {
125
+ ADD_ATTR: ['target'],
126
+ });
127
+
128
+ // Clean up final text
129
+ const finalText = parsedText
130
+ .replace(/(<br>)+/g, '<br>')
131
+ .replace(/<p><\/p>/g, '<br>')
132
+ .replace(/<p><br><\/p>/g, '<br>');
133
+
134
+ return { text: finalText };
135
+ } catch (e) {
136
+ console.error('Error rendering message:', e);
137
+ return { text };
138
+ }
139
+ };
package/src/mocks/data.ts CHANGED
@@ -387,3 +387,14 @@ export const memoryQuestion: Memory = {
387
387
  lastChangeTimestamp: '2022-03-23T09:37:36.957695',
388
388
  lastChangeName: '6cfec2bd-a73f-4a21-b7ff-dd92d6db59c4',
389
389
  };
390
+
391
+
392
+ export const historyWithExpandable: Message[] = [
393
+ {
394
+ text: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
395
+ timestamp: '2021-03-01T12:00:00.000Z',
396
+ fromUser: true,
397
+ },
398
+ ];
399
+
400
+
@@ -1,34 +0,0 @@
1
- import { AnimationState, AnimationConfig } from './types';
2
- import { AnimationAction, AnimationMixer } from 'three';
3
- export declare class AnimationController {
4
- private currentState;
5
- private currentAction;
6
- private mixer;
7
- private actions;
8
- private config;
9
- private lastIdleIndex;
10
- private isTransitioning;
11
- private currentIdleLoopCount;
12
- private readonly MAX_IDLE_LOOPS;
13
- private lastAnimationTime;
14
- private isChatAlreadyStarted;
15
- constructor(mixer: AnimationMixer, actions: Record<string, AnimationAction>, config?: AnimationConfig);
16
- private checkForLoop;
17
- private forceIdleChange;
18
- private getNextIdleAnimation;
19
- transitionTo(state: AnimationState, emotionName?: string): void;
20
- update(delta: number): void;
21
- getCurrentState(): AnimationState;
22
- getLoopCount(): number;
23
- setTimeScale(timeScale: number): void;
24
- updateIsChatAlreadyStarted(isChatAlreadyStarted: boolean): void;
25
- getDebugInfo(): {
26
- currentState: AnimationState;
27
- currentIdleIndex: number;
28
- loopCount: number;
29
- currentTime: number;
30
- lastTime: number;
31
- isTransitioning: boolean;
32
- isChatAlreadyStarted: boolean;
33
- };
34
- }