@memori.ai/memori-react 2.11.0 → 2.13.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 (62) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +51 -0
  3. package/dist/components/Chat/Chat.css +3 -3
  4. package/dist/components/Chat/Chat.d.ts +4 -3
  5. package/dist/components/Chat/Chat.js +9 -4
  6. package/dist/components/Chat/Chat.js.map +1 -1
  7. package/dist/components/ChatBubble/ChatBubble.css +10 -5
  8. package/dist/components/MediaWidget/MediaItemWidget.d.ts +2 -2
  9. package/dist/components/MediaWidget/MediaItemWidget.js +1 -13
  10. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  11. package/dist/components/MediaWidget/MediaWidget.d.ts +2 -2
  12. package/dist/components/MediaWidget/MediaWidget.js +1 -1
  13. package/dist/components/MediaWidget/MediaWidget.js.map +1 -1
  14. package/dist/components/MemoriWidget/MemoriWidget.d.ts +5 -3
  15. package/dist/components/MemoriWidget/MemoriWidget.js +56 -17
  16. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  17. package/dist/components/Typing/Typing.d.ts +7 -0
  18. package/dist/components/Typing/Typing.js +46 -0
  19. package/dist/components/Typing/Typing.js.map +1 -0
  20. package/dist/components/Typing/Typing.test.d.ts +1 -0
  21. package/dist/components/Typing/Typing.test.js +23 -0
  22. package/dist/components/Typing/Typing.test.js.map +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +3 -3
  25. package/dist/index.js.map +1 -1
  26. package/esm/components/Chat/Chat.css +3 -3
  27. package/esm/components/Chat/Chat.d.ts +4 -3
  28. package/esm/components/Chat/Chat.js +10 -5
  29. package/esm/components/Chat/Chat.js.map +1 -1
  30. package/esm/components/ChatBubble/ChatBubble.css +10 -5
  31. package/esm/components/MediaWidget/MediaItemWidget.d.ts +2 -2
  32. package/esm/components/MediaWidget/MediaItemWidget.js +2 -14
  33. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  34. package/esm/components/MediaWidget/MediaWidget.d.ts +2 -2
  35. package/esm/components/MediaWidget/MediaWidget.js +2 -2
  36. package/esm/components/MediaWidget/MediaWidget.js.map +1 -1
  37. package/esm/components/MemoriWidget/MemoriWidget.d.ts +5 -3
  38. package/esm/components/MemoriWidget/MemoriWidget.js +56 -17
  39. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  40. package/esm/components/Typing/Typing.d.ts +7 -0
  41. package/esm/components/Typing/Typing.js +44 -0
  42. package/esm/components/Typing/Typing.js.map +1 -0
  43. package/esm/components/Typing/Typing.test.d.ts +1 -0
  44. package/esm/components/Typing/Typing.test.js +20 -0
  45. package/esm/components/Typing/Typing.test.js.map +1 -0
  46. package/esm/index.d.ts +1 -0
  47. package/esm/index.js +3 -3
  48. package/esm/index.js.map +1 -1
  49. package/package.json +10 -10
  50. package/src/components/Chat/Chat.css +3 -3
  51. package/src/components/Chat/Chat.tsx +22 -13
  52. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +14 -10
  53. package/src/components/ChatBubble/ChatBubble.css +10 -5
  54. package/src/components/MediaWidget/MediaItemWidget.tsx +2 -17
  55. package/src/components/MediaWidget/MediaWidget.tsx +2 -2
  56. package/src/components/MemoriWidget/MemoriWidget.tsx +76 -16
  57. package/src/components/Typing/Typing.stories.tsx +55 -0
  58. package/src/components/Typing/Typing.test.tsx +24 -0
  59. package/src/components/Typing/Typing.tsx +70 -0
  60. package/src/components/Typing/__snapshots__/Typing.test.tsx.snap +106 -0
  61. package/src/components/layouts/layouts.stories.tsx +1 -1
  62. package/src/index.tsx +4 -1
@@ -3506,17 +3506,21 @@ exports[`renders Chat with memori typing unchanged 1`] = `
3506
3506
  class="memori-chat--bubble"
3507
3507
  >
3508
3508
  <div
3509
- id="wave"
3509
+ class="memori-chat--bubble-typing"
3510
3510
  >
3511
- <span
3512
- class="dot"
3513
- />
3514
- <span
3515
- class="dot"
3516
- />
3517
- <span
3518
- class="dot"
3519
- />
3511
+ <div
3512
+ id="wave"
3513
+ >
3514
+ <span
3515
+ class="dot"
3516
+ />
3517
+ <span
3518
+ class="dot"
3519
+ />
3520
+ <span
3521
+ class="dot"
3522
+ />
3523
+ </div>
3520
3524
  </div>
3521
3525
  </div>
3522
3526
  <div
@@ -35,7 +35,7 @@
35
35
 
36
36
  .memori-chat--bubble #wave {
37
37
  position: relative;
38
- width: 100px;
38
+ width: 50px;
39
39
  margin-right: auto;
40
40
  margin-left: auto;
41
41
  text-align: center;
@@ -43,8 +43,8 @@
43
43
 
44
44
  .memori-chat--bubble #wave .dot {
45
45
  display: inline-block;
46
- width: 8px;
47
- height: 8px;
46
+ width: 6px;
47
+ height: 6px;
48
48
  border-radius: 50%;
49
49
  margin-right: 3px;
50
50
  animation: wave 1.5s linear infinite;
@@ -59,12 +59,16 @@
59
59
  animation-delay: -1.1s;
60
60
  }
61
61
 
62
+ .memori-chat--bubble-typing {
63
+ display: flex;
64
+ }
65
+
62
66
  .memori-chat--bubble p {
63
67
  margin-top: 0;
64
68
  margin-bottom: 0;
65
69
  }
66
70
 
67
- .memori-chat--bubble p + p {
71
+ .memori-chat--bubble p+p {
68
72
  margin-top: 0.5em;
69
73
  }
70
74
 
@@ -215,6 +219,7 @@
215
219
  }
216
220
 
217
221
  @keyframes wave {
222
+
218
223
  0%,
219
224
  60%,
220
225
  100% {
@@ -224,4 +229,4 @@
224
229
  30% {
225
230
  transform: translateY(-10px);
226
231
  }
227
- }
232
+ }
@@ -1,5 +1,5 @@
1
1
  import { Medium } from '@memori.ai/memori-api-client/dist/types';
2
- import React, { useCallback, useEffect, useState } from 'react';
2
+ import React, { useCallback, useEffect, useState, memo } from 'react';
3
3
  import { getResourceUrl } from '../../helpers/media';
4
4
  import { getTranslation } from '../../helpers/translations';
5
5
  import { prismSyntaxLangs } from '../../helpers/constants';
@@ -285,21 +285,6 @@ const MediaItemWidget: React.FC<Props> = ({
285
285
  if (translateTo) translateMediaCaptions();
286
286
  }, [translateTo, translateMediaCaptions]);
287
287
 
288
- useEffect(() => {
289
- let executableScripts = items.filter(
290
- m => m.mimeType === 'text/javascript' && !!m.properties?.executable
291
- );
292
- executableScripts.forEach(s => {
293
- try {
294
- // eslint-disable-next-line no-new-func
295
- new Function(s.content ?? '')();
296
- } catch (e) {
297
- console.error(e);
298
- }
299
- });
300
- // eslint-disable-next-line react-hooks/exhaustive-deps
301
- }, []);
302
-
303
288
  return (
304
289
  <Transition appear show as="div" className="memori-media-items">
305
290
  <div className="memori-media-items--grid">
@@ -407,4 +392,4 @@ const MediaItemWidget: React.FC<Props> = ({
407
392
  );
408
393
  };
409
394
 
410
- export default MediaItemWidget;
395
+ export default memo(MediaItemWidget);
@@ -2,7 +2,7 @@ import {
2
2
  Medium,
3
3
  TranslatedHint,
4
4
  } from '@memori.ai/memori-api-client/dist/types';
5
- import React, { useEffect, useState } from 'react';
5
+ import React, { useEffect, useState, memo } from 'react';
6
6
  import Button from '../ui/Button';
7
7
  import LinkItemWidget from './LinkItemWidget';
8
8
  import MediaItemWidget, { Props as MediaItemProps } from './MediaItemWidget';
@@ -103,4 +103,4 @@ const MediaWidget: React.FC<Props> = ({
103
103
  );
104
104
  };
105
105
 
106
- export default MediaWidget;
106
+ export default memo(MediaWidget);
@@ -98,25 +98,31 @@ type MemoriTextEnteredEvent = CustomEvent<{
98
98
  text: string;
99
99
  waitForPrevious?: boolean;
100
100
  hidden?: boolean;
101
+ typingText?: string;
101
102
  }>;
102
103
 
103
104
  const typeMessage = (
104
105
  message: string,
105
106
  waitForPrevious = true,
106
- hidden = false
107
+ hidden = false,
108
+ typingText?: string
107
109
  ) => {
108
110
  const e: MemoriTextEnteredEvent = new CustomEvent('MemoriTextEntered', {
109
111
  detail: {
110
112
  text: message,
111
113
  waitForPrevious,
112
114
  hidden,
115
+ typingText,
113
116
  },
114
117
  });
115
118
 
116
119
  document.dispatchEvent(e);
117
120
  };
118
- const typeMessageHidden = (message: string, waitForPrevious = true) =>
119
- typeMessage(message, waitForPrevious, true);
121
+ const typeMessageHidden = (
122
+ message: string,
123
+ waitForPrevious = true,
124
+ typingText?: string
125
+ ) => typeMessage(message, waitForPrevious, true, typingText);
120
126
 
121
127
  interface CustomEventMap {
122
128
  MemoriTextEntered: MemoriTextEnteredEvent;
@@ -189,6 +195,7 @@ export interface Props {
189
195
  showDates?: boolean;
190
196
  showContextPerLine?: boolean;
191
197
  showSettings?: boolean;
198
+ showTypingText?: boolean;
192
199
  preview?: boolean;
193
200
  embed?: boolean;
194
201
  height?: number | string;
@@ -229,6 +236,7 @@ const MemoriWidget = ({
229
236
  showDates = false,
230
237
  showContextPerLine = false,
231
238
  showSettings = true,
239
+ showTypingText = false,
232
240
  height = '100vh',
233
241
  secret,
234
242
  baseUrl = 'https://app.twincreator.com',
@@ -293,7 +301,7 @@ const MemoriWidget = ({
293
301
  );
294
302
 
295
303
  const [loading, setLoading] = useState(false);
296
- const [memoriTyping, setMemoriTyping] = useState(false);
304
+ const [memoriTyping, setMemoriTyping] = useState<boolean | string>(false);
297
305
 
298
306
  const selectedLayout = layout || integrationConfig?.layout || 'DEFAULT';
299
307
 
@@ -400,7 +408,17 @@ const MemoriWidget = ({
400
408
  const [listening, setListening] = useState(false);
401
409
  const [history, setHistory] = useState<Message[]>([]);
402
410
  const pushMessage = (message: Message) => {
403
- setHistory(history => [...history, { ...message }]);
411
+ setHistory(history => [
412
+ ...history,
413
+ {
414
+ ...message,
415
+ media:
416
+ message.media?.filter(
417
+ m =>
418
+ !(m.mimeType === 'text/javascript' && !!m.properties?.executable)
419
+ ) ?? [],
420
+ },
421
+ ]);
404
422
  };
405
423
  const sendMessage = async (
406
424
  text: string,
@@ -408,7 +426,8 @@ const MemoriWidget = ({
408
426
  newSessionId?: string,
409
427
  translate: boolean = true,
410
428
  translatedText?: string,
411
- hidden: boolean = false
429
+ hidden: boolean = false,
430
+ typingText?: string
412
431
  ) => {
413
432
  const sessionID =
414
433
  newSessionId ||
@@ -427,7 +446,7 @@ const MemoriWidget = ({
427
446
  : !!newSessionId,
428
447
  });
429
448
 
430
- setMemoriTyping(true);
449
+ setMemoriTyping(typingText ?? true);
431
450
 
432
451
  let msg = text;
433
452
 
@@ -654,6 +673,38 @@ const MemoriWidget = ({
654
673
  if (onStateChange) {
655
674
  onStateChange(state);
656
675
  }
676
+
677
+ const executableSnippets = state?.media?.filter(
678
+ m => m.mimeType === 'text/javascript' && !!m.properties?.executable
679
+ );
680
+ executableSnippets?.forEach(s => {
681
+ try {
682
+ setTimeout(() => {
683
+ console.log('snippet', s);
684
+ // eslint-disable-next-line no-new-func
685
+ new Function(s.content ?? '')();
686
+
687
+ setTimeout(() => {
688
+ if (document.body.classList.contains('chat-focused')) {
689
+ document.querySelector('.ant-tabs-nav')?.scrollIntoView();
690
+ document
691
+ .querySelector('.memori-chat--content')
692
+ ?.scrollTo(
693
+ 0,
694
+ document.querySelector('.memori-chat--content')
695
+ ?.scrollHeight ?? 0
696
+ );
697
+ } else {
698
+ document.querySelector('#end-messages-ref')?.scrollIntoView({
699
+ behavior: 'smooth',
700
+ });
701
+ }
702
+ }, 400);
703
+ }, 3000);
704
+ } catch (e) {
705
+ console.error(e);
706
+ }
707
+ });
657
708
  };
658
709
  const fetchSession = async (
659
710
  params: OpenSession
@@ -705,6 +756,7 @@ const MemoriWidget = ({
705
756
  ...params,
706
757
  additionalInfo: {
707
758
  ...(additionalInfo || {}),
759
+ loginToken: additionalInfo?.loginToken ?? authToken,
708
760
  language: getCultureCodeByLanguage(userLang),
709
761
  referral: referral,
710
762
  },
@@ -792,6 +844,7 @@ const MemoriWidget = ({
792
844
  birthDate: birthDate || storageBirthDate || undefined,
793
845
  additionalInfo: {
794
846
  ...(additionalInfo || {}),
847
+ loginToken: additionalInfo?.loginToken ?? authToken,
795
848
  language: getCultureCodeByLanguage(userLang),
796
849
  referral: referral,
797
850
  },
@@ -912,6 +965,7 @@ const MemoriWidget = ({
912
965
  birthDate: birthDate || storageBirthDate || undefined,
913
966
  additionalInfo: {
914
967
  ...(additionalInfo || {}),
968
+ loginToken: additionalInfo?.loginToken ?? authToken,
915
969
  language: getCultureCodeByLanguage(userLang),
916
970
  referral: referral,
917
971
  },
@@ -987,7 +1041,7 @@ const MemoriWidget = ({
987
1041
  !!speechSynthesizer ||
988
1042
  isPlayingAudio ||
989
1043
  !!userMessage.length ||
990
- memoriTyping ||
1044
+ !!memoriTyping ||
991
1045
  listening
992
1046
  ) {
993
1047
  resetInteractionTimeout();
@@ -1053,7 +1107,7 @@ const MemoriWidget = ({
1053
1107
  timeoutRef.current = uiTimeout;
1054
1108
  };
1055
1109
  useEffect(() => {
1056
- if (!!userMessage.length || isPlayingAudio || memoriTyping)
1110
+ if (!!userMessage.length || isPlayingAudio || !!memoriTyping)
1057
1111
  clearInteractionTimeout();
1058
1112
  if (sessionId && !!!userMessage.length) resetInteractionTimeout();
1059
1113
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1954,17 +2008,14 @@ const MemoriWidget = ({
1954
2008
  // to use in integrations or snippets
1955
2009
  const memoriTextEnteredHandler = useCallback(
1956
2010
  (e: MemoriTextEnteredEvent) => {
1957
- const { text, waitForPrevious, hidden } = e.detail;
1958
-
1959
- const sessionID =
1960
- sessionId || (window.getMemoriState() as MemoriSession)?.sessionID;
2011
+ const { text, waitForPrevious, hidden, typingText } = e.detail;
1961
2012
 
1962
2013
  if (text) {
1963
2014
  // wait to finish reading previous emission
1964
2015
  if (
1965
2016
  waitForPrevious &&
1966
2017
  !speakerMuted &&
1967
- (memoriSpeaking || memoriTyping)
2018
+ (memoriSpeaking || !!memoriTyping)
1968
2019
  ) {
1969
2020
  setTimeout(() => {
1970
2021
  memoriTextEnteredHandler(e);
@@ -1972,7 +2023,15 @@ const MemoriWidget = ({
1972
2023
  } else {
1973
2024
  stopListening();
1974
2025
  stopAudio();
1975
- sendMessage(text, undefined, undefined, undefined, undefined, hidden);
2026
+ sendMessage(
2027
+ text,
2028
+ undefined,
2029
+ undefined,
2030
+ undefined,
2031
+ undefined,
2032
+ hidden,
2033
+ typingText
2034
+ );
1976
2035
  }
1977
2036
  }
1978
2037
  },
@@ -2328,7 +2387,7 @@ const MemoriWidget = ({
2328
2387
  setAvatar3dVisible,
2329
2388
  hasUserActivatedSpeak,
2330
2389
  isPlayingAudio,
2331
- loading: memoriTyping,
2390
+ loading: !!memoriTyping,
2332
2391
  baseUrl,
2333
2392
  apiUrl,
2334
2393
  };
@@ -2369,6 +2428,7 @@ const MemoriWidget = ({
2369
2428
  baseUrl,
2370
2429
  apiUrl,
2371
2430
  memoriTyping,
2431
+ showTypingText,
2372
2432
  history: layout === 'TOTEM' ? history.slice(-2) : history,
2373
2433
  authToken: loginToken,
2374
2434
  dialogState: currentDialogState,
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import { Meta, Story } from '@storybook/react';
3
+ import Typing, { Props } from './Typing';
4
+
5
+ const meta: Meta = {
6
+ title: 'Widget/Typing',
7
+ component: Typing,
8
+ argTypes: {
9
+ useDefaultSentences: {
10
+ control: {
11
+ type: 'boolean',
12
+ },
13
+ },
14
+ lang: {
15
+ control: {
16
+ type: 'select',
17
+ options: ['en', 'it'],
18
+ },
19
+ },
20
+ sentence: {
21
+ control: {
22
+ type: 'text',
23
+ },
24
+ },
25
+ },
26
+ parameters: {
27
+ controls: { expanded: false },
28
+ },
29
+ };
30
+
31
+ export default meta;
32
+
33
+ const Template: Story<Props> = args => <Typing {...args} />;
34
+
35
+ // By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
36
+ // https://storybook.js.org/docs/react/workflows/unit-testing
37
+ export const Default = Template.bind({});
38
+ Default.args = {};
39
+
40
+ export const WithLoadingTextIT = Template.bind({});
41
+ WithLoadingTextIT.args = {
42
+ useDefaultSentences: true,
43
+ lang: 'it',
44
+ };
45
+
46
+ export const WithLoadingTextEN = Template.bind({});
47
+ WithLoadingTextEN.args = {
48
+ useDefaultSentences: true,
49
+ lang: 'en',
50
+ };
51
+
52
+ export const WithCustomLoadingText = Template.bind({});
53
+ WithCustomLoadingText.args = {
54
+ sentence: 'Chiedo agli unicorni cosa ne pensano...',
55
+ };
@@ -0,0 +1,24 @@
1
+ import { render } from '@testing-library/react';
2
+ import Typing from './Typing';
3
+
4
+ it('renders Typing unchanged', () => {
5
+ const { container } = render(<Typing />);
6
+ expect(container).toMatchSnapshot();
7
+ });
8
+
9
+ it('renders Typing with default loading text unchanged', () => {
10
+ const { container } = render(<Typing useDefaultSentences lang="en" />);
11
+ expect(container).toMatchSnapshot();
12
+ });
13
+
14
+ it('renders Typing with default italian loading text unchanged', () => {
15
+ const { container } = render(<Typing useDefaultSentences lang="it" />);
16
+ expect(container).toMatchSnapshot();
17
+ });
18
+
19
+ it('renders Typing with custom loading text unchanged', () => {
20
+ const { container } = render(
21
+ <Typing sentence="Chiedo agli unicorni cosa ne pensano..." />
22
+ );
23
+ expect(container).toMatchSnapshot();
24
+ });
@@ -0,0 +1,70 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ const separator = ' ';
4
+ const sentences = {
5
+ en: [
6
+ 'Generating an accurate and fancy response...',
7
+ 'Generating a response that will blow your mind...',
8
+ 'Generating a response that will make you smile...',
9
+ 'Thinking of a response...',
10
+ 'Thinking of a response that will make you smile...',
11
+ 'Gathering my thoughts...',
12
+ 'Gathering my thoughts to give you a response...',
13
+ ],
14
+ it: [
15
+ 'Sto generando una risposta accurata e fantasiosa...',
16
+ 'Sto generando una risposta che ti farà impazzire...',
17
+ 'Sto generando una risposta che ti farà sorridere...',
18
+ 'Sto pensando ad una risposta...',
19
+ 'Sto pensando ad una risposta che ti farà sorridere...',
20
+ 'Sto raccogliendo i miei pensieri...',
21
+ 'Sto raccogliendo i miei pensieri per darti una risposta...',
22
+ ],
23
+ };
24
+
25
+ export interface Props {
26
+ useDefaultSentences?: boolean;
27
+ lang?: 'en' | 'it';
28
+ sentence?: string;
29
+ }
30
+
31
+ const Typing = ({
32
+ useDefaultSentences = false,
33
+ lang = 'en',
34
+ sentence,
35
+ }: Props) => {
36
+ const [text, setText] = useState(sentence ? `${sentence}${separator}` : '');
37
+ const [shownText, setShownText] = useState('');
38
+
39
+ useEffect(() => {
40
+ const interval = setInterval(() => {
41
+ const letter = text[shownText.length];
42
+ if (letter !== undefined && text.length > 0) {
43
+ setShownText(prev => prev + letter);
44
+ } else if (!sentence && useDefaultSentences) {
45
+ setShownText('');
46
+ setText(
47
+ sentences[lang][Math.floor(Math.random() * sentences[lang].length)] +
48
+ separator
49
+ );
50
+ }
51
+ }, 50);
52
+
53
+ return () => clearInterval(interval);
54
+ });
55
+
56
+ return (
57
+ <div className="memori-chat--bubble">
58
+ <div className="memori-chat--bubble-typing">
59
+ <div id="wave">
60
+ <span className="dot"></span>
61
+ <span className="dot"></span>
62
+ <span className="dot"></span>
63
+ </div>
64
+ {text.length > 0 && <p>{shownText}</p>}
65
+ </div>
66
+ </div>
67
+ );
68
+ };
69
+
70
+ export default Typing;
@@ -0,0 +1,106 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`renders Typing unchanged 1`] = `
4
+ <div>
5
+ <div
6
+ class="memori-chat--bubble"
7
+ >
8
+ <div
9
+ class="memori-chat--bubble-typing"
10
+ >
11
+ <div
12
+ id="wave"
13
+ >
14
+ <span
15
+ class="dot"
16
+ />
17
+ <span
18
+ class="dot"
19
+ />
20
+ <span
21
+ class="dot"
22
+ />
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ `;
28
+
29
+ exports[`renders Typing with custom loading text unchanged 1`] = `
30
+ <div>
31
+ <div
32
+ class="memori-chat--bubble"
33
+ >
34
+ <div
35
+ class="memori-chat--bubble-typing"
36
+ >
37
+ <div
38
+ id="wave"
39
+ >
40
+ <span
41
+ class="dot"
42
+ />
43
+ <span
44
+ class="dot"
45
+ />
46
+ <span
47
+ class="dot"
48
+ />
49
+ </div>
50
+ <p />
51
+ </div>
52
+ </div>
53
+ </div>
54
+ `;
55
+
56
+ exports[`renders Typing with default italian loading text unchanged 1`] = `
57
+ <div>
58
+ <div
59
+ class="memori-chat--bubble"
60
+ >
61
+ <div
62
+ class="memori-chat--bubble-typing"
63
+ >
64
+ <div
65
+ id="wave"
66
+ >
67
+ <span
68
+ class="dot"
69
+ />
70
+ <span
71
+ class="dot"
72
+ />
73
+ <span
74
+ class="dot"
75
+ />
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ `;
81
+
82
+ exports[`renders Typing with default loading text unchanged 1`] = `
83
+ <div>
84
+ <div
85
+ class="memori-chat--bubble"
86
+ >
87
+ <div
88
+ class="memori-chat--bubble-typing"
89
+ >
90
+ <div
91
+ id="wave"
92
+ >
93
+ <span
94
+ class="dot"
95
+ />
96
+ <span
97
+ class="dot"
98
+ />
99
+ <span
100
+ class="dot"
101
+ />
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ `;
@@ -22,7 +22,7 @@ const meta: Meta = {
22
22
 
23
23
  export default meta;
24
24
 
25
- const CustomLayout: React.FC<LayoutProps> = ({
25
+ export const CustomLayout: React.FC<LayoutProps> = ({
26
26
  Header,
27
27
  headerProps,
28
28
  Avatar,
package/src/index.tsx CHANGED
@@ -26,6 +26,7 @@ export interface Props {
26
26
  showShare?: boolean;
27
27
  showSettings?: boolean;
28
28
  showInstruct?: boolean;
29
+ showTypingText?: boolean;
29
30
  height?: number | string;
30
31
  baseURL?: string;
31
32
  apiURL?: string;
@@ -75,6 +76,7 @@ const Memori: React.FC<Props> = ({
75
76
  showShare = true,
76
77
  showSettings = true,
77
78
  showInstruct = false,
79
+ showTypingText = false,
78
80
  height = '100%',
79
81
  baseURL,
80
82
  apiURL = 'https://backend.memori.ai',
@@ -204,6 +206,7 @@ const Memori: React.FC<Props> = ({
204
206
  showShare={showShare}
205
207
  showSettings={showSettings}
206
208
  showInstruct={showInstruct}
209
+ showTypingText={showTypingText}
207
210
  integration={memori?.integrations?.find(i =>
208
211
  integrationID
209
212
  ? i.integrationID === integrationID
@@ -248,7 +251,7 @@ Memori.propTypes = {
248
251
  showShare: PropTypes.bool,
249
252
  showSettings: PropTypes.bool,
250
253
  showInstruct: PropTypes.bool,
251
- layout: PropTypes.oneOf(['DEFAULT', 'FULLPAGE', 'TOTEM']),
254
+ layout: PropTypes.oneOf(['DEFAULT', 'FULLPAGE', 'TOTEM', 'CHAT']),
252
255
  height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
253
256
  baseURL: PropTypes.string,
254
257
  apiURL: PropTypes.string,