@memori.ai/memori-react 7.5.0 → 7.6.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 (157) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +10 -2
  3. package/dist/components/Avatar/Avatar.d.ts +2 -0
  4. package/dist/components/Avatar/Avatar.js +11 -6
  5. package/dist/components/Avatar/Avatar.js.map +1 -1
  6. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +20 -0
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +107 -0
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -0
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controls.d.ts +26 -0
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controls.js +59 -0
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controls.js.map +1 -0
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +30 -0
  13. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +148 -0
  14. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -0
  15. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +15 -0
  16. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +77 -0
  17. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -0
  18. package/dist/components/Avatar/AvatarView/AvatarComponent/components/loader.d.ts +5 -0
  19. package/dist/components/Avatar/AvatarView/AvatarComponent/components/loader.js +12 -0
  20. package/dist/components/Avatar/AvatarView/AvatarComponent/components/loader.js.map +1 -0
  21. package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.d.ts +2 -1
  22. package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.js +3 -2
  23. package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.js.map +1 -1
  24. package/dist/components/Avatar/AvatarView/index.d.ts +6 -1
  25. package/dist/components/Avatar/AvatarView/index.js +15 -83
  26. package/dist/components/Avatar/AvatarView/index.js.map +1 -1
  27. package/dist/components/Avatar/AvatarView/utils/useEyeBlink.d.ts +16 -2
  28. package/dist/components/Avatar/AvatarView/utils/useEyeBlink.js +62 -38
  29. package/dist/components/Avatar/AvatarView/utils/useEyeBlink.js.map +1 -1
  30. package/dist/components/Avatar/AvatarView/utils/useMouthAnimation.d.ts +16 -0
  31. package/dist/components/Avatar/AvatarView/utils/useMouthAnimation.js +59 -0
  32. package/dist/components/Avatar/AvatarView/utils/useMouthAnimation.js.map +1 -0
  33. package/dist/components/Avatar/AvatarView/utils/useSmile.js +1 -1
  34. package/dist/components/Avatar/AvatarView/utils/useSmile.js.map +1 -1
  35. package/dist/components/ChatBubble/ChatBubble.js +2 -3
  36. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  37. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.d.ts +1 -1
  38. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +24 -3
  39. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  40. package/dist/components/MemoriWidget/MemoriWidget.d.ts +1 -1
  41. package/dist/components/MemoriWidget/MemoriWidget.js +25 -3
  42. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  43. package/dist/components/StartPanel/StartPanel.js +1 -1
  44. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  45. package/dist/components/layouts/HiddenChat.d.ts +4 -0
  46. package/dist/components/layouts/HiddenChat.js +51 -0
  47. package/dist/components/layouts/HiddenChat.js.map +1 -0
  48. package/dist/components/layouts/ZoomedFullBody.d.ts +4 -0
  49. package/dist/components/layouts/ZoomedFullBody.js +8 -0
  50. package/dist/components/layouts/ZoomedFullBody.js.map +1 -0
  51. package/dist/components/layouts/hidden-chat.css +184 -0
  52. package/dist/context/visemeContext.d.ts +27 -0
  53. package/dist/context/visemeContext.js +221 -0
  54. package/dist/context/visemeContext.js.map +1 -0
  55. package/dist/helpers/utils.d.ts +7 -0
  56. package/dist/helpers/utils.js +51 -1
  57. package/dist/helpers/utils.js.map +1 -1
  58. package/dist/index.js +20 -16
  59. package/dist/index.js.map +1 -1
  60. package/dist/styles.css +1 -0
  61. package/esm/components/Avatar/Avatar.d.ts +2 -0
  62. package/esm/components/Avatar/Avatar.js +11 -6
  63. package/esm/components/Avatar/Avatar.js.map +1 -1
  64. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +20 -0
  65. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +102 -0
  66. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -0
  67. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controls.d.ts +26 -0
  68. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controls.js +56 -0
  69. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controls.js.map +1 -0
  70. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +30 -0
  71. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +145 -0
  72. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -0
  73. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +15 -0
  74. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +73 -0
  75. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -0
  76. package/esm/components/Avatar/AvatarView/AvatarComponent/components/loader.d.ts +5 -0
  77. package/esm/components/Avatar/AvatarView/AvatarComponent/components/loader.js +9 -0
  78. package/esm/components/Avatar/AvatarView/AvatarComponent/components/loader.js.map +1 -0
  79. package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.d.ts +2 -1
  80. package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.js +3 -2
  81. package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.js.map +1 -1
  82. package/esm/components/Avatar/AvatarView/index.d.ts +6 -1
  83. package/esm/components/Avatar/AvatarView/index.js +16 -84
  84. package/esm/components/Avatar/AvatarView/index.js.map +1 -1
  85. package/esm/components/Avatar/AvatarView/utils/useEyeBlink.d.ts +16 -2
  86. package/esm/components/Avatar/AvatarView/utils/useEyeBlink.js +61 -38
  87. package/esm/components/Avatar/AvatarView/utils/useEyeBlink.js.map +1 -1
  88. package/esm/components/Avatar/AvatarView/utils/useMouthAnimation.d.ts +16 -0
  89. package/esm/components/Avatar/AvatarView/utils/useMouthAnimation.js +55 -0
  90. package/esm/components/Avatar/AvatarView/utils/useMouthAnimation.js.map +1 -0
  91. package/esm/components/Avatar/AvatarView/utils/useSmile.js +1 -1
  92. package/esm/components/Avatar/AvatarView/utils/useSmile.js.map +1 -1
  93. package/esm/components/ChatBubble/ChatBubble.js +2 -3
  94. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  95. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.d.ts +1 -1
  96. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +24 -3
  97. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  98. package/esm/components/MemoriWidget/MemoriWidget.d.ts +1 -1
  99. package/esm/components/MemoriWidget/MemoriWidget.js +26 -4
  100. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  101. package/esm/components/StartPanel/StartPanel.js +1 -1
  102. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  103. package/esm/components/layouts/HiddenChat.d.ts +4 -0
  104. package/esm/components/layouts/HiddenChat.js +48 -0
  105. package/esm/components/layouts/HiddenChat.js.map +1 -0
  106. package/esm/components/layouts/ZoomedFullBody.d.ts +4 -0
  107. package/esm/components/layouts/ZoomedFullBody.js +5 -0
  108. package/esm/components/layouts/ZoomedFullBody.js.map +1 -0
  109. package/esm/components/layouts/hidden-chat.css +184 -0
  110. package/esm/context/visemeContext.d.ts +27 -0
  111. package/esm/context/visemeContext.js +216 -0
  112. package/esm/context/visemeContext.js.map +1 -0
  113. package/esm/helpers/utils.d.ts +7 -0
  114. package/esm/helpers/utils.js +45 -0
  115. package/esm/helpers/utils.js.map +1 -1
  116. package/esm/index.js +20 -16
  117. package/esm/index.js.map +1 -1
  118. package/esm/styles.css +1 -0
  119. package/package.json +2 -2
  120. package/src/components/Avatar/Avatar.test.tsx +28 -20
  121. package/src/components/Avatar/Avatar.tsx +19 -5
  122. package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +222 -0
  123. package/src/components/Avatar/AvatarView/{components → AvatarComponent/components}/controls.tsx +16 -10
  124. package/src/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.tsx +234 -0
  125. package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +123 -0
  126. package/src/components/Avatar/AvatarView/{components → AvatarComponent/components}/loader.tsx +1 -1
  127. package/src/components/Avatar/AvatarView/AvatarView.stories.tsx +47 -8
  128. package/src/components/Avatar/AvatarView/index.tsx +47 -174
  129. package/src/components/Avatar/AvatarView/utils/useEyeBlink.ts +89 -48
  130. package/src/components/Avatar/AvatarView/utils/useMouthAnimation.ts +93 -0
  131. package/src/components/Avatar/AvatarView/utils/useSmile.ts +1 -1
  132. package/src/components/ChatBubble/ChatBubble.tsx +3 -4
  133. package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +33 -3
  134. package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +18 -0
  135. package/src/components/MemoriWidget/MemoriWidget.tsx +60 -5
  136. package/src/components/StartPanel/StartPanel.tsx +1 -1
  137. package/src/components/layouts/Chat.test.tsx +7 -5
  138. package/src/components/layouts/FullPage.test.tsx +11 -8
  139. package/src/components/layouts/HiddenChat.test.tsx +37 -0
  140. package/src/components/layouts/HiddenChat.tsx +108 -0
  141. package/src/components/layouts/Totem.test.tsx +6 -4
  142. package/src/components/layouts/WebsiteAssistant.test.tsx +7 -5
  143. package/src/components/layouts/ZoomedFullBody.test.tsx +37 -0
  144. package/src/components/layouts/ZoomedFullBody.tsx +55 -0
  145. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +210 -0
  146. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +444 -0
  147. package/src/components/layouts/hidden-chat.css +184 -0
  148. package/src/components/layouts/layouts.stories.tsx +135 -19
  149. package/src/context/visemeContext.tsx +328 -0
  150. package/src/helpers/utils.test.ts +18 -0
  151. package/src/helpers/utils.ts +73 -0
  152. package/src/index.stories.tsx +40 -17
  153. package/src/index.tsx +82 -78
  154. package/src/styles.css +1 -0
  155. package/src/components/Avatar/AvatarView/components/fullbodyAvatar.tsx +0 -120
  156. package/src/components/Avatar/AvatarView/components/halfbodyAvatar.tsx +0 -69
  157. package/src/components/Avatar/AvatarView/utils/useMouthSpeaking.ts +0 -87
@@ -3,6 +3,7 @@ import {
3
3
  stripEmojis,
4
4
  stripMarkdown,
5
5
  stripOutputTags,
6
+ escapeHTML,
6
7
  } from './utils';
7
8
 
8
9
  describe('Utils/difference', () => {
@@ -139,3 +140,20 @@ describe('utils/stripOutputTags', () => {
139
140
  expect(result).toEqual('test\n');
140
141
  });
141
142
  });
143
+
144
+ describe('utils/parsing combined', () => {
145
+ it('should remove output tag from real message', () => {
146
+ const result = escapeHTML(
147
+ stripMarkdown(
148
+ stripEmojis(
149
+ stripOutputTags(`Beh... grazie, davvero. Non so cosa dire, sono lusingata. Ma... mi scusi se glielo chiedo, è sicuro che non ci sia stato un errore? Di solito ricevo più critiche che complimenti per il mio lavoro. So di impegnarmi molto, faccio spesso straordinari e salto persino la pausa pranzo per finire le pratiche. Però mi rendo conto che a volte ci sono imprecisioni e ritardi nelle consegne... Forse c'è qualcosa che non sto capendo?
150
+
151
+ <output class="memori-emotion">["timore"]</output>`)
152
+ )
153
+ )
154
+ );
155
+ expect(result).toEqual(
156
+ `Beh... grazie, davvero. Non so cosa dire, sono lusingata. Ma... mi scusi se glielo chiedo, è sicuro che non ci sia stato un errore? Di solito ricevo più critiche che complimenti per il mio lavoro. So di impegnarmi molto, faccio spesso straordinari e salto persino la pausa pranzo per finire le pratiche. Però mi rendo conto che a volte ci sono imprecisioni e ritardi nelle consegne... Forse c'è qualcosa che non sto capendo?`
157
+ );
158
+ });
159
+ });
@@ -1,4 +1,6 @@
1
1
  import { useState, useEffect, useRef, useMemo } from 'react';
2
+ import { Material, MeshStandardMaterial, SkinnedMesh } from 'three';
3
+ import * as THREE from 'three';
2
4
 
3
5
  export const hasTouchscreen = (): boolean => {
4
6
  let hasTouchScreen = false;
@@ -148,6 +150,7 @@ export const stripEmojis = (text: string) => {
148
150
 
149
151
  export const stripMarkdown = (text: string) => {
150
152
  // Remove code blocks
153
+ text = text.replaceAll(/```*?```/g, '');
151
154
  text = text.replaceAll(/```[\s\S]*?```/g, '');
152
155
  // Remove inline code
153
156
  text = text.replaceAll(/`[^`]*`/g, '');
@@ -192,6 +195,12 @@ export const stripOutputTags = (text: string): string => {
192
195
  return stripOutputTags(textBefore + textAfter);
193
196
  };
194
197
 
198
+ export const stripHTML = (text: string) => {
199
+ const el = document.createElement('div');
200
+ el.innerHTML = text;
201
+ return el.textContent || '';
202
+ };
203
+
195
204
  export const escapeHTML = (text: string) => {
196
205
  const el = document.createElement('textarea');
197
206
  el.textContent = text;
@@ -308,3 +317,67 @@ export const installMathJax = () => {
308
317
 
309
318
  installMathJaxScript();
310
319
  };
320
+ /**
321
+ * Corrects materials by setting some specific properties.
322
+ * This is often necessary when working with imported 3D models.
323
+ *
324
+ * @param materials - An object containing materials to be corrected.
325
+ */
326
+ export function correctMaterials(materials: { [key: string]: Material }) {
327
+ Object.values(materials).forEach(material => {
328
+ if (material instanceof MeshStandardMaterial) {
329
+ // Improve the material's appearance
330
+ material.roughness = 0.8;
331
+ material.metalness = 0.1;
332
+
333
+ // Enable shadow casting and receiving
334
+ material.shadowSide = 2; // FrontSide and BackSide
335
+
336
+ // Improve texture rendering if the material uses textures
337
+ if (material.map) {
338
+ material.map.anisotropy = 16;
339
+ }
340
+ }
341
+ });
342
+ }
343
+
344
+ /**
345
+ * Type guard to check if an object is a SkinnedMesh.
346
+ * This is useful when working with 3D models that may contain different types of meshes.
347
+ *
348
+ * @param object - The object to check.
349
+ * @returns True if the object is a SkinnedMesh, false otherwise.
350
+ */
351
+ export function isSkinnedMesh(object: any): object is SkinnedMesh {
352
+ return object.isSkinnedMesh === true;
353
+ }
354
+
355
+ /**
356
+ * Disposes of a Three.js object and its children recursively.
357
+ * This is important for memory management, especially when removing objects from the scene.
358
+ *
359
+ * @param object - The Three.js object to dispose.
360
+ */
361
+ export function disposeObject(object: any) {
362
+ if ('geometry' in object && object.geometry instanceof THREE.BufferGeometry) {
363
+ object.geometry.dispose();
364
+ }
365
+
366
+ if ('material' in object) {
367
+ if (Array.isArray(object.material)) {
368
+ if (Array.isArray(object.material)) {
369
+ object.material.forEach((material: any) => {
370
+ if (material instanceof THREE.Material) {
371
+ material.dispose();
372
+ }
373
+ });
374
+ } else if (object && object.material instanceof THREE.Material) {
375
+ object.material.dispose();
376
+ }
377
+ }
378
+ }
379
+
380
+ if (object.children) {
381
+ object.children.forEach(disposeObject);
382
+ }
383
+ }
@@ -42,7 +42,7 @@ Localhost.args = {
42
42
  ownerUserName: 'nicola',
43
43
  memoriID: '1a9c75e8-57aa-4ce3-8ea5-256185fa79a7',
44
44
  ownerUserID: '04a8cff9-13d6-4367-9cb2-72b9af9ee494',
45
- tenantID: 'app.memorytwin.com',
45
+ tenantID: 'www.aisuru.com',
46
46
  apiURL: 'http://localhost:7778',
47
47
  baseURL: 'http://localhost:3000',
48
48
  uiLang: 'EN',
@@ -58,7 +58,7 @@ LocalhostBoE.args = {
58
58
  ownerUserName: 'nicola',
59
59
  memoriID: '2b094cd6-77b8-4e09-a807-0039b84c988e',
60
60
  ownerUserID: '04a8cff9-13d6-4367-9cb2-72b9af9ee494',
61
- tenantID: 'app.memorytwin.com',
61
+ tenantID: 'www.aisuru.com',
62
62
  apiURL: 'http://localhost:7778',
63
63
  baseURL: 'http://localhost:3000',
64
64
  uiLang: 'EN',
@@ -82,24 +82,50 @@ Staging.args = {
82
82
  layout: 'FULLPAGE',
83
83
  };
84
84
 
85
- export const ProductionTotem = Template.bind({});
86
- ProductionTotem.args = {
87
- memoriName: 'Prova12345',
85
+ export const Giovanna = Template.bind({});
86
+ Giovanna.args = {
87
+ memoriName: 'Giovanna',
88
+ ownerUserName: 'memoridev',
89
+ memoriID: '3b308d07-0ff8-4f18-b885-fad501164c43',
90
+ ownerUserID: '13ab0379-a51d-4a83-8389-4f4b95e15567',
91
+ tenantID: 'www.aisuru.com',
92
+ engineURL: 'https://engine.memori.ai',
93
+ apiURL: 'https://backend.memori.ai',
94
+ baseURL: 'https://www.aisuru.com',
95
+ uiLang: 'IT',
96
+ spokenLang: 'IT',
97
+ layout: 'ZOOMED_FULL_BODY',
98
+ showInstruct: 'false',
99
+ showSettings: 'true',
100
+ showClear: 'false',
101
+ showAIicon: 'true',
102
+ showWhyThisAnswer: 'true',
103
+ showTypingText: 'false',
104
+ showOnlyLastMessages: 'false',
105
+ showTranslationOriginal: 'false',
106
+ showCopyButton: 'false',
107
+ showShare: 'true',
108
+ showLogin: 'false',
109
+ enableAudio: 'true',
110
+ };
111
+
112
+ export const GiovannaProva = Template.bind({});
113
+ GiovannaProva.args = {
114
+ memoriName: 'GiovannaProva',
88
115
  ownerUserName: 'patini929',
89
- memoriID: '514dd043-ec26-4c57-a014-a512c9014822',
116
+ memoriID: 'aee4c0ab-66c0-4a4e-acf5-e7be0a3a8ddf',
90
117
  ownerUserID: '1941d326-6986-4fa1-872b-458d09fb654c',
91
118
  tenantID: 'www.aisuru.com',
92
119
  engineURL: 'https://engine.memori.ai',
93
120
  apiURL: 'https://backend.memori.ai',
94
121
  baseURL: 'https://www.aisuru.com',
95
122
  uiLang: 'IT',
96
- spokenLang: 'FR',
97
- layout: 'FULLPAGE',
98
-
123
+ spokenLang: 'IT',
124
+ layout: 'ZOOMED_FULL_BODY',
99
125
  showInstruct: false,
100
126
  showSettings: true,
101
127
  showClear: false,
102
- showAIicon: 'true',
128
+ showAIicon: true,
103
129
  showWhyThisAnswer: true,
104
130
  showTypingText: false,
105
131
  showOnlyLastMessages: false,
@@ -108,7 +134,6 @@ ProductionTotem.args = {
108
134
  showShare: true,
109
135
  showLogin: false,
110
136
  enableAudio: true,
111
- integrationID: '37d368cf-6241-4cc8-a1f3-742786f22431',
112
137
  };
113
138
 
114
139
  const TemplateWithBatchButton: Story<Props> = args => (
@@ -186,13 +211,11 @@ WithCustomUserAvatar.args = {
186
211
 
187
212
  export const Test = Template.bind({});
188
213
  Test.args = {
189
- ownerUserName: 'memoridev',
190
- memoriName: 'Assistente Report',
191
- tenantID: 'bcc-iccrea.aclambda.online',
192
- apiURL: 'https://backend.memori.ai',
193
- baseURL: 'https://bcc-iccrea.aclambda.online',
214
+ ownerUserName: 'dpezzettone',
215
+ memoriName: 'Meta Prompt Engineer',
216
+ tenantID: 'www.aisuru.com',
194
217
  layout: 'CHAT',
195
- uiLang: 'it',
218
+ uiLang: 'en',
196
219
  showShare: true,
197
220
  showSettings: true,
198
221
  showLogin: true,
package/src/index.tsx CHANGED
@@ -16,7 +16,7 @@ import { installMathJax } from './helpers/utils';
16
16
  import i18n from './i18n';
17
17
  import { useTranslation } from 'react-i18next';
18
18
  import I18nWrapper from './I18nWrapper';
19
-
19
+ import { VisemeProvider } from './context/visemeContext';
20
20
  export interface Props {
21
21
  memoriName?: string | null;
22
22
  memoriID?: string | null;
@@ -223,85 +223,87 @@ const Memori: React.FC<Props> = ({
223
223
  installMathJax();
224
224
  }, []);
225
225
 
226
- const renderer = memori ? (
227
- <MemoriWidget
228
- layout={layout}
229
- customLayout={customLayout}
230
- height={height}
231
- baseUrl={
232
- baseURL ||
233
- (tenantID.startsWith('https://') ? tenantID : `https://${tenantID}`)
234
- }
235
- apiUrl={apiURL}
236
- memori={{
237
- ...memori,
238
- secretToken,
239
- }}
240
- ownerUserName={ownerUserName ?? memori.ownerUserName}
241
- ownerUserID={ownerUserID ?? memori.ownerUserID}
242
- tenantID={tenantID}
243
- memoriLang={spokenLang ?? memori.culture?.split('-')?.[0]}
244
- multilingual={multilingual}
245
- tenant={tenant}
246
- secret={secretToken}
247
- sessionID={sessionID}
248
- showShare={showShare}
249
- showCopyButton={showCopyButton}
250
- showTranslationOriginal={showTranslationOriginal}
251
- showSettings={showSettings}
252
- showInstruct={showInstruct}
253
- showTypingText={showTypingText}
254
- showClear={showClear}
255
- showOnlyLastMessages={showOnlyLastMessages}
256
- showInputs={showInputs}
257
- showDates={showDates}
258
- showContextPerLine={showContextPerLine}
259
- showLogin={showLogin ?? memori?.enableDeepThought}
260
- integration={memori?.integrations?.find(i =>
261
- integrationID
262
- ? i.integrationID === integrationID
263
- : !!i.publish && i.type === 'LANDING_EXPERIENCE'
264
- )}
265
- initialContextVars={context}
266
- initialQuestion={initialQuestion}
267
- authToken={authToken}
268
- AZURE_COGNITIVE_SERVICES_TTS_KEY={
269
- speechKey || AZURE_COGNITIVE_SERVICES_TTS_KEY
270
- }
271
- enableAudio={enableAudio}
272
- defaultSpeakerActive={defaultSpeakerActive}
273
- disableTextEnteredEvents={disableTextEnteredEvents}
274
- onStateChange={onStateChange}
275
- additionalInfo={additionalInfo}
276
- customMediaRenderer={customMediaRenderer}
277
- additionalSettings={additionalSettings}
278
- userAvatar={userAvatar}
279
- {...(tag && pin ? { personification: { tag, pin } } : {})}
280
- />
281
- ) : (
282
- <div
283
- style={{
284
- display: 'flex',
285
- alignItems: 'center',
286
- justifyContent: 'center',
287
- }}
288
- >
289
- <p
290
- style={{
291
- textAlign: 'center',
292
- margin: '2rem auto',
293
- textTransform: 'capitalize',
294
- }}
295
- >
296
- {t('loading') || 'Loading'}...
297
- </p>
298
- </div>
299
- );
300
-
301
226
  return (
302
227
  <I18nWrapper>
303
- <Toaster position="top-center" reverseOrder={true} />
304
- {renderer}
228
+ <VisemeProvider>
229
+ <Toaster position="top-center" reverseOrder={true} />
230
+ {memori ? (
231
+ <MemoriWidget
232
+ layout={layout}
233
+ customLayout={customLayout}
234
+ height={height}
235
+ baseUrl={
236
+ baseURL ||
237
+ (tenantID.startsWith('https://')
238
+ ? tenantID
239
+ : `https://${tenantID}`)
240
+ }
241
+ apiUrl={apiURL}
242
+ memori={{
243
+ ...memori,
244
+ secretToken,
245
+ }}
246
+ ownerUserName={ownerUserName ?? memori.ownerUserName}
247
+ ownerUserID={ownerUserID ?? memori.ownerUserID}
248
+ tenantID={tenantID}
249
+ memoriLang={spokenLang ?? memori.culture?.split('-')?.[0]}
250
+ multilingual={multilingual}
251
+ tenant={tenant}
252
+ secret={secretToken}
253
+ sessionID={sessionID}
254
+ showShare={showShare}
255
+ showCopyButton={showCopyButton}
256
+ showTranslationOriginal={showTranslationOriginal}
257
+ showSettings={showSettings}
258
+ showInstruct={showInstruct}
259
+ showTypingText={showTypingText}
260
+ showClear={showClear}
261
+ showOnlyLastMessages={showOnlyLastMessages}
262
+ showInputs={showInputs}
263
+ showDates={showDates}
264
+ showContextPerLine={showContextPerLine}
265
+ showLogin={showLogin ?? memori?.enableDeepThought}
266
+ integration={memori?.integrations?.find(i =>
267
+ integrationID
268
+ ? i.integrationID === integrationID
269
+ : !!i.publish && i.type === 'LANDING_EXPERIENCE'
270
+ )}
271
+ initialContextVars={context}
272
+ initialQuestion={initialQuestion}
273
+ authToken={authToken}
274
+ AZURE_COGNITIVE_SERVICES_TTS_KEY={
275
+ speechKey || AZURE_COGNITIVE_SERVICES_TTS_KEY
276
+ }
277
+ enableAudio={enableAudio}
278
+ defaultSpeakerActive={defaultSpeakerActive}
279
+ disableTextEnteredEvents={disableTextEnteredEvents}
280
+ onStateChange={onStateChange}
281
+ additionalInfo={additionalInfo}
282
+ customMediaRenderer={customMediaRenderer}
283
+ additionalSettings={additionalSettings}
284
+ userAvatar={userAvatar}
285
+ {...(tag && pin ? { personification: { tag, pin } } : {})}
286
+ />
287
+ ) : (
288
+ <div
289
+ style={{
290
+ display: 'flex',
291
+ alignItems: 'center',
292
+ justifyContent: 'center',
293
+ }}
294
+ >
295
+ <p
296
+ style={{
297
+ textAlign: 'center',
298
+ margin: '2rem auto',
299
+ textTransform: 'capitalize',
300
+ }}
301
+ >
302
+ {t('loading') || 'Loading'}...
303
+ </p>
304
+ </div>
305
+ )}
306
+ </VisemeProvider>
305
307
  </I18nWrapper>
306
308
  );
307
309
  };
@@ -321,6 +323,8 @@ Memori.propTypes = {
321
323
  'TOTEM',
322
324
  'WEBSITE_ASSISTANT',
323
325
  'CHAT',
326
+ 'HIDDEN_CHAT',
327
+ 'ZOOMED_FULL_BODY',
324
328
  ]),
325
329
  customLayout: PropTypes.any,
326
330
  showShare: PropTypes.bool,
package/src/styles.css CHANGED
@@ -48,6 +48,7 @@
48
48
 
49
49
  @import url('https://fonts.bunny.net/css?family=lexend-deca:200,400,700');
50
50
 
51
+ @import url('./components/layouts/hidden-chat.css');
51
52
  @import url('./components/layouts/totem.css');
52
53
  @import url('./components/layouts/website-assistant.css');
53
54
  @import url('./components/layouts/chat.css');
@@ -1,120 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
- import {
3
- Vector3,
4
- Euler,
5
- AnimationMixer,
6
- AnimationAction,
7
- AnimationClip,
8
- } from 'three';
9
- import { useAnimations, useGLTF } from '@react-three/drei';
10
- import { useGraph, dispose, useFrame } from '@react-three/fiber';
11
- import { correctMaterials, isSkinnedMesh } from '../utils/utils';
12
- import useEyeBlink from '../utils/useEyeBlink';
13
- import useMouthSpeaking from '../utils/useMouthSpeaking';
14
- import useHeadMovement from '../utils/useHeadMovement';
15
- import useSmile from '../utils/useSmile';
16
-
17
- export interface FullbodyAvatarProps {
18
- url: string;
19
- sex: 'MALE' | 'FEMALE';
20
- onLoaded?: () => void;
21
- currentBaseAction: {
22
- action: string;
23
- weight: number;
24
- };
25
- additiveActions: {
26
- [key: string]: {
27
- weight: number;
28
- };
29
- };
30
- timeScale: number;
31
- loading?: boolean;
32
- speaking?: boolean;
33
- }
34
-
35
- const AVATAR_POSITION = new Vector3(0, -1, 0);
36
- const AVATAR_ROTATION = new Euler(0.175, 0, 0);
37
- const ANIMATION_URLS = {
38
- MALE: 'https://assets.memori.ai/api/v2/asset/5de7456f-0cd8-4e29-95a7-0cd0045a5325.glb',
39
- FEMALE:
40
- 'https://assets.memori.ai/api/v2/asset/84487a2b-377c-4565-800a-51459d580ec8.glb',
41
- };
42
-
43
- export default function FullbodyAvatar({
44
- url,
45
- sex,
46
- onLoaded,
47
- currentBaseAction,
48
- additiveActions,
49
- timeScale
50
- }: FullbodyAvatarProps) {
51
- const { scene } = useGLTF(url);
52
- const { animations } = useGLTF(ANIMATION_URLS[sex]);
53
- const { nodes, materials } = useGraph(scene);
54
- const { actions } = useAnimations(animations, scene);
55
- const [mixer] = useState(() => new AnimationMixer(scene));
56
-
57
- useEffect(() => {
58
- correctMaterials(materials);
59
- onLoaded?.();
60
-
61
- return () => {
62
- Object.values(materials).forEach(dispose);
63
- Object.values(nodes).filter(isSkinnedMesh).forEach(dispose);
64
- };
65
- }, [materials, nodes, url, onLoaded]);
66
-
67
- useEffect(() => {
68
- if (!actions || !currentBaseAction.action) return;
69
-
70
- const newAction = actions[currentBaseAction.action];
71
-
72
- if (!newAction) {
73
- console.warn(
74
- `Animation "${currentBaseAction.action}" not found in actions.`
75
- );
76
- return;
77
- }
78
-
79
- const fadeOutDuration = 0.8;
80
- const fadeInDuration = 0.8;
81
-
82
- newAction.timeScale = timeScale;
83
- newAction.reset().fadeIn(fadeInDuration).play();
84
-
85
- return () => {
86
- newAction.fadeOut(fadeOutDuration);
87
- };
88
- }, [currentBaseAction, timeScale]);
89
-
90
-
91
-
92
-
93
- // useEffect(() => {
94
- // if (speaking && actions['Talk 1'] && actions['Talk 2']) {
95
- // const talk1 = actions['Talk 1'].getClip();
96
- // const talk2 = actions['Talk 2'].getClip();
97
- // const talk = new AnimationClip(
98
- // 'Talk',
99
- // talk1.duration + talk2.duration,
100
- // );
101
- // mixer.clipAction(talk, scene).play();
102
- // }
103
- // }, [speaking]);
104
-
105
- // Additive actions
106
- useEyeBlink(additiveActions.blink.weight > 0, nodes);
107
- useMouthSpeaking(additiveActions.speak.weight > 0, nodes);
108
- useHeadMovement(additiveActions.headMovement.weight > 0, nodes);
109
- useSmile(additiveActions.smile.weight > 0, nodes);
110
-
111
- useFrame((_, delta) => {
112
- mixer.update(delta * 0.001);
113
- });
114
-
115
- return (
116
- <group position={AVATAR_POSITION} rotation={AVATAR_ROTATION}>
117
- <primitive object={scene} />
118
- </group>
119
- );
120
- }
@@ -1,69 +0,0 @@
1
- import React, { useEffect, useMemo } from 'react';
2
- import { Object3D, Vector3 } from 'three';
3
- import { useGLTF } from '@react-three/drei';
4
- import useEyeBlink from '../utils/useEyeBlink';
5
- import useHeadMovement from '../utils/useHeadMovement';
6
- import useMouthSpeaking from '../utils/useMouthSpeaking';
7
- import { dispose, useGraph } from '@react-three/fiber';
8
- import { correctMaterials, hideHands, isSkinnedMesh } from '../utils/utils';
9
-
10
- interface HalfBodyAvatarProps {
11
- url: string;
12
- eyeBlink?: boolean;
13
- headMovement?: boolean;
14
- speaking?: boolean;
15
- onLoaded?: () => void;
16
- }
17
-
18
- const AVATAR_POSITION = new Vector3(0, -0.6, 0);
19
-
20
- export default function HalfBodyAvatar({
21
- url,
22
- eyeBlink,
23
- headMovement,
24
- speaking,
25
- onLoaded,
26
- }: HalfBodyAvatarProps) {
27
- const { scene } = useGLTF(url);
28
- const { nodes, materials } = useGraph(scene);
29
-
30
- useEyeBlink(eyeBlink, nodes);
31
- useHeadMovement(headMovement, nodes);
32
- useMouthSpeaking(!!speaking, nodes);
33
-
34
- useEffect(() => {
35
- const setupAvatar = () => {
36
- hideHands(nodes);
37
- correctMaterials(materials);
38
- onLoaded?.();
39
- };
40
-
41
- setupAvatar();
42
-
43
- return () => {
44
- const disposeObjects = () => {
45
- Object.values(materials).forEach(dispose);
46
- Object.values(nodes).filter(isSkinnedMesh).forEach(dispose);
47
- };
48
-
49
- disposeObjects();
50
- };
51
- }, [materials, nodes, url, onLoaded]);
52
-
53
- const skinnedMeshes = useMemo(
54
- () => Object.values(nodes).filter(isSkinnedMesh),
55
- [nodes]
56
- );
57
-
58
- return (
59
- <group position={AVATAR_POSITION}>
60
- {nodes.Hips && <primitive key="armature" object={nodes.Hips} />}
61
- {skinnedMeshes.map(
62
- (node: Object3D) =>
63
- node && (
64
- <primitive key={node.name} object={node} receiveShadow castShadow />
65
- )
66
- )}
67
- </group>
68
- );
69
- }
@@ -1,87 +0,0 @@
1
- import { Nodes } from './utils';
2
- import { SkinnedMesh } from 'three';
3
- import { useEffect, useRef, useCallback } from 'react';
4
- import { useFrame } from '@react-three/fiber';
5
-
6
- interface MouthState {
7
- moveTime: number;
8
- mesh: SkinnedMesh | null;
9
- morphIndices: {
10
- open: number;
11
- smile: number;
12
- funner: number;
13
- pucker: number;
14
- };
15
- }
16
-
17
- const MOUTH_MOVE_DURATION = 2;
18
- const MOUTH_MOVE_INTERVAL_MIN = 100;
19
- const MOUTH_MOVE_INTERVAL_MAX = 500;
20
-
21
- export default function useMouthSpeaking(speaking: boolean | undefined, nodes: Nodes) {
22
- const mouthStateRef = useRef<MouthState>({
23
- moveTime: 999,
24
- mesh: null,
25
- morphIndices: { open: 0, smile: 0, funner: 0, pucker: 0 },
26
- });
27
-
28
- const setNextMouthMove = useCallback(() => {
29
- mouthStateRef.current.moveTime = 0;
30
- const nextMoveDelay = Math.random() * (MOUTH_MOVE_INTERVAL_MAX - MOUTH_MOVE_INTERVAL_MIN) + MOUTH_MOVE_INTERVAL_MIN;
31
- setTimeout(setNextMouthMove, nextMoveDelay);
32
- }, []);
33
-
34
- useEffect(() => {
35
- if (!speaking) return;
36
-
37
- const mouthMesh = (nodes.Wolf3D_Head || nodes.Wolf3D_Avatar || nodes.Wolf3D_Avatar001) as SkinnedMesh;
38
- mouthStateRef.current.mesh = mouthMesh;
39
-
40
- if (mouthMesh?.morphTargetDictionary && mouthMesh?.morphTargetInfluences) {
41
- mouthStateRef.current.morphIndices = {
42
- open: mouthMesh.morphTargetDictionary.mouthOpen,
43
- smile: mouthMesh.morphTargetDictionary.mouthSmile,
44
- funner: mouthMesh.morphTargetDictionary.mouthFunner,
45
- pucker: mouthMesh.morphTargetDictionary.mouthPucker,
46
- };
47
- }
48
-
49
- const initialMoveDelay = setTimeout(setNextMouthMove, 200);
50
-
51
- return () => {
52
- clearTimeout(initialMoveDelay);
53
- };
54
- }, [nodes, speaking, setNextMouthMove]);
55
-
56
- useFrame((_, delta) => {
57
- const { moveTime, mesh, morphIndices } = mouthStateRef.current;
58
-
59
- if (!speaking || !mesh?.morphTargetInfluences) {
60
- resetMouthShape(mesh, morphIndices);
61
- return;
62
- }
63
-
64
- if (moveTime < MOUTH_MOVE_DURATION) {
65
- const value = Math.abs(Math.sin((moveTime * Math.PI) / 2));
66
- mouthStateRef.current.moveTime += delta * 10;
67
- updateMouthShape(mesh, morphIndices, value);
68
- } else {
69
- resetMouthShape(mesh, morphIndices);
70
- }
71
- });
72
- }
73
-
74
- function updateMouthShape(mesh: SkinnedMesh, morphIndices: MouthState['morphIndices'], value: number) {
75
- mesh.morphTargetInfluences![morphIndices.open] = value / 3;
76
- mesh.morphTargetInfluences![morphIndices.smile] = value / 10;
77
- mesh.morphTargetInfluences![morphIndices.funner] = value / 7;
78
- mesh.morphTargetInfluences![morphIndices.pucker] = value / 5;
79
- }
80
-
81
- function resetMouthShape(mesh: SkinnedMesh | null, morphIndices: MouthState['morphIndices']) {
82
- if (!mesh?.morphTargetInfluences) return;
83
- mesh.morphTargetInfluences[morphIndices.open] = 0;
84
- mesh.morphTargetInfluences[morphIndices.smile] = 0;
85
- mesh.morphTargetInfluences[morphIndices.funner] = 0;
86
- mesh.morphTargetInfluences[morphIndices.pucker] = 0;
87
- }