react-native-molecules 0.5.0-beta.11 → 0.5.0-beta.13
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/hooks/useFilePicker.tsx
CHANGED
|
@@ -7,15 +7,11 @@ import {
|
|
|
7
7
|
} from '../utils/DocumentPicker';
|
|
8
8
|
import { isNil, omitBy } from '../utils/lodash';
|
|
9
9
|
|
|
10
|
-
export const useFilePicker = ({
|
|
11
|
-
multiple,
|
|
12
|
-
onCancel,
|
|
13
|
-
onError,
|
|
14
|
-
...options
|
|
15
|
-
}: DocumentPickerOptions) => {
|
|
10
|
+
export const useFilePicker = (options: DocumentPickerOptions) => {
|
|
16
11
|
const openFilePicker = useCallback(
|
|
17
|
-
async (callback: (response: DocumentResult
|
|
18
|
-
const
|
|
12
|
+
async (callback: (response: DocumentResult[]) => void) => {
|
|
13
|
+
const { multiple, ...rest } = options;
|
|
14
|
+
const omittedOptions = omitBy(rest, isNil);
|
|
19
15
|
|
|
20
16
|
try {
|
|
21
17
|
let response;
|
|
@@ -30,16 +26,10 @@ export const useFilePicker = ({
|
|
|
30
26
|
} catch (e: any) {
|
|
31
27
|
// eslint-disable-next-line no-console
|
|
32
28
|
console.log('FilePicker Error', e, e?.code);
|
|
33
|
-
|
|
34
|
-
if (e?.code === 'DOCUMENT_PICKER_CANCELED.') {
|
|
35
|
-
onCancel?.();
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
// It might result in an error.
|
|
39
|
-
onError?.(e);
|
|
29
|
+
// Error and cancel callbacks are handled by DocumentPicker itself
|
|
40
30
|
}
|
|
41
31
|
},
|
|
42
|
-
[
|
|
32
|
+
[options],
|
|
43
33
|
);
|
|
44
34
|
|
|
45
35
|
return { openFilePicker };
|
package/package.json
CHANGED
|
@@ -2,6 +2,14 @@ import { Platform } from 'react-native';
|
|
|
2
2
|
|
|
3
3
|
import type { DocumentPickerOptions, DocumentResult } from './types';
|
|
4
4
|
|
|
5
|
+
class OperationCanceledError extends Error {
|
|
6
|
+
code = 'OPERATION_CANCELED';
|
|
7
|
+
constructor() {
|
|
8
|
+
super('user canceled the document picker');
|
|
9
|
+
this.name = 'OperationCanceledError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
const resolveFileData = (file: File): Promise<DocumentResult> => {
|
|
6
14
|
return new Promise((resolve, reject) => {
|
|
7
15
|
const mimeType = file.type;
|
|
@@ -31,46 +39,89 @@ const resolveFileData = (file: File): Promise<DocumentResult> => {
|
|
|
31
39
|
const getDocumentAsyncWeb = async ({
|
|
32
40
|
type = '*/*',
|
|
33
41
|
multiple = false,
|
|
34
|
-
|
|
42
|
+
onCancel,
|
|
43
|
+
onError,
|
|
44
|
+
}: DocumentPickerOptions): Promise<DocumentResult[]> => {
|
|
35
45
|
// SSR guard
|
|
36
46
|
if (Platform.OS !== 'web') {
|
|
37
|
-
|
|
47
|
+
const error = new OperationCanceledError();
|
|
48
|
+
onCancel?.();
|
|
49
|
+
throw error;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
try {
|
|
54
|
+
const input = document.createElement('input');
|
|
55
|
+
input.style.display = 'none';
|
|
56
|
+
input.setAttribute('type', 'file');
|
|
57
|
+
// @ts-expect-error
|
|
58
|
+
input.setAttribute('accept', Array.isArray(type) ? type.join(',') : type);
|
|
45
59
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
if (multiple) {
|
|
61
|
+
input.setAttribute('multiple', 'multiple');
|
|
62
|
+
}
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
document.body.appendChild(input);
|
|
51
65
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
const cleanup = () => {
|
|
67
|
+
try {
|
|
68
|
+
document.body.removeChild(input);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
// Input already removed, ignore
|
|
71
|
+
}
|
|
72
|
+
};
|
|
56
73
|
|
|
57
|
-
|
|
74
|
+
input.addEventListener('change', async () => {
|
|
75
|
+
try {
|
|
76
|
+
if (input.files && input.files.length > 0) {
|
|
77
|
+
const response: Promise<DocumentResult>[] = [];
|
|
58
78
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
79
|
+
Array.from(input.files).forEach(file =>
|
|
80
|
+
response.push(resolveFileData(file)),
|
|
81
|
+
);
|
|
63
82
|
|
|
64
|
-
|
|
65
|
-
|
|
83
|
+
const results = await Promise.all(response);
|
|
84
|
+
resolve(results);
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
onError?.(error);
|
|
88
|
+
reject(error);
|
|
89
|
+
} finally {
|
|
90
|
+
cleanup();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
66
93
|
|
|
67
|
-
|
|
68
|
-
|
|
94
|
+
input.addEventListener('cancel', () => {
|
|
95
|
+
const error = new OperationCanceledError();
|
|
96
|
+
onCancel?.();
|
|
97
|
+
cleanup();
|
|
98
|
+
reject(error);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
input.addEventListener('error', () => {
|
|
102
|
+
const error = new Error('File picker error occurred');
|
|
103
|
+
onError?.(error);
|
|
104
|
+
cleanup();
|
|
105
|
+
reject(error);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const event = new MouseEvent('click');
|
|
109
|
+
input.dispatchEvent(event);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
// Handle errors from file picker setup or opening
|
|
112
|
+
onError?.(error);
|
|
113
|
+
reject(error);
|
|
114
|
+
}
|
|
69
115
|
});
|
|
70
116
|
};
|
|
71
117
|
|
|
118
|
+
const pickSingle = (options: DocumentPickerOptions = {}) =>
|
|
119
|
+
getDocumentAsyncWeb({ ...options, multiple: false });
|
|
120
|
+
|
|
121
|
+
const pickMultiple = (options: DocumentPickerOptions = {}) =>
|
|
122
|
+
getDocumentAsyncWeb({ ...options, multiple: true });
|
|
123
|
+
|
|
72
124
|
export default {
|
|
73
|
-
pickSingle
|
|
74
|
-
pickMultiple
|
|
75
|
-
getDocumentAsyncWeb({ type, multiple: true }),
|
|
125
|
+
pickSingle,
|
|
126
|
+
pickMultiple,
|
|
76
127
|
};
|