react-native-rectangle-doc-scanner 3.44.0 → 3.44.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/FullDocScanner.d.ts +2 -0
- package/dist/FullDocScanner.js +84 -9
- package/package.json +1 -1
- package/src/FullDocScanner.tsx +121 -20
package/dist/FullDocScanner.d.ts
CHANGED
package/dist/FullDocScanner.js
CHANGED
|
@@ -55,6 +55,8 @@ const normalizeCapturedDocument = (document) => {
|
|
|
55
55
|
};
|
|
56
56
|
const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3170f3', gridColor, gridLineWidth, showGrid, strings, manualCapture = false, minStableFrames, onError, enableGallery = true, cropWidth = 1200, cropHeight = 1600, }) => {
|
|
57
57
|
const [processing, setProcessing] = (0, react_1.useState)(false);
|
|
58
|
+
const [croppedImageData, setCroppedImageData] = (0, react_1.useState)(null);
|
|
59
|
+
const [isGalleryOpen, setIsGalleryOpen] = (0, react_1.useState)(false);
|
|
58
60
|
const resolvedGridColor = gridColor ?? overlayColor;
|
|
59
61
|
const docScannerRef = (0, react_1.useRef)(null);
|
|
60
62
|
const manualCapturePending = (0, react_1.useRef)(false);
|
|
@@ -64,6 +66,8 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
64
66
|
cancel: strings?.cancel,
|
|
65
67
|
processing: strings?.processing,
|
|
66
68
|
galleryButton: strings?.galleryButton,
|
|
69
|
+
retake: strings?.retake ?? 'Retake',
|
|
70
|
+
confirm: strings?.confirm ?? 'Confirm',
|
|
67
71
|
}), [strings]);
|
|
68
72
|
const emitError = (0, react_1.useCallback)((error, fallbackMessage) => {
|
|
69
73
|
console.error('[FullDocScanner] error', error);
|
|
@@ -87,7 +91,8 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
87
91
|
compressImageQuality: 0.9,
|
|
88
92
|
});
|
|
89
93
|
setProcessing(false);
|
|
90
|
-
|
|
94
|
+
// Show check_DP confirmation screen
|
|
95
|
+
setCroppedImageData({
|
|
91
96
|
path: croppedImage.path,
|
|
92
97
|
base64: croppedImage.data ?? undefined,
|
|
93
98
|
});
|
|
@@ -98,7 +103,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
98
103
|
emitError(error instanceof Error ? error : new Error(String(error)), 'Failed to crop image.');
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
|
-
}, [cropWidth, cropHeight, emitError
|
|
106
|
+
}, [cropWidth, cropHeight, emitError]);
|
|
102
107
|
const handleCapture = (0, react_1.useCallback)(async (document) => {
|
|
103
108
|
console.log('[FullDocScanner] handleCapture called:', {
|
|
104
109
|
origin: document.origin,
|
|
@@ -108,8 +113,18 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
108
113
|
manualCapturePending.current = false;
|
|
109
114
|
}
|
|
110
115
|
const normalizedDoc = normalizeCapturedDocument(document);
|
|
111
|
-
//
|
|
112
|
-
|
|
116
|
+
// Auto-capture: Use already cropped image, skip cropper
|
|
117
|
+
if (document.origin === 'auto' && normalizedDoc.croppedPath) {
|
|
118
|
+
console.log('[FullDocScanner] Auto-capture: using pre-cropped image');
|
|
119
|
+
setCroppedImageData({
|
|
120
|
+
path: normalizedDoc.croppedPath,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Manual capture or gallery: Open cropper
|
|
125
|
+
console.log('[FullDocScanner] Manual capture: opening cropper');
|
|
126
|
+
await openCropper(normalizedDoc.path);
|
|
127
|
+
}
|
|
113
128
|
}, [openCropper]);
|
|
114
129
|
const triggerManualCapture = (0, react_1.useCallback)(() => {
|
|
115
130
|
console.log('[FullDocScanner] triggerManualCapture called');
|
|
@@ -141,15 +156,17 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
141
156
|
}, [processing]);
|
|
142
157
|
const handleGalleryPick = (0, react_1.useCallback)(async () => {
|
|
143
158
|
console.log('[FullDocScanner] handleGalleryPick called');
|
|
144
|
-
if (processing) {
|
|
159
|
+
if (processing || isGalleryOpen) {
|
|
145
160
|
return;
|
|
146
161
|
}
|
|
147
162
|
try {
|
|
163
|
+
setIsGalleryOpen(true);
|
|
148
164
|
const result = await (0, react_native_image_picker_1.launchImageLibrary)({
|
|
149
165
|
mediaType: 'photo',
|
|
150
166
|
quality: 1,
|
|
151
167
|
selectionLimit: 1,
|
|
152
168
|
});
|
|
169
|
+
setIsGalleryOpen(false);
|
|
153
170
|
if (result.didCancel || !result.assets?.[0]?.uri) {
|
|
154
171
|
console.log('[FullDocScanner] User cancelled gallery picker');
|
|
155
172
|
return;
|
|
@@ -160,15 +177,35 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
160
177
|
await openCropper(imageUri);
|
|
161
178
|
}
|
|
162
179
|
catch (error) {
|
|
180
|
+
setIsGalleryOpen(false);
|
|
163
181
|
emitError(error instanceof Error ? error : new Error(String(error)), 'Failed to pick image from gallery.');
|
|
164
182
|
}
|
|
165
|
-
}, [processing, openCropper, emitError]);
|
|
183
|
+
}, [processing, isGalleryOpen, openCropper, emitError]);
|
|
166
184
|
const handleClose = (0, react_1.useCallback)(() => {
|
|
167
185
|
onClose?.();
|
|
168
186
|
}, [onClose]);
|
|
187
|
+
const handleConfirm = (0, react_1.useCallback)(() => {
|
|
188
|
+
if (croppedImageData) {
|
|
189
|
+
onResult({
|
|
190
|
+
path: croppedImageData.path,
|
|
191
|
+
base64: croppedImageData.base64,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}, [croppedImageData, onResult]);
|
|
195
|
+
const handleRetake = (0, react_1.useCallback)(() => {
|
|
196
|
+
setCroppedImageData(null);
|
|
197
|
+
}, []);
|
|
169
198
|
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
170
|
-
|
|
171
|
-
|
|
199
|
+
croppedImageData ? (
|
|
200
|
+
// check_DP: Show confirmation screen
|
|
201
|
+
react_1.default.createElement(react_native_1.View, { style: styles.confirmationContainer },
|
|
202
|
+
react_1.default.createElement(react_native_1.Image, { source: { uri: croppedImageData.path }, style: styles.previewImage, resizeMode: "contain" }),
|
|
203
|
+
react_1.default.createElement(react_native_1.View, { style: styles.confirmationButtons },
|
|
204
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.confirmButton, styles.retakeButton], onPress: handleRetake, accessibilityLabel: mergedStrings.retake, accessibilityRole: "button" },
|
|
205
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.confirmButtonText }, mergedStrings.retake)),
|
|
206
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.confirmButton, styles.confirmButtonPrimary], onPress: handleConfirm, accessibilityLabel: mergedStrings.confirm, accessibilityRole: "button" },
|
|
207
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.confirmButtonText }, mergedStrings.confirm))))) : (react_1.default.createElement(react_native_1.View, { style: styles.flex },
|
|
208
|
+
react_1.default.createElement(DocScanner_1.DocScanner, { ref: docScannerRef, autoCapture: !manualCapture && !isGalleryOpen, overlayColor: overlayColor, showGrid: showGrid, gridColor: resolvedGridColor, gridLineWidth: gridLineWidth, minStableFrames: minStableFrames ?? 6, detectionConfig: detectionConfig, onCapture: handleCapture, showManualCaptureButton: false },
|
|
172
209
|
react_1.default.createElement(react_native_1.View, { style: styles.overlayTop, pointerEvents: "box-none" },
|
|
173
210
|
react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.closeButton, onPress: handleClose, accessibilityLabel: mergedStrings.cancel, accessibilityRole: "button" },
|
|
174
211
|
react_1.default.createElement(react_native_1.Text, { style: styles.closeButtonLabel }, "\u00D7"))),
|
|
@@ -180,7 +217,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
180
217
|
enableGallery && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.galleryButton, processing && styles.buttonDisabled], onPress: handleGalleryPick, disabled: processing, accessibilityLabel: mergedStrings.galleryButton, accessibilityRole: "button" },
|
|
181
218
|
react_1.default.createElement(react_native_1.Text, { style: styles.galleryButtonText }, "\uD83D\uDCC1"))),
|
|
182
219
|
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.shutterButton, processing && styles.buttonDisabled], onPress: triggerManualCapture, disabled: processing, accessibilityLabel: mergedStrings.manualHint, accessibilityRole: "button" },
|
|
183
|
-
react_1.default.createElement(react_native_1.View, { style: styles.shutterInner }))))),
|
|
220
|
+
react_1.default.createElement(react_native_1.View, { style: styles.shutterInner })))))),
|
|
184
221
|
processing && (react_1.default.createElement(react_native_1.View, { style: styles.processingOverlay },
|
|
185
222
|
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: overlayColor }),
|
|
186
223
|
mergedStrings.processing && (react_1.default.createElement(react_native_1.Text, { style: styles.processingText }, mergedStrings.processing))))));
|
|
@@ -288,4 +325,42 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
288
325
|
fontSize: 16,
|
|
289
326
|
fontWeight: '600',
|
|
290
327
|
},
|
|
328
|
+
confirmationContainer: {
|
|
329
|
+
flex: 1,
|
|
330
|
+
backgroundColor: '#000',
|
|
331
|
+
justifyContent: 'center',
|
|
332
|
+
alignItems: 'center',
|
|
333
|
+
},
|
|
334
|
+
previewImage: {
|
|
335
|
+
width: '100%',
|
|
336
|
+
height: '80%',
|
|
337
|
+
},
|
|
338
|
+
confirmationButtons: {
|
|
339
|
+
flexDirection: 'row',
|
|
340
|
+
justifyContent: 'center',
|
|
341
|
+
alignItems: 'center',
|
|
342
|
+
gap: 24,
|
|
343
|
+
paddingVertical: 32,
|
|
344
|
+
},
|
|
345
|
+
confirmButton: {
|
|
346
|
+
paddingHorizontal: 40,
|
|
347
|
+
paddingVertical: 16,
|
|
348
|
+
borderRadius: 12,
|
|
349
|
+
minWidth: 140,
|
|
350
|
+
alignItems: 'center',
|
|
351
|
+
justifyContent: 'center',
|
|
352
|
+
},
|
|
353
|
+
retakeButton: {
|
|
354
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
355
|
+
borderWidth: 2,
|
|
356
|
+
borderColor: '#fff',
|
|
357
|
+
},
|
|
358
|
+
confirmButtonPrimary: {
|
|
359
|
+
backgroundColor: '#3170f3',
|
|
360
|
+
},
|
|
361
|
+
confirmButtonText: {
|
|
362
|
+
color: '#fff',
|
|
363
|
+
fontSize: 18,
|
|
364
|
+
fontWeight: '600',
|
|
365
|
+
},
|
|
291
366
|
});
|
package/package.json
CHANGED
package/src/FullDocScanner.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
|
2
2
|
import {
|
|
3
3
|
ActivityIndicator,
|
|
4
4
|
Alert,
|
|
5
|
+
Image,
|
|
5
6
|
StyleSheet,
|
|
6
7
|
Text,
|
|
7
8
|
TouchableOpacity,
|
|
@@ -41,6 +42,8 @@ export interface FullDocScannerStrings {
|
|
|
41
42
|
cancel?: string;
|
|
42
43
|
processing?: string;
|
|
43
44
|
galleryButton?: string;
|
|
45
|
+
retake?: string;
|
|
46
|
+
confirm?: string;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
export interface FullDocScannerProps {
|
|
@@ -77,6 +80,8 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
77
80
|
cropHeight = 1600,
|
|
78
81
|
}) => {
|
|
79
82
|
const [processing, setProcessing] = useState(false);
|
|
83
|
+
const [croppedImageData, setCroppedImageData] = useState<{path: string; base64?: string} | null>(null);
|
|
84
|
+
const [isGalleryOpen, setIsGalleryOpen] = useState(false);
|
|
80
85
|
const resolvedGridColor = gridColor ?? overlayColor;
|
|
81
86
|
const docScannerRef = useRef<DocScannerHandle | null>(null);
|
|
82
87
|
const manualCapturePending = useRef(false);
|
|
@@ -88,6 +93,8 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
88
93
|
cancel: strings?.cancel,
|
|
89
94
|
processing: strings?.processing,
|
|
90
95
|
galleryButton: strings?.galleryButton,
|
|
96
|
+
retake: strings?.retake ?? 'Retake',
|
|
97
|
+
confirm: strings?.confirm ?? 'Confirm',
|
|
91
98
|
}),
|
|
92
99
|
[strings],
|
|
93
100
|
);
|
|
@@ -121,7 +128,8 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
121
128
|
|
|
122
129
|
setProcessing(false);
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
// Show check_DP confirmation screen
|
|
132
|
+
setCroppedImageData({
|
|
125
133
|
path: croppedImage.path,
|
|
126
134
|
base64: croppedImage.data ?? undefined,
|
|
127
135
|
});
|
|
@@ -135,7 +143,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
135
143
|
}
|
|
136
144
|
}
|
|
137
145
|
},
|
|
138
|
-
[cropWidth, cropHeight, emitError
|
|
146
|
+
[cropWidth, cropHeight, emitError],
|
|
139
147
|
);
|
|
140
148
|
|
|
141
149
|
const handleCapture = useCallback(
|
|
@@ -151,8 +159,17 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
151
159
|
|
|
152
160
|
const normalizedDoc = normalizeCapturedDocument(document);
|
|
153
161
|
|
|
154
|
-
//
|
|
155
|
-
|
|
162
|
+
// Auto-capture: Use already cropped image, skip cropper
|
|
163
|
+
if (document.origin === 'auto' && normalizedDoc.croppedPath) {
|
|
164
|
+
console.log('[FullDocScanner] Auto-capture: using pre-cropped image');
|
|
165
|
+
setCroppedImageData({
|
|
166
|
+
path: normalizedDoc.croppedPath,
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
// Manual capture or gallery: Open cropper
|
|
170
|
+
console.log('[FullDocScanner] Manual capture: opening cropper');
|
|
171
|
+
await openCropper(normalizedDoc.path);
|
|
172
|
+
}
|
|
156
173
|
},
|
|
157
174
|
[openCropper],
|
|
158
175
|
);
|
|
@@ -189,17 +206,20 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
189
206
|
|
|
190
207
|
const handleGalleryPick = useCallback(async () => {
|
|
191
208
|
console.log('[FullDocScanner] handleGalleryPick called');
|
|
192
|
-
if (processing) {
|
|
209
|
+
if (processing || isGalleryOpen) {
|
|
193
210
|
return;
|
|
194
211
|
}
|
|
195
212
|
|
|
196
213
|
try {
|
|
214
|
+
setIsGalleryOpen(true);
|
|
197
215
|
const result = await launchImageLibrary({
|
|
198
216
|
mediaType: 'photo',
|
|
199
217
|
quality: 1,
|
|
200
218
|
selectionLimit: 1,
|
|
201
219
|
});
|
|
202
220
|
|
|
221
|
+
setIsGalleryOpen(false);
|
|
222
|
+
|
|
203
223
|
if (result.didCancel || !result.assets?.[0]?.uri) {
|
|
204
224
|
console.log('[FullDocScanner] User cancelled gallery picker');
|
|
205
225
|
return;
|
|
@@ -211,32 +231,74 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
211
231
|
// Open cropper with the selected image
|
|
212
232
|
await openCropper(imageUri);
|
|
213
233
|
} catch (error) {
|
|
234
|
+
setIsGalleryOpen(false);
|
|
214
235
|
emitError(
|
|
215
236
|
error instanceof Error ? error : new Error(String(error)),
|
|
216
237
|
'Failed to pick image from gallery.',
|
|
217
238
|
);
|
|
218
239
|
}
|
|
219
|
-
}, [processing, openCropper, emitError]);
|
|
240
|
+
}, [processing, isGalleryOpen, openCropper, emitError]);
|
|
220
241
|
|
|
221
242
|
const handleClose = useCallback(() => {
|
|
222
243
|
onClose?.();
|
|
223
244
|
}, [onClose]);
|
|
224
245
|
|
|
246
|
+
const handleConfirm = useCallback(() => {
|
|
247
|
+
if (croppedImageData) {
|
|
248
|
+
onResult({
|
|
249
|
+
path: croppedImageData.path,
|
|
250
|
+
base64: croppedImageData.base64,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}, [croppedImageData, onResult]);
|
|
254
|
+
|
|
255
|
+
const handleRetake = useCallback(() => {
|
|
256
|
+
setCroppedImageData(null);
|
|
257
|
+
}, []);
|
|
258
|
+
|
|
225
259
|
return (
|
|
226
260
|
<View style={styles.container}>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
261
|
+
{croppedImageData ? (
|
|
262
|
+
// check_DP: Show confirmation screen
|
|
263
|
+
<View style={styles.confirmationContainer}>
|
|
264
|
+
<Image
|
|
265
|
+
source={{ uri: croppedImageData.path }}
|
|
266
|
+
style={styles.previewImage}
|
|
267
|
+
resizeMode="contain"
|
|
268
|
+
/>
|
|
269
|
+
<View style={styles.confirmationButtons}>
|
|
270
|
+
<TouchableOpacity
|
|
271
|
+
style={[styles.confirmButton, styles.retakeButton]}
|
|
272
|
+
onPress={handleRetake}
|
|
273
|
+
accessibilityLabel={mergedStrings.retake}
|
|
274
|
+
accessibilityRole="button"
|
|
275
|
+
>
|
|
276
|
+
<Text style={styles.confirmButtonText}>{mergedStrings.retake}</Text>
|
|
277
|
+
</TouchableOpacity>
|
|
278
|
+
<TouchableOpacity
|
|
279
|
+
style={[styles.confirmButton, styles.confirmButtonPrimary]}
|
|
280
|
+
onPress={handleConfirm}
|
|
281
|
+
accessibilityLabel={mergedStrings.confirm}
|
|
282
|
+
accessibilityRole="button"
|
|
283
|
+
>
|
|
284
|
+
<Text style={styles.confirmButtonText}>{mergedStrings.confirm}</Text>
|
|
285
|
+
</TouchableOpacity>
|
|
286
|
+
</View>
|
|
287
|
+
</View>
|
|
288
|
+
) : (
|
|
289
|
+
<View style={styles.flex}>
|
|
290
|
+
<DocScanner
|
|
291
|
+
ref={docScannerRef}
|
|
292
|
+
autoCapture={!manualCapture && !isGalleryOpen}
|
|
293
|
+
overlayColor={overlayColor}
|
|
294
|
+
showGrid={showGrid}
|
|
295
|
+
gridColor={resolvedGridColor}
|
|
296
|
+
gridLineWidth={gridLineWidth}
|
|
297
|
+
minStableFrames={minStableFrames ?? 6}
|
|
298
|
+
detectionConfig={detectionConfig}
|
|
299
|
+
onCapture={handleCapture}
|
|
300
|
+
showManualCaptureButton={false}
|
|
301
|
+
>
|
|
240
302
|
<View style={styles.overlayTop} pointerEvents="box-none">
|
|
241
303
|
<TouchableOpacity
|
|
242
304
|
style={styles.closeButton}
|
|
@@ -282,7 +344,8 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
282
344
|
</TouchableOpacity>
|
|
283
345
|
</View>
|
|
284
346
|
</DocScanner>
|
|
285
|
-
|
|
347
|
+
</View>
|
|
348
|
+
)}
|
|
286
349
|
|
|
287
350
|
{processing && (
|
|
288
351
|
<View style={styles.processingOverlay}>
|
|
@@ -398,4 +461,42 @@ const styles = StyleSheet.create({
|
|
|
398
461
|
fontSize: 16,
|
|
399
462
|
fontWeight: '600',
|
|
400
463
|
},
|
|
464
|
+
confirmationContainer: {
|
|
465
|
+
flex: 1,
|
|
466
|
+
backgroundColor: '#000',
|
|
467
|
+
justifyContent: 'center',
|
|
468
|
+
alignItems: 'center',
|
|
469
|
+
},
|
|
470
|
+
previewImage: {
|
|
471
|
+
width: '100%',
|
|
472
|
+
height: '80%',
|
|
473
|
+
},
|
|
474
|
+
confirmationButtons: {
|
|
475
|
+
flexDirection: 'row',
|
|
476
|
+
justifyContent: 'center',
|
|
477
|
+
alignItems: 'center',
|
|
478
|
+
gap: 24,
|
|
479
|
+
paddingVertical: 32,
|
|
480
|
+
},
|
|
481
|
+
confirmButton: {
|
|
482
|
+
paddingHorizontal: 40,
|
|
483
|
+
paddingVertical: 16,
|
|
484
|
+
borderRadius: 12,
|
|
485
|
+
minWidth: 140,
|
|
486
|
+
alignItems: 'center',
|
|
487
|
+
justifyContent: 'center',
|
|
488
|
+
},
|
|
489
|
+
retakeButton: {
|
|
490
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
491
|
+
borderWidth: 2,
|
|
492
|
+
borderColor: '#fff',
|
|
493
|
+
},
|
|
494
|
+
confirmButtonPrimary: {
|
|
495
|
+
backgroundColor: '#3170f3',
|
|
496
|
+
},
|
|
497
|
+
confirmButtonText: {
|
|
498
|
+
color: '#fff',
|
|
499
|
+
fontSize: 18,
|
|
500
|
+
fontWeight: '600',
|
|
501
|
+
},
|
|
401
502
|
});
|