@groupeactual/ui-kit 1.7.1 → 1.7.2

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.
@@ -11,6 +11,8 @@ interface Props {
11
11
  accept?: string[];
12
12
  acceptText?: AcceptTextType;
13
13
  orText?: string;
14
+ fromLocalText?: string;
15
+ fromGoogleDriveText?: string;
14
16
  disabled?: boolean;
15
17
  error?: string;
16
18
  enableGoogleDrive?: boolean;
@@ -19,7 +21,7 @@ interface Props {
19
21
  _isDroppingFile?: boolean;
20
22
  validateFile?: (_size: number, _type: string, _accept: string[], _setUploadFileError: React.Dispatch<React.SetStateAction<boolean | string>>) => boolean;
21
23
  onTouched?: () => void;
22
- onFilesDataChange?: (_fileData: FileDataType[] | undefined, _filesInput?: File[]) => void;
24
+ onFilesDataChange?: (_fileData: FileDataType[] | undefined) => void;
23
25
  }
24
- declare const FileUploader: ({ title, subTitle, titleAddButton, helperText, titleTooltip, files, isMulti, accept, acceptText, orText, disabled, error, enableGoogleDrive, googleAuthClientId, googleApiKey, _isDroppingFile, validateFile, onTouched, onFilesDataChange, }: Props) => React.JSX.Element;
26
+ declare const FileUploader: ({ title, subTitle, titleAddButton, helperText, titleTooltip, files, isMulti, accept, acceptText, orText, fromLocalText, fromGoogleDriveText, disabled, error, enableGoogleDrive, googleAuthClientId, googleApiKey, _isDroppingFile, validateFile, onTouched, onFilesDataChange, }: Props) => React.JSX.Element;
25
27
  export default FileUploader;
@@ -8,6 +8,7 @@ export interface FileDataType {
8
8
  size: number;
9
9
  type: string;
10
10
  url: string;
11
+ file?: File;
11
12
  driveFileId?: string;
12
13
  driveAccessToken?: string;
13
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groupeactual/ui-kit",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "type": "module",
5
5
  "description": "A simple template for a custom React component library",
6
6
  "main": "dist/cjs/index.js",
@@ -14,7 +14,7 @@
14
14
  "@types/google.picker": "^0.0.46",
15
15
  "@types/styled-components": "^5.1.34",
16
16
  "framer-motion": "^11.12.0",
17
- "eslint": "^9.15.0",
17
+ "eslint": "^9.16.0",
18
18
  "eslint-config-prettier": "^9.1.0",
19
19
  "eslint-plugin-import": "^2.31.0",
20
20
  "eslint-plugin-jest": "^28.9.0",
@@ -33,13 +33,13 @@
33
33
  "@mui/x-date-pickers": "7.15.0",
34
34
  "@mui/x-date-pickers-pro": "7.15.0",
35
35
  "styled-components": "^6.1.13",
36
- "@groupeactual/design-tokens": "1.7.1"
36
+ "@groupeactual/design-tokens": "1.7.2"
37
37
  },
38
38
  "scripts": {
39
39
  "build": "rollup -c",
40
40
  "build:watch": "rollup --bundleConfigAsCjs -c -w",
41
41
  "dev": "npm run build:watch",
42
- "eslint": "eslint --config \"eslint.config.js\" --color \".\"",
42
+ "eslint": "eslint --config \"eslint.config.js\" --color \".\" --max-warnings=0",
43
43
  "lint": "npm run eslint"
44
44
  }
45
45
  }
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-empty-function */
2
1
  import { PaginationProps, PaginationTrans, Props } from './datatable.interface';
3
2
 
4
3
  const usePaginationProps = <T extends object>(
@@ -22,7 +22,6 @@ import {
22
22
  } from '@fortawesome/pro-solid-svg-icons';
23
23
  import { Box, IconButton } from '@mui/material';
24
24
  import Menu from '@mui/material/Menu';
25
- import { set } from 'lodash';
26
25
 
27
26
  import Button from '@/components/Button';
28
27
  import IconProvider from '@/components/IconProvider';
@@ -48,6 +47,8 @@ interface Props {
48
47
  accept?: string[];
49
48
  acceptText?: AcceptTextType;
50
49
  orText?: string;
50
+ fromLocalText?: string;
51
+ fromGoogleDriveText?: string;
51
52
  disabled?: boolean;
52
53
  error?: string;
53
54
  enableGoogleDrive?: boolean;
@@ -61,10 +62,7 @@ interface Props {
61
62
  _setUploadFileError: React.Dispatch<React.SetStateAction<boolean | string>>,
62
63
  ) => boolean;
63
64
  onTouched?: () => void;
64
- onFilesDataChange?: (
65
- _fileData: FileDataType[] | undefined,
66
- _filesInput?: File[],
67
- ) => void;
65
+ onFilesDataChange?: (_fileData: FileDataType[] | undefined) => void;
68
66
  }
69
67
 
70
68
  const FileUploader = ({
@@ -78,6 +76,8 @@ const FileUploader = ({
78
76
  accept = [],
79
77
  acceptText = { fileFormat: '', maxSize: '', subText: '' },
80
78
  orText = 'ou',
79
+ fromLocalText = 'Depuis votre PC',
80
+ fromGoogleDriveText = 'Depuis Google Drive',
81
81
  disabled = false,
82
82
  error,
83
83
  enableGoogleDrive = false,
@@ -94,8 +94,6 @@ const FileUploader = ({
94
94
 
95
95
  // * States
96
96
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
97
- // * currentFiles is used only to revoke the object URL when the component is unmounted for performance reasons
98
- const [currentFiles, setCurrentFiles] = useState<File[]>([]);
99
97
  // * filesData is used to display the files in the component
100
98
  const [filesData, setFilesData] = useState<FileDataType[] | undefined>([]);
101
99
  const [isDroppingFile, setIsDroppingFile] =
@@ -192,12 +190,34 @@ const FileUploader = ({
192
190
  handleClose();
193
191
  onTouched?.();
194
192
 
195
- // * Local Files
196
- if (
193
+ if (token && data && data.docs && data.docs.length > 0) {
194
+ // * Google Drive
195
+ const validDocs = data.docs.filter((doc) =>
196
+ validateFile
197
+ ? validateFile(
198
+ doc.sizeBytes,
199
+ doc.mimeType,
200
+ accept,
201
+ setUploadFileError,
202
+ )
203
+ : true,
204
+ );
205
+
206
+ const googleFileData = validDocs.map((doc) => ({
207
+ name: doc.name,
208
+ size: Math.round(doc.sizeBytes / 1024), // * Convert size to KB
209
+ type: doc.mimeType,
210
+ url: `https://drive.google.com/file/d/${doc.id}/view?usp=drive_we`,
211
+ driveFileId: doc.id,
212
+ driveAccessToken: token,
213
+ }));
214
+
215
+ setFilesData([...(filesData || []), ...googleFileData]);
216
+ } else if (
197
217
  fileInputRef.current?.files &&
198
218
  fileInputRef.current?.files?.length > 0
199
219
  ) {
200
- const validInputFiles: File[] = [];
220
+ // * Local Files
201
221
  const fileList = Array.from(fileInputRef.current?.files);
202
222
 
203
223
  const newFileData: FileDataType[] = fileList
@@ -210,54 +230,27 @@ const FileUploader = ({
210
230
  return null;
211
231
  }
212
232
 
213
- validInputFiles.push(file);
214
-
215
233
  return {
216
234
  name: file?.name ?? '',
217
235
  size: Math.round(file.size / 1024),
218
236
  type: file.type,
219
237
  url: URL.createObjectURL(file),
238
+ file: file,
220
239
  };
221
240
  })
222
- .filter((file): file is FileDataType => file !== null);
241
+ .filter((file) => file !== null);
223
242
 
224
243
  if (newFileData && newFileData?.length > 0) {
225
- setCurrentFiles([...(currentFiles || []), ...validInputFiles]);
226
244
  setFilesData([...(filesData || []), ...newFileData]);
227
245
  }
228
- } else if (token && data && data.docs && data.docs.length > 0) {
229
- // * Google Drive
230
- const validDocs = data.docs.filter((doc) =>
231
- validateFile
232
- ? validateFile(
233
- doc.sizeBytes,
234
- doc.mimeType,
235
- accept,
236
- setUploadFileError,
237
- )
238
- : true,
239
- );
240
-
241
- const googleFileData = validDocs.map((doc) => ({
242
- name: doc.name,
243
- size: Math.round(doc.sizeBytes / 1024), // * Convert size to KB
244
- type: doc.mimeType,
245
- url: `https://drive.google.com/file/d/${doc.id}/view?usp=drive_we`,
246
- driveFileId: doc.id,
247
- driveAccessToken: token,
248
- }));
249
-
250
- setFilesData([...(filesData || []), ...googleFileData]);
251
246
  }
252
247
 
253
248
  setIsDroppingFile(false);
254
249
  },
255
250
  [
256
251
  fileInputRef,
257
- currentFiles,
258
252
  filesData,
259
253
  setIsDroppingFile,
260
- setCurrentFiles,
261
254
  setFilesData,
262
255
  validateFile,
263
256
  onTouched,
@@ -268,8 +261,8 @@ const FileUploader = ({
268
261
  const handleDelete = useCallback(
269
262
  (fileIndex: number) => {
270
263
  //* Remove the file from the currentFiles array
271
- if (currentFiles && currentFiles.length > 0) {
272
- const fileToDelete = currentFiles[fileIndex];
264
+ if (filesData && filesData.length > 0) {
265
+ const fileToDelete = filesData[fileIndex]?.file;
273
266
  if (fileToDelete) {
274
267
  // * 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
275
268
  try {
@@ -279,14 +272,6 @@ const FileUploader = ({
279
272
  // * Do nothing
280
273
  }
281
274
  }
282
-
283
- if (currentFiles.length === 1) {
284
- setCurrentFiles([]);
285
- } else {
286
- setCurrentFiles(
287
- currentFiles.filter((_, index) => index !== fileIndex),
288
- );
289
- }
290
275
  }
291
276
 
292
277
  //* Remove the file from the filesData array
@@ -302,7 +287,7 @@ const FileUploader = ({
302
287
 
303
288
  setIsDroppingFile(false);
304
289
  },
305
- [currentFiles, filesData, setIsDroppingFile, setCurrentFiles, setFilesData],
290
+ [filesData, setIsDroppingFile, setFilesData],
306
291
  );
307
292
 
308
293
  // * Utils
@@ -318,54 +303,54 @@ const FileUploader = ({
318
303
  // * Initialize the component with the files passed as props
319
304
  useEffect(() => {
320
305
  if (!isInitialized && files.length > 0) {
321
- const FilesDataDto: FileDataType[] = files.map((file) => ({
322
- name: file.name,
323
- size: Math.round(file.size / 1024), // Convert size to KB
324
- type: file.type,
325
- url: file.url,
326
- }));
327
-
328
306
  const initializeFiles = async () => {
329
307
  const initialFiles = await Promise.all(
330
- FilesDataDto.map(async (fileData) => {
331
- const response = await fetch(fileData.url);
308
+ files.map(async (file) => {
309
+ const response = await fetch(file.url);
332
310
  const blob = await response.blob();
333
311
 
334
- return new File([blob], fileData.name, {
335
- type: fileData.type,
336
- });
312
+ return {
313
+ name: file.name,
314
+ size: Math.round(file.size / 1024), // Convert size to KB
315
+ type: file.type,
316
+ url: file.url,
317
+ file: new File([blob], file.name, {
318
+ type: file.type,
319
+ }),
320
+ };
337
321
  }),
338
322
  );
339
323
 
340
- setCurrentFiles(initialFiles); // Now files is a File[] array
324
+ setFilesData(initialFiles);
341
325
  };
342
326
 
343
327
  initializeFiles();
344
- setFilesData(FilesDataDto);
345
328
  setIsInitialized(true);
346
329
  }
347
330
  }, [files]);
348
331
 
349
332
  useEffect(() => {
350
333
  // * Notify parent component
351
- onFilesDataChange?.(filesData, currentFiles);
352
- }, [filesData, currentFiles]);
334
+ onFilesDataChange?.(filesData);
335
+ }, [filesData]);
353
336
 
354
337
  useEffect(() => {
355
338
  return () => {
356
- if (!currentFiles?.length) return;
339
+ if (!filesData?.length) return;
357
340
 
358
341
  try {
359
342
  // * Only for file imported with the file input, use try and catch to avoid errors on the other files
360
- currentFiles.forEach((file) => {
361
- const fileURL = URL.createObjectURL(file);
362
- URL.revokeObjectURL(fileURL);
343
+ filesData.forEach((_fileData) => {
344
+ if (_fileData?.file) {
345
+ const fileURL = URL.createObjectURL(_fileData?.file);
346
+ URL.revokeObjectURL(fileURL);
347
+ }
363
348
  });
364
349
  } catch {
365
350
  // * Do nothing
366
351
  }
367
352
  };
368
- }, [currentFiles]);
353
+ }, [filesData]);
369
354
 
370
355
  return (
371
356
  <Box
@@ -517,9 +502,9 @@ const FileUploader = ({
517
502
  testId="pc-add"
518
503
  onClick={() => handleFileChange(null, null, null, [], true)}
519
504
  >
520
- <Box gap={1} display="flex">
505
+ <Box gap={1} display="inline-flex" alignItems="center">
521
506
  <IconProvider size="sm" icon={faFolderOpen} />
522
- <Text variant="body2">Depuis votre PC</Text>
507
+ <Text variant="body2">{fromLocalText}</Text>
523
508
  </Box>
524
509
  </MenuItem>
525
510
  <GooglePickerWrapper
@@ -534,9 +519,9 @@ const FileUploader = ({
534
519
  viewId="FOLDERS"
535
520
  >
536
521
  <MenuItem testId="drive-add" onClick={handleClose}>
537
- <Box gap={1} display="flex">
522
+ <Box gap={1} display="inline-flex" alignItems="center">
538
523
  <IconProvider size="sm" icon={faGoogleDrive} />
539
- <Text variant="body2">Depuis Google Drive</Text>
524
+ <Text variant="body2">{fromGoogleDriveText}</Text>
540
525
  </Box>
541
526
  </MenuItem>
542
527
  </GooglePickerWrapper>
@@ -9,6 +9,7 @@ export interface FileDataType {
9
9
  size: number;
10
10
  type: string;
11
11
  url: string;
12
+ file?: File;
12
13
  driveFileId?: string;
13
14
  driveAccessToken?: string;
14
15
  }