@popsure/dirty-swan 0.38.1 → 0.38.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.
- package/dist/cjs/index.js +20 -14
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/icon/IconWrapper/IconWrapper.js +5 -2
- package/dist/esm/components/icon/IconWrapper/IconWrapper.js.map +1 -1
- package/dist/esm/components/icon/icons.stories.js +1 -1
- package/dist/esm/components/icon/index.stories.js +1 -1
- package/dist/esm/components/multiDropzone/index.js +15 -12
- package/dist/esm/components/multiDropzone/index.js.map +1 -1
- package/dist/esm/components/multiDropzone/index.test.js +71 -51
- package/dist/esm/components/multiDropzone/index.test.js.map +1 -1
- package/dist/esm/{index-38cf6d96.js → index-35a77b9b.js} +1 -1
- package/dist/esm/{index-38cf6d96.js.map → index-35a77b9b.js.map} +1 -1
- package/package.json +1 -1
- package/src/lib/components/icon/IconWrapper/IconWrapper.tsx +5 -1
- package/src/lib/components/icon/IconWrapper/styles.module.scss +1 -1
- package/src/lib/components/multiDropzone/index.test.tsx +101 -81
- package/src/lib/components/multiDropzone/index.tsx +52 -40
- package/src/lib/components/multiDropzone/style.module.scss +2 -2
|
@@ -7,20 +7,20 @@ const mockOnFileSelect = jest.fn();
|
|
|
7
7
|
const mockOnRemoveFile = jest.fn();
|
|
8
8
|
const file = new File(['DummyFile'], 'dummy.png', { type: 'image/png' });
|
|
9
9
|
|
|
10
|
-
const inputTestId =
|
|
11
|
-
const spinnerTestId =
|
|
12
|
-
const progressbarTestId =
|
|
10
|
+
const inputTestId = 'ds-drop-input';
|
|
11
|
+
const spinnerTestId = 'ds-filecell-spinner';
|
|
12
|
+
const progressbarTestId = 'ds-filecell-progressbar';
|
|
13
13
|
const uploadedFilesMock = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
id: '123',
|
|
15
|
+
name: 'File name',
|
|
16
|
+
progress: 100,
|
|
17
|
+
type: 'jpg',
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
const setup = ({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
uploadedFiles = [],
|
|
22
|
+
uploading = false,
|
|
23
|
+
...rest
|
|
24
24
|
}: Partial<MultiDropzoneProps>) => {
|
|
25
25
|
return render(
|
|
26
26
|
<MultiDropzone
|
|
@@ -34,7 +34,7 @@ const setup = ({
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
describe('MultiDropzone component', () => {
|
|
37
|
-
it(
|
|
37
|
+
it('should call onFileSelect on files change', async () => {
|
|
38
38
|
const { getByTestId, user } = setup({});
|
|
39
39
|
const files = [file, file];
|
|
40
40
|
|
|
@@ -44,19 +44,22 @@ describe('MultiDropzone component', () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
describe('Error states', () => {
|
|
47
|
-
it(
|
|
47
|
+
it('should show max files error message', () => {
|
|
48
48
|
const screen = setup({
|
|
49
49
|
maxFiles: 1,
|
|
50
|
-
uploadedFiles: [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
uploadedFiles: [
|
|
51
|
+
uploadedFilesMock,
|
|
52
|
+
{
|
|
53
|
+
...uploadedFilesMock,
|
|
54
|
+
id: '222',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
54
57
|
});
|
|
55
|
-
|
|
56
|
-
expect(screen.getByText(
|
|
58
|
+
|
|
59
|
+
expect(screen.getByText('Too many files.')).toBeVisible();
|
|
57
60
|
});
|
|
58
61
|
|
|
59
|
-
it(
|
|
62
|
+
it('should show max file size error message', async () => {
|
|
60
63
|
const { getByTestId, getByText, user } = setup({ maxSize: 10 });
|
|
61
64
|
const bigFile = file;
|
|
62
65
|
Object.defineProperty(bigFile, 'size', { value: 1024 });
|
|
@@ -64,12 +67,12 @@ describe('MultiDropzone component', () => {
|
|
|
64
67
|
await user.upload(getByTestId(inputTestId), [bigFile]);
|
|
65
68
|
|
|
66
69
|
expect(
|
|
67
|
-
getByText(
|
|
70
|
+
getByText('File is too large. It must be less than 10 Bytes.')
|
|
68
71
|
).toBeInTheDocument();
|
|
69
72
|
});
|
|
70
73
|
|
|
71
|
-
it(
|
|
72
|
-
const { getByTestId, getByText } = setup({ accept:
|
|
74
|
+
it('should show wrong filetype error message', async () => {
|
|
75
|
+
const { getByTestId, getByText } = setup({ accept: 'document' });
|
|
73
76
|
const input = getByTestId(inputTestId);
|
|
74
77
|
|
|
75
78
|
await act(async () => {
|
|
@@ -79,12 +82,14 @@ describe('MultiDropzone component', () => {
|
|
|
79
82
|
});
|
|
80
83
|
|
|
81
84
|
expect(
|
|
82
|
-
getByText(
|
|
85
|
+
getByText('File type must be one of DOC, DOCX, PDF')
|
|
83
86
|
).toBeInTheDocument();
|
|
84
87
|
});
|
|
85
88
|
|
|
86
|
-
it(
|
|
87
|
-
const { getByAltText, getByTestId, queryByText, user } = setup({
|
|
89
|
+
it('should remove wrong filetype error message', async () => {
|
|
90
|
+
const { getByAltText, getByTestId, queryByText, user } = setup({
|
|
91
|
+
accept: 'document',
|
|
92
|
+
});
|
|
88
93
|
const input = getByTestId(inputTestId);
|
|
89
94
|
|
|
90
95
|
await act(async () => {
|
|
@@ -93,135 +98,150 @@ describe('MultiDropzone component', () => {
|
|
|
93
98
|
fireEvent.change(input, { target: { files: [file] } });
|
|
94
99
|
});
|
|
95
100
|
|
|
96
|
-
await user.click(getByAltText(
|
|
101
|
+
await user.click(getByAltText('remove'));
|
|
97
102
|
|
|
98
|
-
expect(
|
|
103
|
+
expect(
|
|
104
|
+
queryByText('File type must be one of DOC, DOCX, PDF')
|
|
105
|
+
).not.toBeInTheDocument();
|
|
99
106
|
});
|
|
100
107
|
});
|
|
101
108
|
|
|
102
109
|
describe('Copy text', () => {
|
|
103
|
-
it(
|
|
110
|
+
it('should show uploader text', () => {
|
|
104
111
|
const screen = setup({});
|
|
105
112
|
|
|
106
|
-
expect(
|
|
113
|
+
expect(
|
|
114
|
+
screen.getByText('Choose file or drag & drop')
|
|
115
|
+
).toBeInTheDocument();
|
|
107
116
|
});
|
|
108
117
|
|
|
109
|
-
it(
|
|
110
|
-
const instructionsText =
|
|
118
|
+
it('should show uploader text translated', () => {
|
|
119
|
+
const instructionsText = 'Drag drop file';
|
|
111
120
|
const screen = setup({
|
|
112
|
-
textOverrides: { instructionsText }
|
|
121
|
+
textOverrides: { instructionsText },
|
|
113
122
|
});
|
|
114
123
|
|
|
115
124
|
expect(screen.getByText(instructionsText)).toBeInTheDocument();
|
|
116
125
|
});
|
|
117
126
|
|
|
118
|
-
it(
|
|
119
|
-
const screen = setup({ accept:
|
|
127
|
+
it('should show image accept file type label', () => {
|
|
128
|
+
const screen = setup({ accept: 'image' });
|
|
120
129
|
|
|
121
130
|
expect(
|
|
122
|
-
screen.getByText(
|
|
131
|
+
screen.getByText('Supports HEIC, BMP, JPEG, JPG, PNG')
|
|
123
132
|
).toBeInTheDocument();
|
|
124
133
|
});
|
|
125
134
|
|
|
126
|
-
it(
|
|
127
|
-
const screen = setup({ accept:
|
|
135
|
+
it('should show document accept file type label', () => {
|
|
136
|
+
const screen = setup({ accept: 'document' });
|
|
128
137
|
|
|
129
|
-
expect(
|
|
130
|
-
screen.getByText("Supports DOC, DOCX, PDF")
|
|
131
|
-
).toBeInTheDocument();
|
|
138
|
+
expect(screen.getByText('Supports DOC, DOCX, PDF')).toBeInTheDocument();
|
|
132
139
|
});
|
|
133
140
|
|
|
134
|
-
it(
|
|
135
|
-
const screen = setup({
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
it('should custom document accept file type label', () => {
|
|
142
|
+
const screen = setup({
|
|
143
|
+
accept: {
|
|
144
|
+
'application/pdf': ['.pdf'],
|
|
145
|
+
'image/jpg': ['.jpg'],
|
|
146
|
+
},
|
|
147
|
+
});
|
|
139
148
|
|
|
140
|
-
expect(
|
|
141
|
-
screen.getByText("Supports PDF, JPG")
|
|
142
|
-
).toBeInTheDocument();
|
|
149
|
+
expect(screen.getByText('Supports PDF, JPG')).toBeInTheDocument();
|
|
143
150
|
});
|
|
144
151
|
|
|
145
|
-
it(
|
|
152
|
+
it('should show disabled text if is uploading', () => {
|
|
146
153
|
const screen = setup({ uploading: true });
|
|
147
154
|
|
|
148
155
|
expect(
|
|
149
|
-
screen.getByText(
|
|
156
|
+
screen.getByText('Please wait while uploading file...')
|
|
150
157
|
).toBeInTheDocument();
|
|
151
158
|
});
|
|
159
|
+
|
|
160
|
+
it('should associate input with its label', () => {
|
|
161
|
+
const { getByLabelText } = setup({});
|
|
162
|
+
const input = getByLabelText('Choose file or drag & drop');
|
|
163
|
+
|
|
164
|
+
expect(input).toBeInTheDocument();
|
|
165
|
+
});
|
|
152
166
|
});
|
|
153
167
|
|
|
154
168
|
describe('Uploaded files', () => {
|
|
155
|
-
it(
|
|
169
|
+
it('should show uploaded files', () => {
|
|
156
170
|
const screen = setup({
|
|
157
171
|
uploadedFiles: [uploadedFilesMock],
|
|
158
172
|
});
|
|
159
173
|
|
|
160
|
-
expect(
|
|
161
|
-
screen.getByText(uploadedFilesMock.name)
|
|
162
|
-
).toBeInTheDocument();
|
|
174
|
+
expect(screen.getByText(uploadedFilesMock.name)).toBeInTheDocument();
|
|
163
175
|
});
|
|
164
176
|
|
|
165
|
-
it(
|
|
177
|
+
it('should call onRemoveFile with uploaded file id', () => {
|
|
166
178
|
const screen = setup({
|
|
167
179
|
uploadedFiles: [uploadedFilesMock],
|
|
168
180
|
});
|
|
169
181
|
|
|
170
|
-
screen.getByAltText(
|
|
182
|
+
screen.getByAltText('remove').click();
|
|
171
183
|
|
|
172
184
|
expect(mockOnRemoveFile).toBeCalledWith(uploadedFilesMock.id);
|
|
173
185
|
});
|
|
174
186
|
|
|
175
|
-
it(
|
|
187
|
+
it('should show uploaded file with uploading label', () => {
|
|
176
188
|
const screen = setup({
|
|
177
189
|
uploadedFiles: [{ ...uploadedFilesMock, progress: 50 }],
|
|
178
190
|
});
|
|
179
191
|
|
|
180
|
-
expect(screen.getByText(
|
|
192
|
+
expect(screen.getByText('Uploading...')).toBeInTheDocument();
|
|
181
193
|
});
|
|
182
194
|
|
|
183
|
-
it(
|
|
195
|
+
it('should show uploaded file with progress bar', () => {
|
|
184
196
|
const screen = setup({
|
|
185
|
-
uploadedFiles: [
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
uploadedFiles: [
|
|
198
|
+
{
|
|
199
|
+
...uploadedFilesMock,
|
|
200
|
+
progress: 50,
|
|
201
|
+
},
|
|
202
|
+
],
|
|
189
203
|
});
|
|
190
204
|
|
|
191
205
|
expect(screen.getByTestId(progressbarTestId)).toBeInTheDocument();
|
|
192
206
|
});
|
|
193
207
|
|
|
194
|
-
it(
|
|
208
|
+
it('should show uploaded file with no progress bar', () => {
|
|
195
209
|
const screen = setup({
|
|
196
|
-
uploadedFiles: [
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
210
|
+
uploadedFiles: [
|
|
211
|
+
{
|
|
212
|
+
...uploadedFilesMock,
|
|
213
|
+
progress: 50,
|
|
214
|
+
showProgressBar: false,
|
|
215
|
+
},
|
|
216
|
+
],
|
|
201
217
|
});
|
|
202
218
|
|
|
203
219
|
expect(screen.queryByTestId(progressbarTestId)).not.toBeInTheDocument();
|
|
204
220
|
});
|
|
205
221
|
|
|
206
|
-
it(
|
|
222
|
+
it('should show uploaded file with loading spinner', () => {
|
|
207
223
|
const screen = setup({
|
|
208
|
-
uploadedFiles: [
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
224
|
+
uploadedFiles: [
|
|
225
|
+
{
|
|
226
|
+
...uploadedFilesMock,
|
|
227
|
+
progress: 50,
|
|
228
|
+
showLoadingSpinner: true,
|
|
229
|
+
},
|
|
230
|
+
],
|
|
213
231
|
});
|
|
214
232
|
|
|
215
233
|
expect(screen.getByTestId(spinnerTestId)).toBeInTheDocument();
|
|
216
234
|
});
|
|
217
235
|
|
|
218
|
-
it(
|
|
236
|
+
it('should show uploaded file with no loading spinner', () => {
|
|
219
237
|
const screen = setup({
|
|
220
|
-
uploadedFiles: [
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
238
|
+
uploadedFiles: [
|
|
239
|
+
{
|
|
240
|
+
...uploadedFilesMock,
|
|
241
|
+
progress: 50,
|
|
242
|
+
showLoadingSpinner: false,
|
|
243
|
+
},
|
|
244
|
+
],
|
|
225
245
|
});
|
|
226
246
|
|
|
227
247
|
expect(screen.queryByTestId(spinnerTestId)).not.toBeInTheDocument();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useState } from 'react';
|
|
1
|
+
import { useCallback, useState, useRef } from 'react';
|
|
2
2
|
import classnames from 'classnames';
|
|
3
3
|
import { useDropzone, FileRejection } from 'react-dropzone';
|
|
4
4
|
import AnimateHeight from 'react-animate-height';
|
|
@@ -6,20 +6,20 @@ import generateId from '../../util/generateId';
|
|
|
6
6
|
import styles from './style.module.scss';
|
|
7
7
|
import icons from './icons/index'; // TODO: inline all of the svgs
|
|
8
8
|
import UploadFileCell from './UploadFileCell';
|
|
9
|
-
import {
|
|
10
|
-
formatAcceptFileList,
|
|
11
|
-
getErrorMessage,
|
|
12
|
-
getFormattedAcceptObject,
|
|
13
|
-
getUploadStatus
|
|
9
|
+
import {
|
|
10
|
+
formatAcceptFileList,
|
|
11
|
+
getErrorMessage,
|
|
12
|
+
getFormattedAcceptObject,
|
|
13
|
+
getUploadStatus,
|
|
14
14
|
} from './utils';
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
AcceptType,
|
|
18
|
-
ErrorMessage,
|
|
16
|
+
import {
|
|
17
|
+
AcceptType,
|
|
18
|
+
ErrorMessage,
|
|
19
19
|
FileType,
|
|
20
|
-
TextOverrides,
|
|
21
|
-
UploadedFile,
|
|
22
|
-
UploadStatus
|
|
20
|
+
TextOverrides,
|
|
21
|
+
UploadedFile,
|
|
22
|
+
UploadStatus,
|
|
23
23
|
} from './types';
|
|
24
24
|
|
|
25
25
|
import { formatBytes } from '../../util/formatBytes';
|
|
@@ -50,21 +50,23 @@ const MultiDropzone = ({
|
|
|
50
50
|
const [errors, setErrors] = useState<ErrorMessage[]>([]);
|
|
51
51
|
const formattedAccept = getFormattedAcceptObject(accept);
|
|
52
52
|
const fileList = formatAcceptFileList(formattedAccept);
|
|
53
|
-
const maxSizePlaceholder =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const maxSizePlaceholder =
|
|
54
|
+
maxSize && maxSize > 0
|
|
55
|
+
? `${textOverrides?.sizeUpToText || 'up to'} ${formatBytes(maxSize)}`
|
|
56
|
+
: '';
|
|
57
|
+
const placeholder = `${textOverrides?.supportsTextShort || 'Supports'} ${
|
|
58
|
+
fileList || 'JPEG, PNG, PDF'
|
|
59
|
+
} ${maxSizePlaceholder}`;
|
|
57
60
|
const isOverMaxFiles = maxFiles > 0 && uploadedFiles.length > maxFiles;
|
|
58
61
|
|
|
59
|
-
const removeError = (removeId: string) =>
|
|
60
|
-
setErrors(errors.filter(({ id }) => id !== removeId))
|
|
61
|
-
);
|
|
62
|
+
const removeError = (removeId: string) =>
|
|
63
|
+
setErrors(errors.filter(({ id }) => id !== removeId));
|
|
62
64
|
|
|
63
65
|
const onDrop = useCallback(
|
|
64
66
|
(acceptedFiles: File[], filesRejected: FileRejection[]) => {
|
|
65
67
|
onFileSelect(acceptedFiles);
|
|
66
68
|
|
|
67
|
-
setErrors((previousErrors) =>
|
|
69
|
+
setErrors((previousErrors) => [
|
|
68
70
|
...previousErrors,
|
|
69
71
|
...filesRejected.map(({ errors }) => ({
|
|
70
72
|
id: generateId(),
|
|
@@ -73,13 +75,12 @@ const placeholder = `${textOverrides?.supportsTextShort || "Supports"} ${fileLis
|
|
|
73
75
|
{ fileList, maxSize },
|
|
74
76
|
textOverrides
|
|
75
77
|
),
|
|
76
|
-
}))
|
|
77
|
-
])
|
|
78
|
+
})),
|
|
79
|
+
]);
|
|
78
80
|
},
|
|
79
81
|
[fileList, maxSize, onFileSelect, textOverrides]
|
|
80
82
|
);
|
|
81
83
|
|
|
82
|
-
|
|
83
84
|
const { getRootProps, getInputProps } = useDropzone({
|
|
84
85
|
accept: formattedAccept,
|
|
85
86
|
disabled: uploading,
|
|
@@ -87,6 +88,8 @@ const placeholder = `${textOverrides?.supportsTextShort || "Supports"} ${fileLis
|
|
|
87
88
|
onDrop,
|
|
88
89
|
});
|
|
89
90
|
|
|
91
|
+
const uniqueId = useRef(generateId());
|
|
92
|
+
|
|
90
93
|
return (
|
|
91
94
|
<div className={styles.container}>
|
|
92
95
|
<div
|
|
@@ -100,6 +103,7 @@ const placeholder = `${textOverrides?.supportsTextShort || "Supports"} ${fileLis
|
|
|
100
103
|
>
|
|
101
104
|
<input
|
|
102
105
|
data-testid="ds-drop-input"
|
|
106
|
+
id={uniqueId.current}
|
|
103
107
|
{...getInputProps()}
|
|
104
108
|
/>
|
|
105
109
|
<img
|
|
@@ -107,31 +111,39 @@ const placeholder = `${textOverrides?.supportsTextShort || "Supports"} ${fileLis
|
|
|
107
111
|
src={isCondensed ? icons.uploadSmallIcon : icons.uploadIcon}
|
|
108
112
|
alt="purple cloud with an arrow"
|
|
109
113
|
/>
|
|
110
|
-
<
|
|
114
|
+
<label
|
|
115
|
+
htmlFor={uniqueId.current}
|
|
116
|
+
className={`p-h4 mt8 d-block c-pointer ${
|
|
117
|
+
isCondensed ? styles.textInline : ''
|
|
118
|
+
}`}
|
|
119
|
+
>
|
|
111
120
|
{uploading
|
|
112
121
|
? textOverrides?.currentlyUploadingText ||
|
|
113
122
|
'Please wait while uploading file...'
|
|
114
123
|
: textOverrides?.instructionsText || 'Choose file or drag & drop'}
|
|
115
|
-
</
|
|
124
|
+
</label>
|
|
116
125
|
<div className="p-p--small tc-grey-500">
|
|
117
126
|
{textOverrides?.supportsText || placeholder}
|
|
118
127
|
</div>
|
|
119
128
|
</div>
|
|
120
129
|
|
|
121
|
-
{errors.map(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
{errors.map(
|
|
131
|
+
({ id, message }) =>
|
|
132
|
+
message && (
|
|
133
|
+
<UploadFileCell
|
|
134
|
+
uploadStatus="ERROR"
|
|
135
|
+
file={{
|
|
136
|
+
error: message,
|
|
137
|
+
id,
|
|
138
|
+
name: message,
|
|
139
|
+
progress: 0,
|
|
140
|
+
}}
|
|
141
|
+
key={id}
|
|
142
|
+
onRemoveFile={() => removeError(id)}
|
|
143
|
+
uploading={false}
|
|
144
|
+
/>
|
|
145
|
+
)
|
|
146
|
+
)}
|
|
135
147
|
|
|
136
148
|
{uploadedFiles.length > 0 && (
|
|
137
149
|
<div className="w100 mt16">
|
|
@@ -149,7 +161,7 @@ const placeholder = `${textOverrides?.supportsTextShort || "Supports"} ${fileLis
|
|
|
149
161
|
|
|
150
162
|
<AnimateHeight duration={300} height={isOverMaxFiles ? 'auto' : 0}>
|
|
151
163
|
<p className="tc-red-500 p-p--small">
|
|
152
|
-
{textOverrides?.tooManyFilesError ||
|
|
164
|
+
{textOverrides?.tooManyFilesError || 'Too many files.'}
|
|
153
165
|
</p>
|
|
154
166
|
</AnimateHeight>
|
|
155
167
|
</div>
|