@widergy/mobile-ui 1.27.0 → 1.28.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 +14 -0
- package/lib/components/CheckList/index.js +4 -0
- package/lib/components/Checkbox/index.js +4 -0
- package/lib/components/MultipleFilePicker/components/Picker/index.js +66 -74
- package/lib/components/MultipleFilePicker/components/Picker/styles.js +26 -34
- package/lib/components/MultipleFilePicker/components/UploadedFiles/index.js +27 -129
- package/lib/components/MultipleFilePicker/components/UploadedFiles/styles.js +8 -57
- package/lib/components/MultipleFilePicker/constants.js +0 -14
- package/lib/components/MultipleFilePicker/index.js +196 -147
- package/lib/components/MultipleFilePicker/propTypes.js +15 -11
- package/lib/components/MultipleFilePicker/styles.js +9 -0
- package/lib/components/MultipleFilePicker/utils.js +22 -51
- package/lib/components/UTBaseInputField/components/IconAdornment/utils.js +2 -3
- package/lib/components/UTCheckBox/constants.js +2 -0
- package/lib/components/UTCheckBox/index.js +25 -16
- package/lib/components/UTCheckBox/theme.js +1 -3
- package/lib/components/UTCheckList/constants.js +0 -2
- package/lib/components/UTCheckList/index.js +7 -6
- package/lib/components/UTCheckList/styles.js +2 -1
- package/lib/components/UTCheckList/utils.js +2 -2
- package/lib/components/UTFieldLabel/index.js +4 -3
- package/package.json +1 -1
- package/lib/components/MultipleFilePicker/components/Input/README.md +0 -77
- package/lib/components/MultipleFilePicker/components/Input/components/ShowPassword/constants.js +0 -2
- package/lib/components/MultipleFilePicker/components/Input/components/ShowPassword/index.js +0 -19
- package/lib/components/MultipleFilePicker/components/Input/components/ShowPassword/propTypes.js +0 -8
- package/lib/components/MultipleFilePicker/components/Input/components/ShowPassword/styles.js +0 -11
- package/lib/components/MultipleFilePicker/components/Input/components/Title/index.js +0 -78
- package/lib/components/MultipleFilePicker/components/Input/components/Title/propTypes.js +0 -14
- package/lib/components/MultipleFilePicker/components/Input/components/Title/styles.js +0 -42
- package/lib/components/MultipleFilePicker/components/Input/components/Underline/index.js +0 -80
- package/lib/components/MultipleFilePicker/components/Input/components/Underline/styles.js +0 -39
- package/lib/components/MultipleFilePicker/components/Input/constants.js +0 -2
- package/lib/components/MultipleFilePicker/components/Input/index.js +0 -299
- package/lib/components/MultipleFilePicker/components/Input/propTypes.js +0 -43
- package/lib/components/MultipleFilePicker/components/Input/styles.js +0 -47
|
@@ -1,168 +1,217 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { isArray, isEmpty } from 'lodash';
|
|
2
|
+
// eslint-disable-next-line import/no-unresolved
|
|
3
|
+
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
|
|
4
|
+
// eslint-disable-next-line react-native/split-platform-components
|
|
5
|
+
import { View, PermissionsAndroid } from 'react-native';
|
|
3
6
|
// eslint-disable-next-line import/no-unresolved
|
|
4
7
|
import DocumentPicker from 'react-native-document-picker';
|
|
5
|
-
import {
|
|
8
|
+
import React, { useEffect, useState } from 'react';
|
|
6
9
|
|
|
10
|
+
import { IS_IOS } from '../../utils/platformUtils/constants';
|
|
7
11
|
import { retrieveFile, blobToFile } from '../../utils/fileUtils.js';
|
|
12
|
+
import UTBottomSheet from '../UTBottomSheet';
|
|
13
|
+
import UTButton from '../UTButton';
|
|
8
14
|
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import { UPLOAD_ICON, DEFAULT_MAX_SIZE } from './constants';
|
|
15
|
+
import { DEFAULT_MAX_SIZE } from './constants';
|
|
16
|
+
import { getInitialValuesFrom, isFileFormatInvalid, isFileSizeInvaid, isFileTypeInvalid } from './utils';
|
|
12
17
|
import filePickerPropTypes from './propTypes';
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
onError,
|
|
49
|
-
maxFileByteSize,
|
|
50
|
-
maxFiles,
|
|
51
|
-
minFiles,
|
|
52
|
-
avoidRetrieveFile,
|
|
53
|
-
fileTypeError,
|
|
54
|
-
allowedPDFUploadSizes,
|
|
55
|
-
pdfFormatError
|
|
56
|
-
} = this.props;
|
|
57
|
-
try {
|
|
58
|
-
const documents = await DocumentPicker.pick({
|
|
59
|
-
allowMultiSelection: true,
|
|
60
|
-
type: allowedTypes && !onlyPDFAllowed(allowedTypes) ? allowedTypes : DocumentPicker.types.allFiles
|
|
61
|
-
});
|
|
62
|
-
const { uploadedFiles } = this.state;
|
|
63
|
-
|
|
64
|
-
const filesSelectedQuantity = uploadedFiles.length + documents.length;
|
|
65
|
-
validateFileQuantity(filesSelectedQuantity, { maxFiles, minFiles }, fileTypeError);
|
|
66
|
-
|
|
67
|
-
await Promise.all(
|
|
68
|
-
documents.map(async document => {
|
|
69
|
-
const hasFileBeenUploaded = uploadedFiles.some(fileAdded => fileAdded.name === document.name);
|
|
70
|
-
|
|
71
|
-
if (!hasFileBeenUploaded) {
|
|
72
|
-
validateOnlyPDFAllowed(document, allowedTypes, fileTypeError);
|
|
73
|
-
validateFileType(document, allowedTypes, fileTypeError);
|
|
74
|
-
|
|
75
|
-
const isValid = isInvalidFileSize(document, maxFileByteSize, onMaxSizeError);
|
|
76
|
-
if (isValid) return;
|
|
18
|
+
import Picker from './components/Picker';
|
|
19
|
+
import styles from './styles';
|
|
20
|
+
|
|
21
|
+
const MultipleFilePicker = ({
|
|
22
|
+
allowedPDFUploadSizes,
|
|
23
|
+
allowedTypes,
|
|
24
|
+
disabled,
|
|
25
|
+
enabledInputs: { camera, files, gallery } = { files: true },
|
|
26
|
+
error,
|
|
27
|
+
filePlaceholder,
|
|
28
|
+
fileTypeError,
|
|
29
|
+
helpText,
|
|
30
|
+
maxFileByteSize = DEFAULT_MAX_SIZE,
|
|
31
|
+
maxFiles,
|
|
32
|
+
onChange,
|
|
33
|
+
onError: onError_,
|
|
34
|
+
onMaxSizeError: onMaxSizeError_,
|
|
35
|
+
pickerText,
|
|
36
|
+
style,
|
|
37
|
+
title,
|
|
38
|
+
value
|
|
39
|
+
}) => {
|
|
40
|
+
const { files: values } = value || {};
|
|
41
|
+
|
|
42
|
+
const [newFile, setNewFile] = useState(null);
|
|
43
|
+
const [uploadedFiles, setUploadedFiles] = useState(isArray(values) ? getInitialValuesFrom(values) : []);
|
|
44
|
+
const [rawFiles, setRawFiles] = useState(isArray(values) ? values : []);
|
|
45
|
+
|
|
46
|
+
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
|
47
|
+
const closeDrawer = () => setIsDrawerOpen(false);
|
|
48
|
+
|
|
49
|
+
const onError = errorMsg => {
|
|
50
|
+
onError_(errorMsg);
|
|
51
|
+
closeDrawer();
|
|
52
|
+
};
|
|
77
53
|
|
|
78
|
-
|
|
79
|
-
|
|
54
|
+
const onMaxSizeError = () => {
|
|
55
|
+
onMaxSizeError_(maxFileByteSize);
|
|
56
|
+
closeDrawer();
|
|
57
|
+
};
|
|
80
58
|
|
|
81
|
-
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
onChange?.(isEmpty(rawFiles) ? null : { files: rawFiles });
|
|
61
|
+
}, [rawFiles]);
|
|
82
62
|
|
|
83
|
-
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (newFile) {
|
|
65
|
+
setUploadedFiles([...uploadedFiles, newFile.uploadFile]);
|
|
66
|
+
setRawFiles([...rawFiles, newFile.rawFile]);
|
|
67
|
+
}
|
|
68
|
+
}, [newFile]);
|
|
69
|
+
|
|
70
|
+
const onPickFiles = async () => {
|
|
71
|
+
const documents = await DocumentPicker.pick({
|
|
72
|
+
allowMultiSelection: true,
|
|
73
|
+
type: allowedTypes ?? DocumentPicker.types.allFiles
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (uploadedFiles.length + documents.length > maxFiles)
|
|
77
|
+
onError('La cantidad de archivos supera al máximo permitido');
|
|
78
|
+
else {
|
|
79
|
+
closeDrawer();
|
|
80
|
+
documents.forEach(async document => {
|
|
81
|
+
if (!uploadedFiles.some(({ name }) => name === document.name)) {
|
|
82
|
+
if (isFileTypeInvalid(document, allowedTypes, fileTypeError, onError)) return;
|
|
83
|
+
if (isFileSizeInvaid(document, maxFileByteSize, onMaxSizeError)) return;
|
|
84
|
+
const file = await retrieveFile(document.uri, document.type, document.name);
|
|
85
|
+
if (await isFileFormatInvalid(file, allowedPDFUploadSizes, onError)) return;
|
|
86
|
+
setNewFile({
|
|
87
|
+
uploadFile: { name: document.name, size: document.size },
|
|
88
|
+
rawFile: blobToFile(file, document.type)
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
};
|
|
84
94
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
// eslint-disable-next-line consistent-return
|
|
96
|
+
const requestPermissionCamera = async () => {
|
|
97
|
+
try {
|
|
98
|
+
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA);
|
|
99
|
+
return granted === PermissionsAndroid.RESULTS.GRANTED
|
|
100
|
+
? launchCamera
|
|
101
|
+
: { errorCode: 'Son necesarios permisos para utilizar la cámara' };
|
|
92
102
|
} catch (err) {
|
|
93
|
-
|
|
94
|
-
onError(err.message);
|
|
95
|
-
}
|
|
103
|
+
onError(err.message);
|
|
96
104
|
}
|
|
97
105
|
};
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
const handleShowImagePicker = sourceImage => {
|
|
108
|
+
if (sourceImage?.errorCode) {
|
|
109
|
+
onError(sourceImage.errorCode);
|
|
110
|
+
return;
|
|
103
111
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
sourceImage(
|
|
113
|
+
{
|
|
114
|
+
mediaType: 'photo',
|
|
115
|
+
selectionLimit: Math.max(maxFiles - uploadedFiles.length, 0)
|
|
116
|
+
},
|
|
117
|
+
async response => {
|
|
118
|
+
if (response.didCancel) return;
|
|
119
|
+
|
|
120
|
+
if (response.errorCode) {
|
|
121
|
+
onError(response.errorCode);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
closeDrawer();
|
|
125
|
+
response.assets.forEach(async asset => {
|
|
126
|
+
const file = await retrieveFile(asset.uri, asset.type);
|
|
127
|
+
if (!file) {
|
|
128
|
+
onError(response.errorCode);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (isFileTypeInvalid(file, allowedTypes, fileTypeError, onError)) return;
|
|
132
|
+
if (isFileSizeInvaid(file, maxFileByteSize, onMaxSizeError)) return;
|
|
133
|
+
|
|
134
|
+
setNewFile({
|
|
135
|
+
uploadFile: { name: file.data.name, size: file.data.size },
|
|
136
|
+
rawFile: blobToFile(file, asset.type)
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
);
|
|
108
141
|
};
|
|
109
142
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
<UploadedFiles
|
|
128
|
-
icon={UPLOAD_ICON}
|
|
129
|
-
error={error}
|
|
130
|
-
onAdd={this.handleShowPicker}
|
|
131
|
-
onDelete={this.handleDeleteFile}
|
|
132
|
-
uploadedFiles={uploadedFiles}
|
|
133
|
-
filePlaceholder={filePlaceholder}
|
|
134
|
-
title={title}
|
|
135
|
-
withMarkdownTitle={withMarkdownTitle}
|
|
136
|
-
markdownStyles={markdownStyles}
|
|
137
|
-
disabled={disabled}
|
|
138
|
-
pickerText={pickerText}
|
|
139
|
-
helpText={helpText}
|
|
140
|
-
/>
|
|
141
|
-
</View>
|
|
142
|
-
) : (
|
|
143
|
-
<View style={style}>
|
|
144
|
-
<Picker
|
|
145
|
-
icon={UPLOAD_ICON}
|
|
146
|
-
error={error}
|
|
147
|
-
onAdd={this.handleShowPicker}
|
|
148
|
-
onDelete={this.handleDeleteFile}
|
|
149
|
-
uploadedFiles={uploadedFiles}
|
|
150
|
-
filePlaceholder={filePlaceholder}
|
|
151
|
-
title={title}
|
|
152
|
-
withMarkdownTitle={withMarkdownTitle}
|
|
153
|
-
markdownStyles={markdownStyles}
|
|
154
|
-
disabled={disabled}
|
|
155
|
-
pickerText={pickerText}
|
|
156
|
-
helpText={helpText}
|
|
157
|
-
UploadIcon={UploadIcon}
|
|
158
|
-
/>
|
|
159
|
-
</View>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
143
|
+
const onPickCamera = async () =>
|
|
144
|
+
handleShowImagePicker(IS_IOS ? launchCamera : await requestPermissionCamera());
|
|
145
|
+
|
|
146
|
+
const onPickGallery = () => handleShowImagePicker(launchImageLibrary);
|
|
147
|
+
|
|
148
|
+
const handleDeleteFile = index => {
|
|
149
|
+
onChange?.(null);
|
|
150
|
+
setUploadedFiles(uploadedFiles.filter((_, i) => i !== index));
|
|
151
|
+
setRawFiles(rawFiles.filter((_, i) => i !== index));
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const onAdd = () => {
|
|
155
|
+
if (Boolean(camera) + Boolean(files) + Boolean(gallery) > 1) setIsDrawerOpen(true);
|
|
156
|
+
else if (camera) onPickCamera();
|
|
157
|
+
else if (files) onPickFiles();
|
|
158
|
+
else if (gallery) onPickGallery();
|
|
159
|
+
};
|
|
163
160
|
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
return (
|
|
162
|
+
<View style={style}>
|
|
163
|
+
<Picker
|
|
164
|
+
disabled={disabled}
|
|
165
|
+
error={error}
|
|
166
|
+
filePlaceholder={filePlaceholder}
|
|
167
|
+
helpText={helpText}
|
|
168
|
+
maxFiles={maxFiles}
|
|
169
|
+
onAdd={onAdd}
|
|
170
|
+
onDelete={handleDeleteFile}
|
|
171
|
+
pickerText={pickerText}
|
|
172
|
+
title={title}
|
|
173
|
+
uploadedFiles={uploadedFiles}
|
|
174
|
+
/>
|
|
175
|
+
<UTBottomSheet onClose={closeDrawer} visible={isDrawerOpen}>
|
|
176
|
+
<View style={styles.actions}>
|
|
177
|
+
{[
|
|
178
|
+
{
|
|
179
|
+
Icon: 'IconCamera',
|
|
180
|
+
onPress: onPickCamera,
|
|
181
|
+
show: camera,
|
|
182
|
+
text: 'Cámara'
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
Icon: 'IconPhoto',
|
|
186
|
+
onPress: onPickGallery,
|
|
187
|
+
show: gallery,
|
|
188
|
+
text: 'Fotos'
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
Icon: 'IconFileArrowRight',
|
|
192
|
+
onPress: onPickFiles,
|
|
193
|
+
show: files,
|
|
194
|
+
text: 'Archivos'
|
|
195
|
+
}
|
|
196
|
+
].map(
|
|
197
|
+
({ Icon, onPress, show, text }) =>
|
|
198
|
+
show && (
|
|
199
|
+
<UTButton
|
|
200
|
+
colorTheme="secondary"
|
|
201
|
+
Icon={Icon}
|
|
202
|
+
key={text}
|
|
203
|
+
onPress={onPress}
|
|
204
|
+
size="large"
|
|
205
|
+
variant="shadow"
|
|
206
|
+
>
|
|
207
|
+
{text}
|
|
208
|
+
</UTButton>
|
|
209
|
+
)
|
|
210
|
+
)}
|
|
211
|
+
</View>
|
|
212
|
+
</UTBottomSheet>
|
|
213
|
+
</View>
|
|
214
|
+
);
|
|
166
215
|
};
|
|
167
216
|
|
|
168
217
|
MultipleFilePicker.propTypes = filePickerPropTypes;
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { string, bool, func, number, array, object } from 'prop-types';
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
allowedPDFUploadSizes: array,
|
|
5
|
+
allowedTypes: array,
|
|
6
|
+
disabled: bool,
|
|
7
|
+
enabledInputs: object,
|
|
8
|
+
error: string,
|
|
7
9
|
filePlaceholder: string,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
fileTypeError: string,
|
|
11
|
+
helpText: string,
|
|
10
12
|
maxFileByteSize: number,
|
|
13
|
+
maxFiles: number,
|
|
14
|
+
onChange: func,
|
|
11
15
|
onError: func,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
onMaxSizeError: func,
|
|
17
|
+
pickerText: string,
|
|
18
|
+
style: object,
|
|
19
|
+
title: string,
|
|
20
|
+
value: object
|
|
17
21
|
};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { PDFDocument } from 'pdf-lib';
|
|
2
2
|
import { isEmpty } from 'lodash';
|
|
3
3
|
|
|
4
|
-
import { isImageByUri } from '../../utils/fileUtils.js';
|
|
5
|
-
|
|
6
|
-
export const onlyPDFAllowed = allowedTypes => allowedTypes.length === 1 && allowedTypes[0].includes('pdf');
|
|
7
|
-
|
|
8
4
|
const lengthMatches = (length1, length2, toleranceInPercentage) => {
|
|
9
5
|
const delta = length1 * (toleranceInPercentage / 100);
|
|
10
6
|
return Math.abs(length1 - length2) < delta;
|
|
@@ -32,7 +28,7 @@ const blobToBase64 = blob =>
|
|
|
32
28
|
reader.readAsDataURL(blob);
|
|
33
29
|
});
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
const pdfAspectRatioValidation = async (file, allowedPDFUploadSizes) => {
|
|
36
32
|
const base64 = await blobToBase64(file);
|
|
37
33
|
const pdf = await PDFDocument.load(base64);
|
|
38
34
|
const pages = pdf.getPages();
|
|
@@ -43,58 +39,33 @@ export const pdfAspectRatioValidation = async (file, allowedPDFUploadSizes) => {
|
|
|
43
39
|
});
|
|
44
40
|
};
|
|
45
41
|
|
|
46
|
-
export const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const isPDF = document => document.type.includes('pdf');
|
|
56
|
-
const isImage = document => document.type.includes('image');
|
|
57
|
-
|
|
58
|
-
export const validateOnlyPDFAllowed = (document, allowedTypes, fileTypeError) => {
|
|
59
|
-
const condition = onlyPDFAllowed(allowedTypes) && !isPDF(document);
|
|
60
|
-
if (condition) {
|
|
61
|
-
throw new Error(fileTypeError || 'El tipo de archivo debe ser PDF.');
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const validateFileType = (document, allowedTypes, fileTypeError) => {
|
|
66
|
-
const isInvalidImage = !isImage(document) && !isImageByUri(document.uri);
|
|
67
|
-
const condition = allowedTypes && isInvalidImage && !isPDF(document);
|
|
68
|
-
if (condition) {
|
|
69
|
-
throw new Error(fileTypeError || 'Tipo de archivo inválido.');
|
|
70
|
-
}
|
|
42
|
+
export const isFileTypeInvalid = (document, allowedTypes, fileTypeError, onError) => {
|
|
43
|
+
const isInvalid = !(
|
|
44
|
+
allowedTypes.includes(document.type) ||
|
|
45
|
+
(document.type.includes('image') && allowedTypes.includes('image/*'))
|
|
46
|
+
);
|
|
47
|
+
if (isInvalid) onError(fileTypeError || 'Tipo de archivo inválido.');
|
|
48
|
+
return isInvalid;
|
|
71
49
|
};
|
|
72
50
|
|
|
73
|
-
export const
|
|
51
|
+
export const isFileSizeInvaid = (document, maxFileByteSize, onError) => {
|
|
74
52
|
const isInvalid = maxFileByteSize && document.size > maxFileByteSize;
|
|
75
|
-
if (isInvalid) {
|
|
76
|
-
if (onMaxSizeError) {
|
|
77
|
-
onMaxSizeError(document.size, maxFileByteSize);
|
|
78
|
-
} else {
|
|
79
|
-
throw new Error(`El archivo debe ser menor a ${maxFileByteSize}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
53
|
+
if (isInvalid) onError(`El archivo debe ser menor a ${maxFileByteSize}`);
|
|
82
54
|
return isInvalid;
|
|
83
55
|
};
|
|
84
56
|
|
|
85
|
-
export const
|
|
86
|
-
const isInvalid =
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
57
|
+
export const isFileFormatInvalid = async (file, allowedPDFUploadSizes, onError) => {
|
|
58
|
+
const isInvalid =
|
|
59
|
+
file.type.includes('pdf') &&
|
|
60
|
+
!isEmpty(allowedPDFUploadSizes) &&
|
|
61
|
+
(await pdfAspectRatioValidation(file, allowedPDFUploadSizes));
|
|
62
|
+
if (isInvalid)
|
|
63
|
+
onError(
|
|
64
|
+
`El formato de archivo es inválido. (Válidos: ${allowedPDFUploadSizes
|
|
65
|
+
?.map(aspectRatio => aspectRatio.name)
|
|
66
|
+
.join(' - ')})`
|
|
67
|
+
);
|
|
68
|
+
return isInvalid;
|
|
98
69
|
};
|
|
99
70
|
|
|
100
71
|
export const getInitialValuesFrom = files =>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export const getIconColorProps = (changeOnError, changeOnFocus, colorTheme, error, focused, shade) =>
|
|
2
|
-
|
|
1
|
+
export const getIconColorProps = (changeOnError, changeOnFocus, colorTheme, error, focused, shade) =>
|
|
2
|
+
changeOnError && error
|
|
3
3
|
? { colorTheme: 'error', shade: '04' }
|
|
4
4
|
: changeOnFocus && focused
|
|
5
5
|
? { colorTheme: 'accent', shade: '04' }
|
|
6
6
|
: { colorTheme: colorTheme || 'gray', shade };
|
|
7
|
-
};
|
|
@@ -5,23 +5,24 @@ import { useTheme } from '../../theming';
|
|
|
5
5
|
import UTFieldLabel from '../UTFieldLabel';
|
|
6
6
|
import UTIcon from '../UTIcon';
|
|
7
7
|
|
|
8
|
-
import { CHECKED_ICON, INDETERMINATE_ICON } from './constants';
|
|
8
|
+
import { BUTTON_VARIANT, CHECKED_ICON, INDETERMINATE_ICON } from './constants';
|
|
9
9
|
import { propTypes, defaultProps } from './proptypes';
|
|
10
10
|
import { retrieveStyle } from './theme';
|
|
11
11
|
import styles from './styles';
|
|
12
12
|
|
|
13
13
|
const UTCheckBox = ({
|
|
14
|
-
|
|
14
|
+
value,
|
|
15
|
+
onChange,
|
|
15
16
|
disabled,
|
|
16
17
|
indeterminate,
|
|
17
18
|
isSimple,
|
|
18
|
-
onPress,
|
|
19
19
|
required,
|
|
20
20
|
reversed,
|
|
21
21
|
spacing,
|
|
22
22
|
style,
|
|
23
23
|
title,
|
|
24
|
-
variant
|
|
24
|
+
variant,
|
|
25
|
+
withMarkdown
|
|
25
26
|
}) => {
|
|
26
27
|
const theme = useTheme();
|
|
27
28
|
const [pressed, setPressed] = useState(false);
|
|
@@ -29,7 +30,7 @@ const UTCheckBox = ({
|
|
|
29
30
|
const { containerStyles, iconContainerStyles, boxStyles, pressableStyles, titleStyles } = useMemo(
|
|
30
31
|
() =>
|
|
31
32
|
retrieveStyle({
|
|
32
|
-
checked,
|
|
33
|
+
checked: value,
|
|
33
34
|
disabled,
|
|
34
35
|
indeterminate,
|
|
35
36
|
pressed,
|
|
@@ -39,33 +40,36 @@ const UTCheckBox = ({
|
|
|
39
40
|
theme,
|
|
40
41
|
variant
|
|
41
42
|
}),
|
|
42
|
-
[
|
|
43
|
+
[value, disabled, indeterminate, reversed, spacing, style, theme, variant, pressed]
|
|
43
44
|
);
|
|
44
45
|
|
|
45
46
|
const iconName = useMemo(
|
|
46
|
-
() => (indeterminate ? INDETERMINATE_ICON :
|
|
47
|
-
[indeterminate,
|
|
47
|
+
() => (indeterminate ? INDETERMINATE_ICON : value ? CHECKED_ICON : ''),
|
|
48
|
+
[indeterminate, value]
|
|
48
49
|
);
|
|
49
50
|
|
|
50
51
|
const handlePressIn = useCallback(() => setPressed(true), []);
|
|
51
52
|
const handlePressOut = useCallback(() => setPressed(false), []);
|
|
52
53
|
|
|
54
|
+
const handlePress = useCallback(() => {
|
|
55
|
+
if (!disabled && onChange) {
|
|
56
|
+
onChange(!value);
|
|
57
|
+
}
|
|
58
|
+
}, [disabled, onChange, value]);
|
|
59
|
+
|
|
60
|
+
const shouldHighlightLabel = value && variant === BUTTON_VARIANT;
|
|
61
|
+
|
|
53
62
|
return (
|
|
54
63
|
<Pressable
|
|
55
64
|
style={pressableStyles}
|
|
56
65
|
disabled={disabled}
|
|
57
|
-
onPress={
|
|
66
|
+
onPress={handlePress}
|
|
58
67
|
onPressIn={handlePressIn}
|
|
59
68
|
onPressOut={handlePressOut}
|
|
60
69
|
>
|
|
61
70
|
<View style={containerStyles}>
|
|
62
71
|
{isSimple ? (
|
|
63
|
-
<UTIcon
|
|
64
|
-
name="IconCheck"
|
|
65
|
-
shade="04"
|
|
66
|
-
colorTheme="accent"
|
|
67
|
-
style={checked ? undefined : styles.hidden}
|
|
68
|
-
/>
|
|
72
|
+
<UTIcon name="IconCheck" shade="04" colorTheme="accent" style={value ? undefined : styles.hidden} />
|
|
69
73
|
) : (
|
|
70
74
|
<View style={boxStyles}>
|
|
71
75
|
<View style={iconContainerStyles}>
|
|
@@ -73,7 +77,12 @@ const UTCheckBox = ({
|
|
|
73
77
|
</View>
|
|
74
78
|
</View>
|
|
75
79
|
)}
|
|
76
|
-
<UTFieldLabel
|
|
80
|
+
<UTFieldLabel
|
|
81
|
+
colorTheme={shouldHighlightLabel ? 'accent' : 'dark'}
|
|
82
|
+
required={required}
|
|
83
|
+
style={titleStyles}
|
|
84
|
+
withMarkdown={withMarkdown}
|
|
85
|
+
>
|
|
77
86
|
{title}
|
|
78
87
|
</UTFieldLabel>
|
|
79
88
|
</View>
|