react-native-rectangle-doc-scanner 3.86.0 → 3.88.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/dist/FullDocScanner.js
CHANGED
|
@@ -109,6 +109,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
109
109
|
const [isGalleryOpen, setIsGalleryOpen] = (0, react_1.useState)(false);
|
|
110
110
|
const [rectangleDetected, setRectangleDetected] = (0, react_1.useState)(false);
|
|
111
111
|
const [rectangleHint, setRectangleHint] = (0, react_1.useState)(false);
|
|
112
|
+
const [flashEnabled, setFlashEnabled] = (0, react_1.useState)(false);
|
|
112
113
|
const resolvedGridColor = gridColor ?? overlayColor;
|
|
113
114
|
const docScannerRef = (0, react_1.useRef)(null);
|
|
114
115
|
const captureModeRef = (0, react_1.useRef)(null);
|
|
@@ -318,6 +319,9 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
318
319
|
const handleClose = (0, react_1.useCallback)(() => {
|
|
319
320
|
onClose?.();
|
|
320
321
|
}, [onClose]);
|
|
322
|
+
const handleFlashToggle = (0, react_1.useCallback)(() => {
|
|
323
|
+
setFlashEnabled(prev => !prev);
|
|
324
|
+
}, []);
|
|
321
325
|
const handleConfirm = (0, react_1.useCallback)(() => {
|
|
322
326
|
if (croppedImageData) {
|
|
323
327
|
onResult({
|
|
@@ -417,7 +421,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
417
421
|
react_1.default.createElement(react_native_1.Text, { style: styles.confirmButtonText }, mergedStrings.retake)),
|
|
418
422
|
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.confirmButton, styles.confirmButtonPrimary], onPress: handleConfirm, accessibilityLabel: mergedStrings.confirm, accessibilityRole: "button" },
|
|
419
423
|
react_1.default.createElement(react_native_1.Text, { style: styles.confirmButtonText }, mergedStrings.confirm))))) : (react_1.default.createElement(react_native_1.View, { style: styles.flex },
|
|
420
|
-
react_1.default.createElement(DocScanner_1.DocScanner, { ref: docScannerRef, autoCapture: false, overlayColor: overlayColor, showGrid: showGrid, gridColor: resolvedGridColor, gridLineWidth: gridLineWidth, minStableFrames: minStableFrames ?? 6, detectionConfig: detectionConfig, onCapture: handleCapture, onRectangleDetect: handleRectangleDetect, showManualCaptureButton: false },
|
|
424
|
+
react_1.default.createElement(DocScanner_1.DocScanner, { ref: docScannerRef, autoCapture: false, overlayColor: overlayColor, showGrid: showGrid, gridColor: resolvedGridColor, gridLineWidth: gridLineWidth, minStableFrames: minStableFrames ?? 6, detectionConfig: detectionConfig, onCapture: handleCapture, onRectangleDetect: handleRectangleDetect, showManualCaptureButton: false, enableTorch: flashEnabled },
|
|
421
425
|
react_1.default.createElement(react_native_1.View, { style: styles.overlayTop, pointerEvents: "box-none" },
|
|
422
426
|
react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.closeButton, onPress: handleClose, accessibilityLabel: mergedStrings.cancel, accessibilityRole: "button" },
|
|
423
427
|
react_1.default.createElement(react_native_1.Text, { style: styles.closeButtonLabel }, "\u00D7"))),
|
|
@@ -426,13 +430,17 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
426
430
|
mergedStrings.captureHint && (react_1.default.createElement(react_native_1.Text, { style: styles.captureText }, mergedStrings.captureHint)),
|
|
427
431
|
mergedStrings.manualHint && (react_1.default.createElement(react_native_1.Text, { style: styles.captureText }, mergedStrings.manualHint))))),
|
|
428
432
|
react_1.default.createElement(react_native_1.View, { style: styles.shutterContainer, pointerEvents: "box-none" },
|
|
429
|
-
|
|
430
|
-
react_1.default.createElement(react_native_1.
|
|
433
|
+
react_1.default.createElement(react_native_1.View, { style: styles.leftButtonsContainer },
|
|
434
|
+
enableGallery && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.galleryButton, processing && styles.buttonDisabled], onPress: handleGalleryPick, disabled: processing, accessibilityLabel: mergedStrings.galleryButton, accessibilityRole: "button" },
|
|
435
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.galleryButtonText }, "\uD83D\uDCC1"))),
|
|
436
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.flashButton, processing && styles.buttonDisabled], onPress: handleFlashToggle, disabled: processing, accessibilityLabel: "Toggle flash", accessibilityRole: "button" },
|
|
437
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.flashButtonText }, flashEnabled ? '⚡' : '⚡️'))),
|
|
431
438
|
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.shutterButton, processing && styles.buttonDisabled], onPress: triggerManualCapture, disabled: processing, accessibilityLabel: mergedStrings.manualHint, accessibilityRole: "button" },
|
|
432
439
|
react_1.default.createElement(react_native_1.View, { style: [
|
|
433
440
|
styles.shutterInner,
|
|
434
441
|
rectangleHint && { backgroundColor: overlayColor }
|
|
435
|
-
] }))
|
|
442
|
+
] })),
|
|
443
|
+
react_1.default.createElement(react_native_1.View, { style: styles.rightButtonsPlaceholder }))))),
|
|
436
444
|
processing && (react_1.default.createElement(react_native_1.View, { style: styles.processingOverlay },
|
|
437
445
|
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: overlayColor }),
|
|
438
446
|
mergedStrings.processing && (react_1.default.createElement(react_native_1.Text, { style: styles.processingText }, mergedStrings.processing))))));
|
|
@@ -466,11 +474,20 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
466
474
|
left: 0,
|
|
467
475
|
right: 0,
|
|
468
476
|
flexDirection: 'row',
|
|
469
|
-
justifyContent: '
|
|
477
|
+
justifyContent: 'space-between',
|
|
470
478
|
alignItems: 'center',
|
|
471
|
-
|
|
479
|
+
paddingHorizontal: 40,
|
|
472
480
|
zIndex: 10,
|
|
473
481
|
},
|
|
482
|
+
leftButtonsContainer: {
|
|
483
|
+
flexDirection: 'row',
|
|
484
|
+
gap: 12,
|
|
485
|
+
alignItems: 'center',
|
|
486
|
+
flex: 1,
|
|
487
|
+
},
|
|
488
|
+
rightButtonsPlaceholder: {
|
|
489
|
+
flex: 1,
|
|
490
|
+
},
|
|
474
491
|
closeButton: {
|
|
475
492
|
width: 40,
|
|
476
493
|
height: 40,
|
|
@@ -497,9 +514,9 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
497
514
|
textAlign: 'center',
|
|
498
515
|
},
|
|
499
516
|
galleryButton: {
|
|
500
|
-
width:
|
|
501
|
-
height:
|
|
502
|
-
borderRadius:
|
|
517
|
+
width: 56,
|
|
518
|
+
height: 56,
|
|
519
|
+
borderRadius: 28,
|
|
503
520
|
borderWidth: 3,
|
|
504
521
|
borderColor: '#fff',
|
|
505
522
|
justifyContent: 'center',
|
|
@@ -507,7 +524,20 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
507
524
|
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
508
525
|
},
|
|
509
526
|
galleryButtonText: {
|
|
510
|
-
fontSize:
|
|
527
|
+
fontSize: 24,
|
|
528
|
+
},
|
|
529
|
+
flashButton: {
|
|
530
|
+
width: 56,
|
|
531
|
+
height: 56,
|
|
532
|
+
borderRadius: 28,
|
|
533
|
+
borderWidth: 3,
|
|
534
|
+
borderColor: '#fff',
|
|
535
|
+
justifyContent: 'center',
|
|
536
|
+
alignItems: 'center',
|
|
537
|
+
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
538
|
+
},
|
|
539
|
+
flashButtonText: {
|
|
540
|
+
fontSize: 24,
|
|
511
541
|
},
|
|
512
542
|
shutterButton: {
|
|
513
543
|
width: 80,
|
package/package.json
CHANGED
package/src/FullDocScanner.tsx
CHANGED
|
@@ -150,6 +150,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
150
150
|
const [isGalleryOpen, setIsGalleryOpen] = useState(false);
|
|
151
151
|
const [rectangleDetected, setRectangleDetected] = useState(false);
|
|
152
152
|
const [rectangleHint, setRectangleHint] = useState(false);
|
|
153
|
+
const [flashEnabled, setFlashEnabled] = useState(false);
|
|
153
154
|
const resolvedGridColor = gridColor ?? overlayColor;
|
|
154
155
|
const docScannerRef = useRef<DocScannerHandle | null>(null);
|
|
155
156
|
const captureModeRef = useRef<'grid' | 'no-grid' | null>(null);
|
|
@@ -426,6 +427,10 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
426
427
|
onClose?.();
|
|
427
428
|
}, [onClose]);
|
|
428
429
|
|
|
430
|
+
const handleFlashToggle = useCallback(() => {
|
|
431
|
+
setFlashEnabled(prev => !prev);
|
|
432
|
+
}, []);
|
|
433
|
+
|
|
429
434
|
const handleConfirm = useCallback(() => {
|
|
430
435
|
if (croppedImageData) {
|
|
431
436
|
onResult({
|
|
@@ -569,6 +574,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
569
574
|
onCapture={handleCapture}
|
|
570
575
|
onRectangleDetect={handleRectangleDetect}
|
|
571
576
|
showManualCaptureButton={false}
|
|
577
|
+
enableTorch={flashEnabled}
|
|
572
578
|
>
|
|
573
579
|
<View style={styles.overlayTop} pointerEvents="box-none">
|
|
574
580
|
<TouchableOpacity
|
|
@@ -593,17 +599,28 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
593
599
|
</View>
|
|
594
600
|
)}
|
|
595
601
|
<View style={styles.shutterContainer} pointerEvents="box-none">
|
|
596
|
-
{
|
|
602
|
+
<View style={styles.leftButtonsContainer}>
|
|
603
|
+
{enableGallery && (
|
|
604
|
+
<TouchableOpacity
|
|
605
|
+
style={[styles.galleryButton, processing && styles.buttonDisabled]}
|
|
606
|
+
onPress={handleGalleryPick}
|
|
607
|
+
disabled={processing}
|
|
608
|
+
accessibilityLabel={mergedStrings.galleryButton}
|
|
609
|
+
accessibilityRole="button"
|
|
610
|
+
>
|
|
611
|
+
<Text style={styles.galleryButtonText}>📁</Text>
|
|
612
|
+
</TouchableOpacity>
|
|
613
|
+
)}
|
|
597
614
|
<TouchableOpacity
|
|
598
|
-
style={[styles.
|
|
599
|
-
onPress={
|
|
615
|
+
style={[styles.flashButton, processing && styles.buttonDisabled]}
|
|
616
|
+
onPress={handleFlashToggle}
|
|
600
617
|
disabled={processing}
|
|
601
|
-
accessibilityLabel=
|
|
618
|
+
accessibilityLabel="Toggle flash"
|
|
602
619
|
accessibilityRole="button"
|
|
603
620
|
>
|
|
604
|
-
<Text style={styles.
|
|
621
|
+
<Text style={styles.flashButtonText}>{flashEnabled ? '⚡' : '⚡️'}</Text>
|
|
605
622
|
</TouchableOpacity>
|
|
606
|
-
|
|
623
|
+
</View>
|
|
607
624
|
<TouchableOpacity
|
|
608
625
|
style={[styles.shutterButton, processing && styles.buttonDisabled]}
|
|
609
626
|
onPress={triggerManualCapture}
|
|
@@ -616,6 +633,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
616
633
|
rectangleHint && { backgroundColor: overlayColor }
|
|
617
634
|
]} />
|
|
618
635
|
</TouchableOpacity>
|
|
636
|
+
<View style={styles.rightButtonsPlaceholder} />
|
|
619
637
|
</View>
|
|
620
638
|
</DocScanner>
|
|
621
639
|
</View>
|
|
@@ -661,11 +679,20 @@ const styles = StyleSheet.create({
|
|
|
661
679
|
left: 0,
|
|
662
680
|
right: 0,
|
|
663
681
|
flexDirection: 'row',
|
|
664
|
-
justifyContent: '
|
|
682
|
+
justifyContent: 'space-between',
|
|
665
683
|
alignItems: 'center',
|
|
666
|
-
|
|
684
|
+
paddingHorizontal: 40,
|
|
667
685
|
zIndex: 10,
|
|
668
686
|
},
|
|
687
|
+
leftButtonsContainer: {
|
|
688
|
+
flexDirection: 'row',
|
|
689
|
+
gap: 12,
|
|
690
|
+
alignItems: 'center',
|
|
691
|
+
flex: 1,
|
|
692
|
+
},
|
|
693
|
+
rightButtonsPlaceholder: {
|
|
694
|
+
flex: 1,
|
|
695
|
+
},
|
|
669
696
|
closeButton: {
|
|
670
697
|
width: 40,
|
|
671
698
|
height: 40,
|
|
@@ -692,9 +719,9 @@ const styles = StyleSheet.create({
|
|
|
692
719
|
textAlign: 'center',
|
|
693
720
|
},
|
|
694
721
|
galleryButton: {
|
|
695
|
-
width:
|
|
696
|
-
height:
|
|
697
|
-
borderRadius:
|
|
722
|
+
width: 56,
|
|
723
|
+
height: 56,
|
|
724
|
+
borderRadius: 28,
|
|
698
725
|
borderWidth: 3,
|
|
699
726
|
borderColor: '#fff',
|
|
700
727
|
justifyContent: 'center',
|
|
@@ -702,7 +729,20 @@ const styles = StyleSheet.create({
|
|
|
702
729
|
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
703
730
|
},
|
|
704
731
|
galleryButtonText: {
|
|
705
|
-
fontSize:
|
|
732
|
+
fontSize: 24,
|
|
733
|
+
},
|
|
734
|
+
flashButton: {
|
|
735
|
+
width: 56,
|
|
736
|
+
height: 56,
|
|
737
|
+
borderRadius: 28,
|
|
738
|
+
borderWidth: 3,
|
|
739
|
+
borderColor: '#fff',
|
|
740
|
+
justifyContent: 'center',
|
|
741
|
+
alignItems: 'center',
|
|
742
|
+
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
743
|
+
},
|
|
744
|
+
flashButtonText: {
|
|
745
|
+
fontSize: 24,
|
|
706
746
|
},
|
|
707
747
|
shutterButton: {
|
|
708
748
|
width: 80,
|
|
@@ -29,11 +29,9 @@
|
|
|
29
29
|
[self start];
|
|
30
30
|
_hasSetupCamera = YES;
|
|
31
31
|
} else if (_hasSetupCamera && self.window && !CGRectIsEmpty(self.bounds)) {
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
[self start];
|
|
36
|
-
}
|
|
32
|
+
// Restart camera if needed (defensive check)
|
|
33
|
+
NSLog(@"[DocumentScanner] Layout update, ensuring camera is running");
|
|
34
|
+
[self start];
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
|
|
@@ -41,12 +39,10 @@
|
|
|
41
39
|
[super didMoveToWindow];
|
|
42
40
|
if (self.window && _hasSetupCamera) {
|
|
43
41
|
// Restart camera when view is added back to window
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
49
|
-
}
|
|
42
|
+
NSLog(@"[DocumentScanner] View added to window, restarting camera...");
|
|
43
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
44
|
+
[self start];
|
|
45
|
+
});
|
|
50
46
|
} else if (!self.window && _hasSetupCamera) {
|
|
51
47
|
// Stop camera when view is removed from window
|
|
52
48
|
NSLog(@"[DocumentScanner] View removed from window, stopping camera");
|