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

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 (132) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/components/AgeVerificationModal/AgeVerificationModal.js +3 -1
  3. package/dist/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  4. package/dist/components/Auth/Auth.js +3 -1
  5. package/dist/components/Auth/Auth.js.map +1 -1
  6. package/dist/components/Chat/Chat.js +3 -1
  7. package/dist/components/Chat/Chat.js.map +1 -1
  8. package/dist/components/ChatBubble/ChatBubble.js +3 -1
  9. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  10. package/dist/components/ChatHistoryDrawer/ChatHistory.js +3 -1
  11. package/dist/components/ChatHistoryDrawer/ChatHistory.js.map +1 -1
  12. package/dist/components/ContentPreviewModal/ContentPreviewModal.js +3 -1
  13. package/dist/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -1
  14. package/dist/components/ExpertsDrawer/ExpertsDrawer.js +3 -1
  15. package/dist/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
  16. package/dist/components/KnownFacts/KnownFacts.js +5 -3
  17. package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
  18. package/dist/components/LoginDrawer/LoginDrawer.js +3 -1
  19. package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
  20. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +19 -5
  21. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +4 -1
  22. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  23. package/dist/components/MemoriWidget/MemoriWidget.css +4 -2
  24. package/dist/components/MemoriWidget/MemoriWidget.js +130 -126
  25. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  26. package/dist/components/SettingsDrawer/SettingsDrawer.js +3 -1
  27. package/dist/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
  28. package/dist/components/StartPanel/StartPanel.js +3 -1
  29. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  30. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +3 -1
  31. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  32. package/dist/components/UploadButton/UploadImages/UploadImages.js +3 -1
  33. package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  34. package/dist/components/WhyThisAnswer/WhyThisAnswer.js +3 -1
  35. package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  36. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js +3 -1
  37. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
  38. package/dist/components/layouts/WebsiteAssistant/website-assistant.css +19 -0
  39. package/dist/components/layouts/chat.css +2 -1
  40. package/dist/components/layouts/fullpage.css +31 -8
  41. package/dist/components/layouts/hidden-chat.css +1 -0
  42. package/dist/components/layouts/totem.css +2 -1
  43. package/dist/components/layouts/zoomed-full-body.css +32 -7
  44. package/dist/context/widgetSurfaceContext.d.ts +3 -0
  45. package/dist/context/widgetSurfaceContext.js +11 -0
  46. package/dist/context/widgetSurfaceContext.js.map +1 -0
  47. package/dist/styles.css +1 -1
  48. package/dist/version.d.ts +1 -1
  49. package/dist/version.js +1 -1
  50. package/esm/components/AgeVerificationModal/AgeVerificationModal.js +3 -1
  51. package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  52. package/esm/components/Auth/Auth.js +3 -1
  53. package/esm/components/Auth/Auth.js.map +1 -1
  54. package/esm/components/Chat/Chat.js +3 -1
  55. package/esm/components/Chat/Chat.js.map +1 -1
  56. package/esm/components/ChatBubble/ChatBubble.js +3 -1
  57. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  58. package/esm/components/ChatHistoryDrawer/ChatHistory.js +3 -1
  59. package/esm/components/ChatHistoryDrawer/ChatHistory.js.map +1 -1
  60. package/esm/components/ContentPreviewModal/ContentPreviewModal.js +3 -1
  61. package/esm/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -1
  62. package/esm/components/ExpertsDrawer/ExpertsDrawer.js +3 -1
  63. package/esm/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
  64. package/esm/components/KnownFacts/KnownFacts.js +5 -3
  65. package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
  66. package/esm/components/LoginDrawer/LoginDrawer.js +3 -1
  67. package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
  68. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +19 -5
  69. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +4 -1
  70. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  71. package/esm/components/MemoriWidget/MemoriWidget.css +4 -2
  72. package/esm/components/MemoriWidget/MemoriWidget.js +130 -126
  73. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  74. package/esm/components/SettingsDrawer/SettingsDrawer.js +3 -1
  75. package/esm/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
  76. package/esm/components/StartPanel/StartPanel.js +3 -1
  77. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  78. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +3 -1
  79. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  80. package/esm/components/UploadButton/UploadImages/UploadImages.js +3 -1
  81. package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  82. package/esm/components/WhyThisAnswer/WhyThisAnswer.js +3 -1
  83. package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  84. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +3 -1
  85. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
  86. package/esm/components/layouts/WebsiteAssistant/website-assistant.css +19 -0
  87. package/esm/components/layouts/chat.css +2 -1
  88. package/esm/components/layouts/fullpage.css +31 -8
  89. package/esm/components/layouts/hidden-chat.css +1 -0
  90. package/esm/components/layouts/totem.css +2 -1
  91. package/esm/components/layouts/zoomed-full-body.css +32 -7
  92. package/esm/context/widgetSurfaceContext.d.ts +3 -0
  93. package/esm/context/widgetSurfaceContext.js +7 -0
  94. package/esm/context/widgetSurfaceContext.js.map +1 -0
  95. package/esm/styles.css +1 -1
  96. package/esm/version.d.ts +1 -1
  97. package/esm/version.js +1 -1
  98. package/package.json +1 -1
  99. package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +3 -0
  100. package/src/components/Auth/Auth.tsx +3 -0
  101. package/src/components/Chat/Chat.tsx +3 -0
  102. package/src/components/ChatBubble/ChatBubble.tsx +3 -0
  103. package/src/components/ChatHistoryDrawer/ChatHistory.tsx +3 -0
  104. package/src/components/ContentPreviewModal/ContentPreviewModal.tsx +3 -0
  105. package/src/components/ExpertsDrawer/ExpertsDrawer.tsx +3 -0
  106. package/src/components/KnownFacts/KnownFacts.tsx +5 -0
  107. package/src/components/LoginDrawer/LoginDrawer.tsx +3 -0
  108. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +19 -5
  109. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +4 -0
  110. package/src/components/MemoriWidget/MemoriWidget.css +4 -2
  111. package/src/components/MemoriWidget/MemoriWidget.tsx +33 -18
  112. package/src/components/SettingsDrawer/SettingsDrawer.tsx +3 -0
  113. package/src/components/StartPanel/StartPanel.tsx +3 -0
  114. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +3 -0
  115. package/src/components/UploadButton/UploadImages/UploadImages.tsx +3 -0
  116. package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +3 -0
  117. package/src/components/layouts/WebsiteAssistant/WebsiteAssistant.tsx +4 -0
  118. package/src/components/layouts/WebsiteAssistant/__snapshots__/WebsiteAssistant.test.tsx.snap +48 -44
  119. package/src/components/layouts/WebsiteAssistant/website-assistant.css +19 -0
  120. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +533 -529
  121. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +1058 -1050
  122. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +443 -439
  123. package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +584 -580
  124. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +528 -524
  125. package/src/components/layouts/chat.css +2 -1
  126. package/src/components/layouts/fullpage.css +31 -8
  127. package/src/components/layouts/hidden-chat.css +1 -0
  128. package/src/components/layouts/totem.css +2 -1
  129. package/src/components/layouts/zoomed-full-body.css +32 -7
  130. package/src/context/widgetSurfaceContext.tsx +14 -0
  131. package/src/styles.css +61 -1
  132. package/src/version.ts +1 -1
package/esm/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "9.0.0-alpha.6";
1
+ export declare const version = "9.0.0-alpha.7";
package/esm/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '9.0.0-alpha.6';
1
+ export const version = '9.0.0-alpha.7';
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "9.0.0-alpha.6",
2
+ "version": "9.0.0-alpha.7",
3
3
  "name": "@memori.ai/memori-react",
4
4
  "author": "Memori Srl",
5
5
  "main": "dist/index.js",
@@ -1,4 +1,5 @@
1
1
  import { useTranslation } from 'react-i18next';
2
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
2
3
  import {
3
4
  Button,
4
5
  FieldGroup,
@@ -18,6 +19,7 @@ export interface Props {
18
19
  }
19
20
 
20
21
  const AgeVerificationModal = ({ visible = false, onClose, minAge }: Props) => {
22
+ const surfaceEl = useWidgetSurfaceEl();
21
23
  const { t } = useTranslation();
22
24
  const { add } = useAlertManager();
23
25
  const [birthDate, setBirthDate] = useState<DateTime>();
@@ -72,6 +74,7 @@ const AgeVerificationModal = ({ visible = false, onClose, minAge }: Props) => {
72
74
 
73
75
  return (
74
76
  <Modal
77
+ container={surfaceEl ?? undefined}
75
78
  open={visible}
76
79
  width="600px"
77
80
  widthMd="600px"
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
3
3
  import { Button, Input, Modal, Form } from '@memori.ai/ui';
4
4
  import { useForm, SubmitHandler } from 'react-hook-form';
5
5
  import { Plus } from 'lucide-react';
6
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
6
7
 
7
8
  export interface Props {
8
9
  pwdOrTokens: null | 'password' | 'tokens';
@@ -32,6 +33,7 @@ export const AuthWidget = ({
32
33
  openModal = false,
33
34
  withModal = false,
34
35
  }: Props) => {
36
+ const surfaceEl = useWidgetSurfaceEl();
35
37
  const { t } = useTranslation();
36
38
  const {
37
39
  register,
@@ -198,6 +200,7 @@ export const AuthWidget = ({
198
200
 
199
201
  return withModal ? (
200
202
  <Modal
203
+ container={surfaceEl ?? undefined}
201
204
  open={openModal || showModal}
202
205
  title={t('auth.title') || 'Authentication'}
203
206
  closable={true}
@@ -30,6 +30,7 @@ import { boardOfExpertsLoadingSentences } from '../../helpers/constants';
30
30
  import { FileText as DocumentIcon } from 'lucide-react';
31
31
  import { useTranslation } from 'react-i18next';
32
32
  import { Tooltip, Modal } from '@memori.ai/ui';
33
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
33
34
  import {
34
35
  maxDocumentsPerMessage,
35
36
  maxDocumentContentLength,
@@ -186,6 +187,7 @@ const Chat: React.FC<Props> = ({
186
187
  useState<UsageBadgeModalState | null>(null);
187
188
  const chatWrapperRef = useRef<HTMLDivElement>(null);
188
189
  const { t } = useTranslation();
190
+ const surfaceEl = useWidgetSurfaceEl();
189
191
  const locale = (translateTo || memori.culture || 'it-IT').replace('_', '-');
190
192
 
191
193
  const llmUsageLabels = useMemo<LlmUsageLabels>(
@@ -625,6 +627,7 @@ const Chat: React.FC<Props> = ({
625
627
  )}
626
628
 
627
629
  <Modal
630
+ container={surfaceEl ?? undefined}
628
631
  open={!!activeUsageBadge}
629
632
  onClose={() => setActiveUsageBadge(null)}
630
633
  title={
@@ -36,6 +36,7 @@ import {
36
36
  import { Expandable, Modal } from '@memori.ai/ui';
37
37
  import memoriApiClient from '@memori.ai/memori-api-client';
38
38
  import { usePressTooltip } from '../../helpers/usePressTooltip';
39
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
39
40
  const ASSET_URL_PATTERN = /https?:\/\/\S*\/api\/v\d+\/asset\/\S+/gi;
40
41
 
41
42
  const sanitizeRawCopyText = (text: string) =>
@@ -122,6 +123,7 @@ const ChatBubble: React.FC<Props> = ({
122
123
  customMediaRenderer,
123
124
  }) => {
124
125
  const { t, i18n } = useTranslation();
126
+ const surfaceEl = useWidgetSurfaceEl();
125
127
  const lang = i18n.language || 'en';
126
128
  const generatedByAiTooltip = usePressTooltip();
127
129
  const [showingWhyThisAnswer, setShowingWhyThisAnswer] = useState(false);
@@ -834,6 +836,7 @@ const ChatBubble: React.FC<Props> = ({
834
836
  )}
835
837
 
836
838
  <Modal
839
+ container={surfaceEl ?? undefined}
837
840
  open={openFunctionCache}
838
841
  className="memori-chat--function-cache-modal"
839
842
  title={t('functionCache') || 'Function Cache'}
@@ -21,6 +21,7 @@ import { stripAllInternalTags } from '../../helpers/message';
21
21
  import debounce from 'lodash/debounce';
22
22
  import { Spin } from '@memori.ai/ui';
23
23
  import { SelectBox } from '@memori.ai/ui';
24
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
24
25
  // Helpers / Utils
25
26
  import { getTranslation } from '../../helpers/translations';
26
27
  import ChatResumeDrawer from './ChatResumeDrawer';
@@ -440,6 +441,7 @@ const ChatHistoryDrawer = ({
440
441
  userLang,
441
442
  isMultilanguageEnabled = false,
442
443
  }: Props) => {
444
+ const surfaceEl = useWidgetSurfaceEl();
443
445
  const { t } = useTranslation();
444
446
  const { add } = useAlertManager();
445
447
  const { getUserChatLogsByTokenPaged } = apiClient.chatLogs;
@@ -1136,6 +1138,7 @@ const ChatHistoryDrawer = ({
1136
1138
 
1137
1139
  return (
1138
1140
  <Drawer
1141
+ container={surfaceEl ?? undefined}
1139
1142
  className="memori-chat-history-drawer"
1140
1143
  open={open}
1141
1144
  onClose={onClose}
@@ -1,6 +1,7 @@
1
1
  import React, { FC } from 'react';
2
2
  import { Modal } from '@memori.ai/ui';
3
3
  import cx from 'classnames';
4
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
4
5
 
5
6
  export interface ContentPreviewModalProps {
6
7
  open: boolean;
@@ -25,10 +26,12 @@ const ContentPreviewModal: FC<ContentPreviewModalProps> = ({
25
26
  children,
26
27
  className,
27
28
  }) => {
29
+ const surfaceEl = useWidgetSurfaceEl();
28
30
  const width = 'min(90vw, 800px)';
29
31
 
30
32
  return (
31
33
  <Modal
34
+ container={surfaceEl ?? undefined}
32
35
  open={open}
33
36
  onClose={() => onClose()}
34
37
  width={width}
@@ -3,6 +3,7 @@ import {
3
3
  Tenant,
4
4
  } from '@memori.ai/memori-api-client/dist/types';
5
5
  import { Drawer } from '@memori.ai/ui';
6
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
6
7
  import { useTranslation } from 'react-i18next';
7
8
  import { getResourceUrl } from '../../helpers/media';
8
9
 
@@ -24,9 +25,11 @@ const ExpertsDrawer = ({
24
25
  onClose,
25
26
  }: Props) => {
26
27
  const { t } = useTranslation();
28
+ const surfaceEl = useWidgetSurfaceEl();
27
29
 
28
30
  return (
29
31
  <Drawer
32
+ container={surfaceEl ?? undefined}
30
33
  open={open}
31
34
  onClose={onClose}
32
35
  className="memori--experts-drawer"
@@ -23,6 +23,7 @@ import type {
23
23
  } from '@tanstack/react-table';
24
24
  import { getErrori18nKey } from '../../helpers/error';
25
25
  import { useTranslation } from 'react-i18next';
26
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
26
27
  import { Trash2 } from 'lucide-react';
27
28
 
28
29
  export interface Props {
@@ -45,6 +46,7 @@ const KnownFacts = ({
45
46
  initialKnownFacts = [],
46
47
  closeDrawer,
47
48
  }: Props) => {
49
+ const surfaceEl = useWidgetSurfaceEl();
48
50
  const { t, i18n } = useTranslation();
49
51
  const { add } = useAlertManager();
50
52
  const { getKnownFactsPaginated, deleteKnownFact } = apiClient.knownFacts;
@@ -168,6 +170,7 @@ const KnownFacts = ({
168
170
 
169
171
  return (
170
172
  <Drawer
173
+ container={surfaceEl ?? undefined}
171
174
  open={visible}
172
175
  anchor="right"
173
176
  className="memori-known-facts-drawer"
@@ -180,6 +183,7 @@ const KnownFacts = ({
180
183
  >
181
184
  <div className="memori-known-facts-body">
182
185
  <Modal
186
+ container={surfaceEl ?? undefined}
183
187
  className="memori-known-facts-modal"
184
188
  open={bulkDeleteModalVisible}
185
189
  closable
@@ -316,6 +320,7 @@ const KnownFacts = ({
316
320
  />
317
321
 
318
322
  <Modal
323
+ container={surfaceEl ?? undefined}
319
324
  className="memori-known-facts-modal"
320
325
  open={deleteModalVisibleFor !== undefined}
321
326
  closable
@@ -11,6 +11,7 @@ import {
11
11
  Form,
12
12
  } from '@memori.ai/ui';
13
13
  import { useTranslation } from 'react-i18next';
14
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
14
15
  import cx from 'classnames';
15
16
  import memoriApiClient from '@memori.ai/memori-api-client';
16
17
  import { getErrori18nKey } from '../../helpers/error';
@@ -50,6 +51,7 @@ const LoginDrawer = ({
50
51
  __TEST__signup = false,
51
52
  __TEST__needMissingData = false,
52
53
  }: Props) => {
54
+ const surfaceEl = useWidgetSurfaceEl();
53
55
  const { t, i18n } = useTranslation();
54
56
  const { add } = useAlertManager();
55
57
  const lang = i18n.language === 'it' ? 'it' : 'en';
@@ -436,6 +438,7 @@ const LoginDrawer = ({
436
438
 
437
439
  return (
438
440
  <Drawer
441
+ container={surfaceEl ?? undefined}
439
442
  open={open}
440
443
  onClose={onClose}
441
444
  className={cx('memori--login-drawer', {
@@ -17,16 +17,30 @@
17
17
  --artifact-drawer-radius-lg: var(--memori-radius-box);
18
18
  }
19
19
 
20
- /* Override drawer width for ArtifactDrawer */
21
- .memori-artifact-panel-drawer {
22
- --memori-drawer--width-lg: 46%;
23
- /* background-color: var(--memori-main-background); */
20
+ /*
21
+ * Split-panel width for ArtifactDrawer.
22
+ * Must stay in sync with HiddenChat's sidebar shift (`right: 46%`).
23
+ * @memori.ai/ui Drawer uses `--memori-modal-size-*` (not the legacy
24
+ * `--memori-drawer--width-*` tokens), and size="md" maps to `--memori-modal-size-md`.
25
+ */
26
+ .memori-drawer--right.memori-drawer--size-md.memori-artifact-panel-drawer {
27
+ --memori-modal-size-md: 46%;
28
+ width: 46%;
29
+ max-width: 100vw;
30
+ }
31
+
32
+ .memori-drawer--right.memori-artifact-panel-drawer-fullscreen {
33
+ --memori-modal-size-md: 100%;
34
+ width: 100% !important;
35
+ max-width: 100% !important;
24
36
  }
25
37
 
26
38
  /* Hide the Drawer backdrop so the chat remains fully visible on the left
27
39
  (applies to the mobile/legacy Drawer-overlay path) */
28
40
  body:has(.memori-artifact-panel-drawer) .memori-drawer__backdrop,
29
- body:has(.memori-artifact-panel-drawer-fullscreen) .memori-drawer__backdrop {
41
+ body:has(.memori-artifact-panel-drawer-fullscreen) .memori-drawer__backdrop,
42
+ .memori-widget:has(.memori-artifact-panel-drawer) .memori-drawer__backdrop,
43
+ .memori-widget:has(.memori-artifact-panel-drawer-fullscreen) .memori-drawer__backdrop {
30
44
  display: none !important;
31
45
  }
32
46
 
@@ -7,6 +7,7 @@
7
7
  import React, { useState, useCallback, useMemo, useEffect } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
  import { Button, Dropdown, Drawer } from '@memori.ai/ui';
10
+ import { useWidgetSurfaceEl } from '../../../../context/widgetSurfaceContext';
10
11
  import {
11
12
  X,
12
13
  Maximize,
@@ -31,6 +32,7 @@ const ArtifactDrawer: React.FC<{
31
32
  * component falls back to the Drawer overlay regardless of this flag. */
32
33
  isLayoutColumn?: boolean;
33
34
  }> = ({ isChatLogPanel = false, isLayoutColumn = false }) => {
35
+ const surfaceEl = useWidgetSurfaceEl();
34
36
  const { state, closeArtifact, toggleFullscreen } = useArtifact();
35
37
  const { t } = useTranslation();
36
38
  const [isMobile, setIsMobile] = useState(false);
@@ -144,6 +146,7 @@ const ArtifactDrawer: React.FC<{
144
146
  // Mobile or legacy: floating Drawer overlay
145
147
  return (
146
148
  <Drawer
149
+ container={surfaceEl ?? undefined}
147
150
  open={state.isDrawerOpen}
148
151
  onClose={handleClose}
149
152
  anchor="right"
@@ -167,6 +170,7 @@ const ArtifactDrawer: React.FC<{
167
170
  state.isDrawerOpen,
168
171
  state.isFullscreen,
169
172
  isMobile,
173
+ surfaceEl,
170
174
  ]
171
175
  );
172
176
 
@@ -9,7 +9,8 @@
9
9
  box-sizing: border-box;
10
10
  }
11
11
 
12
- .memori-widget > .memori-spin {
12
+ .memori-widget > .memori-spin,
13
+ .memori-widget > .memori-widget__surface > .memori-spin {
13
14
  height: calc(100vh - 50px);
14
15
  }
15
16
 
@@ -17,7 +18,8 @@
17
18
  .memori-widget {
18
19
  overflow-y: hidden;
19
20
  }
20
- .memori-widget > .memori-spin {
21
+ .memori-widget > .memori-spin,
22
+ .memori-widget > .memori-widget__surface > .memori-spin {
21
23
  height: calc(100vh - 100px);
22
24
  }
23
25
  }
@@ -44,6 +44,7 @@ import {
44
44
  createAlertOptions,
45
45
  MemoriUIProvider,
46
46
  } from '@memori.ai/ui';
47
+ import { WidgetSurfaceProvider } from '../../context/widgetSurfaceContext';
47
48
 
48
49
  // Components
49
50
  import MemoriAuth from '../Auth/Auth';
@@ -633,6 +634,11 @@ const MemoriWidget = ({
633
634
  // UI primitives via `MemoriUIProvider`). `useRef` would not trigger a
634
635
  // re-render and would leave the value `null` on the first pass.
635
636
  const [widgetRootEl, setWidgetRootEl] = useState<HTMLDivElement | null>(null);
637
+ // Inner surface establishes `contain: layout` for Drawers/Modals. Kept separate
638
+ // from widgetRootEl so Floating UI menus can portal outside containment.
639
+ const [widgetSurfaceEl, setWidgetSurfaceEl] = useState<HTMLDivElement | null>(
640
+ null
641
+ );
636
642
  const [isDarkTheme, setIsDarkTheme] = useState(false);
637
643
  useEffect(() => {
638
644
  if (!widgetRootEl) return;
@@ -3679,9 +3685,12 @@ const MemoriWidget = ({
3679
3685
 
3680
3686
  // Resolve the widget theme once so both `data-theme` on the root and the
3681
3687
  // `MemoriUIProvider` (which stamps portaled popups) stay in sync.
3688
+ // Prefer integration config; fall back to host dark mode when unset.
3682
3689
  const widgetTheme: 'light' | 'dark' | undefined =
3683
3690
  integrationConfig?.theme === 'light' || integrationConfig?.theme === 'dark'
3684
3691
  ? integrationConfig.theme
3692
+ : isDarkTheme
3693
+ ? 'dark'
3685
3694
  : undefined;
3686
3695
 
3687
3696
  return (
@@ -3717,24 +3726,28 @@ const MemoriWidget = ({
3717
3726
  style={{ height }}
3718
3727
  >
3719
3728
  <MemoriUIProvider container={widgetRootEl} theme={widgetTheme}>
3720
- <Layout
3721
- Header={Header}
3722
- headerProps={headerProps}
3723
- Avatar={Avatar}
3724
- avatarProps={avatarProps}
3725
- Chat={Chat}
3726
- chatProps={chatProps}
3727
- StartPanel={StartPanel}
3728
- startPanelProps={startPanelProps}
3729
- integrationStyle={integrationStyle}
3730
- integrationBackground={integrationBackground}
3731
- poweredBy={poweredBy}
3732
- autoStart={autoStart}
3733
- sessionId={sessionId}
3734
- hasUserActivatedSpeak={hasUserActivatedSpeak}
3735
- loading={loading}
3736
- avatar3dHidden={avatar3dHidden ?? integrationConfig?.avatar_3d_hidden}
3737
- />
3729
+ <WidgetSurfaceProvider value={widgetSurfaceEl}>
3730
+ <div ref={setWidgetSurfaceEl} className="memori-widget__surface">
3731
+ <Layout
3732
+ Header={Header}
3733
+ headerProps={headerProps}
3734
+ Avatar={Avatar}
3735
+ avatarProps={avatarProps}
3736
+ Chat={Chat}
3737
+ chatProps={chatProps}
3738
+ StartPanel={StartPanel}
3739
+ startPanelProps={startPanelProps}
3740
+ integrationStyle={integrationStyle}
3741
+ integrationBackground={integrationBackground}
3742
+ poweredBy={poweredBy}
3743
+ autoStart={autoStart}
3744
+ sessionId={sessionId}
3745
+ hasUserActivatedSpeak={hasUserActivatedSpeak}
3746
+ loading={loading}
3747
+ avatar3dHidden={
3748
+ avatar3dHidden ?? integrationConfig?.avatar_3d_hidden
3749
+ }
3750
+ />
3738
3751
 
3739
3752
  <ArtifactAPIBridge
3740
3753
  pushMessage={(message: Message) => {
@@ -4023,6 +4036,8 @@ const MemoriWidget = ({
4023
4036
  }}
4024
4037
  />
4025
4038
  )}
4039
+ </div>
4040
+ </WidgetSurfaceProvider>
4026
4041
  </MemoriUIProvider>
4027
4042
  </div>
4028
4043
  );
@@ -1,4 +1,5 @@
1
1
  import { Drawer, Checkbox, Button, Slider, Tooltip } from '@memori.ai/ui';
2
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
2
3
  import { useTranslation } from 'react-i18next';
3
4
  import { setLocalConfig } from '../../helpers/configuration';
4
5
  import { Props as WidgetProps } from '../MemoriWidget/MemoriWidget';
@@ -46,9 +47,11 @@ const SettingsDrawer = ({
46
47
  isAvatar3d,
47
48
  }: Props) => {
48
49
  const { t } = useTranslation();
50
+ const surfaceEl = useWidgetSurfaceEl();
49
51
 
50
52
  return (
51
53
  <Drawer
54
+ container={surfaceEl ?? undefined}
52
55
  className="memori-settings-drawer"
53
56
  open={open}
54
57
  onClose={onClose}
@@ -28,6 +28,7 @@ import CompletionProviderStatus, {
28
28
  } from '../CompletionProviderStatus/CompletionProviderStatus';
29
29
  import { Expandable } from '@memori.ai/ui';
30
30
  import { usePressTooltip } from '../../helpers/usePressTooltip';
31
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
31
32
 
32
33
  /**
33
34
  * Sentinel values used as non-selectable section headers in the language
@@ -97,6 +98,7 @@ const StartPanel: React.FC<Props> = ({
97
98
  showFullDescriptionOnMobile = false,
98
99
  }) => {
99
100
  const { t, i18n } = useTranslation();
101
+ const surfaceEl = useWidgetSurfaceEl();
100
102
  const boardOfExpertsTooltip = usePressTooltip();
101
103
  const nsfwTooltip = usePressTooltip();
102
104
  const deepThoughtTooltip = usePressTooltip();
@@ -683,6 +685,7 @@ const StartPanel: React.FC<Props> = ({
683
685
  )}
684
686
  </div>
685
687
  <Modal
688
+ container={surfaceEl ?? undefined}
686
689
  open={isMobile && mobileInfoModal !== null}
687
690
  onClose={() => setMobileInfoModal(null)}
688
691
  title={
@@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next';
7
7
  import memoriApiClient from '@memori.ai/memori-api-client';
8
8
  import { officeNativeExtensions } from '../../../helpers/constants';
9
9
  import { isOfficeNativeFilename } from '../../../helpers/utils';
10
+ import { useWidgetSurfaceEl } from '../../../context/widgetSurfaceContext';
10
11
  // Types
11
12
  type PreviewFile = {
12
13
  name: string;
@@ -80,6 +81,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
80
81
  onValidatePayloadSize,
81
82
  }) => {
82
83
  const { t } = useTranslation();
84
+ const surfaceEl = useWidgetSurfaceEl();
83
85
  const { backend } = client || {
84
86
  backend: { uploadAsset: null, uploadAssetUnlogged: null },
85
87
  };
@@ -555,6 +557,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
555
557
 
556
558
  {/* Modal */}
557
559
  <Modal
560
+ container={surfaceEl ?? undefined}
558
561
  width="80%"
559
562
  widthMd="80%"
560
563
  open={!!selectedFile}
@@ -8,6 +8,7 @@ import { Asset, Medium } from '@memori.ai/memori-api-client/dist/types';
8
8
  import { useTranslation } from 'react-i18next';
9
9
  import { Button } from '@memori.ai/ui';
10
10
  import { compressImage } from '../../../helpers/imageCompression';
11
+ import { useWidgetSurfaceEl } from '../../../context/widgetSurfaceContext';
11
12
 
12
13
  // Types
13
14
  type PreviewFile = {
@@ -54,6 +55,7 @@ const UploadImages: React.FC<UploadImagesProps> = ({
54
55
  onValidateImageFile,
55
56
  }) => {
56
57
  const { t, i18n } = useTranslation();
58
+ const surfaceEl = useWidgetSurfaceEl();
57
59
  // Client
58
60
  const { backend, dialog } = client || {
59
61
  backend: { uploadAsset: null, uploadAssetUnlogged: null },
@@ -483,6 +485,7 @@ const UploadImages: React.FC<UploadImagesProps> = ({
483
485
 
484
486
  {/* Upload Modal with Title Input */}
485
487
  <Modal
488
+ container={surfaceEl ?? undefined}
486
489
  open={showUploadModal && !!selectedFile}
487
490
  className="memori--modal-preview-file memori--upload-image-preview-modal"
488
491
  onClose={handleCancelUpload}
@@ -13,6 +13,7 @@ import {
13
13
  } from '@memori.ai/ui';
14
14
  import { getErrori18nKey } from '../../helpers/error';
15
15
  import { useTranslation } from 'react-i18next';
16
+ import { useWidgetSurfaceEl } from '../../context/widgetSurfaceContext';
16
17
  import Snippet from '../Snippet/Snippet';
17
18
  import MediaWidget from '../MediaWidget/MediaWidget';
18
19
  import { Card } from '@memori.ai/ui';
@@ -40,6 +41,7 @@ const WhyThisAnswer = ({
40
41
  client,
41
42
  _TEST_loading = false,
42
43
  }: Props) => {
44
+ const surfaceEl = useWidgetSurfaceEl();
43
45
  const { t } = useTranslation();
44
46
  const { add } = useAlertManager();
45
47
  const searchMemory = client?.search.searchMemory;
@@ -97,6 +99,7 @@ const WhyThisAnswer = ({
97
99
 
98
100
  return (
99
101
  <Drawer
102
+ container={surfaceEl ?? undefined}
100
103
  open={visible}
101
104
  anchor="right"
102
105
  className="memori-whythisanswer-drawer"
@@ -62,6 +62,10 @@ const WebsiteAssistantLayout: React.FC<LayoutProps> = ({
62
62
  <div
63
63
  className={`memori-website_assistant--${
64
64
  collapsed ? 'collapsed' : 'expanded'
65
+ }${
66
+ useSideArtifactChrome
67
+ ? ' memori-website_assistant--artifact-open'
68
+ : ''
65
69
  }`}
66
70
  >
67
71
  {!collapsed && (
@@ -12,56 +12,60 @@ exports[`renders WEBSITE_ASSISTANT layout unchanged 1`] = `
12
12
  style="height: 100vh;"
13
13
  >
14
14
  <div
15
- class="memori-website_assistant--trigger"
15
+ class="memori-widget__surface"
16
16
  >
17
- <button
18
- aria-expanded="false"
19
- aria-label="expand"
20
- class="memori-button memori-button--ghost memori-button--md memori-button--circle memori-website_assistant--trigger-button"
21
- tabindex="0"
22
- title="expand"
23
- type="button"
17
+ <div
18
+ class="memori-website_assistant--trigger"
24
19
  >
25
- <span
26
- class="memori-button__content"
20
+ <button
21
+ aria-expanded="false"
22
+ aria-label="expand"
23
+ class="memori-button memori-button--ghost memori-button--md memori-button--circle memori-website_assistant--trigger-button"
24
+ tabindex="0"
25
+ title="expand"
26
+ type="button"
27
27
  >
28
- <div
29
- class="memori-blob"
28
+ <span
29
+ class="memori-button__content"
30
30
  >
31
- <figure>
32
- <img
33
- alt=""
34
- role="presentation"
35
- src="https://aisuru.com/images/aisuru/square_logo.png"
36
- />
37
- </figure>
38
- <div
39
- class="mainDiv"
40
- />
41
- <div
42
- class="mainDiv"
43
- />
44
31
  <div
45
- class="mainDiv"
46
- />
47
- <div
48
- class="mainDiv"
49
- />
50
- <div
51
- class="mainDiv"
52
- />
53
- </div>
54
- </span>
55
- </button>
32
+ class="memori-blob"
33
+ >
34
+ <figure>
35
+ <img
36
+ alt=""
37
+ role="presentation"
38
+ src="https://aisuru.com/images/aisuru/square_logo.png"
39
+ />
40
+ </figure>
41
+ <div
42
+ class="mainDiv"
43
+ />
44
+ <div
45
+ class="mainDiv"
46
+ />
47
+ <div
48
+ class="mainDiv"
49
+ />
50
+ <div
51
+ class="mainDiv"
52
+ />
53
+ <div
54
+ class="mainDiv"
55
+ />
56
+ </div>
57
+ </span>
58
+ </button>
59
+ </div>
60
+ <div
61
+ class="memori-website_assistant--collapsed"
62
+ />
63
+ <audio
64
+ id="memori-audio"
65
+ src="https://aisuru.com/intro.mp3"
66
+ style="display: none;"
67
+ />
56
68
  </div>
57
- <div
58
- class="memori-website_assistant--collapsed"
59
- />
60
- <audio
61
- id="memori-audio"
62
- src="https://aisuru.com/intro.mp3"
63
- style="display: none;"
64
- />
65
69
  </div>
66
70
  <div
67
71
  aria-atomic="false"