@memori.ai/memori-react 8.2.0 → 8.4.0-rc.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 (146) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/components/Chat/Chat.js +8 -1
  3. package/dist/components/Chat/Chat.js.map +1 -1
  4. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.css +160 -0
  5. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.d.ts +4 -0
  6. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +166 -0
  7. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -0
  8. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +877 -0
  9. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.d.ts +3 -0
  10. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +115 -0
  11. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -0
  12. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.css +238 -0
  13. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.d.ts +4 -0
  14. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +104 -0
  15. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -0
  16. package/dist/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.css +319 -0
  17. package/dist/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.d.ts +4 -0
  18. package/dist/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.js +50 -0
  19. package/dist/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.js.map +1 -0
  20. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +343 -0
  21. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.d.ts +4 -0
  22. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +78 -0
  23. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -0
  24. package/dist/components/MemoriArtifactSystem/context/ArtifactSystemContext.d.ts +12 -0
  25. package/dist/components/MemoriArtifactSystem/context/ArtifactSystemContext.js +22 -0
  26. package/dist/components/MemoriArtifactSystem/context/ArtifactSystemContext.js.map +1 -0
  27. package/dist/components/MemoriArtifactSystem/hooks/useArtifactSystem.d.ts +12 -0
  28. package/dist/components/MemoriArtifactSystem/hooks/useArtifactSystem.js +288 -0
  29. package/dist/components/MemoriArtifactSystem/hooks/useArtifactSystem.js.map +1 -0
  30. package/dist/components/MemoriArtifactSystem/index.d.ts +9 -0
  31. package/dist/components/MemoriArtifactSystem/index.js +28 -0
  32. package/dist/components/MemoriArtifactSystem/index.js.map +1 -0
  33. package/dist/components/MemoriArtifactSystem/types/artifact.types.d.ts +108 -0
  34. package/dist/components/MemoriArtifactSystem/types/artifact.types.js +31 -0
  35. package/dist/components/MemoriArtifactSystem/types/artifact.types.js.map +1 -0
  36. package/dist/components/icons/Print.d.ts +6 -0
  37. package/dist/components/icons/Print.js +6 -0
  38. package/dist/components/icons/Print.js.map +1 -0
  39. package/dist/components/layouts/Chat.js +29 -1
  40. package/dist/components/layouts/Chat.js.map +1 -1
  41. package/dist/components/layouts/FullPage.js +33 -1
  42. package/dist/components/layouts/FullPage.js.map +1 -1
  43. package/dist/components/layouts/ZoomedFullBody.js +29 -2
  44. package/dist/components/layouts/ZoomedFullBody.js.map +1 -1
  45. package/dist/components/layouts/chat.css +335 -13
  46. package/dist/components/layouts/zoomed-full-body.css +1 -3
  47. package/dist/helpers/message.js +1 -0
  48. package/dist/helpers/message.js.map +1 -1
  49. package/dist/helpers/stt/useSTT.js +76 -9
  50. package/dist/helpers/stt/useSTT.js.map +1 -1
  51. package/dist/index.js +58 -15
  52. package/dist/index.js.map +1 -1
  53. package/dist/styles.css +5 -0
  54. package/esm/components/Chat/Chat.js +8 -1
  55. package/esm/components/Chat/Chat.js.map +1 -1
  56. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.css +160 -0
  57. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.d.ts +4 -0
  58. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +163 -0
  59. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -0
  60. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +877 -0
  61. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.d.ts +3 -0
  62. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +112 -0
  63. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -0
  64. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.css +238 -0
  65. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.d.ts +4 -0
  66. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +101 -0
  67. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -0
  68. package/esm/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.css +319 -0
  69. package/esm/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.d.ts +4 -0
  70. package/esm/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.js +47 -0
  71. package/esm/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.js.map +1 -0
  72. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +343 -0
  73. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.d.ts +4 -0
  74. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +75 -0
  75. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -0
  76. package/esm/components/MemoriArtifactSystem/context/ArtifactSystemContext.d.ts +12 -0
  77. package/esm/components/MemoriArtifactSystem/context/ArtifactSystemContext.js +17 -0
  78. package/esm/components/MemoriArtifactSystem/context/ArtifactSystemContext.js.map +1 -0
  79. package/esm/components/MemoriArtifactSystem/hooks/useArtifactSystem.d.ts +12 -0
  80. package/esm/components/MemoriArtifactSystem/hooks/useArtifactSystem.js +281 -0
  81. package/esm/components/MemoriArtifactSystem/hooks/useArtifactSystem.js.map +1 -0
  82. package/esm/components/MemoriArtifactSystem/index.d.ts +9 -0
  83. package/esm/components/MemoriArtifactSystem/index.js +9 -0
  84. package/esm/components/MemoriArtifactSystem/index.js.map +1 -0
  85. package/esm/components/MemoriArtifactSystem/types/artifact.types.d.ts +108 -0
  86. package/esm/components/MemoriArtifactSystem/types/artifact.types.js +28 -0
  87. package/esm/components/MemoriArtifactSystem/types/artifact.types.js.map +1 -0
  88. package/esm/components/icons/Print.d.ts +6 -0
  89. package/esm/components/icons/Print.js +4 -0
  90. package/esm/components/icons/Print.js.map +1 -0
  91. package/esm/components/layouts/Chat.js +29 -1
  92. package/esm/components/layouts/Chat.js.map +1 -1
  93. package/esm/components/layouts/FullPage.js +33 -1
  94. package/esm/components/layouts/FullPage.js.map +1 -1
  95. package/esm/components/layouts/ZoomedFullBody.js +30 -3
  96. package/esm/components/layouts/ZoomedFullBody.js.map +1 -1
  97. package/esm/components/layouts/chat.css +335 -13
  98. package/esm/components/layouts/zoomed-full-body.css +1 -3
  99. package/esm/helpers/message.js +1 -0
  100. package/esm/helpers/message.js.map +1 -1
  101. package/esm/helpers/stt/useSTT.js +76 -9
  102. package/esm/helpers/stt/useSTT.js.map +1 -1
  103. package/esm/index.js +58 -15
  104. package/esm/index.js.map +1 -1
  105. package/esm/styles.css +5 -0
  106. package/package.json +1 -1
  107. package/src/components/Avatar/Avatar.test.tsx +13 -0
  108. package/src/components/Chat/Chat.stories.tsx +33 -2
  109. package/src/components/Chat/Chat.test.tsx +340 -213
  110. package/src/components/Chat/Chat.tsx +27 -4
  111. package/src/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.css +160 -0
  112. package/src/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.tsx +278 -0
  113. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +877 -0
  114. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +308 -0
  115. package/src/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.css +238 -0
  116. package/src/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.tsx +282 -0
  117. package/src/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.css +319 -0
  118. package/src/components/MemoriArtifactSystem/components/ArtifactHistory/ArtifactHistory.tsx +178 -0
  119. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +343 -0
  120. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.tsx +190 -0
  121. package/src/components/MemoriArtifactSystem/context/ArtifactSystemContext.tsx +57 -0
  122. package/src/components/MemoriArtifactSystem/hooks/useArtifactSystem.ts +419 -0
  123. package/src/components/MemoriArtifactSystem/index.ts +45 -0
  124. package/src/components/MemoriArtifactSystem/types/artifact.types.ts +180 -0
  125. package/src/components/icons/Print.tsx +34 -0
  126. package/src/components/layouts/Chat.test.tsx +13 -0
  127. package/src/components/layouts/Chat.tsx +80 -25
  128. package/src/components/layouts/FullPage.test.tsx +40 -11
  129. package/src/components/layouts/FullPage.tsx +92 -24
  130. package/src/components/layouts/HiddenChat.test.tsx +13 -0
  131. package/src/components/layouts/Totem.test.tsx +13 -0
  132. package/src/components/layouts/WebsiteAssistant.test.tsx +13 -0
  133. package/src/components/layouts/ZoomedFullBody.test.tsx +13 -0
  134. package/src/components/layouts/ZoomedFullBody.tsx +78 -14
  135. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +252 -248
  136. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +504 -496
  137. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +252 -248
  138. package/src/components/layouts/chat.css +335 -13
  139. package/src/components/layouts/layouts.stories.tsx +13 -2
  140. package/src/components/layouts/zoomed-full-body.css +1 -3
  141. package/src/helpers/message.ts +1 -0
  142. package/src/helpers/stt/useSTT.ts +101 -16
  143. package/src/index.stories.tsx +26 -22
  144. package/src/index.tsx +46 -0
  145. package/src/mocks/data.ts +258 -0
  146. package/src/styles.css +5 -0
@@ -0,0 +1,34 @@
1
+ import * as React from 'react';
2
+ const PrintIcon: React.FC<{ className?: string, title?: string }> = ({ className, title }) => (
3
+ <svg
4
+ {...(!title ? { 'aria-hidden': 'true' } : {})}
5
+ aria-label={title}
6
+ className={className}
7
+ viewBox="0 -2 32 32"
8
+ version="1.1"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ >
11
+ <title>{title}</title>
12
+ <desc>Created with Sketch Beta.</desc>
13
+ <defs></defs>
14
+ <g
15
+ id="Page-1"
16
+ stroke="none"
17
+ stroke-width="1"
18
+ fill="none"
19
+ fill-rule="evenodd"
20
+ >
21
+ <g
22
+ id="Icon-Set"
23
+ transform="translate(-100.000000, -205.000000)"
24
+ fill="#000000"
25
+ >
26
+ <path
27
+ d="M130,226 C130,227.104 129.104,228 128,228 L125.858,228 C125.413,226.278 123.862,225 122,225 L110,225 C108.138,225 106.587,226.278 106.142,228 L104,228 C102.896,228 102,227.104 102,226 L102,224 C102,222.896 102.896,222 104,222 L128,222 C129.104,222 130,222.896 130,224 L130,226 L130,226 Z M122,231 L110,231 C108.896,231 108,230.104 108,229 C108,227.896 108.896,227 110,227 L122,227 C123.104,227 124,227.896 124,229 C124,230.104 123.104,231 122,231 L122,231 Z M108,209 C108,207.896 108.896,207 110,207 L122,207 C123.104,207 124,207.896 124,209 L124,220 L108,220 L108,209 L108,209 Z M128,220 L126,220 L126,209 C126,206.791 124.209,205 122,205 L110,205 C107.791,205 106,206.791 106,209 L106,220 L104,220 C101.791,220 100,221.791 100,224 L100,226 C100,228.209 101.791,230 104,230 L106.142,230 C106.587,231.723 108.138,233 110,233 L122,233 C123.862,233 125.413,231.723 125.858,230 L128,230 C130.209,230 132,228.209 132,226 L132,224 C132,221.791 130.209,220 128,220 L128,220 Z"
28
+ id="print"
29
+ ></path>
30
+ </g>
31
+ </g>
32
+ </svg>
33
+ );
34
+ export default PrintIcon;
@@ -3,6 +3,7 @@ import Memori from '../MemoriWidget/MemoriWidget';
3
3
  import { integration, memori, tenant } from '../../mocks/data';
4
4
  import I18nWrapper from '../../I18nWrapper';
5
5
  import { VisemeProvider } from '../../context/visemeContext';
6
+ import { ArtifactSystemProvider } from '../MemoriArtifactSystem';
6
7
  Object.defineProperty(window, 'matchMedia', {
7
8
  writable: true,
8
9
  value: jest.fn().mockImplementation(query => ({
@@ -20,6 +21,17 @@ Object.defineProperty(window, 'matchMedia', {
20
21
  it('renders Chat layout unchanged', () => {
21
22
  const { container } = render(
22
23
  <I18nWrapper>
24
+ <ArtifactSystemProvider config={{
25
+ supportedMimeTypes: {
26
+ html: {
27
+ name: 'HTML',
28
+ icon: '🌐',
29
+ hasPreview: true,
30
+ language: 'html',
31
+ mimeType: 'text/html',
32
+ },
33
+ },
34
+ }}>
23
35
  <VisemeProvider>
24
36
  <Memori
25
37
  showShare={true}
@@ -31,6 +43,7 @@ it('renders Chat layout unchanged', () => {
31
43
  layout="CHAT"
32
44
  />
33
45
  </VisemeProvider>
46
+ </ArtifactSystemProvider>
34
47
  </I18nWrapper>
35
48
  );
36
49
  expect(container).toMatchSnapshot();
@@ -1,6 +1,8 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import Spin from '../ui/Spin';
3
3
  import { LayoutProps } from '../MemoriWidget/MemoriWidget';
4
+ import { ArtifactDrawer } from '../MemoriArtifactSystem';
5
+ import { useArtifactSystemContext } from '../MemoriArtifactSystem/context/ArtifactSystemContext';
4
6
 
5
7
  const ChatLayout: React.FC<LayoutProps> = ({
6
8
  Header,
@@ -15,29 +17,82 @@ const ChatLayout: React.FC<LayoutProps> = ({
15
17
  hasUserActivatedSpeak,
16
18
  loading = false,
17
19
  poweredBy,
18
- }) => (
19
- <>
20
- {integrationStyle}
21
- {integrationBackground}
22
-
23
- <Spin spinning={loading} className="memori-chat-layout">
24
- {poweredBy}
25
-
26
- <div className="memori-chat-layout--header">
27
- {Header && headerProps && <Header {...headerProps} />}
28
- </div>
29
-
30
- <div id="extension" />
31
-
32
- <div className="memori-chat-layout--controls">
33
- {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
34
- <Chat {...chatProps} />
35
- ) : startPanelProps ? (
36
- <StartPanel {...startPanelProps} />
37
- ) : null}
38
- </div>
39
- </Spin>
40
- </>
41
- );
20
+ }) => {
21
+ const { actions, state } = useArtifactSystemContext();
22
+ const [isMobile, setIsMobile] = useState(false);
23
+
24
+ useEffect(() => {
25
+ const handleResize = () => {
26
+ const newIsMobile = window.innerWidth < 769;
27
+ if (newIsMobile !== isMobile) {
28
+ setTimeout(() => {
29
+ setIsMobile(newIsMobile);
30
+ }, 300);
31
+ } else {
32
+ setIsMobile(newIsMobile);
33
+ }
34
+ };
35
+
36
+ handleResize();
37
+ window.addEventListener('resize', handleResize);
38
+ return () => window.removeEventListener('resize', handleResize);
39
+ }, [isMobile]);
40
+
41
+ const hasArtifact = state.currentArtifact && !isMobile;
42
+
43
+ return (
44
+ <>
45
+ {integrationStyle}
46
+ {integrationBackground}
47
+
48
+ <Spin spinning={loading} className="memori-chat-layout">
49
+ {poweredBy}
50
+
51
+ <div className="memori-chat-layout--header">
52
+ {Header && headerProps && <Header {...headerProps} />}
53
+ </div>
54
+
55
+ <div id="extension" />
56
+
57
+ <div
58
+ className={`memori-chat-layout--main ${
59
+ hasArtifact ? 'memori-chat-layout--main-with-artifact' : ''
60
+ }`}
61
+ >
62
+ <div
63
+ className={
64
+ state.isFullscreen
65
+ ? `memori-chat-layout-controls-hide`
66
+ : `memori-chat-layout--controls ${
67
+ hasArtifact
68
+ ? 'memori-chat-layout--controls-with-artifact'
69
+ : ''
70
+ }`
71
+ }
72
+ >
73
+ {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
74
+ <Chat {...chatProps} />
75
+ ) : startPanelProps ? (
76
+ <StartPanel {...startPanelProps} />
77
+ ) : null}
78
+ </div>
79
+
80
+ {hasArtifact && (
81
+ <div className={state.isFullscreen ? `memori-chat-layout-artifact-panel-full-screen` : `memori-chat-layout--artifact-panel memori-chat-layout--artifact-panel-enter`}>
82
+ <ArtifactDrawer />
83
+ </div>
84
+ )}
85
+ </div>
86
+
87
+ {/* Mobile drawer - always rendered but only shown on mobile */}
88
+ {state.currentArtifact && isMobile && (
89
+ <div className="memori-chat-layout--artifact-drawer">
90
+ <ArtifactDrawer />
91
+ </div>
92
+ )}
93
+ </Spin>
94
+ </>
95
+ );
96
+ };
42
97
 
43
98
  export default ChatLayout;
@@ -3,6 +3,7 @@ import Memori from '../MemoriWidget/MemoriWidget';
3
3
  import { integration, memori, tenant } from '../../mocks/data';
4
4
  import I18nWrapper from '../../I18nWrapper';
5
5
  import { VisemeProvider } from '../../context/visemeContext';
6
+ import { ArtifactSystemProvider } from '../MemoriArtifactSystem';
6
7
 
7
8
  Object.defineProperty(window, 'matchMedia', {
8
9
  writable: true,
@@ -21,17 +22,31 @@ Object.defineProperty(window, 'matchMedia', {
21
22
  it('renders FullPage layout unchanged', () => {
22
23
  const { container } = render(
23
24
  <I18nWrapper>
24
- <VisemeProvider>
25
- <Memori
26
- showShare={true}
27
- showSettings={true}
28
- memori={memori}
29
- tenant={tenant}
30
- tenantID="aisuru.com"
31
- integration={integration}
32
- layout="FULLPAGE"
33
- />
34
- </VisemeProvider>
25
+ <ArtifactSystemProvider
26
+ config={{
27
+ supportedMimeTypes: {
28
+ html: {
29
+ name: 'HTML',
30
+ icon: '🌐',
31
+ hasPreview: true,
32
+ language: 'html',
33
+ mimeType: 'text/html',
34
+ },
35
+ },
36
+ }}
37
+ >
38
+ <VisemeProvider>
39
+ <Memori
40
+ showShare={true}
41
+ showSettings={true}
42
+ memori={memori}
43
+ tenant={tenant}
44
+ tenantID="aisuru.com"
45
+ integration={integration}
46
+ layout="FULLPAGE"
47
+ />
48
+ </VisemeProvider>
49
+ </ArtifactSystemProvider>
35
50
  </I18nWrapper>
36
51
  );
37
52
  expect(container).toMatchSnapshot();
@@ -40,6 +55,19 @@ it('renders FullPage layout unchanged', () => {
40
55
  it('renders FullPage layout with root css properties unchanged', () => {
41
56
  const { container } = render(
42
57
  <I18nWrapper>
58
+ <ArtifactSystemProvider
59
+ config={{
60
+ supportedMimeTypes: {
61
+ html: {
62
+ name: 'HTML',
63
+ icon: '🌐',
64
+ hasPreview: true,
65
+ language: 'html',
66
+ mimeType: 'text/html',
67
+ },
68
+ },
69
+ }}
70
+ >
43
71
  <VisemeProvider>
44
72
  <Memori
45
73
  showShare={true}
@@ -52,6 +80,7 @@ it('renders FullPage layout with root css properties unchanged', () => {
52
80
  applyVarsToRoot
53
81
  />
54
82
  </VisemeProvider>
83
+ </ArtifactSystemProvider>
55
84
  </I18nWrapper>
56
85
  );
57
86
  expect(container).toMatchSnapshot();
@@ -1,6 +1,10 @@
1
- import React from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import Spin from '../ui/Spin';
3
3
  import { LayoutProps } from '../MemoriWidget/MemoriWidget';
4
+ import {
5
+ ArtifactDrawer,
6
+ useArtifactSystemContext,
7
+ } from '../MemoriArtifactSystem';
4
8
 
5
9
  const FullPageLayout: React.FC<LayoutProps> = ({
6
10
  Header,
@@ -17,32 +21,96 @@ const FullPageLayout: React.FC<LayoutProps> = ({
17
21
  hasUserActivatedSpeak,
18
22
  loading = false,
19
23
  poweredBy,
20
- }) => (
21
- <>
22
- {integrationStyle}
23
- {integrationBackground}
24
+ }) => {
25
+ const { state } = useArtifactSystemContext();
26
+ const [isMobile, setIsMobile] = useState(false);
27
+ const [isAnimating, setIsAnimating] = useState(false);
24
28
 
25
- <Spin spinning={loading}>
26
- {Header && headerProps && <Header {...headerProps} />}
29
+ useEffect(() => {
30
+ const handleResize = () => {
31
+ const newIsMobile = window.innerWidth < 769;
32
+ if (newIsMobile !== isMobile) {
33
+ setIsAnimating(true);
34
+ setTimeout(() => {
35
+ setIsMobile(newIsMobile);
36
+ setIsAnimating(false);
37
+ }, 300);
38
+ } else {
39
+ setIsMobile(newIsMobile);
40
+ }
41
+ };
27
42
 
28
- <div className="memori--grid">
29
- <div className="memori--grid-column memori--grid-column-left">
30
- {Avatar && avatarProps && <Avatar chatProps={chatProps} {...avatarProps} />}
43
+ handleResize();
44
+ window.addEventListener('resize', handleResize);
45
+ return () => window.removeEventListener('resize', handleResize);
46
+ }, [isMobile]);
31
47
 
32
- <div id="extension" />
33
- </div>
34
- <div className="memori--grid-column memori--grid-column-right">
35
- {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
36
- <Chat {...chatProps} />
37
- ) : startPanelProps ? (
38
- <StartPanel {...startPanelProps} />
39
- ) : null}
40
- </div>
48
+ const hasArtifact = state.currentArtifact && !isMobile;
49
+ return (
50
+ <>
51
+ {integrationStyle}
52
+ {integrationBackground}
53
+
54
+ <Spin spinning={loading}>
55
+ {Header && headerProps && <Header {...headerProps} />}
56
+
57
+ <div className="memori--grid">
58
+ {!hasArtifact && (
59
+ <div className="memori--grid-column memori--grid-column-left">
60
+ {Avatar && avatarProps && !hasArtifact && (
61
+ <Avatar chatProps={chatProps} {...avatarProps} />
62
+ )}
41
63
 
42
- {poweredBy}
43
- </div>
44
- </Spin>
45
- </>
46
- );
64
+ <div id="extension" />
65
+ </div>
66
+ )}
67
+ <div
68
+ className={`memori-chat-layout--main ${
69
+ hasArtifact ? 'memori-chat-layout--main-with-artifact' : ''
70
+ }`}
71
+ >
72
+ <div
73
+ className={
74
+ state.isFullscreen
75
+ ? `memori-chat-layout-controls-hide`
76
+ : `memori-chat-layout--controls ${
77
+ hasArtifact
78
+ ? 'memori-chat-layout--controls-with-artifact'
79
+ : ''
80
+ }`
81
+ }
82
+ >
83
+ {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
84
+ <Chat {...chatProps} />
85
+ ) : startPanelProps ? (
86
+ <StartPanel {...startPanelProps} />
87
+ ) : null}
88
+ </div>
89
+
90
+ {hasArtifact && (
91
+ <div
92
+ className={
93
+ state.isFullscreen
94
+ ? `memori-chat-layout-artifact-panel-full-screen`
95
+ : `memori-chat-layout--artifact-panel memori-chat-layout--artifact-panel-enter`
96
+ }
97
+ >
98
+ <ArtifactDrawer />
99
+ </div>
100
+ )}
101
+ </div>
102
+ {/* Mobile drawer - always rendered but only shown on mobile */}
103
+ {state.currentArtifact && isMobile && (
104
+ <div className="memori-chat-layout--artifact-drawer">
105
+ <ArtifactDrawer />
106
+ </div>
107
+ )}
108
+
109
+ {poweredBy}
110
+ </div>
111
+ </Spin>
112
+ </>
113
+ );
114
+ };
47
115
 
48
116
  export default FullPageLayout;
@@ -3,6 +3,7 @@ import Memori from '../MemoriWidget/MemoriWidget';
3
3
  import { integration, memori, tenant } from '../../mocks/data';
4
4
  import I18nWrapper from '../../I18nWrapper';
5
5
  import { VisemeProvider } from '../../context/visemeContext';
6
+ import { ArtifactSystemProvider } from '../MemoriArtifactSystem';
6
7
  Object.defineProperty(window, 'matchMedia', {
7
8
  writable: true,
8
9
  value: jest.fn().mockImplementation(query => ({
@@ -20,6 +21,17 @@ Object.defineProperty(window, 'matchMedia', {
20
21
  it('renders HIDDEN_CHAT layout unchanged', () => {
21
22
  const { container } = render(
22
23
  <I18nWrapper>
24
+ <ArtifactSystemProvider config={{
25
+ supportedMimeTypes: {
26
+ html: {
27
+ name: 'HTML',
28
+ icon: '🌐',
29
+ hasPreview: true,
30
+ language: 'html',
31
+ mimeType: 'text/html',
32
+ },
33
+ },
34
+ }}>
23
35
  <VisemeProvider>
24
36
  <Memori
25
37
  showShare={true}
@@ -31,6 +43,7 @@ it('renders HIDDEN_CHAT layout unchanged', () => {
31
43
  layout="HIDDEN_CHAT"
32
44
  />
33
45
  </VisemeProvider>
46
+ </ArtifactSystemProvider>
34
47
  </I18nWrapper>
35
48
  );
36
49
  expect(container).toMatchSnapshot();
@@ -3,6 +3,7 @@ import Memori from '../MemoriWidget/MemoriWidget';
3
3
  import { integration, memori, tenant } from '../../mocks/data';
4
4
  import I18nWrapper from '../../I18nWrapper';
5
5
  import { VisemeProvider } from '../../context/visemeContext';
6
+ import { ArtifactSystemProvider } from '../MemoriArtifactSystem';
6
7
  Object.defineProperty(window, 'matchMedia', {
7
8
  writable: true,
8
9
  value: jest.fn().mockImplementation(query => ({
@@ -20,6 +21,17 @@ Object.defineProperty(window, 'matchMedia', {
20
21
  it('renders Totem layout unchanged', () => {
21
22
  const { container } = render(
22
23
  <I18nWrapper>
24
+ <ArtifactSystemProvider config={{
25
+ supportedMimeTypes: {
26
+ html: {
27
+ name: 'HTML',
28
+ icon: '🌐',
29
+ hasPreview: true,
30
+ language: 'html',
31
+ mimeType: 'text/html',
32
+ },
33
+ },
34
+ }}>
23
35
  <VisemeProvider>
24
36
  <Memori
25
37
  showShare={true}
@@ -31,6 +43,7 @@ it('renders Totem layout unchanged', () => {
31
43
  layout="TOTEM"
32
44
  />
33
45
  </VisemeProvider>
46
+ </ArtifactSystemProvider>
34
47
  </I18nWrapper>
35
48
  );
36
49
  expect(container).toMatchSnapshot();
@@ -3,6 +3,7 @@ import Memori from '../MemoriWidget/MemoriWidget';
3
3
  import { integration, memori, tenant } from '../../mocks/data';
4
4
  import I18nWrapper from '../../I18nWrapper';
5
5
  import { VisemeProvider } from '../../context/visemeContext';
6
+ import { ArtifactSystemProvider } from '../MemoriArtifactSystem';
6
7
  Object.defineProperty(window, 'matchMedia', {
7
8
  writable: true,
8
9
  value: jest.fn().mockImplementation(query => ({
@@ -20,6 +21,17 @@ Object.defineProperty(window, 'matchMedia', {
20
21
  it('renders WEBSITE_ASSISTANT layout unchanged', () => {
21
22
  const { container } = render(
22
23
  <I18nWrapper>
24
+ <ArtifactSystemProvider config={{
25
+ supportedMimeTypes: {
26
+ html: {
27
+ name: 'HTML',
28
+ icon: '🌐',
29
+ hasPreview: true,
30
+ language: 'html',
31
+ mimeType: 'text/html',
32
+ },
33
+ },
34
+ }}>
23
35
  <VisemeProvider>
24
36
  <Memori
25
37
  showShare={true}
@@ -31,6 +43,7 @@ it('renders WEBSITE_ASSISTANT layout unchanged', () => {
31
43
  layout="WEBSITE_ASSISTANT"
32
44
  />
33
45
  </VisemeProvider>
46
+ </ArtifactSystemProvider>
34
47
  </I18nWrapper>
35
48
  );
36
49
  expect(container).toMatchSnapshot();
@@ -3,6 +3,7 @@ import Memori from '../MemoriWidget/MemoriWidget';
3
3
  import { integration, memori, tenant } from '../../mocks/data';
4
4
  import I18nWrapper from '../../I18nWrapper';
5
5
  import { VisemeProvider } from '../../context/visemeContext';
6
+ import { ArtifactSystemProvider } from '../MemoriArtifactSystem';
6
7
  Object.defineProperty(window, 'matchMedia', {
7
8
  writable: true,
8
9
  value: jest.fn().mockImplementation(query => ({
@@ -20,6 +21,17 @@ Object.defineProperty(window, 'matchMedia', {
20
21
  it('renders ZOOMED_FULL_BODY layout unchanged', () => {
21
22
  const { container } = render(
22
23
  <I18nWrapper>
24
+ <ArtifactSystemProvider config={{
25
+ supportedMimeTypes: {
26
+ html: {
27
+ name: 'HTML',
28
+ icon: '🌐',
29
+ hasPreview: true,
30
+ language: 'html',
31
+ mimeType: 'text/html',
32
+ },
33
+ },
34
+ }}>
23
35
  <VisemeProvider>
24
36
  <Memori
25
37
  showShare={true}
@@ -31,6 +43,7 @@ it('renders ZOOMED_FULL_BODY layout unchanged', () => {
31
43
  layout="ZOOMED_FULL_BODY"
32
44
  />
33
45
  </VisemeProvider>
46
+ </ArtifactSystemProvider>
34
47
  </I18nWrapper>
35
48
  );
36
49
  expect(container).toMatchSnapshot();
@@ -1,6 +1,10 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import Spin from '../ui/Spin';
3
3
  import { LayoutProps } from '../MemoriWidget/MemoriWidget';
4
+ import {
5
+ ArtifactDrawer,
6
+ useArtifactSystemContext,
7
+ } from '../MemoriArtifactSystem';
4
8
 
5
9
  const ZoomedFullBodyLayout: React.FC<LayoutProps> = ({
6
10
  Header,
@@ -18,12 +22,35 @@ const ZoomedFullBodyLayout: React.FC<LayoutProps> = ({
18
22
  loading = false,
19
23
  poweredBy,
20
24
  }) => {
25
+ const { state } = useArtifactSystemContext();
26
+ const [isMobile, setIsMobile] = useState(false);
27
+ const [isAnimating, setIsAnimating] = useState(false);
28
+
21
29
  useEffect(() => {
30
+ const handleResize = () => {
31
+ const newIsMobile = window.innerWidth < 769;
32
+ if (newIsMobile !== isMobile) {
33
+ setIsAnimating(true);
34
+ setTimeout(() => {
35
+ setIsMobile(newIsMobile);
36
+ setIsAnimating(false);
37
+ }, 300);
38
+ } else {
39
+ setIsMobile(newIsMobile);
40
+ }
41
+ };
42
+
22
43
  document.body.style.overflow = 'hidden';
44
+
45
+ handleResize();
46
+ window.addEventListener('resize', handleResize);
23
47
  return () => {
24
48
  document.body.style.overflow = '';
49
+ window.removeEventListener('resize', handleResize);
25
50
  };
26
- }, []);
51
+ }, [isMobile]);
52
+
53
+ const hasArtifact = state.currentArtifact && !isMobile;
27
54
 
28
55
  return (
29
56
  <>
@@ -34,21 +61,58 @@ const ZoomedFullBodyLayout: React.FC<LayoutProps> = ({
34
61
  {Header && headerProps && <Header {...headerProps} />}
35
62
 
36
63
  <div className="memori--grid">
37
- <div className="memori--grid-column memori--grid-column-left">
38
- {Avatar && avatarProps && (
39
- <Avatar chatProps={chatProps} isZoomed {...avatarProps} />
40
- )}
64
+ {!hasArtifact && (
65
+ <div className="memori--grid-column memori--grid-column-left">
66
+ {Avatar && avatarProps && !hasArtifact && (
67
+ <Avatar isZoomed chatProps={chatProps} {...avatarProps} />
68
+ )}
41
69
 
42
- <div id="extension" />
43
- </div>
44
- <div className="memori--grid-column memori--grid-column--zoomed-full-body memori--grid-column-right">
45
- {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
46
- <Chat {...chatProps} />
47
- ) : startPanelProps ? (
48
- <StartPanel {...startPanelProps} />
49
- ) : null}
70
+ <div id="extension" />
71
+ </div>
72
+ )}
73
+ <div
74
+ className={`memori-chat-layout--main ${
75
+ hasArtifact ? 'memori-chat-layout--main-with-artifact' : ''
76
+ }`}
77
+ >
78
+ <div
79
+ className={
80
+ state.isFullscreen
81
+ ? `memori-chat-layout-controls-hide`
82
+ : `memori-chat-layout--controls ${
83
+ hasArtifact
84
+ ? 'memori-chat-layout--controls-with-artifact'
85
+ : ''
86
+ }`
87
+ }
88
+ >
89
+ {sessionId && hasUserActivatedSpeak && Chat && chatProps ? (
90
+ <Chat {...chatProps} />
91
+ ) : startPanelProps ? (
92
+ <StartPanel {...startPanelProps} />
93
+ ) : null}
94
+ </div>
95
+
96
+ {hasArtifact && (
97
+ <div
98
+ className={
99
+ state.isFullscreen
100
+ ? `memori-chat-layout-artifact-panel-full-screen`
101
+ : `memori-chat-layout--artifact-panel memori-chat-layout--artifact-panel-enter`
102
+ }
103
+ >
104
+ <ArtifactDrawer />
105
+ </div>
106
+ )}
50
107
  </div>
51
108
 
109
+ {/* Mobile drawer - always rendered but only shown on mobile */}
110
+ {state.currentArtifact && isMobile && (
111
+ <div className="memori-chat-layout--artifact-drawer">
112
+ <ArtifactDrawer />
113
+ </div>
114
+ )}
115
+
52
116
  <div className="memori--powered-by-custom">{poweredBy}</div>
53
117
  </div>
54
118
  </Spin>