@groupeactual/ui-kit 1.7.10 → 2.0.0-beta.1

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 (143) hide show
  1. package/dist/cjs/index.js +15095 -66
  2. package/dist/es/{src/DesignSystemProvider.d.ts → DesignSystemProvider.d.ts} +6 -5
  3. package/dist/es/{src/components → components}/Accordion/Accordion.d.ts +1 -1
  4. package/dist/es/{src/components → components}/BannerNotification/BannerNotification.d.ts +1 -1
  5. package/dist/es/{src/components → components}/Breadcrumbs/Breadcrumbs.d.ts +2 -2
  6. package/dist/es/{src/components → components}/Button/Button.d.ts +2 -2
  7. package/dist/es/{src/components → components}/Chip/Chip.d.ts +1 -1
  8. package/dist/es/components/Datatable/Datatable.d.ts +4 -0
  9. package/dist/es/{src/components → components}/EmbbededNotification/EmbeddedNotification.d.ts +1 -1
  10. package/dist/es/{src/components/UploadDocument → components/FileUploader}/FileUploader.d.ts +1 -1
  11. package/dist/es/components/Form/AutoCompleteMulti/AutoCompleteMulti.d.ts +23 -0
  12. package/dist/es/{src/components → components}/Form/AutoCompleteSingle/AutoCompleteSingle.d.ts +8 -5
  13. package/dist/es/components/Form/Checkbox/Checkbox.d.ts +12 -0
  14. package/dist/es/components/Form/CheckboxGroup/CheckboxGroup.d.ts +12 -0
  15. package/dist/es/components/Form/CheckboxGroup/checkboxgroup.interface.d.ts +6 -0
  16. package/dist/es/{src/components → components}/Form/DatePicker/DatePicker.d.ts +6 -4
  17. package/dist/es/{src/components → components}/Form/MultiSelect/MultiSelect.d.ts +3 -3
  18. package/dist/es/components/Form/RadioGroup/RadioGroup.d.ts +16 -0
  19. package/dist/es/{src/components → components}/Form/Select/Select.d.ts +3 -3
  20. package/dist/es/components/Form/Switch/Switch.d.ts +11 -0
  21. package/dist/es/{src/components → components}/Form/TextField/TextField.d.ts +6 -5
  22. package/dist/es/{src/components → components}/Form/TimePicker/TimePicker.d.ts +3 -3
  23. package/dist/es/{src/components → components}/IconButton/IconButton.d.ts +3 -3
  24. package/dist/es/components/IconProvider/IconProvider.d.ts +24 -0
  25. package/dist/es/{src/components → components}/Link/Link.d.ts +1 -2
  26. package/dist/es/components/MenuItem/MenuItem.d.ts +9 -0
  27. package/dist/es/components/Modal/Dialog/Dialog.d.ts +4 -0
  28. package/dist/es/components/Modal/Drawer/Drawer.d.ts +4 -0
  29. package/dist/es/{src/components → components}/Navigation/Stepper/Stepper.d.ts +1 -1
  30. package/dist/es/{src/components → components}/Pagination/Pagination.d.ts +2 -1
  31. package/dist/es/{src/components → components}/Snackbar/Snackbar.d.ts +1 -1
  32. package/dist/es/components/TabsPanel/TabsPanel.d.ts +4 -0
  33. package/dist/es/components/TabsPanel/index.d.ts +1 -0
  34. package/dist/es/components/TabsPanel/tab.interface.d.ts +17 -0
  35. package/dist/es/components/Text/Text.d.ts +8 -0
  36. package/dist/es/{src/components → components}/Tooltip/Tooltip.d.ts +1 -1
  37. package/dist/es/{src/components → components}/index.d.ts +3 -2
  38. package/dist/es/index.d.ts +104 -152
  39. package/dist/es/index.js +37 -79
  40. package/package.json +20 -17
  41. package/src/DesignSystemProvider.tsx +21 -36
  42. package/src/components/Accordion/Accordion.tsx +41 -59
  43. package/src/components/BannerNotification/BannerNotification.tsx +19 -20
  44. package/src/components/Breadcrumbs/Breadcrumbs.tsx +32 -28
  45. package/src/components/Button/Button.tsx +70 -17
  46. package/src/components/Chip/Chip.tsx +88 -117
  47. package/src/components/Datatable/Datatable.tsx +49 -37
  48. package/src/components/Datatable/DatatableCellRender.tsx +1 -1
  49. package/src/components/EmbbededNotification/EmbeddedNotification.tsx +78 -69
  50. package/src/components/FileUploader/FileUploader.tsx +767 -0
  51. package/src/components/Form/AutoCompleteMulti/AutoCompleteMulti.tsx +289 -172
  52. package/src/components/Form/AutoCompleteSingle/AutoCompleteSingle.tsx +228 -126
  53. package/src/components/Form/Checkbox/Checkbox.tsx +38 -96
  54. package/src/components/Form/CheckboxGroup/CheckboxGroup.tsx +86 -60
  55. package/src/components/Form/CheckboxGroup/checkboxgroup.interface.ts +0 -15
  56. package/src/components/Form/DatePicker/DatePicker.tsx +88 -40
  57. package/src/components/Form/MultiSelect/MultiSelect.tsx +196 -171
  58. package/src/components/Form/RadioGroup/RadioGroup.tsx +76 -82
  59. package/src/components/Form/Select/Select.tsx +156 -136
  60. package/src/components/Form/Switch/Switch.tsx +87 -47
  61. package/src/components/Form/TextField/TextField.tsx +125 -76
  62. package/src/components/Form/TimePicker/TimePicker.tsx +26 -7
  63. package/src/components/IconButton/IconButton.tsx +64 -39
  64. package/src/components/IconProvider/IconProvider.tsx +88 -69
  65. package/src/components/Link/Link.tsx +6 -10
  66. package/src/components/MenuItem/MenuItem.tsx +35 -23
  67. package/src/components/Modal/Dialog/Dialog.tsx +17 -14
  68. package/src/components/Modal/Drawer/Drawer.tsx +95 -74
  69. package/src/components/Navigation/Stepper/Step.tsx +7 -6
  70. package/src/components/Navigation/Stepper/Stepper.tsx +24 -23
  71. package/src/components/NotistackAdapter/NotistackAdapter.tsx +1 -1
  72. package/src/components/Pagination/Pagination.tsx +131 -118
  73. package/src/components/Snackbar/Snackbar.tsx +29 -29
  74. package/src/components/TabsPanel/TabsPanel.tsx +151 -0
  75. package/src/components/TabsPanel/index.ts +1 -0
  76. package/src/components/TabsPanel/tab.interface.ts +20 -0
  77. package/src/components/Text/Text.tsx +25 -12
  78. package/src/components/Tooltip/Tooltip.tsx +54 -51
  79. package/src/components/index.ts +3 -2
  80. package/src/index.ts +0 -1
  81. package/dist/es/src/components/Datatable/Datatable.d.ts +0 -4
  82. package/dist/es/src/components/Form/AutoCompleteMulti/AutoCompleteMulti.d.ts +0 -19
  83. package/dist/es/src/components/Form/Checkbox/Checkbox.d.ts +0 -14
  84. package/dist/es/src/components/Form/CheckboxGroup/CheckboxGroup.d.ts +0 -12
  85. package/dist/es/src/components/Form/CheckboxGroup/checkboxgroup.interface.d.ts +0 -8
  86. package/dist/es/src/components/Form/RadioGroup/RadioGroup.d.ts +0 -18
  87. package/dist/es/src/components/Form/Switch/Switch.d.ts +0 -10
  88. package/dist/es/src/components/IconProvider/IconProvider.d.ts +0 -19
  89. package/dist/es/src/components/MenuItem/MenuItem.d.ts +0 -10
  90. package/dist/es/src/components/Modal/Dialog/Dialog.d.ts +0 -4
  91. package/dist/es/src/components/Modal/Drawer/Drawer.d.ts +0 -4
  92. package/dist/es/src/components/Text/Text.d.ts +0 -8
  93. package/dist/es/src/index.d.ts +0 -5
  94. package/dist/es/src/interfaces/theme.d.ts +0 -51
  95. package/src/components/UploadDocument/FileUploader.tsx +0 -728
  96. package/src/interfaces/theme.ts +0 -51
  97. /package/dist/es/{src/components → components}/Accordion/index.d.ts +0 -0
  98. /package/dist/es/{src/components → components}/BannerNotification/index.d.ts +0 -0
  99. /package/dist/es/{src/components → components}/Breadcrumbs/index.d.ts +0 -0
  100. /package/dist/es/{src/components → components}/Button/index.d.ts +0 -0
  101. /package/dist/es/{src/components → components}/Chip/index.d.ts +0 -0
  102. /package/dist/es/{src/components → components}/Datatable/DatatableCellRender.d.ts +0 -0
  103. /package/dist/es/{src/components → components}/Datatable/datatable.interface.d.ts +0 -0
  104. /package/dist/es/{src/components → components}/Datatable/index.d.ts +0 -0
  105. /package/dist/es/{src/components → components}/Datatable/use-pagination-props.hook.d.ts +0 -0
  106. /package/dist/es/{src/components → components}/EmbbededNotification/index.d.ts +0 -0
  107. /package/dist/es/{src/components/UploadDocument → components/FileUploader}/fileuploader.interface.d.ts +0 -0
  108. /package/dist/es/{src/components/UploadDocument → components/FileUploader}/index.d.ts +0 -0
  109. /package/dist/es/{src/components → components}/Form/AutoCompleteMulti/index.d.ts +0 -0
  110. /package/dist/es/{src/components → components}/Form/AutoCompleteSingle/index.d.ts +0 -0
  111. /package/dist/es/{src/components → components}/Form/Checkbox/index.d.ts +0 -0
  112. /package/dist/es/{src/components → components}/Form/CheckboxGroup/index.d.ts +0 -0
  113. /package/dist/es/{src/components → components}/Form/DatePicker/index.d.ts +0 -0
  114. /package/dist/es/{src/components → components}/Form/MultiSelect/index.d.ts +0 -0
  115. /package/dist/es/{src/components → components}/Form/RadioGroup/index.d.ts +0 -0
  116. /package/dist/es/{src/components → components}/Form/Select/index.d.ts +0 -0
  117. /package/dist/es/{src/components → components}/Form/Switch/index.d.ts +0 -0
  118. /package/dist/es/{src/components → components}/Form/TextField/index.d.ts +0 -0
  119. /package/dist/es/{src/components → components}/Form/TimePicker/index.d.ts +0 -0
  120. /package/dist/es/{src/components → components}/IconButton/index.d.ts +0 -0
  121. /package/dist/es/{src/components → components}/IconProvider/index.d.ts +0 -0
  122. /package/dist/es/{src/components → components}/Link/index.d.ts +0 -0
  123. /package/dist/es/{src/components → components}/MenuItem/index.d.ts +0 -0
  124. /package/dist/es/{src/components → components}/Modal/Dialog/index.d.ts +0 -0
  125. /package/dist/es/{src/components → components}/Modal/Drawer/index.d.ts +0 -0
  126. /package/dist/es/{src/components → components}/Modal/modal.interface.d.ts +0 -0
  127. /package/dist/es/{src/components → components}/Navigation/Stepper/Step.d.ts +0 -0
  128. /package/dist/es/{src/components → components}/Navigation/Stepper/index.d.ts +0 -0
  129. /package/dist/es/{src/components → components}/Navigation/Stepper/stepper.helper.d.ts +0 -0
  130. /package/dist/es/{src/components → components}/Navigation/Stepper/stepper.interface.d.ts +0 -0
  131. /package/dist/es/{src/components → components}/NotistackAdapter/NotistackAdapter.d.ts +0 -0
  132. /package/dist/es/{src/components → components}/NotistackAdapter/index.d.ts +0 -0
  133. /package/dist/es/{src/components → components}/Pagination/index.d.ts +0 -0
  134. /package/dist/es/{src/components → components}/Pagination/pagination.helper.d.ts +0 -0
  135. /package/dist/es/{src/components → components}/Snackbar/index.d.ts +0 -0
  136. /package/dist/es/{src/components → components}/Text/index.d.ts +0 -0
  137. /package/dist/es/{src/components → components}/Tooltip/index.d.ts +0 -0
  138. /package/dist/es/{src/components → components}/Tooltip/tooltip.interface.d.ts +0 -0
  139. /package/dist/es/{src/helpers → helpers}/GooglePickerWrapper.d.ts +0 -0
  140. /package/dist/es/{src/hooks → hooks}/useGooleDrivePicker.d.ts +0 -0
  141. /package/dist/es/{src/types → types}/googleDrive.d.ts +0 -0
  142. /package/src/components/{UploadDocument → FileUploader}/fileuploader.interface.ts +0 -0
  143. /package/src/components/{UploadDocument → FileUploader}/index.ts +0 -0
@@ -1,728 +0,0 @@
1
- import React, {
2
- ChangeEvent,
3
- DragEvent,
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useRef,
8
- useState,
9
- } from 'react';
10
-
11
- import { faGoogleDrive } from '@fortawesome/free-brands-svg-icons';
12
- import {
13
- faEye,
14
- faFolderOpen,
15
- faTrash,
16
- faUpload,
17
- } from '@fortawesome/pro-regular-svg-icons';
18
- import {
19
- faCaretDown,
20
- faFile,
21
- faInfoCircle,
22
- } from '@fortawesome/pro-solid-svg-icons';
23
- import { Box, IconButton } from '@mui/material';
24
- import Menu from '@mui/material/Menu';
25
-
26
- import Button from '@/components/Button';
27
- import IconProvider from '@/components/IconProvider';
28
- import MenuItem from '@/components/MenuItem';
29
- import Text from '@/components/Text';
30
- import Tooltip from '@/components/Tooltip';
31
- import GooglePickerWrapper from '@/helpers/GooglePickerWrapper';
32
-
33
- import {
34
- AcceptTextType,
35
- FileDataType,
36
- GoogleDriveFile,
37
- } from './fileuploader.interface';
38
-
39
- interface Props {
40
- title?: string;
41
- subTitle?: string;
42
- titleAddButton?: string;
43
- helperText?: string;
44
- titleTooltip?: string;
45
- files?: FileDataType[];
46
- isMulti?: boolean;
47
- accept?: string[];
48
- acceptText?: AcceptTextType;
49
- orText?: string;
50
- fromLocalText?: string;
51
- fromGoogleDriveText?: string;
52
- disabled?: boolean;
53
- error?: string;
54
- enableGoogleDrive?: boolean;
55
- googleAuthClientId?: string;
56
- googleApiKey?: string;
57
- _isDroppingFile?: boolean; // * Only used for storybook
58
- validateFile?: (
59
- _size: number,
60
- _type: string,
61
- _accept: string[],
62
- _setUploadFileError: React.Dispatch<React.SetStateAction<boolean | string>>,
63
- ) => boolean;
64
- onTouched?: () => void;
65
- onFilesDataChange?: (_fileData: FileDataType[] | undefined) => void;
66
- }
67
-
68
- const FileUploader = ({
69
- title = '',
70
- subTitle = 'Déposer un fichier ici',
71
- titleAddButton = 'Ajouter un fichier',
72
- helperText = '',
73
- titleTooltip,
74
- files = [],
75
- isMulti = false,
76
- accept = [],
77
- acceptText = { fileFormat: '', maxSize: '', subText: '' },
78
- orText = 'ou',
79
- fromLocalText = 'Depuis votre PC',
80
- fromGoogleDriveText = 'Depuis Google Drive',
81
- disabled = false,
82
- error,
83
- enableGoogleDrive = false,
84
- googleAuthClientId,
85
- googleApiKey,
86
- _isDroppingFile = false,
87
- validateFile,
88
- onTouched,
89
- onFilesDataChange,
90
- }: Props) => {
91
- const DEFAULT_COLOR = '%23CBCBCB';
92
- const ERROR_COLOR = '%23b80025';
93
- const DROPPING_COLOR = '%23004F88';
94
-
95
- // * States
96
- const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
97
- // * filesData is used to display the files in the component
98
- const [filesData, setFilesData] = useState<FileDataType[] | undefined>(
99
- undefined,
100
- );
101
- const [isDroppingFile, setIsDroppingFile] =
102
- useState<boolean>(_isDroppingFile);
103
- // * uploadFileError is used to display the error message when the file is not valid from the validateFile function
104
- const [uploadFileError, setUploadFileError] = useState<string | boolean>(
105
- false,
106
- );
107
- const [isInitialized, setIsInitialized] = useState(false);
108
-
109
- // * Refs
110
- const fileInputRef = useRef<HTMLInputElement | null>(null);
111
-
112
- // * Colors
113
- const dashedColor = useMemo(() => {
114
- if ((!isMulti && filesData?.[0]?.name) || disabled) return DEFAULT_COLOR;
115
- if (isDroppingFile) return DROPPING_COLOR;
116
- if (error || uploadFileError !== false) return ERROR_COLOR;
117
- return DEFAULT_COLOR;
118
- }, [isDroppingFile, error, uploadFileError]);
119
-
120
- const bgColor = useMemo(() => {
121
- if ((!isMulti && filesData?.[0]?.name) || disabled) return 'greyXLight';
122
- if (isDroppingFile) return 'blueHoverEquivalence';
123
- return 'white';
124
- }, [filesData?.length, disabled, isDroppingFile]);
125
-
126
- const titleColor = useMemo(() => {
127
- if (!isMulti && filesData?.[0]?.name) return 'greyDark';
128
- if (error || uploadFileError !== false) return 'redError';
129
- return 'greyXDark';
130
- }, [filesData?.length, error, uploadFileError]);
131
-
132
- // * Styles
133
- const inputCss = useMemo(
134
- () => ({
135
- height: '87px',
136
- backgroundImage: `url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='4' ry='4' stroke='${dashedColor}' stroke-width='2' stroke-dasharray='8%2c 8' stroke-dashoffset='0' stroke-linecap='round'/%3e%3c/svg%3e")`,
137
- borderRadius: '4px',
138
- py: '24px',
139
- px: '22px',
140
- display: 'flex',
141
- justifyContent: 'space-between',
142
- position: 'relative',
143
- alignItems: 'center',
144
- overflow: 'hidden',
145
- backgroundColor: bgColor,
146
- }),
147
- [dashedColor, bgColor],
148
- );
149
-
150
- // * Events handlers
151
- const handleClick = (event: React.MouseEvent<HTMLElement>) => {
152
- setAnchorEl(event.currentTarget);
153
- };
154
- const handleClose = () => {
155
- setAnchorEl(null);
156
- };
157
-
158
- const handleDragOver = (event: DragEvent<HTMLDivElement>) => {
159
- event.preventDefault();
160
- event.stopPropagation();
161
-
162
- if ((!isMulti && filesData?.[0]?.name) || disabled) return;
163
-
164
- setIsDroppingFile(true);
165
- };
166
-
167
- const handleDragLeave = (event: DragEvent<HTMLDivElement>) => {
168
- event.preventDefault();
169
- event.stopPropagation();
170
-
171
- if ((!isMulti && filesData?.[0]?.name) || disabled) return;
172
-
173
- setIsDroppingFile(false);
174
- };
175
-
176
- // * Handle file change and file deletion
177
- const handleFileChange = useCallback(
178
- async (
179
- _event: ChangeEvent<HTMLInputElement> | null,
180
- data?: {
181
- docs: GoogleDriveFile[];
182
- } | null,
183
- token: string | null = null,
184
- accept: string[] = [],
185
- fakeClick?: boolean,
186
- ) => {
187
- if (fakeClick) {
188
- fileInputRef?.current?.click();
189
- return;
190
- }
191
-
192
- handleClose();
193
- onTouched?.();
194
-
195
- if (token && data && data.docs && data.docs.length > 0) {
196
- // * Google Drive
197
- const validDocs = data.docs.filter((doc) =>
198
- validateFile
199
- ? validateFile(
200
- doc.sizeBytes,
201
- doc.mimeType,
202
- accept,
203
- setUploadFileError,
204
- )
205
- : true,
206
- );
207
-
208
- const googleFileData = await Promise.all(
209
- validDocs.map(async (doc) => {
210
- const baseUrl = `https://www.googleapis.com/drive/v3/files/${doc.id}`;
211
- const params = new URLSearchParams({
212
- alt: 'media',
213
- supportsAllDrives: 'true',
214
- });
215
-
216
- const url = `${baseUrl}?${params}`;
217
-
218
- const response = await fetch(url, {
219
- method: 'GET',
220
- headers: {
221
- Authorization: `Bearer ${token}`,
222
- },
223
- });
224
-
225
- const blob = await response.blob();
226
-
227
- let file: File | undefined = undefined;
228
-
229
- if (response.status === 200) {
230
- file = new File([blob], doc.name, {
231
- type: doc.mimeType,
232
- });
233
- }
234
-
235
- return {
236
- name: doc.name,
237
- size: Math.round(doc.sizeBytes / 1024), // * Convert size to KB
238
- type: doc.mimeType,
239
- url: `https://drive.google.com/file/d/${doc.id}/view?usp=drive_we`,
240
- file: file,
241
- driveFileId: doc.id,
242
- driveAccessToken: token,
243
- };
244
- }),
245
- );
246
-
247
- setFilesData([...(filesData || []), ...googleFileData]);
248
- } else if (
249
- fileInputRef.current?.files &&
250
- fileInputRef.current?.files?.length > 0
251
- ) {
252
- // * Local Files
253
- const fileList = Array.from(fileInputRef.current?.files);
254
-
255
- const newFileData: FileDataType[] = fileList
256
- .map((file) => {
257
- if (
258
- validateFile &&
259
- !validateFile(file.size, file.type, accept, setUploadFileError)
260
- ) {
261
- setIsDroppingFile(false);
262
- return null;
263
- }
264
-
265
- return {
266
- name: file?.name ?? '',
267
- size: Math.round(file.size / 1024),
268
- type: file.type,
269
- url: URL.createObjectURL(file),
270
- file: file,
271
- };
272
- })
273
- .filter((file) => file !== null);
274
-
275
- if (newFileData && newFileData?.length > 0) {
276
- setFilesData([...(filesData || []), ...newFileData]);
277
- }
278
- }
279
-
280
- setIsDroppingFile(false);
281
- },
282
- [
283
- fileInputRef,
284
- filesData,
285
- setIsDroppingFile,
286
- setFilesData,
287
- validateFile,
288
- onTouched,
289
- handleClose,
290
- ],
291
- );
292
-
293
- const handleDelete = useCallback(
294
- (fileIndex: number) => {
295
- //* Remove the file from the currentFiles array
296
- if (filesData && filesData.length > 0) {
297
- const fileToDelete = filesData[fileIndex]?.file;
298
- if (fileToDelete) {
299
- // * Revoke the object URL to free up memory, use try and catch to avoid errors on the other files not imported with the file input
300
- try {
301
- const fileURL = URL.createObjectURL(fileToDelete);
302
- URL.revokeObjectURL(fileURL);
303
- } catch {
304
- // * Do nothing
305
- }
306
- }
307
- }
308
-
309
- //* Remove the file from the filesData array
310
- if (filesData && filesData.length === 1) {
311
- setFilesData([]);
312
- } else {
313
- setFilesData(
314
- Object.values(filesData || []).filter(
315
- (_, index) => index !== fileIndex,
316
- ),
317
- );
318
- }
319
-
320
- setIsDroppingFile(false);
321
- },
322
- [filesData, setIsDroppingFile, setFilesData],
323
- );
324
-
325
- // * Utils
326
- const extractExtensions = (types: string[]): string[] => {
327
- return types.map((type) => {
328
- const extension = type.split('/')[1].toUpperCase();
329
- return extension;
330
- });
331
- };
332
-
333
- const initializeFiles = async () => {
334
- const initialFiles = await Promise.all(
335
- files.map(async (file) => {
336
- let fileTmp: File | undefined = undefined;
337
-
338
- if (isMulti) {
339
- const response = await fetch(file.url);
340
- const blob = await response.blob();
341
- fileTmp = new File([blob], file.name, {
342
- type: file.type,
343
- });
344
- }
345
-
346
- return {
347
- name: file.name,
348
- size: Math.round(file.size / 1024), // Convert size to KB
349
- type: file.type,
350
- url: file.url,
351
- file: fileTmp,
352
- };
353
- }),
354
- );
355
-
356
- setFilesData(initialFiles);
357
- };
358
-
359
- // * UseEffects
360
-
361
- // * Manage isInitialized state
362
- useEffect(() => {
363
- if (!isInitialized && filesData && filesData.length >= 0) {
364
- setIsInitialized(true);
365
- }
366
- }, [isInitialized, filesData]);
367
-
368
- // * Manage filesData state
369
- useEffect(() => {
370
- if (isInitialized && typeof filesData !== 'undefined') {
371
- onFilesDataChange?.(filesData);
372
- } else if (!isInitialized && typeof filesData === 'undefined') {
373
- initializeFiles();
374
- }
375
- }, [filesData]);
376
-
377
- // * Revoke the object URL to free up memory
378
- useEffect(() => {
379
- return () => {
380
- if (!filesData?.length) return;
381
-
382
- try {
383
- // * Only for file imported with the file input, use try and catch to avoid errors on the other files
384
- filesData.forEach((_fileData) => {
385
- if (_fileData?.file) {
386
- const fileURL = URL.createObjectURL(_fileData?.file);
387
- URL.revokeObjectURL(fileURL);
388
- }
389
- });
390
- } catch {
391
- // * Do nothing
392
- }
393
- };
394
- }, [filesData]);
395
-
396
- return (
397
- <Box
398
- data-testid="Uploader-document"
399
- sx={{
400
- pb: 3,
401
- }}
402
- >
403
- <Box sx={{ display: 'inline-flex', alignItems: 'center' }}>
404
- <Text variant="body2Medium" color={titleColor} pl={1}>
405
- {title}
406
- </Text>
407
- {titleTooltip && (
408
- <Box sx={{ marginLeft: '4px' }}>
409
- <Tooltip
410
- title={titleTooltip}
411
- sx={{
412
- display: 'flex',
413
- }}
414
- >
415
- <IconProvider icon={faInfoCircle} size="sm" color="blueInfo" />
416
- </Tooltip>
417
- </Box>
418
- )}
419
- </Box>
420
-
421
- <Box
422
- mt={1}
423
- p={2}
424
- sx={inputCss}
425
- onDragOver={handleDragOver}
426
- onDragEnter={handleDragOver}
427
- onDragLeave={handleDragLeave}
428
- onDragEnd={handleDragLeave}
429
- >
430
- <Box
431
- sx={{
432
- opacity: 0,
433
- position: 'absolute',
434
- top: '0px',
435
- right: '0px',
436
- width: '100%',
437
- height: '100%',
438
- 'input[type="file"]': {
439
- cursor:
440
- disabled || (filesData?.[0]?.name && !isMulti)
441
- ? 'not-allowed'
442
- : 'pointer',
443
- color: 'transparent',
444
- width: '100%',
445
- height: '100%',
446
- },
447
- }}
448
- >
449
- <input
450
- title=""
451
- data-testid="document-input"
452
- disabled={!!(!isMulti && filesData?.[0]?.name) || disabled}
453
- type="file"
454
- ref={fileInputRef}
455
- onChange={(event) => handleFileChange(event, null, null, accept)}
456
- onBlur={onTouched}
457
- multiple={isMulti}
458
- accept={accept.join(',')}
459
- />
460
- </Box>
461
- <Box sx={{ display: 'flex', flexDirection: 'column' }}>
462
- <Text
463
- variant="body2Medium"
464
- color={
465
- (!isMulti && filesData?.[0]?.name && 'greyDark') || 'greyXDark'
466
- }
467
- >
468
- {subTitle}
469
- </Text>
470
- <Box sx={{ maxWidth: '240px' }}>
471
- <Text
472
- variant="caption"
473
- sx={{
474
- color: 'greyDark',
475
- marginTop: '2px',
476
- }}
477
- >
478
- Format{' '}
479
- {(acceptText?.fileFormat && acceptText?.fileFormat?.trim() !== ''
480
- ? acceptText.fileFormat
481
- : extractExtensions(accept).join(', ')) + ' - '}
482
- {(acceptText.maxSize && acceptText.maxSize) || 'Max. 10 Mo'}
483
- {acceptText.subText && (
484
- <>
485
- <br />
486
- {acceptText.subText}
487
- </>
488
- )}
489
- </Text>
490
- </Box>
491
- </Box>
492
- <Box>
493
- <Text
494
- variant="body2Medium"
495
- color={
496
- (!isMulti && filesData?.[0]?.name && 'greyDark') || 'greyXDark'
497
- }
498
- >
499
- {orText}
500
- </Text>
501
- </Box>
502
- <Box>
503
- {(enableGoogleDrive && (
504
- <>
505
- <Button
506
- variant="secondary"
507
- sx={{
508
- display: 'flex',
509
- '&.MuiButton-secondaryPrimary.Mui-disabled': {
510
- backgroundColor: '#FFFFFF !important',
511
- },
512
- }}
513
- onClick={handleClick}
514
- disabled={!!(!isMulti && filesData?.[0]?.name)}
515
- endIcon={<IconProvider icon={faCaretDown} />}
516
- >
517
- <IconProvider icon={faUpload} size="md" mr={1} />
518
- {titleAddButton}
519
- </Button>
520
- <Menu
521
- data-testid="seizure-card-menu"
522
- anchorEl={anchorEl}
523
- open={Boolean(anchorEl)}
524
- onClose={handleClose}
525
- anchorOrigin={{
526
- vertical: 'bottom',
527
- horizontal: 'right',
528
- }}
529
- transformOrigin={{
530
- vertical: 'top',
531
- horizontal: 'right',
532
- }}
533
- slotProps={{
534
- paper: {
535
- style: {
536
- marginTop: '8px',
537
- marginLeft: '0',
538
- },
539
- },
540
- }}
541
- >
542
- <MenuItem
543
- testId="pc-add"
544
- onClick={() => handleFileChange(null, null, null, [], true)}
545
- >
546
- <Box gap={1} display="inline-flex" alignItems="center">
547
- <IconProvider size="sm" icon={faFolderOpen} />
548
- <Text variant="body2">{fromLocalText}</Text>
549
- </Box>
550
- </MenuItem>
551
- <GooglePickerWrapper
552
- callback={(data, token) =>
553
- handleFileChange(null, data, token, accept)
554
- }
555
- multiselect={true}
556
- navHidden={false}
557
- googleAuthClientId={googleAuthClientId ?? ''}
558
- googleApiKey={googleApiKey ?? ''}
559
- scopes="https://www.googleapis.com/auth/drive.file"
560
- viewId="FOLDERS"
561
- >
562
- <MenuItem testId="drive-add" onClick={handleClose}>
563
- <Box gap={1} display="inline-flex" alignItems="center">
564
- <IconProvider size="sm" icon={faGoogleDrive} />
565
- <Text variant="body2">{fromGoogleDriveText}</Text>
566
- </Box>
567
- </MenuItem>
568
- </GooglePickerWrapper>
569
- </Menu>
570
- </>
571
- )) || (
572
- <Button
573
- variant="secondary"
574
- sx={{
575
- display: 'flex',
576
- '&.MuiButton-secondaryPrimary.Mui-disabled': {
577
- backgroundColor: '#FFFFFF !important',
578
- },
579
- }}
580
- onClick={() => handleFileChange(null, null, null, [], true)}
581
- disabled={!!(!isMulti && filesData?.[0]?.name)}
582
- >
583
- <IconProvider icon={faUpload} size="md" mr={1} />
584
- {titleAddButton}
585
- </Button>
586
- )}
587
- </Box>
588
- </Box>
589
- {(error || helperText || uploadFileError !== false) && (
590
- <Box pl={1} pt={1}>
591
- <Text
592
- variant="caption"
593
- color={
594
- ((error || uploadFileError !== false) && 'redError') || 'greyDark'
595
- }
596
- data-testid="helperText"
597
- >
598
- {uploadFileError !== false
599
- ? uploadFileError
600
- : (error ?? helperText)}
601
- </Text>
602
- </Box>
603
- )}
604
- <Box sx={{ mt: '16px' }}>
605
- {(isMulti
606
- ? Object.values(filesData ?? [])
607
- : Object.values(filesData ?? [])?.slice(0, 1)
608
- )?.map((fileData, index) => (
609
- <Box
610
- key={index}
611
- sx={{
612
- display: 'flex',
613
- alignItems: 'center',
614
- border: '0.5px solid',
615
- borderColor: error ? 'redError' : 'greyLightDefaultBorder',
616
- borderRadius: '0',
617
- justifyContent: 'space-between',
618
- maxHeight: '50px',
619
- p: '16px',
620
- mb: '8px',
621
- }}
622
- >
623
- <Box
624
- sx={{
625
- display: 'flex',
626
- alignItems: 'center',
627
- flexShrink: 1,
628
- minWidth: 0,
629
- }}
630
- >
631
- <IconProvider
632
- icon={faFile}
633
- color="greyMediumInactive"
634
- size="sm"
635
- mr={1}
636
- />
637
- <Text
638
- variant="body2Medium"
639
- color="greyXDark"
640
- sx={{
641
- overflow: 'hidden',
642
- whiteSpace: 'nowrap',
643
- textAlign: 'left',
644
- textOverflow: 'ellipsis',
645
- flexShrink: 1,
646
- }}
647
- >
648
- {fileData?.name}
649
- </Text>
650
- {fileData?.size && fileData.size !== 0 ? (
651
- <Text
652
- component="span"
653
- variant="body2Regular"
654
- color="greyDark"
655
- sx={{ minWidth: '41px', marginLeft: '8px' }}
656
- >
657
- ({fileData?.size} ko)
658
- </Text>
659
- ) : null}
660
- </Box>
661
- <Box
662
- sx={{
663
- display: 'flex',
664
- alignItems: 'center',
665
- flexShrink: 0,
666
- }}
667
- >
668
- <IconButton
669
- size="medium"
670
- color="primary"
671
- sx={{
672
- height: '42px',
673
- width: '42px',
674
- mx: 1 / 2,
675
- outline: 'none !important',
676
- borderRadius: '4px',
677
- '&:hover': {
678
- backgroundColor: 'blueHoverOpacity12',
679
- },
680
- }}
681
- data-testid={`view-btn-${index}`}
682
- onClick={() => {
683
- if (fileData?.url) {
684
- window.open(fileData.url, '_blank');
685
- }
686
- }}
687
- >
688
- <IconProvider
689
- icon={faEye}
690
- color="grey"
691
- size="md"
692
- height="16px"
693
- width="16px"
694
- />
695
- </IconButton>
696
- <IconButton
697
- size="medium"
698
- color="primary"
699
- sx={{
700
- mx: 1 / 2,
701
- height: '42px',
702
- width: '42px',
703
- outline: 'none !important',
704
- borderRadius: '4px',
705
- '&:hover': {
706
- backgroundColor: 'blueHoverOpacity12',
707
- },
708
- }}
709
- data-testid={`delete-btn-${index}`}
710
- onClick={() => handleDelete(index)}
711
- >
712
- <IconProvider
713
- icon={faTrash}
714
- color="grey"
715
- size="md"
716
- height="16px"
717
- width="16px"
718
- />
719
- </IconButton>
720
- </Box>
721
- </Box>
722
- ))}
723
- </Box>
724
- </Box>
725
- );
726
- };
727
-
728
- export default FileUploader;