@widergy/mobile-ui 1.27.1 → 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 +7 -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/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 =>
|
package/package.json
CHANGED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Input
|
|
2
|
-
|
|
3
|
-
## Input
|
|
4
|
-
|
|
5
|
-
Material Text Input with Title and Underline.
|
|
6
|
-
|
|
7
|
-
### Props
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
| NAME | TYPE | REQUIRED | DESCRIPTION | DEFAULT VALUE |
|
|
11
|
-
| --- | --- | --- | --- | --- |
|
|
12
|
-
| [TextInput](https://facebook.github.io/react-native/docs/textinput#props) props. | TextInput props | No | | - |
|
|
13
|
-
| activeColor | string | No | The color the input will have when active. If this prop is not specified, the color defaults to `theme.colors.primary`. | - |
|
|
14
|
-
| backgroundColor | string | No | Background color for the input. Defaults to `theme.colors.inputBackground`. | - |
|
|
15
|
-
| caption | string | No | Helper text to show below the input if no error is present. | - |
|
|
16
|
-
| captionProps | CaptionType | No | Additional props for caption. | - |
|
|
17
|
-
| containerStyle | ViewStyle | No | Style for the outer container of the input. | - |
|
|
18
|
-
| disabled | bool | No | If `true` sets all styles to disabled and disables interactions with the input. | - |
|
|
19
|
-
| error | string | No | Error to display instead of the caption. Also sets colors to the error color. | - |
|
|
20
|
-
| errorColor | string | No | The color that errors will be displayed in. Defaults to `theme.colors.error`. | - |
|
|
21
|
-
| iconSize | number | No | The size that applies to all icons. | DEFAULT ICON SIZE |
|
|
22
|
-
| inactiveColor | string | No | The color the input will have when inactive. If this prop is not specified, the color defaults to `theme.fonts.fontColor`. | - |
|
|
23
|
-
| inputRef | func | No | A way to pass a `ref` from outside the component to the input. | - |
|
|
24
|
-
| leadingIcon | IconType | No | Icon to display on the left side. | - |
|
|
25
|
-
| showEye | bool | No | Show eye icon to show `secureTextEntry` text if that prop is enabled. | - |
|
|
26
|
-
| textStyles | TextStyle | No | Style for the input. | - |
|
|
27
|
-
| title | string | No | Input title to show when the input is not active. Will float to the top once it is active. | - |
|
|
28
|
-
| trailingIcon | IconButtonType | No | Icon button to display on the right side. | - |
|
|
29
|
-
| underlineHeight | number | No | The underline component height (reminder: underline is scaled twice as big when active). | `portraitVerticalScale(1)` |
|
|
30
|
-
| withValueColor | string | No | The color of the title when it has values, but is not focused. | - |
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
#### Example
|
|
34
|
-
```js
|
|
35
|
-
import React, { PureComponent } from 'react';
|
|
36
|
-
import { Input } from '@widergy/mobile-ui';
|
|
37
|
-
|
|
38
|
-
class InputShowcase extends PureComponent {
|
|
39
|
-
state = {
|
|
40
|
-
value: '',
|
|
41
|
-
error: ''
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
changeValue = value => this.setState({ value });
|
|
45
|
-
|
|
46
|
-
handleBlur = () => {
|
|
47
|
-
const { value } = this.state;
|
|
48
|
-
this.validate(value);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
handleFocus = () => {
|
|
52
|
-
this.setState({ error: '' });
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
validate = text => {
|
|
56
|
-
const error =
|
|
57
|
-
text && text.length < 5 ? 'Debe tener más de 5 caracteres y este mensaje es de dos líneas' : '';
|
|
58
|
-
|
|
59
|
-
this.setState({ error });
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
render() {
|
|
63
|
-
return (
|
|
64
|
-
<Input
|
|
65
|
-
{...this.state}
|
|
66
|
-
{...this.props}
|
|
67
|
-
onBlur={this.handleBlur}
|
|
68
|
-
onFocus={this.handleFocus}
|
|
69
|
-
onChange={this.changeValue}
|
|
70
|
-
onSubmit={this.validate}
|
|
71
|
-
containerStyle={styles.input}
|
|
72
|
-
/>
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
```
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import UTButton from '../../../../../UTButton';
|
|
5
|
-
|
|
6
|
-
import propTypes from './propTypes';
|
|
7
|
-
import styles from './styles';
|
|
8
|
-
|
|
9
|
-
const ShowPassword = ({ onShowPassword, passwordVisible }) => (
|
|
10
|
-
<View style={styles.container}>
|
|
11
|
-
<UTButton Icon={passwordVisible ? 'IconEye' : 'IconEyeOff'} onPress={onShowPassword} variant="text" />
|
|
12
|
-
</View>
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
ShowPassword.displayName = 'ShowPassword';
|
|
16
|
-
|
|
17
|
-
ShowPassword.propTypes = propTypes;
|
|
18
|
-
|
|
19
|
-
export default ShowPassword;
|