@memori.ai/memori-react 8.11.0 → 8.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/dist/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
- package/dist/components/AgeVerificationModal/AgeVerificationModal.js +2 -2
- package/dist/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
- package/dist/components/Auth/Auth.js +36 -8
- package/dist/components/Auth/Auth.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
- package/dist/components/Chat/Chat.css +37 -3
- package/dist/components/Chat/Chat.js +61 -23
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.css +87 -15
- package/dist/components/ChatBubble/ChatBubble.js +129 -19
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ChatHistoryDrawer/ChatHistory.css +5 -1
- package/dist/components/ChatInputs/ChatInputs.css +293 -17
- package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
- package/dist/components/ChatInputs/ChatInputs.js +48 -27
- package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
- package/dist/components/ChatTextArea/ChatTextArea.css +75 -31
- package/dist/components/ChatTextArea/ChatTextArea.js +47 -18
- package/dist/components/ChatTextArea/ChatTextArea.js.map +1 -1
- package/dist/components/DateSelector/DateSelector.css +125 -104
- package/dist/components/DateSelector/DateSelector.d.ts +1 -1
- package/dist/components/DateSelector/DateSelector.js +110 -52
- package/dist/components/DateSelector/DateSelector.js.map +1 -1
- package/dist/components/FilePreview/FilePreview.css +225 -146
- package/dist/components/FilePreview/FilePreview.d.ts +1 -2
- package/dist/components/FilePreview/FilePreview.js +20 -6
- package/dist/components/FilePreview/FilePreview.js.map +1 -1
- package/dist/components/Header/Header.css +2 -2
- package/dist/components/Header/Header.js +1 -1
- package/dist/components/Header/Header.js.map +1 -1
- package/dist/components/LoginDrawer/LoginDrawer.css +37 -5
- package/dist/components/LoginDrawer/LoginDrawer.d.ts +1 -2
- package/dist/components/LoginDrawer/LoginDrawer.js +2 -9
- package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.js +2 -1
- package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js +3 -0
- package/dist/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +2 -2
- package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
- package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +6 -4
- package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.css +11 -2
- package/dist/components/MemoriWidget/MemoriWidget.js +105 -25
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/MicrophoneButton/MicrophoneButton.css +2 -2
- package/dist/components/StartPanel/StartPanel.css +8 -0
- package/dist/components/UploadButton/UploadButton.css +20 -17
- package/dist/components/UploadButton/UploadButton.js +218 -87
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +14 -4
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/dist/components/UploadButton/UploadImages/UploadImages.js +143 -16
- package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
- package/dist/components/layouts/chat.css +1 -1
- package/dist/components/ui/Drawer.css +8 -0
- package/dist/components/ui/Drawer.d.ts +2 -0
- package/dist/components/ui/Drawer.js +2 -2
- package/dist/components/ui/Drawer.js.map +1 -1
- package/dist/components/ui/Tooltip.css +49 -1
- package/dist/components/ui/Tooltip.d.ts +1 -1
- package/dist/helpers/constants.d.ts +1 -0
- package/dist/helpers/constants.js +2 -1
- package/dist/helpers/constants.js.map +1 -1
- package/dist/helpers/imageCompression.d.ts +7 -0
- package/dist/helpers/imageCompression.js +123 -0
- package/dist/helpers/imageCompression.js.map +1 -0
- package/dist/locales/de.json +13 -5
- package/dist/locales/en.json +17 -6
- package/dist/locales/es.json +13 -5
- package/dist/locales/fr.json +12 -5
- package/dist/locales/it.json +16 -6
- package/dist/styles.css +4 -4
- package/esm/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
- package/esm/components/AgeVerificationModal/AgeVerificationModal.js +2 -2
- package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
- package/esm/components/Auth/Auth.js +36 -8
- package/esm/components/Auth/Auth.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
- package/esm/components/Chat/Chat.css +37 -3
- package/esm/components/Chat/Chat.js +61 -23
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.css +87 -15
- package/esm/components/ChatBubble/ChatBubble.js +130 -20
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ChatHistoryDrawer/ChatHistory.css +5 -1
- package/esm/components/ChatInputs/ChatInputs.css +293 -17
- package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
- package/esm/components/ChatInputs/ChatInputs.js +49 -28
- package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
- package/esm/components/ChatTextArea/ChatTextArea.css +75 -31
- package/esm/components/ChatTextArea/ChatTextArea.js +49 -20
- package/esm/components/ChatTextArea/ChatTextArea.js.map +1 -1
- package/esm/components/DateSelector/DateSelector.css +125 -104
- package/esm/components/DateSelector/DateSelector.d.ts +1 -1
- package/esm/components/DateSelector/DateSelector.js +111 -52
- package/esm/components/DateSelector/DateSelector.js.map +1 -1
- package/esm/components/FilePreview/FilePreview.css +225 -146
- package/esm/components/FilePreview/FilePreview.d.ts +1 -2
- package/esm/components/FilePreview/FilePreview.js +21 -7
- package/esm/components/FilePreview/FilePreview.js.map +1 -1
- package/esm/components/Header/Header.css +2 -2
- package/esm/components/Header/Header.js +1 -1
- package/esm/components/Header/Header.js.map +1 -1
- package/esm/components/LoginDrawer/LoginDrawer.css +37 -5
- package/esm/components/LoginDrawer/LoginDrawer.d.ts +1 -2
- package/esm/components/LoginDrawer/LoginDrawer.js +2 -9
- package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.js +2 -1
- package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js +3 -0
- package/esm/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +2 -2
- package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
- package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +6 -4
- package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.css +11 -2
- package/esm/components/MemoriWidget/MemoriWidget.js +105 -25
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/MicrophoneButton/MicrophoneButton.css +2 -2
- package/esm/components/StartPanel/StartPanel.css +8 -0
- package/esm/components/UploadButton/UploadButton.css +20 -17
- package/esm/components/UploadButton/UploadButton.js +219 -88
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +14 -4
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/esm/components/UploadButton/UploadImages/UploadImages.js +143 -16
- package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
- package/esm/components/layouts/chat.css +1 -1
- package/esm/components/ui/Drawer.css +8 -0
- package/esm/components/ui/Drawer.d.ts +2 -0
- package/esm/components/ui/Drawer.js +2 -2
- package/esm/components/ui/Drawer.js.map +1 -1
- package/esm/components/ui/Tooltip.css +49 -1
- package/esm/components/ui/Tooltip.d.ts +1 -1
- package/esm/helpers/constants.d.ts +1 -0
- package/esm/helpers/constants.js +1 -0
- package/esm/helpers/constants.js.map +1 -1
- package/esm/helpers/imageCompression.d.ts +7 -0
- package/esm/helpers/imageCompression.js +119 -0
- package/esm/helpers/imageCompression.js.map +1 -0
- package/esm/locales/de.json +13 -5
- package/esm/locales/en.json +17 -6
- package/esm/locales/es.json +13 -5
- package/esm/locales/fr.json +12 -5
- package/esm/locales/it.json +16 -6
- package/esm/styles.css +4 -4
- package/package.json +2 -2
- package/src/components/AgeVerificationModal/AgeVerificationModal.css +41 -14
- package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +3 -1
- package/src/components/Auth/Auth.tsx +55 -11
- package/src/components/Avatar/Avatar.stories.tsx +3 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +2 -2
- package/src/components/Chat/Chat.css +37 -3
- package/src/components/Chat/Chat.stories.tsx +16 -2
- package/src/components/Chat/Chat.tsx +90 -21
- package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +1752 -812
- package/src/components/ChatBubble/ChatBubble.css +87 -15
- package/src/components/ChatBubble/ChatBubble.stories.tsx +16 -2
- package/src/components/ChatBubble/ChatBubble.test.tsx +17 -0
- package/src/components/ChatBubble/ChatBubble.tsx +237 -33
- package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +304 -8
- package/src/components/ChatHistoryDrawer/ChatHistory.css +5 -1
- package/src/components/ChatInputs/ChatInputs.css +293 -17
- package/src/components/ChatInputs/ChatInputs.tsx +156 -86
- package/src/components/ChatInputs/__snapshots__/ChatInputs.test.tsx.snap +430 -424
- package/src/components/ChatTextArea/ChatTextArea.css +75 -31
- package/src/components/ChatTextArea/ChatTextArea.test.tsx +1 -16
- package/src/components/ChatTextArea/ChatTextArea.tsx +51 -22
- package/src/components/ChatTextArea/__snapshots__/ChatTextArea.test.tsx.snap +9 -72
- package/src/components/DateSelector/DateSelector.css +125 -104
- package/src/components/DateSelector/DateSelector.stories.tsx +1 -1
- package/src/components/DateSelector/DateSelector.test.tsx +137 -23
- package/src/components/DateSelector/DateSelector.tsx +203 -177
- package/src/components/FilePreview/FilePreview.css +225 -146
- package/src/components/FilePreview/FilePreview.tsx +49 -36
- package/src/components/FilePreview/__snapshots__/FilePreview.test.tsx.snap +2 -2
- package/src/components/Header/Header.css +2 -2
- package/src/components/Header/Header.stories.tsx +5 -1
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/Header/__snapshots__/Header.test.tsx.snap +1 -1
- package/src/components/LoginDrawer/LoginDrawer.css +37 -5
- package/src/components/LoginDrawer/LoginDrawer.stories.tsx +0 -1
- package/src/components/LoginDrawer/LoginDrawer.test.tsx +0 -1
- package/src/components/LoginDrawer/LoginDrawer.tsx +0 -19
- package/src/components/MediaWidget/MediaItemWidget.tsx +2 -1
- package/src/components/MemoriArtifactSystem/ArtifactDrawer.stories.tsx +996 -204
- package/src/components/MemoriArtifactSystem/components/ArtifactActions/ArtifactActions.tsx +2 -2
- package/src/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyButtonWithDropdown.tsx +1 -1
- package/src/components/MemoriArtifactSystem/components/ArtifactActions/components/CopyMenuItem.tsx +3 -0
- package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +56 -54
- package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.css +16 -7
- package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.tsx +12 -3
- package/src/components/MemoriWidget/MemoriWidget.css +11 -2
- package/src/components/MemoriWidget/MemoriWidget.stories.tsx +6 -3
- package/src/components/MemoriWidget/MemoriWidget.tsx +173 -49
- package/src/components/MicrophoneButton/MicrophoneButton.css +2 -2
- package/src/components/StartPanel/StartPanel.css +8 -0
- package/src/components/UploadButton/UploadButton.css +20 -17
- package/src/components/UploadButton/UploadButton.stories.tsx +247 -35
- package/src/components/UploadButton/UploadButton.tsx +280 -173
- package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +19 -4
- package/src/components/UploadButton/UploadImages/UploadImages.tsx +196 -35
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +10 -1
- package/src/components/layouts/FullBody/FullBody.stories.tsx +9 -10
- package/src/components/layouts/Totem/Totem.stories.tsx +8 -9
- package/src/components/layouts/ZoomedFullBody/ZoomedFullBody.stories.tsx +8 -9
- package/src/components/layouts/chat.css +1 -1
- package/src/components/layouts/layouts.stories.tsx +10 -9
- package/src/components/ui/Drawer.css +8 -0
- package/src/components/ui/Drawer.tsx +16 -12
- package/src/components/ui/Tooltip.css +49 -1
- package/src/components/ui/Tooltip.tsx +1 -1
- package/src/helpers/constants.ts +1 -1
- package/src/helpers/imageCompression.ts +230 -0
- package/src/index.stories.tsx +18 -0
- package/src/locales/de.json +13 -5
- package/src/locales/en.json +17 -6
- package/src/locales/es.json +13 -5
- package/src/locales/fr.json +12 -5
- package/src/locales/it.json +16 -6
- package/src/mocks/data.ts +4 -2
- package/src/styles.css +4 -4
- package/src/components/SignupForm/SignupForm.test.tsx +0 -40
- package/src/components/SignupForm/SignupForm.tsx +0 -457
- package/src/components/SignupForm/__snapshots__/SignupForm.test.tsx.snap +0 -247
- package/src/components/UploadMenu/UploadMenu.css +0 -47
- package/src/components/UploadMenu/UploadMenu.stories.tsx +0 -66
- package/src/components/UploadMenu/UploadMenu.test.tsx +0 -34
- package/src/components/UploadMenu/UploadMenu.tsx +0 -68
- package/src/components/UploadMenu/__snapshots__/UploadMenu.test.tsx.snap +0 -137
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
2
2
|
import { DocumentIcon } from '../icons/Document';
|
|
3
3
|
import { ImageIcon } from '../icons/Image';
|
|
4
4
|
import { UploadIcon } from '../icons/Upload';
|
|
@@ -9,10 +9,10 @@ import UploadDocuments from './UploadDocuments/UploadDocuments';
|
|
|
9
9
|
import UploadImages from './UploadImages/UploadImages';
|
|
10
10
|
import { useTranslation } from 'react-i18next';
|
|
11
11
|
import memoriApiClient from '@memori.ai/memori-api-client';
|
|
12
|
+
import Tooltip from '../ui/Tooltip';
|
|
12
13
|
|
|
13
14
|
// Constants
|
|
14
|
-
const
|
|
15
|
-
const MAX_DOCUMENTS = 5;
|
|
15
|
+
const MAX_MEDIA = 10;
|
|
16
16
|
|
|
17
17
|
// Props interface
|
|
18
18
|
interface UploadManagerProps {
|
|
@@ -42,29 +42,23 @@ const UploadButton: React.FC<UploadManagerProps> = ({
|
|
|
42
42
|
}) => {
|
|
43
43
|
// State
|
|
44
44
|
const [isLoading, setIsLoading] = useState(false);
|
|
45
|
-
const [menuOpen, setMenuOpen] = useState(false);
|
|
46
45
|
const [errors, setErrors] = useState<
|
|
47
46
|
{ message: string; severity: 'error' | 'warning' | 'info' }[]
|
|
48
47
|
>([]);
|
|
48
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
49
49
|
const { t, i18n } = useTranslation();
|
|
50
50
|
|
|
51
51
|
// Refs
|
|
52
|
-
const menuRef = useRef<HTMLDivElement>(null);
|
|
53
52
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
54
53
|
const documentRef = useRef<HTMLDivElement>(null);
|
|
55
54
|
const imageRef = useRef<HTMLDivElement>(null);
|
|
55
|
+
const unifiedInputRef = useRef<HTMLInputElement>(null);
|
|
56
|
+
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
56
57
|
|
|
57
|
-
// Calculate
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const remainingSlots = MAX_IMAGES - currentImageCount;
|
|
62
|
-
const currentDocumentCount = documentPreviewFiles.filter(
|
|
63
|
-
file => file.type === 'document'
|
|
64
|
-
).length;
|
|
65
|
-
const remainingDocumentSlots = MAX_DOCUMENTS - currentDocumentCount;
|
|
66
|
-
const hasReachedImageLimit = remainingSlots <= 0;
|
|
67
|
-
const hasReachedDocumentLimit = remainingDocumentSlots <= 0;
|
|
58
|
+
// Calculate total media count
|
|
59
|
+
const currentMediaCount = documentPreviewFiles.length;
|
|
60
|
+
const remainingSlots = MAX_MEDIA - currentMediaCount;
|
|
61
|
+
const hasReachedMediaLimit = remainingSlots <= 0;
|
|
68
62
|
|
|
69
63
|
// Error handling
|
|
70
64
|
const removeError = (errorMessage: string) => {
|
|
@@ -79,33 +73,259 @@ const UploadButton: React.FC<UploadManagerProps> = ({
|
|
|
79
73
|
setTimeout(() => removeError(error.message), 5000);
|
|
80
74
|
};
|
|
81
75
|
|
|
82
|
-
//
|
|
83
|
-
const
|
|
84
|
-
|
|
76
|
+
// Check if file is an image
|
|
77
|
+
const isImageFile = (file: File): boolean => {
|
|
78
|
+
const imageTypes = ['image/jpeg', 'image/jpg', 'image/png'];
|
|
79
|
+
const imageExtensions = ['.jpg', '.jpeg', '.png'];
|
|
80
|
+
const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
|
|
81
|
+
return imageTypes.includes(file.type) || imageExtensions.includes(fileExt);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Check if file is a document
|
|
85
|
+
const isDocumentFile = (file: File): boolean => {
|
|
86
|
+
const documentExtensions = ['.pdf', '.txt', '.json', '.xlsx', '.csv', '.md', '.html'];
|
|
87
|
+
const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
|
|
88
|
+
return documentExtensions.includes(fileExt);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Use refs to access latest values in event handlers
|
|
92
|
+
const isMediaAcceptedRef = useRef(isMediaAccepted);
|
|
93
|
+
const currentMediaCountRef = useRef(currentMediaCount);
|
|
94
|
+
const addErrorRef = useRef(addError);
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
isMediaAcceptedRef.current = isMediaAccepted;
|
|
98
|
+
currentMediaCountRef.current = currentMediaCount;
|
|
99
|
+
addErrorRef.current = addError;
|
|
100
|
+
}, [isMediaAccepted, currentMediaCount, addError]);
|
|
101
|
+
|
|
102
|
+
// Handle unified file selection
|
|
103
|
+
const handleUnifiedFileSelection = useCallback((files: FileList | File[]) => {
|
|
104
|
+
const fileArray = Array.from(files);
|
|
105
|
+
if (fileArray.length === 0) return;
|
|
106
|
+
|
|
107
|
+
const imageFiles: File[] = [];
|
|
108
|
+
const documentFiles: File[] = [];
|
|
109
|
+
|
|
110
|
+
// Separate files by type
|
|
111
|
+
fileArray.forEach(file => {
|
|
112
|
+
if (isImageFile(file)) {
|
|
113
|
+
imageFiles.push(file);
|
|
114
|
+
} else if (isDocumentFile(file)) {
|
|
115
|
+
documentFiles.push(file);
|
|
116
|
+
} else {
|
|
117
|
+
addErrorRef.current({
|
|
118
|
+
message: `File "${file.name}" is not a supported image or document type`,
|
|
119
|
+
severity: 'error',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Calculate total files to be added
|
|
125
|
+
const totalFilesToAdd = imageFiles.length + documentFiles.length;
|
|
126
|
+
const newTotalCount = currentMediaCountRef.current + totalFilesToAdd;
|
|
127
|
+
|
|
128
|
+
// Check if adding these files would exceed the limit
|
|
129
|
+
if (newTotalCount > MAX_MEDIA) {
|
|
130
|
+
addErrorRef.current({
|
|
131
|
+
message: `Maximum ${MAX_MEDIA} media files allowed.`,
|
|
132
|
+
severity: 'error',
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Process images
|
|
138
|
+
if (imageFiles.length > 0) {
|
|
139
|
+
if (!isMediaAcceptedRef.current) {
|
|
140
|
+
addErrorRef.current({
|
|
141
|
+
message:
|
|
142
|
+
t('upload.mediaNotAccepted') ?? 'Media uploads are not accepted',
|
|
143
|
+
severity: 'info',
|
|
144
|
+
});
|
|
145
|
+
} else {
|
|
146
|
+
// Trigger image upload by creating a synthetic event
|
|
147
|
+
const imageInput = imageRef.current?.querySelector('input[type="file"]') as HTMLInputElement;
|
|
148
|
+
if (imageInput) {
|
|
149
|
+
const dataTransfer = new DataTransfer();
|
|
150
|
+
imageFiles.forEach(file => {
|
|
151
|
+
try {
|
|
152
|
+
dataTransfer.items.add(file);
|
|
153
|
+
} catch (err) {
|
|
154
|
+
console.warn('Failed to add image file to DataTransfer:', err);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Only proceed if we successfully added files
|
|
159
|
+
if (dataTransfer.files.length > 0) {
|
|
160
|
+
imageInput.files = dataTransfer.files;
|
|
161
|
+
const changeEvent = new Event('change', { bubbles: true });
|
|
162
|
+
imageInput.dispatchEvent(changeEvent);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Process documents
|
|
169
|
+
if (documentFiles.length > 0) {
|
|
170
|
+
// Trigger document upload by creating a synthetic event
|
|
171
|
+
const documentInput = documentRef.current?.querySelector('input[type="file"]') as HTMLInputElement;
|
|
172
|
+
if (documentInput) {
|
|
173
|
+
const dataTransfer = new DataTransfer();
|
|
174
|
+
documentFiles.forEach(file => {
|
|
175
|
+
try {
|
|
176
|
+
dataTransfer.items.add(file);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
console.warn('Failed to add document file to DataTransfer:', err);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Only proceed if we successfully added files
|
|
183
|
+
if (dataTransfer.files.length > 0) {
|
|
184
|
+
documentInput.files = dataTransfer.files;
|
|
185
|
+
const changeEvent = new Event('change', { bubbles: true });
|
|
186
|
+
documentInput.dispatchEvent(changeEvent);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}, [t]);
|
|
191
|
+
|
|
192
|
+
// Handle button click - open file chooser directly
|
|
193
|
+
const handleButtonClick = () => {
|
|
194
|
+
if (unifiedInputRef.current) {
|
|
195
|
+
unifiedInputRef.current.click();
|
|
196
|
+
}
|
|
85
197
|
};
|
|
86
198
|
|
|
87
|
-
|
|
88
|
-
|
|
199
|
+
// Handle file input change
|
|
200
|
+
const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
201
|
+
const files = e.target.files;
|
|
202
|
+
if (files && files.length > 0) {
|
|
203
|
+
handleUnifiedFileSelection(files);
|
|
204
|
+
}
|
|
205
|
+
// Reset input value to allow selecting the same file again
|
|
206
|
+
if (unifiedInputRef.current) {
|
|
207
|
+
unifiedInputRef.current.value = '';
|
|
208
|
+
}
|
|
89
209
|
};
|
|
90
210
|
|
|
91
|
-
//
|
|
211
|
+
// Paste handler for files
|
|
92
212
|
useEffect(() => {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
213
|
+
const handlePaste = (e: ClipboardEvent) => {
|
|
214
|
+
const clipboardData = e.clipboardData;
|
|
215
|
+
if (!clipboardData) {
|
|
216
|
+
console.log('[UploadButton] handlePaste: No clipboardData available.');
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const files: File[] = [];
|
|
221
|
+
|
|
222
|
+
// Helper to check if a file is already in the array
|
|
223
|
+
const isDuplicate = (file: File) => {
|
|
224
|
+
return files.some(f =>
|
|
225
|
+
f.name === file.name &&
|
|
226
|
+
f.size === file.size &&
|
|
227
|
+
f.lastModified === file.lastModified
|
|
228
|
+
);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// First, try to get files directly from clipboardData.files (most reliable for multiple files)
|
|
232
|
+
if (clipboardData.files && clipboardData.files.length > 0) {
|
|
233
|
+
const clipboardFiles = Array.from(clipboardData.files);
|
|
234
|
+
console.log(`[UploadButton] handlePaste: clipboardData.files found`, clipboardFiles);
|
|
235
|
+
clipboardFiles.forEach(file => {
|
|
236
|
+
if (!isDuplicate(file)) {
|
|
237
|
+
files.push(file);
|
|
238
|
+
} else {
|
|
239
|
+
console.log(`[UploadButton] handlePaste: Duplicate file skipped from clipboardData.files:`, file);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Also check items array (some browsers populate this instead of or in addition to files)
|
|
245
|
+
const items = clipboardData.items;
|
|
246
|
+
if (items) {
|
|
247
|
+
for (let i = 0; i < items.length; i++) {
|
|
248
|
+
const item = items[i];
|
|
249
|
+
if (item.kind === 'file') {
|
|
250
|
+
const file = item.getAsFile();
|
|
251
|
+
if (file && !isDuplicate(file)) {
|
|
252
|
+
console.log(`[UploadButton] handlePaste: Adding file from items array:`, file);
|
|
253
|
+
files.push(file);
|
|
254
|
+
} else if (file) {
|
|
255
|
+
console.log(`[UploadButton] handlePaste: Duplicate file skipped from items array:`, file);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (files.length > 0) {
|
|
262
|
+
console.log(`[UploadButton] handlePaste: ${files.length} file(s) to process from paste`, files);
|
|
263
|
+
e.preventDefault();
|
|
264
|
+
handleUnifiedFileSelection(files);
|
|
265
|
+
} else {
|
|
266
|
+
console.log('[UploadButton] handlePaste: No files found in paste event.');
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// Add paste listener to document
|
|
271
|
+
document.addEventListener('paste', handlePaste);
|
|
272
|
+
return () => {
|
|
273
|
+
document.removeEventListener('paste', handlePaste);
|
|
274
|
+
};
|
|
275
|
+
}, [handleUnifiedFileSelection]);
|
|
276
|
+
|
|
277
|
+
// Drag and drop handlers
|
|
278
|
+
useEffect(() => {
|
|
279
|
+
let dragCounter = 0;
|
|
280
|
+
|
|
281
|
+
const handleDragEnter = (e: DragEvent) => {
|
|
282
|
+
e.preventDefault();
|
|
283
|
+
e.stopPropagation();
|
|
284
|
+
dragCounter++;
|
|
285
|
+
if (dragCounter === 1) {
|
|
286
|
+
setIsDragging(true);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const handleDragLeave = (e: DragEvent) => {
|
|
291
|
+
e.preventDefault();
|
|
292
|
+
e.stopPropagation();
|
|
293
|
+
dragCounter--;
|
|
294
|
+
if (dragCounter === 0) {
|
|
295
|
+
setIsDragging(false);
|
|
101
296
|
}
|
|
102
297
|
};
|
|
103
298
|
|
|
104
|
-
|
|
299
|
+
const handleDragOver = (e: DragEvent) => {
|
|
300
|
+
e.preventDefault();
|
|
301
|
+
e.stopPropagation();
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const handleDrop = (e: DragEvent) => {
|
|
305
|
+
e.preventDefault();
|
|
306
|
+
e.stopPropagation();
|
|
307
|
+
dragCounter = 0;
|
|
308
|
+
setIsDragging(false);
|
|
309
|
+
|
|
310
|
+
const files = e.dataTransfer?.files;
|
|
311
|
+
if (files && files.length > 0) {
|
|
312
|
+
handleUnifiedFileSelection(files);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// Add drag and drop listeners to document
|
|
317
|
+
document.addEventListener('dragenter', handleDragEnter);
|
|
318
|
+
document.addEventListener('dragleave', handleDragLeave);
|
|
319
|
+
document.addEventListener('dragover', handleDragOver);
|
|
320
|
+
document.addEventListener('drop', handleDrop);
|
|
321
|
+
|
|
105
322
|
return () => {
|
|
106
|
-
document.removeEventListener('
|
|
323
|
+
document.removeEventListener('dragenter', handleDragEnter);
|
|
324
|
+
document.removeEventListener('dragleave', handleDragLeave);
|
|
325
|
+
document.removeEventListener('dragover', handleDragOver);
|
|
326
|
+
document.removeEventListener('drop', handleDrop);
|
|
107
327
|
};
|
|
108
|
-
}, []);
|
|
328
|
+
}, [handleUnifiedFileSelection]);
|
|
109
329
|
|
|
110
330
|
// Handler for document files - now supports multiple documents
|
|
111
331
|
const handleDocumentFiles = (
|
|
@@ -161,6 +381,7 @@ ${file.content}
|
|
|
161
381
|
'.xlsx',
|
|
162
382
|
'.csv',
|
|
163
383
|
'.md',
|
|
384
|
+
'.html',
|
|
164
385
|
];
|
|
165
386
|
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
166
387
|
|
|
@@ -267,56 +488,6 @@ ${file.content}
|
|
|
267
488
|
addError(error);
|
|
268
489
|
};
|
|
269
490
|
|
|
270
|
-
// When document option is clicked
|
|
271
|
-
const handleDocumentClick = () => {
|
|
272
|
-
// Check if document limit has been reached
|
|
273
|
-
if (hasReachedDocumentLimit) {
|
|
274
|
-
addError({
|
|
275
|
-
message: `Maximum ${MAX_DOCUMENTS} documents allowed.`,
|
|
276
|
-
severity: 'error',
|
|
277
|
-
});
|
|
278
|
-
closeMenu();
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Find the actual button in the UploadDocuments component and click it
|
|
283
|
-
const documentButtonElement = documentRef.current?.querySelector('button');
|
|
284
|
-
if (documentButtonElement) {
|
|
285
|
-
documentButtonElement.click();
|
|
286
|
-
}
|
|
287
|
-
closeMenu();
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// When image option is clicked
|
|
291
|
-
const handleImageClick = () => {
|
|
292
|
-
if (!isMediaAccepted) {
|
|
293
|
-
addError({
|
|
294
|
-
message:
|
|
295
|
-
t('upload.mediaNotAccepted') ?? 'Media uploads are not accepted',
|
|
296
|
-
severity: 'info',
|
|
297
|
-
});
|
|
298
|
-
closeMenu();
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (hasReachedImageLimit) {
|
|
303
|
-
addError({
|
|
304
|
-
message:
|
|
305
|
-
t('upload.maxImagesReached', { max: MAX_IMAGES }) ??
|
|
306
|
-
`Maximum ${MAX_IMAGES} images already uploaded`,
|
|
307
|
-
severity: 'warning',
|
|
308
|
-
});
|
|
309
|
-
closeMenu();
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// If all checks pass, click the button in UploadImages component
|
|
314
|
-
const imageButtonElement = imageRef.current?.querySelector('button');
|
|
315
|
-
if (imageButtonElement) {
|
|
316
|
-
imageButtonElement.click();
|
|
317
|
-
}
|
|
318
|
-
closeMenu();
|
|
319
|
-
};
|
|
320
491
|
|
|
321
492
|
// Set loading state for child components
|
|
322
493
|
const handleLoadingChange = (loading: boolean) => {
|
|
@@ -324,7 +495,23 @@ ${file.content}
|
|
|
324
495
|
};
|
|
325
496
|
|
|
326
497
|
return (
|
|
327
|
-
<div
|
|
498
|
+
<div
|
|
499
|
+
className={cx('memori--unified-upload-wrapper', {
|
|
500
|
+
'memori--dragging': isDragging,
|
|
501
|
+
})}
|
|
502
|
+
ref={wrapperRef}
|
|
503
|
+
>
|
|
504
|
+
{/* Unified file input - accepts both images and documents */}
|
|
505
|
+
<input
|
|
506
|
+
ref={unifiedInputRef}
|
|
507
|
+
type="file"
|
|
508
|
+
accept=".jpg,.jpeg,.png,.pdf,.txt,.json,.xlsx,.csv,.md,.html"
|
|
509
|
+
multiple
|
|
510
|
+
className="memori--upload-file-input"
|
|
511
|
+
onChange={handleFileInputChange}
|
|
512
|
+
style={{ display: 'none' }}
|
|
513
|
+
/>
|
|
514
|
+
|
|
328
515
|
{/* Main upload button */}
|
|
329
516
|
<button
|
|
330
517
|
ref={buttonRef}
|
|
@@ -337,9 +524,9 @@ ${file.content}
|
|
|
337
524
|
'memori--unified-upload-button',
|
|
338
525
|
{ 'memori--error': errors.length > 0 }
|
|
339
526
|
)}
|
|
340
|
-
onClick={
|
|
341
|
-
disabled={isLoading}
|
|
342
|
-
title={t('upload.uploadFiles') ?? 'Upload files'}
|
|
527
|
+
onClick={handleButtonClick}
|
|
528
|
+
disabled={isLoading || hasReachedMediaLimit}
|
|
529
|
+
title={t('upload.uploadFiles', { shortcut: /Mac|iPhone|iPod|iPad/i.test(navigator.platform) || navigator.userAgent.includes('Mac') ? 'Cmd' : 'Ctrl' }) ?? 'Upload files (drag & drop)'}
|
|
343
530
|
>
|
|
344
531
|
{isLoading ? (
|
|
345
532
|
<Spin spinning className="memori--upload-icon" />
|
|
@@ -348,94 +535,14 @@ ${file.content}
|
|
|
348
535
|
)}
|
|
349
536
|
</button>
|
|
350
537
|
|
|
351
|
-
{/*
|
|
352
|
-
{
|
|
353
|
-
<div
|
|
354
|
-
className={cx('memori--image-count', {
|
|
355
|
-
'memori--image-count-full': hasReachedImageLimit,
|
|
356
|
-
})}
|
|
357
|
-
>
|
|
358
|
-
{currentImageCount}/{MAX_IMAGES}
|
|
359
|
-
</div>
|
|
360
|
-
)}
|
|
361
|
-
|
|
362
|
-
{/* Document count indicator */}
|
|
363
|
-
{currentDocumentCount > 0 && (
|
|
538
|
+
{/* Media count indicator */}
|
|
539
|
+
{currentMediaCount > 0 && (
|
|
364
540
|
<div
|
|
365
541
|
className={cx('memori--document-count', {
|
|
366
|
-
'memori--document-count-full':
|
|
542
|
+
'memori--document-count-full': hasReachedMediaLimit,
|
|
367
543
|
})}
|
|
368
544
|
>
|
|
369
|
-
{
|
|
370
|
-
</div>
|
|
371
|
-
)}
|
|
372
|
-
|
|
373
|
-
{/* Floating menu */}
|
|
374
|
-
{menuOpen && (
|
|
375
|
-
<div className="memori--upload-menu" ref={menuRef}>
|
|
376
|
-
<div
|
|
377
|
-
className={cx('memori--upload-menu-item', {
|
|
378
|
-
'memori--upload-menu-item--disabled': hasReachedDocumentLimit,
|
|
379
|
-
})}
|
|
380
|
-
onClick={handleDocumentClick}
|
|
381
|
-
title={
|
|
382
|
-
hasReachedDocumentLimit
|
|
383
|
-
? t('upload.maxDocumentsReached', { max: MAX_DOCUMENTS }) ??
|
|
384
|
-
`Maximum ${MAX_DOCUMENTS} documents already uploaded`
|
|
385
|
-
: remainingDocumentSlots === 1
|
|
386
|
-
? t('upload.lastDocumentSlot') ?? 'Upload last document'
|
|
387
|
-
: t('upload.uploadDocument', {
|
|
388
|
-
remaining: remainingDocumentSlots,
|
|
389
|
-
}) ?? `Upload document (${remainingDocumentSlots} remaining)`
|
|
390
|
-
}
|
|
391
|
-
>
|
|
392
|
-
<DocumentIcon className="memori--upload-menu-icon" />
|
|
393
|
-
<span>
|
|
394
|
-
{t('upload.uploadDocument') ?? 'Upload document'}
|
|
395
|
-
{/* {currentDocumentCount > 0 && (
|
|
396
|
-
<span className="memori--upload-slots-info">
|
|
397
|
-
{hasReachedDocumentLimit
|
|
398
|
-
? ` (${t('upload.maxReached') ?? 'Max reached'})`
|
|
399
|
-
: ` (${remainingDocumentSlots} ${
|
|
400
|
-
t('upload.remaining') ?? 'remaining'
|
|
401
|
-
})`}
|
|
402
|
-
</span>
|
|
403
|
-
)} */}
|
|
404
|
-
</span>
|
|
405
|
-
</div>
|
|
406
|
-
|
|
407
|
-
<div
|
|
408
|
-
className={cx('memori--upload-menu-item', {
|
|
409
|
-
'memori--upload-menu-item--disabled':
|
|
410
|
-
!isMediaAccepted || hasReachedImageLimit,
|
|
411
|
-
})}
|
|
412
|
-
onClick={handleImageClick}
|
|
413
|
-
title={
|
|
414
|
-
!isMediaAccepted
|
|
415
|
-
? t('upload.mediaNotAccepted') ?? 'Media uploads not accepted'
|
|
416
|
-
: hasReachedImageLimit
|
|
417
|
-
? t('upload.maxImagesReached', { max: MAX_IMAGES }) ??
|
|
418
|
-
`Maximum ${MAX_IMAGES} images already uploaded`
|
|
419
|
-
: remainingSlots === 1
|
|
420
|
-
? t('upload.lastImageSlot') ?? 'Upload last image'
|
|
421
|
-
: t('upload.uploadImage', { remaining: remainingSlots }) ??
|
|
422
|
-
`Upload image (${remainingSlots} remaining)`
|
|
423
|
-
}
|
|
424
|
-
>
|
|
425
|
-
<ImageIcon className="memori--upload-menu-icon-image" />
|
|
426
|
-
<span>
|
|
427
|
-
{t('upload.uploadImage') ?? 'Upload image'}
|
|
428
|
-
{/* {currentImageCount > 0 && (
|
|
429
|
-
<span className="memori--upload-slots-info">
|
|
430
|
-
{hasReachedImageLimit
|
|
431
|
-
? ` (${t('upload.maxReached') ?? 'Max reached'})`
|
|
432
|
-
: ` (${remainingSlots} ${
|
|
433
|
-
t('upload.remaining') ?? 'remaining'
|
|
434
|
-
})`}
|
|
435
|
-
</span>
|
|
436
|
-
)} */}
|
|
437
|
-
</span>
|
|
438
|
-
</div>
|
|
545
|
+
{currentMediaCount}/{MAX_MEDIA}
|
|
439
546
|
</div>
|
|
440
547
|
)}
|
|
441
548
|
|
|
@@ -443,7 +550,7 @@ ${file.content}
|
|
|
443
550
|
<div className="memori--hidden-uploader" ref={documentRef}>
|
|
444
551
|
<UploadDocuments
|
|
445
552
|
setDocumentPreviewFiles={handleDocumentFiles}
|
|
446
|
-
maxDocuments={
|
|
553
|
+
maxDocuments={MAX_MEDIA}
|
|
447
554
|
documentPreviewFiles={documentPreviewFiles}
|
|
448
555
|
onLoadingChange={handleLoadingChange}
|
|
449
556
|
onDocumentError={handleDocumentError}
|
|
@@ -461,7 +568,7 @@ ${file.content}
|
|
|
461
568
|
documentPreviewFiles={documentPreviewFiles}
|
|
462
569
|
isMediaAccepted={isMediaAccepted}
|
|
463
570
|
onLoadingChange={handleLoadingChange}
|
|
464
|
-
maxImages={
|
|
571
|
+
maxImages={MAX_MEDIA}
|
|
465
572
|
memoriID={memoriID}
|
|
466
573
|
onImageError={handleImageError}
|
|
467
574
|
onValidateImageFile={validateImageFile}
|
|
@@ -220,7 +220,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
220
220
|
|
|
221
221
|
if (fileExt === 'pdf') {
|
|
222
222
|
text = await extractTextFromPDF(file);
|
|
223
|
-
} else if (['txt', 'md', 'json', 'csv'].includes(fileExt)) {
|
|
223
|
+
} else if (['txt', 'md', 'json', 'csv', 'html'].includes(fileExt)) {
|
|
224
224
|
text = await file.text();
|
|
225
225
|
} else if (fileExt === 'xlsx') {
|
|
226
226
|
text = await extractTextFromXLSX(file);
|
|
@@ -258,6 +258,21 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
258
258
|
const files = Array.from(e.target.files || []);
|
|
259
259
|
if (files.length === 0) return;
|
|
260
260
|
|
|
261
|
+
// Check current total media count (images + documents)
|
|
262
|
+
const currentMediaCount = documentPreviewFiles.length;
|
|
263
|
+
|
|
264
|
+
// Check if adding these files would exceed the total media limit
|
|
265
|
+
if (maxDocuments && currentMediaCount + files.length > maxDocuments) {
|
|
266
|
+
onDocumentError?.({
|
|
267
|
+
message: `Maximum ${maxDocuments} media files allowed. You can upload ${Math.max(0, maxDocuments - currentMediaCount)} more file${maxDocuments - currentMediaCount !== 1 ? 's' : ''}.`,
|
|
268
|
+
severity: 'error',
|
|
269
|
+
});
|
|
270
|
+
if (documentInputRef.current) {
|
|
271
|
+
documentInputRef.current.value = '';
|
|
272
|
+
}
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
261
276
|
setIsLoading(true);
|
|
262
277
|
|
|
263
278
|
// Process each file
|
|
@@ -335,7 +350,8 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
335
350
|
<input
|
|
336
351
|
ref={documentInputRef}
|
|
337
352
|
type="file"
|
|
338
|
-
accept=".pdf,.txt,.md,.json,.xlsx,.csv"
|
|
353
|
+
accept=".pdf,.txt,.md,.json,.xlsx,.csv,.html"
|
|
354
|
+
multiple
|
|
339
355
|
className="memori--upload-file-input"
|
|
340
356
|
onChange={handleDocumentUpload}
|
|
341
357
|
/>
|
|
@@ -355,8 +371,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
355
371
|
disabled={
|
|
356
372
|
isLoading ||
|
|
357
373
|
(maxDocuments &&
|
|
358
|
-
documentPreviewFiles.
|
|
359
|
-
.length >= maxDocuments) ||
|
|
374
|
+
documentPreviewFiles.length >= maxDocuments) ||
|
|
360
375
|
false
|
|
361
376
|
}
|
|
362
377
|
title="Upload documents"
|