@memori.ai/memori-react 8.15.1 → 8.16.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 (166) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/components/Chat/Chat.css +2 -1
  3. package/dist/components/Chat/Chat.js +17 -17
  4. package/dist/components/Chat/Chat.js.map +1 -1
  5. package/dist/components/ChatBubble/ChatBubble.css +1 -1
  6. package/dist/components/ContentPreviewModal/ContentPreviewModal.css +114 -0
  7. package/dist/components/ContentPreviewModal/ContentPreviewModal.d.ts +14 -0
  8. package/dist/components/ContentPreviewModal/ContentPreviewModal.js +18 -0
  9. package/dist/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -0
  10. package/dist/components/ContentPreviewModal/index.d.ts +2 -0
  11. package/dist/components/ContentPreviewModal/index.js +9 -0
  12. package/dist/components/ContentPreviewModal/index.js.map +1 -0
  13. package/dist/components/FilePreview/FilePreview.css +1 -1
  14. package/dist/components/FilePreview/FilePreview.js +43 -13
  15. package/dist/components/FilePreview/FilePreview.js.map +1 -1
  16. package/dist/components/MediaWidget/DocumentCard.d.ts +3 -0
  17. package/dist/components/MediaWidget/DocumentCard.js +9 -0
  18. package/dist/components/MediaWidget/DocumentCard.js.map +1 -0
  19. package/dist/components/MediaWidget/MediaItemWidget.css +946 -19
  20. package/dist/components/MediaWidget/MediaItemWidget.d.ts +5 -36
  21. package/dist/components/MediaWidget/MediaItemWidget.js +295 -198
  22. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  23. package/dist/components/MediaWidget/MediaItemWidget.types.d.ts +62 -0
  24. package/dist/components/MediaWidget/MediaItemWidget.types.js +3 -0
  25. package/dist/components/MediaWidget/MediaItemWidget.types.js.map +1 -0
  26. package/dist/components/MediaWidget/MediaItemWidget.utils.d.ts +23 -0
  27. package/dist/components/MediaWidget/MediaItemWidget.utils.js +162 -0
  28. package/dist/components/MediaWidget/MediaItemWidget.utils.js.map +1 -0
  29. package/dist/components/MediaWidget/MediaPreviewModal.d.ts +15 -0
  30. package/dist/components/MediaWidget/MediaPreviewModal.js +162 -0
  31. package/dist/components/MediaWidget/MediaPreviewModal.js.map +1 -0
  32. package/dist/components/MediaWidget/MediaWidget.js +1 -2
  33. package/dist/components/MediaWidget/MediaWidget.js.map +1 -1
  34. package/dist/components/Snippet/Snippet.css +64 -33
  35. package/dist/components/Snippet/Snippet.js +17 -4
  36. package/dist/components/Snippet/Snippet.js.map +1 -1
  37. package/dist/components/StartPanel/StartPanel.js +1 -2
  38. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  39. package/dist/components/UploadButton/UploadButton.css +0 -5
  40. package/dist/components/layouts/WebsiteAssistant.js +8 -8
  41. package/dist/components/layouts/WebsiteAssistant.js.map +1 -1
  42. package/dist/components/layouts/chat.css +1 -1
  43. package/dist/components/layouts/website-assistant.css +405 -197
  44. package/dist/helpers/constants.js +0 -7
  45. package/dist/helpers/constants.js.map +1 -1
  46. package/dist/helpers/utils.d.ts +1 -0
  47. package/dist/helpers/utils.js +3 -1
  48. package/dist/helpers/utils.js.map +1 -1
  49. package/dist/index.js +43 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/styles.css +0 -2
  52. package/dist/version.d.ts +1 -0
  53. package/dist/version.js +5 -0
  54. package/dist/version.js.map +1 -0
  55. package/esm/components/Chat/Chat.css +2 -1
  56. package/esm/components/Chat/Chat.js +17 -17
  57. package/esm/components/Chat/Chat.js.map +1 -1
  58. package/esm/components/ChatBubble/ChatBubble.css +1 -1
  59. package/esm/components/ContentPreviewModal/ContentPreviewModal.css +114 -0
  60. package/esm/components/ContentPreviewModal/ContentPreviewModal.d.ts +14 -0
  61. package/esm/components/ContentPreviewModal/ContentPreviewModal.js +15 -0
  62. package/esm/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -0
  63. package/esm/components/ContentPreviewModal/index.d.ts +2 -0
  64. package/esm/components/ContentPreviewModal/index.js +2 -0
  65. package/esm/components/ContentPreviewModal/index.js.map +1 -0
  66. package/esm/components/FilePreview/FilePreview.css +1 -1
  67. package/esm/components/FilePreview/FilePreview.js +44 -14
  68. package/esm/components/FilePreview/FilePreview.js.map +1 -1
  69. package/esm/components/MediaWidget/DocumentCard.d.ts +3 -0
  70. package/esm/components/MediaWidget/DocumentCard.js +5 -0
  71. package/esm/components/MediaWidget/DocumentCard.js.map +1 -0
  72. package/esm/components/MediaWidget/MediaItemWidget.css +946 -19
  73. package/esm/components/MediaWidget/MediaItemWidget.d.ts +5 -36
  74. package/esm/components/MediaWidget/MediaItemWidget.js +296 -197
  75. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  76. package/esm/components/MediaWidget/MediaItemWidget.types.d.ts +62 -0
  77. package/esm/components/MediaWidget/MediaItemWidget.types.js +2 -0
  78. package/esm/components/MediaWidget/MediaItemWidget.types.js.map +1 -0
  79. package/esm/components/MediaWidget/MediaItemWidget.utils.d.ts +23 -0
  80. package/esm/components/MediaWidget/MediaItemWidget.utils.js +149 -0
  81. package/esm/components/MediaWidget/MediaItemWidget.utils.js.map +1 -0
  82. package/esm/components/MediaWidget/MediaPreviewModal.d.ts +15 -0
  83. package/esm/components/MediaWidget/MediaPreviewModal.js +157 -0
  84. package/esm/components/MediaWidget/MediaPreviewModal.js.map +1 -0
  85. package/esm/components/MediaWidget/MediaWidget.js +1 -2
  86. package/esm/components/MediaWidget/MediaWidget.js.map +1 -1
  87. package/esm/components/Snippet/Snippet.css +64 -33
  88. package/esm/components/Snippet/Snippet.js +18 -5
  89. package/esm/components/Snippet/Snippet.js.map +1 -1
  90. package/esm/components/StartPanel/StartPanel.js +1 -2
  91. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  92. package/esm/components/UploadButton/UploadButton.css +0 -5
  93. package/esm/components/layouts/WebsiteAssistant.js +8 -8
  94. package/esm/components/layouts/WebsiteAssistant.js.map +1 -1
  95. package/esm/components/layouts/chat.css +1 -1
  96. package/esm/components/layouts/website-assistant.css +405 -197
  97. package/esm/helpers/constants.js +0 -7
  98. package/esm/helpers/constants.js.map +1 -1
  99. package/esm/helpers/utils.d.ts +1 -0
  100. package/esm/helpers/utils.js +1 -0
  101. package/esm/helpers/utils.js.map +1 -1
  102. package/esm/index.js +43 -1
  103. package/esm/index.js.map +1 -1
  104. package/esm/styles.css +0 -2
  105. package/esm/version.d.ts +1 -0
  106. package/esm/version.js +2 -0
  107. package/esm/version.js.map +1 -0
  108. package/package.json +5 -3
  109. package/src/components/Chat/Chat.css +2 -1
  110. package/src/components/Chat/Chat.stories.tsx +124 -0
  111. package/src/components/Chat/Chat.tsx +72 -71
  112. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +567 -1034
  113. package/src/components/ChatBubble/ChatBubble.css +1 -1
  114. package/src/components/ContentPreviewModal/ContentPreviewModal.css +114 -0
  115. package/src/components/ContentPreviewModal/ContentPreviewModal.tsx +69 -0
  116. package/src/components/ContentPreviewModal/index.ts +2 -0
  117. package/src/components/FilePreview/FilePreview.css +1 -1
  118. package/src/components/FilePreview/FilePreview.tsx +60 -37
  119. package/src/components/FilePreview/__snapshots__/FilePreview.test.tsx.snap +15 -105
  120. package/src/components/MediaWidget/DocumentCard.test.tsx +45 -0
  121. package/src/components/MediaWidget/DocumentCard.tsx +19 -0
  122. package/src/components/MediaWidget/MediaItemWidget.css +946 -19
  123. package/src/components/MediaWidget/MediaItemWidget.test.tsx +89 -1
  124. package/src/components/MediaWidget/MediaItemWidget.tsx +734 -461
  125. package/src/components/MediaWidget/MediaItemWidget.types.ts +65 -0
  126. package/src/components/MediaWidget/MediaItemWidget.utils.test.ts +324 -0
  127. package/src/components/MediaWidget/MediaItemWidget.utils.ts +194 -0
  128. package/src/components/MediaWidget/MediaPreviewModal.test.tsx +271 -0
  129. package/src/components/MediaWidget/MediaPreviewModal.tsx +423 -0
  130. package/src/components/MediaWidget/MediaWidget.stories.tsx +193 -0
  131. package/src/components/MediaWidget/MediaWidget.tsx +2 -4
  132. package/src/components/MediaWidget/__snapshots__/DocumentCard.test.tsx.snap +24 -0
  133. package/src/components/MediaWidget/__snapshots__/MediaItemWidget.test.tsx.snap +162 -170
  134. package/src/components/MediaWidget/__snapshots__/MediaWidget.test.tsx.snap +21 -63
  135. package/src/components/Snippet/Snippet.css +64 -33
  136. package/src/components/Snippet/Snippet.tsx +30 -21
  137. package/src/components/Snippet/__snapshots__/Snippet.test.tsx.snap +314 -297
  138. package/src/components/StartPanel/StartPanel.tsx +0 -9
  139. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +12 -636
  140. package/src/components/UploadButton/UploadButton.css +0 -5
  141. package/src/components/layouts/WebsiteAssistant.tsx +66 -62
  142. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +1 -53
  143. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +2 -106
  144. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +1 -53
  145. package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +1 -53
  146. package/src/components/layouts/__snapshots__/WebsiteAssistant.test.tsx.snap +32 -33
  147. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +1 -53
  148. package/src/components/layouts/chat.css +1 -1
  149. package/src/components/layouts/layouts.stories.tsx +68 -0
  150. package/src/components/layouts/website-assistant.css +405 -197
  151. package/src/helpers/constants.ts +0 -7
  152. package/src/helpers/utils.ts +4 -0
  153. package/src/index.test.tsx +8 -0
  154. package/src/index.tsx +51 -1
  155. package/src/styles.css +0 -2
  156. package/src/version.ts +2 -0
  157. package/src/components/AttachmentLinkModal/AttachmentLinkModal.css +0 -68
  158. package/src/components/AttachmentLinkModal/AttachmentLinkModal.stories.tsx +0 -32
  159. package/src/components/AttachmentLinkModal/AttachmentLinkModal.test.tsx +0 -10
  160. package/src/components/AttachmentLinkModal/AttachmentLinkModal.tsx +0 -131
  161. package/src/components/AttachmentLinkModal/__snapshots__/AttachmentLinkModal.test.tsx.snap +0 -9
  162. package/src/components/MediaWidget/LinkItemWidget.css +0 -46
  163. package/src/components/MediaWidget/LinkItemWidget.stories.tsx +0 -61
  164. package/src/components/MediaWidget/LinkItemWidget.test.tsx +0 -33
  165. package/src/components/MediaWidget/LinkItemWidget.tsx +0 -204
  166. package/src/components/MediaWidget/__snapshots__/LinkItemWidget.test.tsx.snap +0 -253
@@ -3,7 +3,7 @@
3
3
  align-items: flex-end;
4
4
  padding-right: 10px;
5
5
  padding-left: 10px;
6
- margin-bottom: 5px;
6
+ margin-bottom: 1rem;
7
7
  }
8
8
 
9
9
  .memori-chat--bubble-initial {
@@ -0,0 +1,114 @@
1
+ /* ContentPreviewModal – modern preview modal for files and media */
2
+
3
+ .memori-content-preview-modal.memori-modal .memori-modal--panel {
4
+ overflow: hidden;
5
+ border-radius: 16px;
6
+ background: var(--memori-content-preview-bg, #fafafa);
7
+ box-shadow:
8
+ 0 25px 50px -12px rgba(0, 0, 0, 0.25),
9
+ 0 0 0 1px rgba(0, 0, 0, 0.05);
10
+ }
11
+
12
+ /* Image variant: modal at least 600px wide (capped by viewport on small screens) */
13
+ .memori-content-preview-modal--image.memori-modal .memori-modal--panel {
14
+ min-width: min(600px, 100vw);
15
+ }
16
+
17
+ .memori-content-preview-modal .memori-modal--title {
18
+ padding: 1rem 1.25rem 0.75rem;
19
+ border-bottom: 1px solid var(--memori-content-preview-border, rgba(0, 0, 0, 0.06));
20
+ color: var(--memori-content-preview-title, #1f2937);
21
+ font-size: 1rem;
22
+ font-weight: 600;
23
+ letter-spacing: -0.01em;
24
+ }
25
+
26
+ .memori-content-preview-modal .memori-modal--close {
27
+ top: 0.75rem;
28
+ right: 0.75rem;
29
+ }
30
+
31
+ .memori-content-preview-modal .memori-modal--close button {
32
+ border-radius: 10px;
33
+ background: var(--memori-content-preview-close-bg, rgba(0, 0, 0, 0.05));
34
+ transition: background 0.2s ease, transform 0.15s ease;
35
+ }
36
+
37
+ .memori-content-preview-modal .memori-modal--close button:hover {
38
+ background: var(--memori-content-preview-close-hover, rgba(0, 0, 0, 0.1));
39
+ transform: scale(1.05);
40
+ }
41
+
42
+ /* Body area */
43
+ .memori-content-preview-modal--body {
44
+ overflow: auto;
45
+ max-height: 70vh;
46
+ padding: 1.25rem;
47
+ }
48
+
49
+ .memori-content-preview-modal--body--image {
50
+ display: flex;
51
+ min-height: 400px;
52
+ align-items: center;
53
+ justify-content: center;
54
+ padding: 1.5rem;
55
+ background: var(--memori-content-preview-image-bg, #f3f4f6);
56
+ }
57
+
58
+ .memori-content-preview-modal--body--content {
59
+ padding: 1rem 1.25rem;
60
+ }
61
+
62
+ /* Image */
63
+ .memori-content-preview-modal--image-wrap {
64
+ display: flex;
65
+ width: 100%;
66
+ min-width: 0;
67
+ align-items: center;
68
+ justify-content: center;
69
+ }
70
+
71
+ .memori-content-preview-modal--image {
72
+ width: 100%;
73
+ height: 100%;
74
+ max-height: 70vh;
75
+ border-radius: 8px;
76
+ object-fit: contain;
77
+ }
78
+
79
+ /* Snippet / text content area */
80
+ .memori-content-preview-modal--snippet-wrap {
81
+ min-height: 120px;
82
+ border: 1px solid var(--memori-content-preview-snippet-border, #e2e8f0);
83
+ border-radius: 12px;
84
+ background: var(--memori-content-preview-snippet-bg, #f8fafc);
85
+ color: var(--memori-content-preview-snippet-text, #334155);
86
+ font-family: 'SF Mono', 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
87
+ font-size: 0.875rem;
88
+ line-height: 1.6;
89
+ overflow-x: auto;
90
+ white-space: pre-wrap;
91
+ word-break: break-word;
92
+ }
93
+
94
+ /* When Snippet component is used inside, give it consistent spacing */
95
+ .memori-content-preview-modal--snippet-wrap .memori-snippet {
96
+ border: none;
97
+ border-radius: 12px;
98
+ background: transparent;
99
+ box-shadow: none;
100
+ }
101
+
102
+ .memori-content-preview-modal--snippet-wrap .memori-snippet--content pre {
103
+ padding: 1rem 1.25rem;
104
+ overflow-wrap: break-word;
105
+ /* Override Prism theme so PDF/text content wraps instead of one long line */
106
+ white-space: pre-wrap !important;
107
+ word-break: break-word;
108
+ }
109
+
110
+ .memori-content-preview-modal--snippet-wrap .memori-snippet--content pre code {
111
+ overflow-wrap: break-word;
112
+ white-space: pre-wrap !important;
113
+ word-break: break-word;
114
+ }
@@ -0,0 +1,69 @@
1
+ import React, { FC } from 'react';
2
+ import Modal from '../ui/Modal';
3
+ import cx from 'classnames';
4
+
5
+ import './ContentPreviewModal.css';
6
+
7
+ export interface ContentPreviewModalProps {
8
+ open: boolean;
9
+ onClose: () => void;
10
+ title?: string;
11
+ /** When true, renders image with min 600px width; otherwise renders children in snippet-style area */
12
+ isImage?: boolean;
13
+ imageSrc?: string;
14
+ imageAlt?: string;
15
+ /** Content for non-image preview (text, Snippet, iframe, etc.) */
16
+ children?: React.ReactNode;
17
+ className?: string;
18
+ }
19
+
20
+ const ContentPreviewModal: FC<ContentPreviewModalProps> = ({
21
+ open,
22
+ onClose,
23
+ title,
24
+ isImage = false,
25
+ imageSrc,
26
+ imageAlt = '',
27
+ children,
28
+ className,
29
+ }) => {
30
+ const width = 'min(90vw, 800px)';
31
+
32
+ return (
33
+ <Modal
34
+ open={open}
35
+ onClose={() => onClose()}
36
+ width={width}
37
+ widthMd={width}
38
+ className={cx('memori-content-preview-modal', className, {
39
+ 'memori-content-preview-modal--image': isImage,
40
+ })}
41
+ closable
42
+ title={title}
43
+ footer={null}
44
+ >
45
+ <div
46
+ className={cx('memori-content-preview-modal--body', {
47
+ 'memori-content-preview-modal--body--image': isImage,
48
+ 'memori-content-preview-modal--body--content': !isImage,
49
+ })}
50
+ >
51
+ {isImage && imageSrc ? (
52
+ <div className="memori-content-preview-modal--image-wrap">
53
+ <img
54
+ src={imageSrc}
55
+ alt={imageAlt}
56
+ className="memori-content-preview-modal--image"
57
+ />
58
+ </div>
59
+ ) : (
60
+ <div className="memori-content-preview-modal--snippet-wrap">
61
+ {children}
62
+ </div>
63
+ )}
64
+ </div>
65
+ </Modal>
66
+ );
67
+ };
68
+
69
+ export default ContentPreviewModal;
@@ -0,0 +1,2 @@
1
+ export { default } from './ContentPreviewModal';
2
+ export type { ContentPreviewModalProps } from './ContentPreviewModal';
@@ -147,7 +147,7 @@
147
147
  height: 20px;
148
148
  flex-shrink: 0;
149
149
  color: #fff;
150
- fill: var(--memori-primary);
150
+ fill: #868e96;
151
151
  }
152
152
 
153
153
  .memori--preview-thumbnail {
@@ -1,11 +1,10 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { PreviewIcon } from '../icons/Preview';
3
- import { DocumentIcon } from '../icons/Document';
4
- import { ImageIcon } from '../icons/Image';
2
+ import File from '../icons/File';
5
3
  import CloseIcon from '../icons/Close';
6
4
  import Button from '../ui/Button';
7
- import Modal from '../ui/Modal';
8
- import { stripHTML } from '../../helpers/utils';
5
+ import ContentPreviewModal from '../ContentPreviewModal';
6
+ import Snippet from '../Snippet/Snippet';
7
+ import { stripHTML, stripDocumentAttachmentTags } from '../../helpers/utils';
9
8
 
10
9
  type FilePreviewProps = {
11
10
  previewFiles: any;
@@ -57,6 +56,8 @@ FilePreviewProps) => {
57
56
  return 'Excel';
58
57
  case 'csv':
59
58
  return 'CSV';
59
+ case 'html':
60
+ return 'HTML';
60
61
  case 'jpg':
61
62
  case 'jpeg':
62
63
  return 'JPEG';
@@ -80,6 +81,33 @@ FilePreviewProps) => {
80
81
  }
81
82
  }
82
83
  }, [previewFiles]);
84
+ // Detect if the file is HTML (by type or filename)
85
+ const isHtmlFile = (file: { name?: string; type?: string; mimeType?: string } | null): boolean => {
86
+ if (!file) return false;
87
+ const ext = file.name?.split('.').pop()?.toLowerCase();
88
+ return (
89
+ file.type === 'document' && (ext === 'html' || file.mimeType === 'text/html')
90
+ ) || ext === 'html' || file.mimeType === 'text/html';
91
+ };
92
+
93
+ // Get display content for non-image files (strip document_attachment for HTML, stripHTML for others)
94
+ const getDisplayContent = (file: { content?: string; name?: string; type?: string; mimeType?: string } | null): string => {
95
+ if (!file?.content) return '';
96
+ const content = file.content;
97
+ if (isHtmlFile(file)) {
98
+ let htmlContent = content;
99
+ if (htmlContent.includes('&lt;') || htmlContent.includes('&quot;')) {
100
+ const div = document.createElement('div');
101
+ div.innerHTML = htmlContent;
102
+ htmlContent = div.textContent || div.innerText || htmlContent;
103
+ } else {
104
+ htmlContent = stripDocumentAttachmentTags(htmlContent);
105
+ }
106
+ return htmlContent;
107
+ }
108
+ return stripHTML(content);
109
+ };
110
+
83
111
  // Detect if the content is an image URL
84
112
  const isImageContent = (content: string, type?: string): boolean => {
85
113
  if (type === 'image') return true;
@@ -117,7 +145,7 @@ FilePreviewProps) => {
117
145
  <img src={file.content} alt={file.name} />
118
146
  </div>
119
147
  ) : (
120
- <DocumentIcon className="memori--preview-icon" />
148
+ <File className="memori--preview-icon" />
121
149
  )}
122
150
 
123
151
  <div className="memori--preview-file-info">
@@ -147,42 +175,37 @@ FilePreviewProps) => {
147
175
  </div>
148
176
  )}
149
177
 
150
- <Modal
151
- width="80%"
152
- widthMd="80%"
178
+ <ContentPreviewModal
153
179
  open={!!selectedFile}
154
- className="memori--modal-preview-file"
155
180
  onClose={() => setSelectedFile(null)}
156
- closable
157
181
  title={selectedFile?.name}
182
+ isImage={
183
+ !!selectedFile &&
184
+ isImageContent(selectedFile.content, selectedFile.type)
185
+ }
186
+ imageSrc={
187
+ selectedFile && isImageContent(selectedFile.content, selectedFile.type)
188
+ ? selectedFile.content
189
+ : undefined
190
+ }
191
+ imageAlt={selectedFile?.name ?? ''}
158
192
  >
159
- <div
160
- className="memori--preview-content"
161
- style={{
162
- maxHeight: '70vh',
163
- overflowY: 'auto',
164
- textAlign: 'center',
165
- whiteSpace:
166
- selectedFile &&
167
- !isImageContent(selectedFile.content, selectedFile.type)
168
- ? 'pre-wrap'
169
- : 'normal',
170
- }}
171
- >
172
- {selectedFile &&
173
- isImageContent(selectedFile.content, selectedFile.type) ? (
174
- <>
175
- <img
176
- src={selectedFile.content}
177
- alt={selectedFile.name}
178
- style={{ maxWidth: '100%', maxHeight: '60vh' }}
179
- />
180
- </>
193
+ {selectedFile &&
194
+ !isImageContent(selectedFile.content, selectedFile.type) &&
195
+ (isHtmlFile(selectedFile) ? (
196
+ <Snippet
197
+ preview={false}
198
+ medium={{
199
+ mediumID: selectedFile.id,
200
+ mimeType: 'application/xml',
201
+ content: getDisplayContent(selectedFile),
202
+ title: selectedFile.name,
203
+ }}
204
+ />
181
205
  ) : (
182
- stripHTML(selectedFile?.content || '')
183
- )}
184
- </div>
185
- </Modal>
206
+ getDisplayContent(selectedFile)
207
+ ))}
208
+ </ContentPreviewModal>
186
209
  </>
187
210
  );
188
211
  };
@@ -14,45 +14,15 @@ exports[`renders FilePreview with one file 1`] = `
14
14
  class="memori--preview-item memori--preview-item--document"
15
15
  >
16
16
  <svg
17
+ aria-hidden="true"
17
18
  class="memori--preview-icon"
18
- fill="none"
19
- viewBox="0 0 24 24"
19
+ focusable="false"
20
+ role="img"
21
+ viewBox="0 0 1024 1024"
20
22
  xmlns="http://www.w3.org/2000/svg"
21
23
  >
22
24
  <path
23
- d="M14 2.5H6C5.60218 2.5 5.22064 2.65804 4.93934 2.93934C4.65804 3.22064 4.5 3.60218 4.5 4V20C4.5 20.3978 4.65804 20.7794 4.93934 21.0607C5.22064 21.342 5.60218 21.5 6 21.5H18C18.3978 21.5 18.7794 21.342 19.0607 21.0607C19.342 20.7794 19.5 20.3978 19.5 20V8L14 2.5Z"
24
- stroke="currentColor"
25
- stroke-linecap="round"
26
- stroke-linejoin="round"
27
- stroke-width="1.5"
28
- />
29
- <path
30
- d="M14 2.5V8H19.5"
31
- stroke="currentColor"
32
- stroke-linecap="round"
33
- stroke-linejoin="round"
34
- stroke-width="1.5"
35
- />
36
- <path
37
- d="M16 13H8"
38
- stroke="currentColor"
39
- stroke-linecap="round"
40
- stroke-linejoin="round"
41
- stroke-width="1.5"
42
- />
43
- <path
44
- d="M16 17H8"
45
- stroke="currentColor"
46
- stroke-linecap="round"
47
- stroke-linejoin="round"
48
- stroke-width="1.5"
49
- />
50
- <path
51
- d="M10 9H8"
52
- stroke="currentColor"
53
- stroke-linecap="round"
54
- stroke-linejoin="round"
55
- stroke-width="1.5"
25
+ d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"
56
26
  />
57
27
  </svg>
58
28
  <div
@@ -109,45 +79,15 @@ exports[`renders FilePreview with two files 1`] = `
109
79
  class="memori--preview-item memori--preview-item--document"
110
80
  >
111
81
  <svg
82
+ aria-hidden="true"
112
83
  class="memori--preview-icon"
113
- fill="none"
114
- viewBox="0 0 24 24"
84
+ focusable="false"
85
+ role="img"
86
+ viewBox="0 0 1024 1024"
115
87
  xmlns="http://www.w3.org/2000/svg"
116
88
  >
117
89
  <path
118
- d="M14 2.5H6C5.60218 2.5 5.22064 2.65804 4.93934 2.93934C4.65804 3.22064 4.5 3.60218 4.5 4V20C4.5 20.3978 4.65804 20.7794 4.93934 21.0607C5.22064 21.342 5.60218 21.5 6 21.5H18C18.3978 21.5 18.7794 21.342 19.0607 21.0607C19.342 20.7794 19.5 20.3978 19.5 20V8L14 2.5Z"
119
- stroke="currentColor"
120
- stroke-linecap="round"
121
- stroke-linejoin="round"
122
- stroke-width="1.5"
123
- />
124
- <path
125
- d="M14 2.5V8H19.5"
126
- stroke="currentColor"
127
- stroke-linecap="round"
128
- stroke-linejoin="round"
129
- stroke-width="1.5"
130
- />
131
- <path
132
- d="M16 13H8"
133
- stroke="currentColor"
134
- stroke-linecap="round"
135
- stroke-linejoin="round"
136
- stroke-width="1.5"
137
- />
138
- <path
139
- d="M16 17H8"
140
- stroke="currentColor"
141
- stroke-linecap="round"
142
- stroke-linejoin="round"
143
- stroke-width="1.5"
144
- />
145
- <path
146
- d="M10 9H8"
147
- stroke="currentColor"
148
- stroke-linecap="round"
149
- stroke-linejoin="round"
150
- stroke-width="1.5"
90
+ d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"
151
91
  />
152
92
  </svg>
153
93
  <div
@@ -191,45 +131,15 @@ exports[`renders FilePreview with two files 1`] = `
191
131
  class="memori--preview-item memori--preview-item--document"
192
132
  >
193
133
  <svg
134
+ aria-hidden="true"
194
135
  class="memori--preview-icon"
195
- fill="none"
196
- viewBox="0 0 24 24"
136
+ focusable="false"
137
+ role="img"
138
+ viewBox="0 0 1024 1024"
197
139
  xmlns="http://www.w3.org/2000/svg"
198
140
  >
199
141
  <path
200
- d="M14 2.5H6C5.60218 2.5 5.22064 2.65804 4.93934 2.93934C4.65804 3.22064 4.5 3.60218 4.5 4V20C4.5 20.3978 4.65804 20.7794 4.93934 21.0607C5.22064 21.342 5.60218 21.5 6 21.5H18C18.3978 21.5 18.7794 21.342 19.0607 21.0607C19.342 20.7794 19.5 20.3978 19.5 20V8L14 2.5Z"
201
- stroke="currentColor"
202
- stroke-linecap="round"
203
- stroke-linejoin="round"
204
- stroke-width="1.5"
205
- />
206
- <path
207
- d="M14 2.5V8H19.5"
208
- stroke="currentColor"
209
- stroke-linecap="round"
210
- stroke-linejoin="round"
211
- stroke-width="1.5"
212
- />
213
- <path
214
- d="M16 13H8"
215
- stroke="currentColor"
216
- stroke-linecap="round"
217
- stroke-linejoin="round"
218
- stroke-width="1.5"
219
- />
220
- <path
221
- d="M16 17H8"
222
- stroke="currentColor"
223
- stroke-linecap="round"
224
- stroke-linejoin="round"
225
- stroke-width="1.5"
226
- />
227
- <path
228
- d="M10 9H8"
229
- stroke="currentColor"
230
- stroke-linecap="round"
231
- stroke-linejoin="round"
232
- stroke-width="1.5"
142
+ d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494z"
233
143
  />
234
144
  </svg>
235
145
  <div
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import { DocumentCard } from './DocumentCard';
5
+ import File from '../icons/File';
6
+
7
+ describe('DocumentCard', () => {
8
+ it('renders title and badge', () => {
9
+ render(
10
+ <DocumentCard
11
+ title="My Document"
12
+ badge="PDF"
13
+ icon={<File />}
14
+ />
15
+ );
16
+ expect(screen.getByText('My Document')).toBeInTheDocument();
17
+ expect(screen.getByText('PDF')).toBeInTheDocument();
18
+ });
19
+
20
+ it('applies document and badge classes', () => {
21
+ const { container } = render(
22
+ <DocumentCard
23
+ title="Report"
24
+ badge="DOCX"
25
+ meta="1.2 MB"
26
+ icon={<File />}
27
+ />
28
+ );
29
+ expect(container.querySelector('.memori-media-item--document')).toBeInTheDocument();
30
+ expect(container.querySelector('.memori-media-item--document-title')).toHaveTextContent('Report');
31
+ expect(container.querySelector('.memori-media-item--document-badge')).toHaveTextContent('DOCX');
32
+ });
33
+
34
+ it('renders unchanged snapshot', () => {
35
+ const { container } = render(
36
+ <DocumentCard
37
+ title="Spreadsheet"
38
+ badge="XLSX"
39
+ meta="256 KB"
40
+ icon={<File />}
41
+ />
42
+ );
43
+ expect(container).toMatchSnapshot();
44
+ });
45
+ });
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { DocumentCardProps } from './MediaItemWidget.types';
3
+
4
+ export function DocumentCard({
5
+ title,
6
+ badge,
7
+ }: DocumentCardProps): React.ReactElement {
8
+ return (
9
+ <div className="memori-media-item--document">
10
+ <div className="memori-media-item--document-header">
11
+ {/* <div className="memori-media-item--document-icon" aria-hidden>
12
+ {icon}
13
+ </div> */}
14
+ <div className="memori-media-item--document-title">{title}</div>
15
+ </div>
16
+ <span className="memori-media-item--document-badge">{badge}</span>
17
+ </div>
18
+ );
19
+ }