@memori.ai/memori-react 9.0.0-alpha.7 → 9.0.0-alpha.9

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 (102) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/components/Chat/Chat.css +48 -7
  3. package/dist/components/Chat/Chat.d.ts +1 -0
  4. package/dist/components/Chat/Chat.js +7 -2
  5. package/dist/components/Chat/Chat.js.map +1 -1
  6. package/dist/components/ChatBubble/ChatBubble.css +16 -14
  7. package/dist/components/ChatInputs/ChatInputs.css +233 -100
  8. package/dist/components/ChatTextArea/ChatTextArea.css +28 -6
  9. package/dist/components/KnownFacts/KnownFacts.js +2 -2
  10. package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
  11. package/dist/components/MemoriWidget/MemoriWidget.css +1 -3
  12. package/dist/components/MemoriWidget/MemoriWidget.js +18 -15
  13. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  14. package/dist/components/MicrophoneButton/MicrophoneButton.css +50 -18
  15. package/dist/components/PoweredBy/PoweredBy.css +10 -2
  16. package/dist/components/UploadButton/UploadImages/UploadImages.js +1 -1
  17. package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  18. package/dist/components/layouts/Chat.js +5 -5
  19. package/dist/components/layouts/Chat.js.map +1 -1
  20. package/dist/components/layouts/HiddenChat.js +10 -236
  21. package/dist/components/layouts/HiddenChat.js.map +1 -1
  22. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js +23 -2
  23. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
  24. package/dist/components/layouts/WebsiteAssistant/website-assistant.css +138 -55
  25. package/dist/components/layouts/ZoomedFullBody.js +2 -2
  26. package/dist/components/layouts/ZoomedFullBody.js.map +1 -1
  27. package/dist/components/layouts/chat.css +42 -29
  28. package/dist/components/layouts/fullpage.css +29 -22
  29. package/dist/components/layouts/hidden-chat.css +147 -33
  30. package/dist/components/layouts/zoomed-full-body.css +33 -32
  31. package/dist/helpers/positionPopover.d.ts +1 -0
  32. package/dist/helpers/positionPopover.js +7 -0
  33. package/dist/helpers/positionPopover.js.map +1 -0
  34. package/dist/styles.css +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/esm/components/Chat/Chat.css +48 -7
  38. package/esm/components/Chat/Chat.d.ts +1 -0
  39. package/esm/components/Chat/Chat.js +7 -2
  40. package/esm/components/Chat/Chat.js.map +1 -1
  41. package/esm/components/ChatBubble/ChatBubble.css +16 -14
  42. package/esm/components/ChatInputs/ChatInputs.css +233 -100
  43. package/esm/components/ChatTextArea/ChatTextArea.css +28 -6
  44. package/esm/components/KnownFacts/KnownFacts.js +2 -2
  45. package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
  46. package/esm/components/MemoriWidget/MemoriWidget.css +1 -3
  47. package/esm/components/MemoriWidget/MemoriWidget.js +18 -15
  48. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  49. package/esm/components/MicrophoneButton/MicrophoneButton.css +50 -18
  50. package/esm/components/PoweredBy/PoweredBy.css +10 -2
  51. package/esm/components/UploadButton/UploadImages/UploadImages.js +1 -1
  52. package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  53. package/esm/components/layouts/Chat.js +5 -5
  54. package/esm/components/layouts/Chat.js.map +1 -1
  55. package/esm/components/layouts/HiddenChat.js +12 -238
  56. package/esm/components/layouts/HiddenChat.js.map +1 -1
  57. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +23 -2
  58. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
  59. package/esm/components/layouts/WebsiteAssistant/website-assistant.css +138 -55
  60. package/esm/components/layouts/ZoomedFullBody.js +2 -2
  61. package/esm/components/layouts/ZoomedFullBody.js.map +1 -1
  62. package/esm/components/layouts/chat.css +42 -29
  63. package/esm/components/layouts/fullpage.css +29 -22
  64. package/esm/components/layouts/hidden-chat.css +147 -33
  65. package/esm/components/layouts/zoomed-full-body.css +33 -32
  66. package/esm/helpers/positionPopover.d.ts +1 -0
  67. package/esm/helpers/positionPopover.js +4 -0
  68. package/esm/helpers/positionPopover.js.map +1 -0
  69. package/esm/styles.css +1 -1
  70. package/esm/version.d.ts +1 -1
  71. package/esm/version.js +1 -1
  72. package/package.json +1 -1
  73. package/src/components/Chat/Chat.css +48 -7
  74. package/src/components/Chat/Chat.tsx +11 -0
  75. package/src/components/ChatBubble/ChatBubble.css +16 -14
  76. package/src/components/ChatInputs/ChatInputs.css +233 -100
  77. package/src/components/ChatTextArea/ChatTextArea.css +28 -6
  78. package/src/components/KnownFacts/KnownFacts.tsx +2 -0
  79. package/src/components/MemoriWidget/MemoriWidget.css +1 -3
  80. package/src/components/MemoriWidget/MemoriWidget.tsx +397 -384
  81. package/src/components/MicrophoneButton/MicrophoneButton.css +50 -18
  82. package/src/components/PoweredBy/PoweredBy.css +10 -2
  83. package/src/components/UploadButton/UploadImages/UploadImages.tsx +1 -1
  84. package/src/components/layouts/Chat.tsx +42 -44
  85. package/src/components/layouts/HiddenChat.tsx +16 -413
  86. package/src/components/layouts/WebsiteAssistant/WebsiteAssistant.tsx +59 -15
  87. package/src/components/layouts/WebsiteAssistant/website-assistant.css +138 -55
  88. package/src/components/layouts/ZoomedFullBody.tsx +3 -1
  89. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +227 -236
  90. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +30 -40
  91. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +165 -66
  92. package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +15 -20
  93. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +153 -158
  94. package/src/components/layouts/chat.css +42 -29
  95. package/src/components/layouts/fullpage.css +29 -22
  96. package/src/components/layouts/hidden-chat.css +147 -33
  97. package/src/components/layouts/layouts.stories.tsx +1 -0
  98. package/src/components/layouts/zoomed-full-body.css +33 -32
  99. package/src/helpers/positionPopover.test.ts +33 -0
  100. package/src/helpers/positionPopover.ts +13 -0
  101. package/src/styles.css +34 -13
  102. package/src/version.ts +1 -1
@@ -1,32 +1,13 @@
1
1
  /* eslint-disable react/prop-types */
2
2
  import React, { useState, useEffect, useRef, useMemo } from 'react';
3
- import { Button, Spin } from '@memori.ai/ui';
3
+ import { Spin } from '@memori.ai/ui';
4
4
  import { LayoutProps } from '../MemoriWidget/MemoriWidget';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { useArtifact } from '../MemoriArtifactSystem/context/ArtifactContext';
7
- import {
8
- EllipsisVertical,
9
- HelpCircle,
10
- LogIn,
11
- LogOut,
12
- MapPin,
13
- MessageCircle,
14
- RefreshCw,
15
- Settings,
16
- Share2,
17
- Trash2,
18
- User,
19
- Users,
20
- Volume2,
21
- VolumeX,
22
- Maximize,
23
- X,
24
- } from 'lucide-react';
7
+ import { HelpCircle, X } from 'lucide-react';
25
8
  import { getResourceUrl } from '../../helpers/media';
26
9
  import ArtifactDrawer from '../MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer';
27
10
  import ChatInputs from '../ChatInputs/ChatInputs';
28
- import ShareButton from '../ShareButton/ShareButton';
29
- import MobileSessionPanel from '../MobileSessionPanel/MobileSessionPanel';
30
11
  import {
31
12
  maxDocumentsPerMessage,
32
13
  maxDocumentContentLength,
@@ -46,12 +27,12 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
46
27
  autoStart,
47
28
  StartPanel,
48
29
  onSidebarToggle,
30
+ poweredBy,
49
31
  }) => {
50
- const { t, i18n } = useTranslation();
32
+ const { t } = useTranslation();
51
33
  const [isOpen, setIsOpen] = useState(false);
52
34
  const [fullScreen, setFullScreen] = useState(false);
53
35
  const [hasTriggeredAutostart, setHasTriggeredAutostart] = useState(false);
54
- const [sessionPanelOpen, setSessionPanelOpen] = useState(false);
55
36
 
56
37
  const { state, closeArtifact } = useArtifact();
57
38
  const useSideArtifactChrome =
@@ -61,18 +42,6 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
61
42
  const memori = headerProps?.memori;
62
43
  const tenant = headerProps?.tenant;
63
44
  const baseUrl = headerProps?.baseUrl;
64
- const hasSustainabilityData = useMemo(
65
- () =>
66
- !!headerProps?.history?.some(
67
- line =>
68
- !!(
69
- line as {
70
- llmUsage?: { energyImpact?: unknown };
71
- }
72
- ).llmUsage?.energyImpact
73
- ),
74
- [headerProps?.history]
75
- );
76
45
  const hiddenChatHeaderProps = useMemo(() => {
77
46
  if (!headerProps) return undefined;
78
47
  return {
@@ -95,260 +64,8 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
95
64
  };
96
65
  }, [headerProps]);
97
66
 
98
- const loggedUser =
99
- headerProps?.loginToken && headerProps?.user ? headerProps.user : undefined;
100
- const sharedUrl = useMemo(() => {
101
- if (!headerProps?.memori || !headerProps?.sessionID) return undefined;
102
- const currentLanguage = i18n.language === 'it' ? 'it' : 'en';
103
- if (headerProps.memori.ownerUserID) {
104
- return `${
105
- headerProps.baseUrl ?? 'https://www.aisuru.com'
106
- }/${currentLanguage}/shared/${headerProps.memori.ownerUserID}/${
107
- headerProps.memori.memoriID
108
- }/${headerProps.sessionID}`;
109
- }
110
- if (headerProps.memori.exposed) {
111
- return `${
112
- headerProps.baseUrl ?? 'https://www.aisuru.com'
113
- }/${currentLanguage}/shared/${headerProps.memori.ownerUserName}/${
114
- headerProps.memori.name
115
- }/${headerProps.sessionID}`;
116
- }
117
- return window.location.href;
118
- }, [headerProps, i18n.language]);
119
- const loggedUserDisplayName = useMemo(() => {
120
- if (!loggedUser) return '';
121
- const enrichedUser = loggedUser as typeof loggedUser & {
122
- name?: string;
123
- surname?: string;
124
- firstName?: string;
125
- lastName?: string;
126
- };
127
- const fullName =
128
- [enrichedUser.name, enrichedUser.surname]
129
- .filter(Boolean)
130
- .join(' ')
131
- .trim() ||
132
- [enrichedUser.firstName, enrichedUser.lastName]
133
- .filter(Boolean)
134
- .join(' ')
135
- .trim();
136
- return fullName || loggedUser.userName || loggedUser.eMail || '';
137
- }, [loggedUser]);
138
- const loggedUserInitial = useMemo(
139
- () => (loggedUserDisplayName || 'U').charAt(0).toUpperCase(),
140
- [loggedUserDisplayName]
141
- );
142
67
  const isSessionStarted = Boolean(sessionId && hasUserActivatedSpeak);
143
68
 
144
- const handleOverflowActionClick = (
145
- action:
146
- | 'reload'
147
- | 'clear'
148
- | 'chatHistory'
149
- | 'fullscreen'
150
- | 'deepThought'
151
- | 'experts'
152
- | 'audio'
153
- | 'settings'
154
- | 'share'
155
- | 'login'
156
- ) => {
157
- if (!headerProps) return;
158
- switch (action) {
159
- case 'reload':
160
- window.location.reload();
161
- break;
162
- case 'clear':
163
- headerProps.clearHistory();
164
- break;
165
- case 'chatHistory':
166
- headerProps.setShowChatHistoryDrawer(true);
167
- break;
168
- case 'fullscreen':
169
- handleFullscreenToggle();
170
- break;
171
- case 'deepThought':
172
- headerProps.setShowKnownFactsDrawer(true);
173
- break;
174
- case 'experts':
175
- headerProps.setShowExpertsDrawer(true);
176
- break;
177
- case 'audio':
178
- headerProps.setSpeakerMuted(!headerProps.speakerMuted);
179
- break;
180
- case 'settings':
181
- headerProps.setShowSettingsDrawer(true);
182
- break;
183
- case 'share': {
184
- const targetUrl = sharedUrl || window.location.href;
185
- if (navigator.share) {
186
- navigator
187
- .share({
188
- title: headerProps.memori?.name,
189
- url: targetUrl,
190
- })
191
- .catch(() => {
192
- // User dismissed share sheet or browser blocked it.
193
- });
194
- break;
195
- }
196
- if (navigator.clipboard?.writeText) {
197
- navigator.clipboard.writeText(targetUrl).catch(() => {
198
- const opened = window.open(targetUrl, '_blank');
199
- if (!opened) window.location.assign(targetUrl);
200
- });
201
- break;
202
- }
203
- {
204
- const opened = window.open(targetUrl, '_blank');
205
- if (!opened) window.location.assign(targetUrl);
206
- }
207
- break;
208
- }
209
- case 'login':
210
- if (loggedUser && headerProps.onLogout) {
211
- headerProps.onLogout();
212
- } else {
213
- headerProps.setShowLoginDrawer(true);
214
- }
215
- break;
216
- default:
217
- break;
218
- }
219
- };
220
-
221
- const handleEnableLocation = () => {
222
- if (!headerProps) return;
223
- if (!navigator.geolocation) {
224
- headerProps.setPositionPopoverOpen(true);
225
- return;
226
- }
227
- navigator.geolocation.getCurrentPosition(
228
- position => {
229
- const latitude = position.coords.latitude;
230
- const longitude = position.coords.longitude;
231
- headerProps.setVenue({
232
- latitude,
233
- longitude,
234
- placeName: `${latitude.toFixed(5)}, ${longitude.toFixed(5)}`,
235
- uncertainty: position.coords.accuracy / 1000,
236
- });
237
- },
238
- () => {
239
- headerProps.setPositionPopoverOpen(true);
240
- },
241
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 0 }
242
- );
243
- };
244
-
245
- const handleDisableLocation = () => {
246
- headerProps?.setVenue({
247
- latitude: 0,
248
- longitude: 0,
249
- placeName: '',
250
- uncertainty: 0,
251
- });
252
- };
253
-
254
- const sessionPanelActions = useMemo(
255
- () => [
256
- {
257
- key: 'fullscreen',
258
- icon: <Maximize size={18} />,
259
- title: t('fullscreenEnter') || 'Full screen',
260
- subtitle: t('widget.expandToImmersive') || 'Expand to immersive view',
261
- onClick: () => {
262
- handleFullscreenToggle();
263
- setSessionPanelOpen(false);
264
- },
265
- },
266
- ...(headerProps?.loginToken
267
- ? [
268
- {
269
- key: 'chatHistory',
270
- icon: <MessageCircle size={18} />,
271
- title: t('write_and_speak.chatHistory') || 'Chat history',
272
- onClick: () => {
273
- handleOverflowActionClick('chatHistory');
274
- setSessionPanelOpen(false);
275
- },
276
- },
277
- ]
278
- : []),
279
- {
280
- key: 'share',
281
- icon: <Share2 size={18} />,
282
- title: t('widget.share') || 'Share chat',
283
- subtitle:
284
- t('widget.mobileSession.copyLinkOrDownload') ||
285
- 'Copy link or download',
286
- view: 'share' as const,
287
- },
288
- {
289
- key: 'location',
290
- icon: <MapPin size={18} />,
291
- title:
292
- t('widget.mobileSession.locationTracking') || 'Location tracking',
293
- subtitle:
294
- headerProps?.position?.placeName ||
295
- t('widget.mobileSession.currentlyOff') ||
296
- 'Currently off',
297
- view: 'location' as const,
298
- trailing: (
299
- <span className="memori-mobile-session-panel--chevron">{'>'}</span>
300
- ),
301
- },
302
- ...(headerProps?.showReload
303
- ? [
304
- {
305
- key: 'reload',
306
- icon: <RefreshCw size={18} />,
307
- title: t('reload') || 'Reload',
308
- onClick: () => handleOverflowActionClick('reload'),
309
- },
310
- ]
311
- : []),
312
- ...(headerProps?.showClear
313
- ? [
314
- {
315
- key: 'clear',
316
- icon: <Trash2 size={18} />,
317
- title: t('clearHistory') || 'Clear chat',
318
- onClick: () => handleOverflowActionClick('clear'),
319
- },
320
- ]
321
- : []),
322
- // ...(headerProps?.memori?.enableBoardOfExperts
323
- // ? [
324
- // {
325
- // key: 'experts',
326
- // icon: <Users size={18} />,
327
- // title:
328
- // t('widget.showExpertsInTheBoard') || 'Experts in this board',
329
- // disabled: !isSessionStarted,
330
- // onClick: () => handleOverflowActionClick('experts'),
331
- // },
332
- // ]
333
- // : []),
334
- // ...(headerProps?.enableAudio
335
- // ? [
336
- // {
337
- // key: 'audio',
338
- // icon: headerProps?.speakerMuted ? (
339
- // <VolumeX size={18} />
340
- // ) : (
341
- // <Volume2 size={18} />
342
- // ),
343
- // title: t('widget.sound') || 'Sound',
344
- // onClick: () => handleOverflowActionClick('audio'),
345
- // },
346
- // ]
347
- // : []),
348
- ],
349
- [t, headerProps, isSessionStarted]
350
- );
351
-
352
69
  const brandAvatarSrc = memori
353
70
  ? memori.avatarURL && memori.avatarURL.length > 0
354
71
  ? getResourceUrl({
@@ -452,11 +169,6 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
452
169
  const restoreFromFullscreen = () => {
453
170
  const sidebarElement = document.querySelector('.memori-sidebar');
454
171
  if (sidebarElement) {
455
- //restore closing button
456
- const closeButton = document.querySelector('.memori-close-label');
457
- if (closeButton) {
458
- (closeButton as HTMLElement).style.display = 'flex';
459
- }
460
172
  // Restore original styles
461
173
  const sidebar = sidebarElement as HTMLElement;
462
174
  sidebar.style.right = originalSidebarStyles.current.right;
@@ -477,12 +189,6 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
477
189
  if (sidebarElement) {
478
190
  const sidebar = sidebarElement as HTMLElement;
479
191
 
480
- //hide closing button
481
- const closeButton = document.querySelector('.memori-close-label');
482
- if (closeButton) {
483
- (closeButton as HTMLElement).style.display = 'none';
484
- }
485
-
486
192
  // Store original styles before modifying
487
193
  originalSidebarStyles.current = {
488
194
  right: sidebar.style.right,
@@ -490,10 +196,11 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
490
196
  backgroundColor: sidebar.style.backgroundColor,
491
197
  };
492
198
 
493
- // Set styles for fullscreen
199
+ // Set styles for fullscreen — keep --memori-secondary-background via CSS, clear inline white
494
200
  sidebar.style.right = '0';
495
201
  sidebar.style.width = '100%';
496
- sidebar.style.backgroundColor = '#FFFFFF';
202
+ sidebar.style.backgroundColor = '';
203
+ sidebar.classList.add('memori-sidebar-fullscreen');
497
204
 
498
205
  // Request fullscreen
499
206
  sidebar.requestFullscreen().catch(err => {
@@ -539,17 +246,6 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
539
246
  fullScreen ? 'memori-sidebar-fullscreen' : ''
540
247
  }`}
541
248
  >
542
- <label
543
- htmlFor="memori-sidebar-toggle"
544
- className="memori-sidebar-toggle-label memori-close-label"
545
- >
546
- <span>
547
- <X
548
- className="memori-icon-close"
549
- aria-label={t('collapse') ?? undefined}
550
- />
551
- </span>
552
- </label>
553
249
  <div className="memori-hidden-chat-layout--controls memori-chat-layout--controls">
554
250
  <div className="memori-chat-layout--header">
555
251
  {Header && headerProps && (
@@ -585,115 +281,21 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
585
281
  {...hiddenChatHeaderProps}
586
282
  buttonVariant="outline"
587
283
  fullScreenHandler={handleFullscreenToggle}
588
- extraActions={
589
- <Button
590
- variant="outline"
591
- className={`memori-hidden-chat-layout--overflow-trigger ${
592
- sessionPanelOpen ? 'memori-button--active' : ''
593
- }`}
594
- aria-label={
595
- t('widget.moreActions') || 'More actions'
596
- }
597
- icon={<EllipsisVertical />}
598
- onClick={() =>
599
- setSessionPanelOpen(currentOpen => !currentOpen)
600
- }
601
- />
602
- }
603
284
  />
604
285
  )}
286
+ <label
287
+ htmlFor="memori-sidebar-toggle"
288
+ className="memori-sidebar-toggle-label memori-close-label memori-hidden-chat-layout--header-close"
289
+ aria-label={t('collapse') || 'Close'}
290
+ title={t('collapse') || 'Close'}
291
+ >
292
+ <X className="memori-icon-close" aria-hidden />
293
+ </label>
605
294
  </div>
606
295
  </div>
607
296
  )}
608
297
  </div>
609
298
  <div className="memori-chat-layout--body">
610
- {headerProps && (
611
- <MobileSessionPanel
612
- open={sessionPanelOpen}
613
- onClose={() => setSessionPanelOpen(false)}
614
- presentation="popover"
615
- title={t('widget.mobileSession.session') || 'Session'}
616
- loginToken={headerProps.loginToken}
617
- user={headerProps.user}
618
- apiClient={headerProps.apiClient}
619
- userName={loggedUserDisplayName || memori?.name || 'User'}
620
- userEmail={loggedUser?.eMail}
621
- userInitial={loggedUserInitial}
622
- avatarURL={loggedUser?.avatarURL}
623
- birthDate={loggedUser?.birthDate}
624
- actions={sessionPanelActions}
625
- knownFactsPageTitle={t('knownFacts.title') || 'Known facts'}
626
- sharePageTitle={t('widget.share') || 'Share'}
627
- locationPageTitle={
628
- t('widget.mobileSession.locationTracking') ||
629
- 'Location tracking'
630
- }
631
- backLabel={t('back') || 'Back'}
632
- locationStatusLabel={
633
- t('widget.mobileSession.locationStatus') || 'Status'
634
- }
635
- locationPlace={headerProps.position?.placeName}
636
- locationUnknownLabel={
637
- t('write_and_speak.unknownPosition') || 'Unknown position'
638
- }
639
- locationEnableLabel={
640
- t('widget.shareLocation') || 'Share location'
641
- }
642
- locationDisableLabel={
643
- t('widget.mobileSession.disableLocationSharing') ||
644
- 'Disable location sharing'
645
- }
646
- knownFactsDescription={
647
- t('knownFacts.description', {
648
- memoriName: memori?.name || '',
649
- }) || ''
650
- }
651
- knownFactsCtaLabel={
652
- t('widget.mobileSession.openKnownFacts') ||
653
- 'Open full known facts'
654
- }
655
- knownFactsCountLabel={
656
- (t('widget.mobileSession.knownFactsMessages', {
657
- count: headerProps.history?.length || 0,
658
- }) as string) || ''
659
- }
660
- shareContent={
661
- <ShareButton
662
- tenant={headerProps?.tenant}
663
- memori={headerProps?.memori}
664
- sessionID={headerProps?.sessionID}
665
- title={headerProps?.memori?.name}
666
- baseUrl={headerProps?.baseUrl}
667
- align="left"
668
- history={headerProps?.history}
669
- renderMode="inline"
670
- />
671
- }
672
- knownFactsDisabled={!isSessionStarted}
673
- showSessionInfo={isSessionStarted}
674
- history={headerProps.history ?? []}
675
- isLoggedIn={!!loggedUser}
676
- loginLabel={t('login.login') || 'Log in'}
677
- onLogin={() => {
678
- headerProps.setShowLoginDrawer(true);
679
- setSessionPanelOpen(false);
680
- }}
681
- onKnownFactsOpen={() => {
682
- if (!isSessionStarted) return;
683
- headerProps.setShowKnownFactsDrawer(true);
684
- setSessionPanelOpen(false);
685
- }}
686
- onLocationEnable={handleEnableLocation}
687
- onLocationDisable={handleDisableLocation}
688
- venue={headerProps.position}
689
- setVenue={headerProps.setVenue}
690
- logoutLabel={t('login.logout') || 'Log out'}
691
- onLogout={() => {
692
- handleOverflowActionClick('login');
693
- setSessionPanelOpen(false);
694
- }}
695
- />
696
- )}
697
299
  {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
698
300
  <Chat {...chatProps} />
699
301
  ) : !autoStart && startPanelProps ? (
@@ -750,6 +352,7 @@ const HiddenChatLayout: React.FC<LayoutProps> = ({
750
352
  )}
751
353
  <div id="extension" />
752
354
  </div>
355
+ {poweredBy}
753
356
  </div>
754
357
  </aside>
755
358
  </div>
@@ -6,6 +6,7 @@ import { X } from 'lucide-react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { useArtifact } from '../../MemoriArtifactSystem/context/ArtifactContext';
8
8
  import ArtifactDrawer from '../../MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer';
9
+ import { getResourceUrl } from '../../../helpers/media';
9
10
 
10
11
  const WebsiteAssistantLayout: React.FC<LayoutProps> = ({
11
12
  Header,
@@ -32,6 +33,28 @@ const WebsiteAssistantLayout: React.FC<LayoutProps> = ({
32
33
 
33
34
  const stopAudio = useMemo(() => chatProps?.stopAudio, [chatProps?.stopAudio]);
34
35
 
36
+ const memori = headerProps?.memori;
37
+ const tenant = headerProps?.tenant;
38
+ const baseUrl = headerProps?.baseUrl;
39
+ const isSessionStarted = Boolean(sessionId && hasUserActivatedSpeak);
40
+
41
+ const brandAvatarSrc = memori
42
+ ? memori.avatarURL && memori.avatarURL.length > 0
43
+ ? getResourceUrl({
44
+ type: 'avatar',
45
+ tenantID: tenant?.name,
46
+ resourceURI: memori.avatarURL,
47
+ baseURL: baseUrl,
48
+ apiURL: '',
49
+ })
50
+ : getResourceUrl({
51
+ type: 'avatar',
52
+ tenantID: tenant?.name,
53
+ baseURL: baseUrl,
54
+ apiURL: '',
55
+ })
56
+ : undefined;
57
+
35
58
  const setCollapsed = (collapsed: boolean) => {
36
59
  _setCollapsed(collapsed);
37
60
  setExpandedKey(collapsed ? undefined : new Date().toISOString());
@@ -76,25 +99,45 @@ const WebsiteAssistantLayout: React.FC<LayoutProps> = ({
76
99
  spinning={loading}
77
100
  className="memori-website_assistant-layout"
78
101
  >
79
- {poweredBy}
80
102
  <div className="memori-website_assistant-layout--header-row">
81
- {Header && headerProps && (
82
- <Header
83
- buttonVariant="outline"
84
- {...headerProps}
85
- showSettings={false}
86
- showReload={false}
87
- />
103
+ {memori && brandAvatarSrc && (
104
+ <div className="memori-chat-layout--brand">
105
+ <img
106
+ className="memori-chat-layout--brand-avatar"
107
+ src={brandAvatarSrc}
108
+ alt=""
109
+ role="presentation"
110
+ />
111
+ <div className="memori-chat-layout--brand-text">
112
+ {isSessionStarted && (
113
+ <span
114
+ className="memori-chat-layout--brand-name"
115
+ title={memori.name}
116
+ >
117
+ {memori.name}
118
+ </span>
119
+ )}
120
+ </div>
121
+ </div>
88
122
  )}
89
- <div className="memori-website_assistant--close-button-wrapper">
90
- <Button
123
+ <div className="memori-website_assistant-layout--header-actions">
124
+ {Header && headerProps && (
125
+ <Header
126
+ buttonVariant="outline"
127
+ {...headerProps}
128
+ showSettings={false}
129
+ showReload={false}
130
+ />
131
+ )}
132
+ <button
133
+ type="button"
91
134
  className="memori-website_assistant--close-button"
92
- variant="ghost"
93
135
  onClick={() => setCollapsed(true)}
94
- aria-label={t('close') || 'Close'}
95
- icon={<X aria-hidden />}
96
- title={t('close') || 'Close'}
97
- />
136
+ aria-label={t('collapse') || 'Close'}
137
+ title={t('collapse') || 'Close'}
138
+ >
139
+ <X className="memori-icon-close" aria-hidden />
140
+ </button>
98
141
  </div>
99
142
  </div>
100
143
 
@@ -136,6 +179,7 @@ const WebsiteAssistantLayout: React.FC<LayoutProps> = ({
136
179
  />
137
180
  ) : null}
138
181
  </div>
182
+ {poweredBy}
139
183
  </Spin>
140
184
  </>
141
185
  )}