@memori.ai/memori-react 7.9.1 → 7.11.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 (73) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +1 -0
  3. package/dist/components/AgeVerificationModal/AgeVerificationModal.css +1 -1
  4. package/dist/components/Chat/Chat.d.ts +1 -0
  5. package/dist/components/Chat/Chat.js +2 -2
  6. package/dist/components/Chat/Chat.js.map +1 -1
  7. package/dist/components/ChatBubble/ChatBubble.d.ts +1 -0
  8. package/dist/components/ChatBubble/ChatBubble.js +66 -50
  9. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  10. package/dist/components/MemoriWidget/MemoriWidget.d.ts +2 -1
  11. package/dist/components/MemoriWidget/MemoriWidget.js +62 -15
  12. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  13. package/dist/components/StartPanel/StartPanel.d.ts +1 -0
  14. package/dist/components/StartPanel/StartPanel.js +6 -2
  15. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  16. package/dist/components/layouts/chat.css +0 -1
  17. package/dist/helpers/utils.js +2 -15
  18. package/dist/helpers/utils.js.map +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +3 -5
  21. package/dist/index.js.map +1 -1
  22. package/dist/locales/de.json +3 -0
  23. package/dist/locales/en.json +4 -0
  24. package/dist/locales/es.json +3 -0
  25. package/dist/locales/fr.json +3 -0
  26. package/dist/locales/it.json +4 -0
  27. package/esm/components/AgeVerificationModal/AgeVerificationModal.css +1 -1
  28. package/esm/components/Chat/Chat.d.ts +1 -0
  29. package/esm/components/Chat/Chat.js +2 -2
  30. package/esm/components/Chat/Chat.js.map +1 -1
  31. package/esm/components/ChatBubble/ChatBubble.d.ts +1 -0
  32. package/esm/components/ChatBubble/ChatBubble.js +66 -50
  33. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  34. package/esm/components/MemoriWidget/MemoriWidget.d.ts +2 -1
  35. package/esm/components/MemoriWidget/MemoriWidget.js +63 -16
  36. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  37. package/esm/components/StartPanel/StartPanel.d.ts +1 -0
  38. package/esm/components/StartPanel/StartPanel.js +6 -2
  39. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  40. package/esm/components/layouts/chat.css +0 -1
  41. package/esm/helpers/utils.js +2 -15
  42. package/esm/helpers/utils.js.map +1 -1
  43. package/esm/index.d.ts +1 -0
  44. package/esm/index.js +3 -5
  45. package/esm/index.js.map +1 -1
  46. package/esm/locales/de.json +3 -0
  47. package/esm/locales/en.json +4 -0
  48. package/esm/locales/es.json +3 -0
  49. package/esm/locales/fr.json +3 -0
  50. package/esm/locales/it.json +4 -0
  51. package/package.json +9 -10
  52. package/src/components/AgeVerificationModal/AgeVerificationModal.css +1 -1
  53. package/src/components/Chat/Chat.tsx +4 -1
  54. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +99 -33
  55. package/src/components/ChatBubble/ChatBubble.stories.tsx +51 -1
  56. package/src/components/ChatBubble/ChatBubble.test.tsx +22 -0
  57. package/src/components/ChatBubble/ChatBubble.tsx +111 -90
  58. package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +247 -6
  59. package/src/components/MemoriWidget/MemoriWidget.stories.tsx +4 -1
  60. package/src/components/MemoriWidget/MemoriWidget.tsx +138 -25
  61. package/src/components/StartPanel/StartPanel.stories.tsx +18 -0
  62. package/src/components/StartPanel/StartPanel.test.tsx +20 -0
  63. package/src/components/StartPanel/StartPanel.tsx +9 -1
  64. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +101 -0
  65. package/src/components/layouts/chat.css +0 -1
  66. package/src/helpers/utils.ts +4 -17
  67. package/src/index.stories.tsx +6 -0
  68. package/src/index.tsx +4 -3
  69. package/src/locales/de.json +3 -0
  70. package/src/locales/en.json +4 -0
  71. package/src/locales/es.json +3 -0
  72. package/src/locales/fr.json +3 -0
  73. package/src/locales/it.json +4 -0
@@ -266,12 +266,30 @@ it('renders ChatBubble with markdown table unchanged', () => {
266
266
  expect(container).toMatchSnapshot();
267
267
  });
268
268
 
269
+ it('renders ChatBubble with complex markdown and math but disabled unchanged', () => {
270
+ const { container } = render(
271
+ <ChatBubble
272
+ memori={memori}
273
+ tenant={tenant}
274
+ sessionID={sessionID}
275
+ useMathFormatting={false}
276
+ message={{
277
+ fromUser: false,
278
+ text: `Per calcolare l'ipotenusa di un triangolo rettangolo, puoi usare il Teorema di Pitagora. Il teorema afferma che in un triangolo rettangolo, il quadrato dell'ipotenusa (la lato opposto all'angolo retto) è uguale alla somma dei quadrati degli altri due lati.\n\nLa formula è:\n\n\\[ c = \\sqrt{a^2 + b^2} \\]\n\nDove:\n- $c$ è l'ipotenusa.\n- $a$ e $ b $ sono i due cateti del triangolo.\n\n### Passaggi per il Calcolo\n\n1. **Misura o identifica i cateti $ a $ e $ b $**:\n I cateti sono i due lati che formano l'angolo retto.\n\n2. **Calcola i quadrati dei cateti**:\n Eleva al quadrato entrambe le misure dei cateti: $ a^2 $ e $ b^2 $.\n\n3. **Somma i quadrati dei cateti**:\n Somma i risultati ottenuti: $ a^2 + b^2 $.\n\n4. **Calcola la radice quadrata della somma**:\n Prendi la radice quadrata della somma per trovare l'ipotenusa: $ c = \\sqrt{a^2 + b^2} $.\n\n### Esempio di Calcolo\n\nSupponiamo di avere un triangolo rettangolo con i cateti di lunghezza 3 cm e 4 cm.\n\n1. **Cateto $ a $**: 3 cm\n2. **Cateto $ b $**: 4 cm\n\nUsiamo la formula:\n\n\\[ c = \\sqrt{a^2 + b^2} \\]\n\n\\[ c = \\sqrt{(3 \\, \\text{cm})^2 + (4 \\, \\text{cm})^2} \\]\n\n\\[ c = \\sqrt{9 \\, \\text{cm}^2 + 16 \\, \\text{cm}^2} \\]\n\n\\[ c = \\sqrt{25 \\, \\text{cm}^2} \\]\n\n\\[ c = 5 \\, \\text{cm} \\]\n\nQuindi, l'ipotenusa del triangolo è di 5 cm.`,
279
+ initial: false,
280
+ }}
281
+ />
282
+ );
283
+ expect(container).toMatchSnapshot();
284
+ });
285
+
269
286
  it('renders ChatBubble with complex markdown and math 1 unchanged', () => {
270
287
  const { container } = render(
271
288
  <ChatBubble
272
289
  memori={memori}
273
290
  tenant={tenant}
274
291
  sessionID={sessionID}
292
+ useMathFormatting
275
293
  message={{
276
294
  fromUser: false,
277
295
  text: `Per calcolare l'ipotenusa di un triangolo rettangolo, puoi usare il Teorema di Pitagora. Il teorema afferma che in un triangolo rettangolo, il quadrato dell'ipotenusa (la lato opposto all'angolo retto) è uguale alla somma dei quadrati degli altri due lati.\n\nLa formula è:\n\n\\[ c = \\sqrt{a^2 + b^2} \\]\n\nDove:\n- $c$ è l'ipotenusa.\n- $a$ e $ b $ sono i due cateti del triangolo.\n\n### Passaggi per il Calcolo\n\n1. **Misura o identifica i cateti $ a $ e $ b $**:\n I cateti sono i due lati che formano l'angolo retto.\n\n2. **Calcola i quadrati dei cateti**:\n Eleva al quadrato entrambe le misure dei cateti: $ a^2 $ e $ b^2 $.\n\n3. **Somma i quadrati dei cateti**:\n Somma i risultati ottenuti: $ a^2 + b^2 $.\n\n4. **Calcola la radice quadrata della somma**:\n Prendi la radice quadrata della somma per trovare l'ipotenusa: $ c = \\sqrt{a^2 + b^2} $.\n\n### Esempio di Calcolo\n\nSupponiamo di avere un triangolo rettangolo con i cateti di lunghezza 3 cm e 4 cm.\n\n1. **Cateto $ a $**: 3 cm\n2. **Cateto $ b $**: 4 cm\n\nUsiamo la formula:\n\n\\[ c = \\sqrt{a^2 + b^2} \\]\n\n\\[ c = \\sqrt{(3 \\, \\text{cm})^2 + (4 \\, \\text{cm})^2} \\]\n\n\\[ c = \\sqrt{9 \\, \\text{cm}^2 + 16 \\, \\text{cm}^2} \\]\n\n\\[ c = \\sqrt{25 \\, \\text{cm}^2} \\]\n\n\\[ c = 5 \\, \\text{cm} \\]\n\nQuindi, l'ipotenusa del triangolo è di 5 cm.`,
@@ -288,6 +306,7 @@ it('renders ChatBubble with complex markdown and math 2 unchanged', () => {
288
306
  memori={memori}
289
307
  tenant={tenant}
290
308
  sessionID={sessionID}
309
+ useMathFormatting
291
310
  message={{
292
311
  fromUser: false,
293
312
  text: "Per calcolare le resistenze dei materiali per le verifiche rispetto ad azioni antropiche e ambientali secondo la Specifica Tecnica ST-VAL4, si procede in questo modo:\n\n1. **Determinazione della resistenza dei materiali:**\n La resistenza dei materiali da utilizzare nelle verifiche accurate si determina a partire dalle indagini sull’opera. La caratterizzazione deve essere distinta per tutti i materiali presenti nell'opera, in accordo con la ST-PI. Le resistenze per verifiche rispetto ad azioni antropiche come i carichi da traffico e le azioni ambientali sono definite dalle LG20. Questo include la distinzione rispetto a quelle utilizzate per le azioni sismiche, come dettagliato dalle NTC18 e CIR19 .\n\n2. **Calcolo della resistenza:**\n Il valore della resistenza dei materiali $ f_d $ da utilizzare nelle verifiche per carichi gravitazionali si ottiene mediante la seguente espressione:\n\n \\[\n f_d = \\min \\left( \\frac{f_m}{FC \\cdot \\gamma_M}, \\frac{f_k}{FC} \\right)\n \\]\n\n Dove:\n - $ f_m $ è il valor medio della resistenza valutato dai risultati delle prove effettuate sui campioni prelevati in situ;\n - $ f_k $ è la resistenza caratteristica calcolata sulla base dei risultati delle prove sui campioni prelevati in situ;\n - $ FC $ è il Fattore di Confidenza associato al Livello di Conoscenza raggiunto;\n - $ \\gamma_M $ è il fattore parziale di sicurezza del materiale .\n\n3. **Caratterizzazione dei materiali:**\n I valori medi, caratteristici e di progetto delle resistenze a compressione e trazione per il calcestruzzo, e delle resistenze a snervamento per l’acciaio ordinario sono determinati a partire dai risultati delle prove. Specifiche espressioni e metodi sono forniti per diversi materiali nell'Appendice 13 della ST-VAL4 .\n\n4. **Stima della resistenza da prove non distruttive:**\n Per valutare le resistenze dei materiali, si possono anche utilizzare prove non distruttive come le prove SonReb per il calcestruzzo e le prove di durezza per l'acciaio ordinario e armonico. Formulazioni specifiche per queste prove si trovano in Appendice al §13.1 della ST-VAL4 .\n\n5. **Analisi dei risultati delle indagini:**\n Gli esiti delle prove devono essere attentamente analizzati per confermare le caratteristiche originarie o rilevare eventuali decadimenti del materiale. Questo processo include anche l'identificazione delle cause di dispersione significative nei risultati delle prove .\n\nSeguendo questi passaggi, si ottiene una stima accurata delle resistenze dei materiali che possono essere utilizzate per le verifiche di sicurezza rispetto ad azioni antropiche e ambientali.",
@@ -304,6 +323,7 @@ it('renders ChatBubble with complex markdown and math 3 unchanged', () => {
304
323
  memori={memori}
305
324
  tenant={tenant}
306
325
  sessionID={sessionID}
326
+ useMathFormatting
307
327
  message={{
308
328
  fromUser: false,
309
329
  initial: false,
@@ -320,6 +340,7 @@ it('renders ChatBubble with complex markdown and math 4 unchanged', () => {
320
340
  memori={memori}
321
341
  tenant={tenant}
322
342
  sessionID={sessionID}
343
+ useMathFormatting
323
344
  message={{
324
345
  fromUser: false,
325
346
  initial: false,
@@ -336,6 +357,7 @@ it('renders ChatBubble with complex markdown and math 5 unchanged', () => {
336
357
  memori={memori}
337
358
  tenant={tenant}
338
359
  sessionID={sessionID}
360
+ useMathFormatting
339
361
  message={{
340
362
  fromUser: false,
341
363
  initial: false,
@@ -29,32 +29,15 @@ import markedLinkifyIt from 'marked-linkify-it';
29
29
  import markedKatex from 'marked-katex-extension';
30
30
  import markedExtendedTables from '../../helpers/markedExtendedTables';
31
31
 
32
- export interface Props {
33
- message: Message;
34
- memori: Memori;
35
- sessionID: string;
36
- tenant?: Tenant;
37
- baseUrl?: string;
38
- apiUrl?: string;
39
- showFeedback?: boolean;
40
- showWhyThisAnswer?: boolean;
41
- showCopyButton?: boolean;
42
- showTranslationOriginal?: boolean;
43
- simulateUserPrompt?: (msg: string) => void;
44
- showAIicon?: boolean;
45
- isFirst?: boolean;
46
- userAvatar?: MemoriProps['userAvatar'];
47
- user?: User;
48
- experts?: ExpertReference[];
49
- }
50
32
 
51
33
  marked.use({
52
34
  async: false,
53
35
  gfm: true,
54
36
  pedantic: true,
55
37
  renderer: {
56
- link(href: string, title: string | null | undefined, text: string) {
38
+ link: ({ href, title, text }) => {
57
39
  const cleanHref = cleanUrl(href);
40
+
58
41
  if (cleanHref === null) {
59
42
  return text;
60
43
  }
@@ -69,14 +52,100 @@ marked.use({
69
52
  },
70
53
  });
71
54
  marked.use(markedLinkifyIt());
72
- marked.use(
73
- markedKatex({
74
- throwOnError: false,
75
- output: 'htmlAndMathml',
76
- })
77
- );
78
55
  marked.use(markedExtendedTables());
79
56
 
57
+ const parseSquaredBrackets = (text: string) => {
58
+ const rows = text.split('\n');
59
+
60
+ return rows.reduce((acc, row) => {
61
+ if (row.includes('=')) {
62
+ let result = '';
63
+ let isEscaped = false;
64
+ for (let i = 0; i < row.length; i++) {
65
+ if (row[i] === '[' && !isEscaped) {
66
+ result += '\\[';
67
+ } else if (row[i] === ']' && !isEscaped) {
68
+ result += '\\]';
69
+ } else {
70
+ result += row[i];
71
+ }
72
+ isEscaped = row[i] === '\\' && !isEscaped;
73
+ }
74
+
75
+ return acc?.length ? `${acc}\n${result}` : result;
76
+ } else {
77
+ return acc?.length ? `${acc}\n${row}` : row;
78
+ }
79
+ }, '');
80
+ };
81
+
82
+ const renderMsg = (text: string, useMathFormatting = false) => {
83
+ try {
84
+ let parsedText = DOMPurify.sanitize(
85
+ (
86
+ marked.parse(
87
+ text
88
+ // remove leading and trailing whitespaces
89
+ .trim()
90
+ // remove markdown links
91
+ .replaceAll(
92
+ /\[([^\]]+)\]\(([^\)]+)\)/g,
93
+ '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
94
+ )
95
+ // remove markdown multiline code blocks but keep the content
96
+ .replaceAll(/```markdown([^```]+)```/g, '$1')
97
+ .replaceAll('($', '( $')
98
+ .replaceAll(':$', ': $')
99
+ .replaceAll('\frac', '\\frac')
100
+ .replaceAll('\beta', '\\beta')
101
+ .replaceAll('cdot', '\\cdot')
102
+ ) as string
103
+ )
104
+ .trim()
105
+ .replace(/\n/g, '<br>'),
106
+ {
107
+ ADD_ATTR: ['target'],
108
+ }
109
+ );
110
+
111
+ if (useMathFormatting) {
112
+ parsedText = parseSquaredBrackets(parsedText);
113
+ }
114
+
115
+ return (
116
+ parsedText
117
+ // replace consecutive <br> with a single <br>
118
+ .replace(/(<br>)+/g, '<br>')
119
+ // remove empty paragraphs
120
+ .replace(/<p><\/p>/g, '<br>')
121
+ .replace(/<p><br><\/p>/g, '<br>')
122
+ );
123
+ } catch (e) {
124
+ console.error(e);
125
+ return text;
126
+ }
127
+ };
128
+
129
+ export interface Props {
130
+ message: Message;
131
+ memori: Memori;
132
+ sessionID: string;
133
+ tenant?: Tenant;
134
+ baseUrl?: string;
135
+ apiUrl?: string;
136
+ showFeedback?: boolean;
137
+ showWhyThisAnswer?: boolean;
138
+ showCopyButton?: boolean;
139
+ showTranslationOriginal?: boolean;
140
+ simulateUserPrompt?: (msg: string) => void;
141
+ showAIicon?: boolean;
142
+ useMathFormatting?: boolean;
143
+ isFirst?: boolean;
144
+ userAvatar?: MemoriProps['userAvatar'];
145
+ user?: User;
146
+ experts?: ExpertReference[];
147
+ }
148
+
80
149
  const ChatBubble: React.FC<Props> = ({
81
150
  message,
82
151
  memori,
@@ -91,6 +160,7 @@ const ChatBubble: React.FC<Props> = ({
91
160
  simulateUserPrompt,
92
161
  showAIicon = true,
93
162
  isFirst = false,
163
+ useMathFormatting = false,
94
164
  user,
95
165
  userAvatar,
96
166
  experts,
@@ -99,78 +169,29 @@ const ChatBubble: React.FC<Props> = ({
99
169
  const lang = i18n.language || 'en';
100
170
  const [showingWhyThisAnswer, setShowingWhyThisAnswer] = useState(false);
101
171
 
102
- const text = message.translatedText || message.text;
172
+ if (useMathFormatting) {
173
+ marked.use(
174
+ markedKatex({
175
+ throwOnError: false,
176
+ output: 'htmlAndMathml',
177
+ })
178
+ );
179
+ }
103
180
 
104
- // remove redundant mathjax delimiters: old code
105
- // .replaceAll(/(?<!\\)\[/g, '\\[')
106
- // .replaceAll(/(?<!\\)\]/g, '\\]')
107
- // since old Safari < 16.4 doesn't support negative lookbehind, we need to use a workaround
108
- const parseSquaredBrackets = (text: string) => {
109
- let result = '';
110
- let isEscaped = false;
111
- for (let i = 0; i < text.length; i++) {
112
- if (text[i] === '[' && !isEscaped) {
113
- result += '\\[';
114
- } else if (text[i] === ']' && !isEscaped) {
115
- result += '\\]';
116
- } else {
117
- result += text[i];
118
- }
119
- isEscaped = text[i] === '\\' && !isEscaped;
120
- }
121
- return result;
122
- };
181
+ const text = message.translatedText || message.text;
123
182
 
124
- const renderMsg = (text: string) => {
125
- try {
126
- return (
127
- parseSquaredBrackets(
128
- DOMPurify.sanitize(
129
- (
130
- marked.parse(
131
- text
132
- // remove leading and trailing whitespaces
133
- .trim()
134
- // remove markdown links
135
- .replaceAll(
136
- /\[([^\]]+)\]\(([^\)]+)\)/g,
137
- '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
138
- )
139
- // remove markdown multiline code blocks but keep the content
140
- .replaceAll(/```markdown([^```]+)```/g, '$1')
141
- .replaceAll('($', '( $')
142
- .replaceAll(':$', ': $')
143
- .replaceAll('\frac', '\\frac')
144
- .replaceAll('\beta', '\\beta')
145
- .replaceAll('cdot', '\\cdot')
146
- ) as string
147
- )
148
- .trim()
149
- .replace(/\n/g, '<br>'),
150
- {
151
- ADD_ATTR: ['target'],
152
- }
153
- )
154
- )
155
- // replace consecutive <br> with a single <br>
156
- .replace(/(<br>)+/g, '<br>')
157
- // remove empty paragraphs
158
- .replace(/<p><\/p>/g, '<br>')
159
- .replace(/<p><br><\/p>/g, '<br>')
160
- );
161
- } catch (e) {
162
- console.error(e);
163
- return text;
164
- }
165
- };
166
- const renderedText = message.fromUser ? text : renderMsg(text);
183
+ const renderedText = renderMsg(text, useMathFormatting);
167
184
 
168
185
  const plainText = message.fromUser
169
186
  ? text
170
187
  : stripHTML(stripOutputTags(renderedText));
171
188
 
172
189
  useLayoutEffect(() => {
173
- if (typeof window !== 'undefined' && !message.fromUser) {
190
+ if (
191
+ typeof window !== 'undefined' &&
192
+ !message.fromUser &&
193
+ useMathFormatting
194
+ ) {
174
195
  // @ts-ignore
175
196
  // eslint-disable-next-line no-undef
176
197
  if ('MathJax' in window && window.MathJax.typesetPromise)
@@ -178,7 +199,7 @@ const ChatBubble: React.FC<Props> = ({
178
199
  // eslint-disable-next-line no-undef
179
200
  window.MathJax.typesetPromise(['.memori-chat--bubble-content']);
180
201
  }
181
- }, [message.text, message.fromUser]);
202
+ }, [message.text, message.fromUser, useMathFormatting]);
182
203
 
183
204
  return (
184
205
  <>
@@ -12,7 +12,9 @@ exports[`renders ChatBubble from user with avatar as react element unchanged 1`]
12
12
  class="memori-chat--bubble-content"
13
13
  dir="auto"
14
14
  >
15
- Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
15
+ <p>
16
+ Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
17
+ </p>
16
18
  </div>
17
19
  </div>
18
20
  <div
@@ -38,7 +40,9 @@ exports[`renders ChatBubble from user with avatar unchanged 1`] = `
38
40
  class="memori-chat--bubble-content"
39
41
  dir="auto"
40
42
  >
41
- Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
43
+ <p>
44
+ Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
45
+ </p>
42
46
  </div>
43
47
  </div>
44
48
  <picture
@@ -66,7 +70,9 @@ exports[`renders ChatBubble from user with custom avatar unchanged 1`] = `
66
70
  class="memori-chat--bubble-content"
67
71
  dir="auto"
68
72
  >
69
- Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
73
+ <p>
74
+ Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
75
+ </p>
70
76
  </div>
71
77
  </div>
72
78
  <picture
@@ -3422,6 +3428,235 @@ exports[`renders ChatBubble with complex markdown and math 5 unchanged 1`] = `
3422
3428
  </div>
3423
3429
  `;
3424
3430
 
3431
+ exports[`renders ChatBubble with complex markdown and math but disabled unchanged 1`] = `
3432
+ <div>
3433
+ <div
3434
+ class="memori-chat--bubble-container"
3435
+ >
3436
+ <picture
3437
+ class="memori-chat--bubble-avatar transition ease-in-out duration-300 opacity-0 scale-075 translate-x--15"
3438
+ title="Memori"
3439
+ >
3440
+ <img
3441
+ alt="Memori"
3442
+ class="memori-chat--bubble-avatar-img"
3443
+ src="https://aisuru.com/images/aisuru/square_logo.png"
3444
+ />
3445
+ </picture>
3446
+ <div
3447
+ class="memori-chat--bubble memori-chat--with-addon transition ease-in-out duration-300 opacity-0 scale-09 translate-x--30"
3448
+ >
3449
+ <div
3450
+ class="memori-chat--bubble-content"
3451
+ dir="auto"
3452
+ >
3453
+ <p>
3454
+ Per calcolare l'ipotenusa di un triangolo rettangolo, puoi usare il Teorema di Pitagora. Il teorema afferma che in un triangolo rettangolo, il quadrato dell'ipotenusa (la lato opposto all'angolo retto) è uguale alla somma dei quadrati degli altri due lati.
3455
+ </p>
3456
+ <br />
3457
+ <p>
3458
+ La formula è:
3459
+ </p>
3460
+ <br />
3461
+ <p>
3462
+ [ c = \\sqrt{a^2 + b^2} ]
3463
+ </p>
3464
+ <br />
3465
+ <p>
3466
+ Dove:
3467
+ <br />
3468
+ - $c$ è l'ipotenusa.
3469
+ <br />
3470
+ - $a$ e $ b $ sono i due cateti del triangolo.
3471
+ </p>
3472
+ <br />
3473
+ <h3>
3474
+ Passaggi per il Calcolo
3475
+ </h3>
3476
+ <br />
3477
+ <ol>
3478
+ <br />
3479
+ <li>
3480
+ <p>
3481
+ <strong>
3482
+ Misura o identifica i cateti $ a $ e $ b $
3483
+ </strong>
3484
+ :
3485
+ <br />
3486
+ I cateti sono i due lati che formano l'angolo retto.
3487
+ </p>
3488
+ <br />
3489
+ </li>
3490
+ <br />
3491
+ <li>
3492
+ <p>
3493
+ <strong>
3494
+ Calcola i quadrati dei cateti
3495
+ </strong>
3496
+ :
3497
+ <br />
3498
+ Eleva al quadrato entrambe le misure dei cateti: $ a^2 $ e $ b^2 $.
3499
+ </p>
3500
+ <br />
3501
+ </li>
3502
+ <br />
3503
+ <li>
3504
+ <p>
3505
+ <strong>
3506
+ Somma i quadrati dei cateti
3507
+ </strong>
3508
+ :
3509
+ <br />
3510
+ Somma i risultati ottenuti: $ a^2 + b^2 $.
3511
+ </p>
3512
+ <br />
3513
+ </li>
3514
+ <br />
3515
+ <li>
3516
+ <p>
3517
+ <strong>
3518
+ Calcola la radice quadrata della somma
3519
+ </strong>
3520
+ :
3521
+ <br />
3522
+ Prendi la radice quadrata della somma per trovare l'ipotenusa: $ c = \\sqrt{a^2 + b^2} $.
3523
+ </p>
3524
+ <br />
3525
+ </li>
3526
+ <br />
3527
+ </ol>
3528
+ <br />
3529
+ <h3>
3530
+ Esempio di Calcolo
3531
+ </h3>
3532
+ <br />
3533
+ <p>
3534
+ Supponiamo di avere un triangolo rettangolo con i cateti di lunghezza 3 cm e 4 cm.
3535
+ </p>
3536
+ <br />
3537
+ <ol>
3538
+ <br />
3539
+ <li>
3540
+ <strong>
3541
+ Cateto $ a $
3542
+ </strong>
3543
+ : 3 cm
3544
+ </li>
3545
+ <br />
3546
+ <li>
3547
+ <strong>
3548
+ Cateto $ b $
3549
+ </strong>
3550
+ : 4 cm
3551
+ </li>
3552
+ <br />
3553
+ </ol>
3554
+ <br />
3555
+ <p>
3556
+ Usiamo la formula:
3557
+ </p>
3558
+ <br />
3559
+ <p>
3560
+ [ c = \\sqrt{a^2 + b^2} ]
3561
+ </p>
3562
+ <br />
3563
+ <p>
3564
+ [ c = \\sqrt{(3 , \\text{cm})^2 + (4 , \\text{cm})^2} ]
3565
+ </p>
3566
+ <br />
3567
+ <p>
3568
+ [ c = \\sqrt{9 , \\text{cm}^2 + 16 , \\text{cm}^2} ]
3569
+ </p>
3570
+ <br />
3571
+ <p>
3572
+ [ c = \\sqrt{25 , \\text{cm}^2} ]
3573
+ </p>
3574
+ <br />
3575
+ <p>
3576
+ [ c = 5 , \\text{cm} ]
3577
+ </p>
3578
+ <br />
3579
+ <p>
3580
+ Quindi, l'ipotenusa del triangolo è di 5 cm.
3581
+ </p>
3582
+ </div>
3583
+ <div
3584
+ class="memori-chat--bubble-addon"
3585
+ >
3586
+ <button
3587
+ class="memori-button memori-button--ghost memori-button--circle memori-button--padded memori-button--icon-only memori-chat--bubble-action-icon"
3588
+ title="copy"
3589
+ >
3590
+ <span
3591
+ class="memori-button--icon"
3592
+ >
3593
+ <svg
3594
+ aria-hidden="true"
3595
+ fill="none"
3596
+ focusable="false"
3597
+ role="img"
3598
+ stroke="currentColor"
3599
+ stroke-linecap="round"
3600
+ stroke-linejoin="round"
3601
+ stroke-width="1.5"
3602
+ viewBox="0 0 24 24"
3603
+ xmlns="http://www.w3.org/2000/svg"
3604
+ >
3605
+ <rect
3606
+ height="14"
3607
+ rx="2"
3608
+ ry="2"
3609
+ width="14"
3610
+ x="8"
3611
+ y="8"
3612
+ />
3613
+ <path
3614
+ d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
3615
+ />
3616
+ </svg>
3617
+ </span>
3618
+ </button>
3619
+ <button
3620
+ class="memori-button memori-button--ghost memori-button--circle memori-button--padded memori-button--icon-only memori-chat--bubble-action-icon"
3621
+ title="copyRawCode"
3622
+ >
3623
+ <span
3624
+ class="memori-button--icon"
3625
+ >
3626
+ <svg
3627
+ aria-hidden="true"
3628
+ fill="none"
3629
+ focusable="false"
3630
+ role="img"
3631
+ stroke="currentColor"
3632
+ stroke-linecap="round"
3633
+ stroke-linejoin="round"
3634
+ stroke-width="1.5"
3635
+ viewBox="0 0 24 24"
3636
+ xmlns="http://www.w3.org/2000/svg"
3637
+ >
3638
+ <path
3639
+ d="M10 9.5 8 12l2 2.5"
3640
+ />
3641
+ <path
3642
+ d="m14 9.5 2 2.5-2 2.5"
3643
+ />
3644
+ <rect
3645
+ height="18"
3646
+ rx="2"
3647
+ width="18"
3648
+ x="3"
3649
+ y="3"
3650
+ />
3651
+ </svg>
3652
+ </span>
3653
+ </button>
3654
+ </div>
3655
+ </div>
3656
+ </div>
3657
+ </div>
3658
+ `;
3659
+
3425
3660
  exports[`renders ChatBubble with copy disabled unchanged 1`] = `
3426
3661
  <div>
3427
3662
  <div
@@ -4174,7 +4409,9 @@ exports[`renders ChatBubble with msg from BoE expert unchanged 1`] = `
4174
4409
  class="memori-chat--bubble-content"
4175
4410
  dir="auto"
4176
4411
  >
4177
- Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
4412
+ <p>
4413
+ Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
4414
+ </p>
4178
4415
  </div>
4179
4416
  <div
4180
4417
  class="memori-chat--bubble-addon"
@@ -4257,7 +4494,9 @@ exports[`renders ChatBubble with msg generated by AI unchanged 1`] = `
4257
4494
  class="memori-chat--bubble-content"
4258
4495
  dir="auto"
4259
4496
  >
4260
- Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
4497
+ <p>
4498
+ Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
4499
+ </p>
4261
4500
  </div>
4262
4501
  <div
4263
4502
  class="memori-chat--bubble-addon"
@@ -4472,7 +4711,9 @@ exports[`renders ChatBubble with user msg unchanged 1`] = `
4472
4711
  class="memori-chat--bubble-content"
4473
4712
  dir="auto"
4474
4713
  >
4475
- Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
4714
+ <p>
4715
+ Proin libero ante, dignissim sit amet turpis a, pretium condimentum dolor.
4716
+ </p>
4476
4717
  </div>
4477
4718
  </div>
4478
4719
  <div
@@ -5,6 +5,7 @@ import I18nWrapper from '../../I18nWrapper';
5
5
  import MemoriWidget, { Props } from './MemoriWidget';
6
6
 
7
7
  import './MemoriWidget.css';
8
+ import { VisemeProvider } from '../../context/visemeContext';
8
9
 
9
10
  const meta: Meta = {
10
11
  title: 'Widget/Default',
@@ -36,7 +37,9 @@ export default meta;
36
37
 
37
38
  const Template: Story<Props> = args => (
38
39
  <I18nWrapper>
39
- <MemoriWidget {...args} />
40
+ <VisemeProvider>
41
+ <MemoriWidget {...args} />
42
+ </VisemeProvider>
40
43
  </I18nWrapper>
41
44
  );
42
45
  // By passing using the Args format for exported stories, you can control the props for a component for reuse in a test