@popsure/dirty-swan 0.57.9 → 0.58.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 (38) hide show
  1. package/dist/cjs/index.js +65 -29
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/lib/components/multiDropzone/utils/index.d.ts +9 -2
  4. package/dist/esm/{TableSection-a26ba0c5.js → TableSection-ebace923.js} +1 -1
  5. package/dist/esm/{TableSection-a26ba0c5.js.map → TableSection-ebace923.js.map} +1 -1
  6. package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js +1 -1
  7. package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js.map +1 -1
  8. package/dist/esm/components/input/checkbox/index.js +5 -2
  9. package/dist/esm/components/input/checkbox/index.js.map +1 -1
  10. package/dist/esm/components/input/index.js +4 -2
  11. package/dist/esm/components/input/index.js.map +1 -1
  12. package/dist/esm/components/multiDropzone/UploadFileCell/index.js +6 -7
  13. package/dist/esm/components/multiDropzone/UploadFileCell/index.js.map +1 -1
  14. package/dist/esm/components/multiDropzone/index.js +51 -17
  15. package/dist/esm/components/multiDropzone/index.js.map +1 -1
  16. package/dist/esm/components/multiDropzone/index.stories.js +1 -0
  17. package/dist/esm/components/multiDropzone/index.stories.js.map +1 -1
  18. package/dist/esm/components/multiDropzone/index.test.js +1 -0
  19. package/dist/esm/components/multiDropzone/index.test.js.map +1 -1
  20. package/dist/esm/components/table/Table.js +1 -1
  21. package/dist/esm/components/table/Table.stories.js +1 -1
  22. package/dist/esm/components/table/Table.test.js +1 -1
  23. package/dist/esm/components/table/components/TableContents/TableContents.js +1 -1
  24. package/dist/esm/components/table/components/TableContents/TableContents.test.js +1 -1
  25. package/dist/esm/components/table/components/TableSection/TableSection.js +1 -1
  26. package/dist/esm/components/table/components/TableSection/TableSection.test.js +1 -1
  27. package/dist/esm/index.js +1 -1
  28. package/dist/esm/lib/components/multiDropzone/utils/index.d.ts +9 -2
  29. package/package.json +1 -1
  30. package/src/lib/components/comparisonTable/components/TableInfoButton/index.tsx +2 -0
  31. package/src/lib/components/input/checkbox/index.tsx +8 -2
  32. package/src/lib/components/input/index.tsx +20 -13
  33. package/src/lib/components/multiDropzone/UploadFileCell/index.tsx +25 -19
  34. package/src/lib/components/multiDropzone/UploadFileCell/style.module.scss +11 -29
  35. package/src/lib/components/multiDropzone/index.tsx +17 -5
  36. package/src/lib/components/multiDropzone/style.module.scss +12 -9
  37. package/src/lib/components/multiDropzone/utils/index.test.ts +128 -45
  38. package/src/lib/components/multiDropzone/utils/index.ts +89 -36
@@ -1,53 +1,56 @@
1
1
  import { ErrorCode } from 'react-dropzone';
2
- import {
2
+ import {
3
3
  formatAcceptFileList,
4
4
  getErrorMessage,
5
- getFormattedAcceptObject,
6
- getUploadStatus
5
+ getFormattedAcceptObject,
6
+ getStatusMessage,
7
+ getUploadStatus,
7
8
  } from '.';
8
9
 
9
10
  const documentsAccept = {
10
11
  'application/msword': ['.doc'],
11
12
  'application/pdf': ['.pdf'],
12
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx']
13
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': [
14
+ '.docx',
15
+ ],
13
16
  };
14
17
 
15
18
  const imagesAccept = {
16
- 'image/heic': [".heic"],
17
- 'image/bmp': [".bmp"],
18
- 'image/jpeg': [".jpeg"],
19
- 'image/jpg': [".jpg"],
20
- 'image/png': [".png"],
21
- 'image/svg+xml': [".svg"],
22
- 'image/tiff': [".tiff"],
23
- 'image/webp': [".webp"]
19
+ 'image/heic': ['.heic'],
20
+ 'image/bmp': ['.bmp'],
21
+ 'image/jpeg': ['.jpeg'],
22
+ 'image/jpg': ['.jpg'],
23
+ 'image/png': ['.png'],
24
+ 'image/svg+xml': ['.svg'],
25
+ 'image/tiff': ['.tiff'],
26
+ 'image/webp': ['.webp'],
24
27
  };
25
28
 
26
29
  describe('getUploadStatus', () => {
27
30
  it('Should return error status if error is passed', () => {
28
- expect(getUploadStatus(0, "Error message")).toEqual("ERROR");
31
+ expect(getUploadStatus(0, 'Error message')).toEqual('ERROR');
29
32
  });
30
33
 
31
34
  it("Should return uploading status if progress hasn't finished", () => {
32
- expect(getUploadStatus(50)).toEqual("UPLOADING");
35
+ expect(getUploadStatus(50)).toEqual('UPLOADING');
33
36
  });
34
37
 
35
- it("Should return complete status if progress has finished", () => {
36
- expect(getUploadStatus(100)).toEqual("COMPLETE");
38
+ it('Should return complete status if progress has finished', () => {
39
+ expect(getUploadStatus(100)).toEqual('COMPLETE');
37
40
  });
38
41
  });
39
42
 
40
43
  describe('getFormattedAcceptObject', () => {
41
44
  it('Should return image accept object if is of type image', () => {
42
- expect(getFormattedAcceptObject("image")).toEqual(imagesAccept);
45
+ expect(getFormattedAcceptObject('image')).toEqual(imagesAccept);
43
46
  });
44
47
 
45
48
  it('Should return documents accept object if is of type document', () => {
46
- expect(getFormattedAcceptObject("document")).toEqual(documentsAccept);
49
+ expect(getFormattedAcceptObject('document')).toEqual(documentsAccept);
47
50
  });
48
51
 
49
52
  it('Should return accept object if it is manually defined', () => {
50
- const accept = { "application/pdf": [".pdf"] };
53
+ const accept = { 'application/pdf': ['.pdf'] };
51
54
 
52
55
  expect(getFormattedAcceptObject(accept)).toEqual(accept);
53
56
  });
@@ -55,61 +58,141 @@ describe('getFormattedAcceptObject', () => {
55
58
 
56
59
  describe('formatAcceptFileList', () => {
57
60
  it('Should return empty object if accept is empty', () => {
58
- expect(formatAcceptFileList({})).toEqual("");
61
+ expect(formatAcceptFileList({})).toEqual('');
59
62
  });
60
63
 
61
64
  it('Should return documents list if documents accept is passed', () => {
62
- expect(formatAcceptFileList(documentsAccept)).toEqual("DOC, PDF, DOCX");
65
+ expect(formatAcceptFileList(documentsAccept)).toEqual('DOC, PDF, DOCX');
63
66
  });
64
67
 
65
68
  it('Should return images list if images accept is passed', () => {
66
- expect(formatAcceptFileList(imagesAccept)).toEqual("HEIC, BMP, JPEG, JPG, PNG, SVG, TIFF, WEBP");
69
+ expect(formatAcceptFileList(imagesAccept)).toEqual(
70
+ 'HEIC, BMP, JPEG, JPG, PNG, SVG, TIFF, WEBP'
71
+ );
67
72
  });
68
73
 
69
74
  it('Should return extension based on accept passed', () => {
70
- const accept = {
71
- "application/pdf": [".pdf"],
72
- "image/jpg": [".jpg"]
75
+ const accept = {
76
+ 'application/pdf': ['.pdf'],
77
+ 'image/jpg': ['.jpg'],
73
78
  };
74
79
 
75
- expect(formatAcceptFileList(accept)).toEqual("PDF, JPG");
80
+ expect(formatAcceptFileList(accept)).toEqual('PDF, JPG');
76
81
  });
77
82
  });
78
83
 
79
84
  describe('getErrorMessage', () => {
80
85
  it('Should return default error message', () => {
81
- const defaultMessage = "Default Error Message.";
86
+ const defaultMessage = 'Default Error Message.';
82
87
 
83
88
  expect(
84
- getErrorMessage({
85
- code: "UNKNOWN",
86
- message: defaultMessage
87
- }, {
88
- fileList: ""
89
- })
89
+ getErrorMessage(
90
+ {
91
+ code: 'UNKNOWN',
92
+ message: defaultMessage,
93
+ },
94
+ {
95
+ fileList: '',
96
+ }
97
+ )
90
98
  ).toEqual(defaultMessage);
91
99
  });
92
100
 
93
101
  it('Should return default FileInvalidType default message', () => {
94
- const fileList = "JPG, PDF";
102
+ const fileList = 'JPG, PDF';
95
103
 
96
104
  expect(
97
- getErrorMessage({
98
- code: ErrorCode.FileInvalidType,
99
- message: ""
100
- }, { fileList })
105
+ getErrorMessage(
106
+ {
107
+ code: ErrorCode.FileInvalidType,
108
+ message: '',
109
+ },
110
+ { fileList }
111
+ )
101
112
  ).toEqual(`File type must be ${fileList}`);
102
113
  });
103
114
 
104
115
  it('Should return FileInvalidType with textOverride message', () => {
105
- const fileTypeError = "File Invalid Error";
106
- const fileList = "JPG, PDF";
107
-
116
+ const fileTypeError = 'File Invalid Error';
117
+ const fileList = 'JPG, PDF';
118
+
108
119
  expect(
109
- getErrorMessage({
110
- code: ErrorCode.FileInvalidType,
111
- message: ""
112
- }, { fileList }, { fileTypeError })
120
+ getErrorMessage(
121
+ {
122
+ code: ErrorCode.FileInvalidType,
123
+ message: '',
124
+ },
125
+ { fileList },
126
+ { fileTypeError }
127
+ )
113
128
  ).toEqual(`${fileTypeError} ${fileList}`);
114
129
  });
115
130
  });
131
+
132
+ describe('getStatusMessage', () => {
133
+ it('returns accepted file message for multiple files', () => {
134
+ const acceptedFiles = [
135
+ new File([''], 'photo.jpg'),
136
+ new File([''], 'invoice.pdf'),
137
+ ];
138
+
139
+ const result = getStatusMessage({
140
+ acceptedFiles,
141
+ filesRejected: [],
142
+ maxSize: 5000000,
143
+ });
144
+
145
+ expect(result).toBe('Files uploaded: photo.jpg, invoice.pdf.');
146
+ });
147
+
148
+ it('returns rejection message for invalid file type with default text', () => {
149
+ const filesRejected = [
150
+ {
151
+ file: new File([''], 'script.exe'),
152
+ errors: [
153
+ { code: ErrorCode.FileInvalidType, message: 'Invalid file type' },
154
+ ],
155
+ },
156
+ ];
157
+
158
+ const result = getStatusMessage({
159
+ acceptedFiles: [],
160
+ filesRejected,
161
+ maxSize: 5000000,
162
+ fileList: 'PDF, JPG',
163
+ });
164
+
165
+ expect(result).toBe(
166
+ 'Could not upload script.exe: File type must be PDF, JPG.'
167
+ );
168
+ });
169
+
170
+ it('returns rejection message for file too large with default text', () => {
171
+ const filesRejected = [
172
+ {
173
+ file: new File([''], 'video.mov'),
174
+ errors: [{ code: ErrorCode.FileTooLarge, message: 'Too big' }],
175
+ },
176
+ ];
177
+
178
+ const result = getStatusMessage({
179
+ acceptedFiles: [],
180
+ filesRejected,
181
+ maxSize: 1048576,
182
+ });
183
+
184
+ expect(result).toBe(
185
+ 'Could not upload video.mov: File is too large. It must be less than 1 MB.'
186
+ );
187
+ });
188
+
189
+ it('returns fallback when no files are accepted or rejected', () => {
190
+ const result = getStatusMessage({
191
+ acceptedFiles: [],
192
+ filesRejected: [],
193
+ maxSize: 1000000,
194
+ });
195
+
196
+ expect(result).toBe('');
197
+ });
198
+ });
@@ -1,17 +1,20 @@
1
- import { Accept, ErrorCode, FileError } from "react-dropzone";
2
- import { formatBytes } from "../../../util/formatBytes";
3
- import {
4
- AcceptType,
5
- DOCUMENT_FILES,
1
+ import { Accept, ErrorCode, FileError, FileRejection } from 'react-dropzone';
2
+ import { formatBytes } from '../../../util/formatBytes';
3
+ import {
4
+ AcceptType,
5
+ DOCUMENT_FILES,
6
6
  FileMimeTypes,
7
7
  FileType,
8
- IMAGE_FILES,
8
+ IMAGE_FILES,
9
9
  TextOverrides,
10
10
  UploadStatus,
11
- VIDEO_FILES
12
- } from "../types";
11
+ VIDEO_FILES,
12
+ } from '../types';
13
13
 
14
- export const getUploadStatus = (progress: number, error?: string): UploadStatus => {
14
+ export const getUploadStatus = (
15
+ progress: number,
16
+ error?: string
17
+ ): UploadStatus => {
15
18
  if (error) {
16
19
  return 'ERROR';
17
20
  }
@@ -23,7 +26,7 @@ export const getUploadStatus = (progress: number, error?: string): UploadStatus
23
26
  return 'COMPLETE';
24
27
  };
25
28
 
26
- const formatMimeType = (values: FileType[]): Accept => {
29
+ const formatMimeType = (values: FileType[]): Accept => {
27
30
  const formatedValues = {} as Accept;
28
31
 
29
32
  values.forEach((value) => {
@@ -36,17 +39,17 @@ const formatMimeType = (values: FileType[]): Accept => {
36
39
  export const DOCUMENT_FILES_ACCEPT = formatMimeType(DOCUMENT_FILES);
37
40
  export const IMAGE_FILES_ACCEPT = formatMimeType(IMAGE_FILES);
38
41
  export const VIDEO_FILES_ACCEPT = formatMimeType(VIDEO_FILES);
39
-
42
+
40
43
  export const getFormattedAcceptObject = (accept: AcceptType = {}): Accept => {
41
- if (accept === "document") {
44
+ if (accept === 'document') {
42
45
  return DOCUMENT_FILES_ACCEPT;
43
- };
46
+ }
44
47
 
45
- if (accept === "image") {
48
+ if (accept === 'image') {
46
49
  return IMAGE_FILES_ACCEPT;
47
- };
50
+ }
48
51
 
49
- if (accept === "video") {
52
+ if (accept === 'video') {
50
53
  return VIDEO_FILES_ACCEPT;
51
54
  }
52
55
 
@@ -57,17 +60,16 @@ export const getFormattedAcceptObject = (accept: AcceptType = {}): Accept => {
57
60
  return {
58
61
  ...DOCUMENT_FILES_ACCEPT,
59
62
  ...IMAGE_FILES_ACCEPT,
60
- ...VIDEO_FILES_ACCEPT
63
+ ...VIDEO_FILES_ACCEPT,
61
64
  };
62
- }
63
-
64
- export const formatAcceptFileList = (accept: Accept): string => (
65
+ };
66
+
67
+ export const formatAcceptFileList = (accept: Accept): string =>
65
68
  Object.values(accept)
66
69
  .reduce((acc, value) => [...acc, ...value], [])
67
- .join(", ")
70
+ .join(', ')
68
71
  .replace(/\./g, '')
69
- .toUpperCase()
70
- );
72
+ .toUpperCase();
71
73
 
72
74
  export const getPlaceholder = (
73
75
  textOverrides?: TextOverrides,
@@ -78,28 +80,79 @@ export const getPlaceholder = (
78
80
  maxSize && maxSize > 0
79
81
  ? `${textOverrides?.sizeUpToText || 'up to'} ${formatBytes(maxSize)}`
80
82
  : '';
81
-
82
- const isAcceptString =
83
- typeof accept === 'string' &&
84
- ['video', 'image', 'document'].includes(accept)
85
-
86
- const defaultPlaceholder = `${textOverrides?.supportsTextShort || 'Supports images, videos and documents'} ${maxSizePlaceholder}`;
87
- const acceptPlaceholder = `${textOverrides?.supportsTextShort || `Supports ${accept}s ${maxSizePlaceholder}`}`;
83
+
84
+ const isAcceptString =
85
+ typeof accept === 'string' &&
86
+ ['video', 'image', 'document'].includes(accept);
87
+
88
+ const defaultPlaceholder = `${
89
+ textOverrides?.supportsTextShort || 'Supports images, videos and documents'
90
+ } ${maxSizePlaceholder}`;
91
+ const acceptPlaceholder = `${
92
+ textOverrides?.supportsTextShort ||
93
+ `Supports ${accept}s ${maxSizePlaceholder}`
94
+ }`;
88
95
 
89
96
  return isAcceptString ? acceptPlaceholder : defaultPlaceholder;
90
- }
97
+ };
91
98
 
92
99
  export const getErrorMessage = (
93
100
  { code, message }: FileError,
94
- { fileList = "", maxSize }: { fileList?: string, maxSize?: number },
95
- textOverrides?: TextOverrides,
101
+ { fileList = '', maxSize }: { fileList?: string; maxSize?: number },
102
+ textOverrides?: TextOverrides
96
103
  ): string => {
97
104
  switch (code) {
98
105
  case ErrorCode.FileInvalidType:
99
- return `${textOverrides?.fileTypeError || "File type must be"} ${fileList}`;
106
+ return `${
107
+ textOverrides?.fileTypeError || 'File type must be'
108
+ } ${fileList}`;
100
109
  case ErrorCode.FileTooLarge:
101
- return `${textOverrides?.fileTooLargeError || "File is too large. It must be less than"} ${formatBytes(maxSize || 0)}.`;
110
+ return `${
111
+ textOverrides?.fileTooLargeError ||
112
+ 'File is too large. It must be less than'
113
+ } ${formatBytes(maxSize || 0)}.`;
102
114
  default:
103
115
  return message;
104
116
  }
105
- }
117
+ };
118
+
119
+ export const getStatusMessage = ({
120
+ acceptedFiles,
121
+ filesRejected,
122
+ fileList,
123
+ maxSize,
124
+ textOverrides,
125
+ }: {
126
+ acceptedFiles: File[];
127
+ filesRejected: FileRejection[];
128
+ fileList?: string;
129
+ maxSize?: number;
130
+ textOverrides?: TextOverrides;
131
+ }): string => {
132
+ let message = '';
133
+ if (acceptedFiles.length > 0) {
134
+ const fileNames = acceptedFiles.map((file) => file.name).join(', ');
135
+ message += `File${
136
+ acceptedFiles.length > 1 ? 's' : ''
137
+ } uploaded: ${fileNames}. `;
138
+ }
139
+
140
+ if (filesRejected.length > 0) {
141
+ const rejectionMessages = filesRejected.map((rejection) => {
142
+ const firstError = rejection.errors[0];
143
+ const rejectionMessage = getErrorMessage(
144
+ firstError,
145
+ { fileList, maxSize },
146
+ textOverrides
147
+ );
148
+ return `Could not upload ${rejection.file.name}: ${
149
+ rejectionMessage.endsWith('.')
150
+ ? rejectionMessage
151
+ : `${rejectionMessage}.`
152
+ }`;
153
+ });
154
+
155
+ message += rejectionMessages.join('');
156
+ }
157
+ return message.trim();
158
+ };