@cleanuidev/react-native-scanner 1.0.0-beta.1

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.
Files changed (52) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +609 -0
  3. package/Scanner.podspec +20 -0
  4. package/android/build.gradle +90 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +8 -0
  7. package/android/src/main/java/com/scanner/CameraInfoModule.kt +253 -0
  8. package/android/src/main/java/com/scanner/ScannerPackage.kt +21 -0
  9. package/android/src/main/java/com/scanner/ScannerView.kt +783 -0
  10. package/android/src/main/java/com/scanner/ScannerViewManager.kt +181 -0
  11. package/android/src/main/java/com/scanner/utils/BarcodeFrameManager.kt +170 -0
  12. package/android/src/main/java/com/scanner/views/BarcodeFrameOverlayView.kt +43 -0
  13. package/android/src/main/java/com/scanner/views/FocusAreaView.kt +124 -0
  14. package/ios/BarcodeDetectionManager.swift +229 -0
  15. package/ios/BarcodeFrameManager.swift +175 -0
  16. package/ios/BarcodeFrameOverlayView.swift +102 -0
  17. package/ios/CameraManager.swift +396 -0
  18. package/ios/CoordinateTransformer.swift +140 -0
  19. package/ios/FocusAreaOverlayView.swift +161 -0
  20. package/ios/Models.swift +341 -0
  21. package/ios/Protocols.swift +194 -0
  22. package/ios/ScannerView.h +14 -0
  23. package/ios/ScannerView.mm +358 -0
  24. package/ios/ScannerViewImpl.swift +580 -0
  25. package/ios/react-native-scanner-Bridging-Header.h +26 -0
  26. package/lib/module/CameraInfoModule.js +8 -0
  27. package/lib/module/CameraInfoModule.js.map +1 -0
  28. package/lib/module/ScannerViewNativeComponent.ts +121 -0
  29. package/lib/module/hooks/useCameraInfo.js +106 -0
  30. package/lib/module/hooks/useCameraInfo.js.map +1 -0
  31. package/lib/module/index.js +13 -0
  32. package/lib/module/index.js.map +1 -0
  33. package/lib/module/package.json +1 -0
  34. package/lib/module/types.js +47 -0
  35. package/lib/module/types.js.map +1 -0
  36. package/lib/typescript/package.json +1 -0
  37. package/lib/typescript/src/CameraInfoModule.d.ts +8 -0
  38. package/lib/typescript/src/CameraInfoModule.d.ts.map +1 -0
  39. package/lib/typescript/src/ScannerViewNativeComponent.d.ts +91 -0
  40. package/lib/typescript/src/ScannerViewNativeComponent.d.ts.map +1 -0
  41. package/lib/typescript/src/hooks/useCameraInfo.d.ts +25 -0
  42. package/lib/typescript/src/hooks/useCameraInfo.d.ts.map +1 -0
  43. package/lib/typescript/src/index.d.ts +8 -0
  44. package/lib/typescript/src/index.d.ts.map +1 -0
  45. package/lib/typescript/src/types.d.ts +145 -0
  46. package/lib/typescript/src/types.d.ts.map +1 -0
  47. package/package.json +178 -0
  48. package/src/CameraInfoModule.ts +11 -0
  49. package/src/ScannerViewNativeComponent.ts +121 -0
  50. package/src/hooks/useCameraInfo.ts +190 -0
  51. package/src/index.tsx +30 -0
  52. package/src/types.ts +177 -0
package/package.json ADDED
@@ -0,0 +1,178 @@
1
+ {
2
+ "name": "@cleanuidev/react-native-scanner",
3
+ "version": "1.0.0-beta.1",
4
+ "description": "scanner",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*",
33
+ "!node_modules",
34
+ "!**/node_modules"
35
+ ],
36
+ "scripts": {
37
+ "example": "yarn workspace react-native-scanner-example",
38
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
39
+ "prepare": "bob build",
40
+ "typecheck": "tsc",
41
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
42
+ "test": "jest",
43
+ "release": "release-it --only-version"
44
+ },
45
+ "keywords": [
46
+ "react-native",
47
+ "ios",
48
+ "android"
49
+ ],
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/cleanui-dev/react-native-scanner.git"
53
+ },
54
+ "author": "Rahul Gupta <rahulgwebdev@gmail.com> (https://github.com/rahulgwebdev)",
55
+ "license": "MIT",
56
+ "bugs": {
57
+ "url": "https://github.com/cleanui-dev/react-native-scanner/issues"
58
+ },
59
+ "homepage": "https://github.com/cleanui-dev/react-native-scanner#readme",
60
+ "publishConfig": {
61
+ "registry": "https://registry.npmjs.org/",
62
+ "access": "public"
63
+ },
64
+ "devDependencies": {
65
+ "@commitlint/config-conventional": "^19.8.1",
66
+ "@eslint/compat": "^1.3.2",
67
+ "@eslint/eslintrc": "^3.3.1",
68
+ "@eslint/js": "^9.35.0",
69
+ "@react-native/babel-preset": "0.83.0",
70
+ "@react-native/eslint-config": "0.83.0",
71
+ "@release-it/conventional-changelog": "^10.0.1",
72
+ "@types/jest": "^29.5.14",
73
+ "@types/react": "^19.2.0",
74
+ "commitlint": "^19.8.1",
75
+ "del-cli": "^6.0.0",
76
+ "eslint": "^9.35.0",
77
+ "eslint-config-prettier": "^10.1.8",
78
+ "eslint-plugin-prettier": "^5.5.4",
79
+ "jest": "^29.7.0",
80
+ "lefthook": "^2.0.3",
81
+ "prettier": "^2.8.8",
82
+ "react": "19.2.0",
83
+ "react-native": "0.83.0",
84
+ "react-native-builder-bob": "^0.40.17",
85
+ "release-it": "^19.0.4",
86
+ "turbo": "^2.5.6",
87
+ "typescript": "^5.9.2"
88
+ },
89
+ "peerDependencies": {
90
+ "react": "*",
91
+ "react-native": "*"
92
+ },
93
+ "workspaces": [
94
+ "example"
95
+ ],
96
+ "packageManager": "yarn@4.11.0",
97
+ "react-native-builder-bob": {
98
+ "source": "src",
99
+ "output": "lib",
100
+ "targets": [
101
+ [
102
+ "module",
103
+ {
104
+ "esm": true
105
+ }
106
+ ],
107
+ [
108
+ "typescript",
109
+ {
110
+ "project": "tsconfig.build.json"
111
+ }
112
+ ]
113
+ ]
114
+ },
115
+ "codegenConfig": {
116
+ "name": "ScannerViewSpec",
117
+ "type": "all",
118
+ "jsSrcsDir": "src",
119
+ "android": {
120
+ "javaPackageName": "com.scanner"
121
+ },
122
+ "ios": {
123
+ "componentProvider": {
124
+ "ScannerView": "ScannerView"
125
+ }
126
+ }
127
+ },
128
+ "prettier": {
129
+ "quoteProps": "consistent",
130
+ "singleQuote": true,
131
+ "tabWidth": 2,
132
+ "trailingComma": "es5",
133
+ "useTabs": false
134
+ },
135
+ "jest": {
136
+ "preset": "react-native",
137
+ "modulePathIgnorePatterns": [
138
+ "<rootDir>/example/node_modules",
139
+ "<rootDir>/lib/"
140
+ ]
141
+ },
142
+ "commitlint": {
143
+ "extends": [
144
+ "@commitlint/config-conventional"
145
+ ]
146
+ },
147
+ "release-it": {
148
+ "git": {
149
+ "commitMessage": "chore: release ${version}",
150
+ "tagName": "v${version}"
151
+ },
152
+ "npm": {
153
+ "publish": true,
154
+ "tag": "beta"
155
+ },
156
+ "github": {
157
+ "release": true
158
+ },
159
+ "plugins": {
160
+ "@release-it/conventional-changelog": {
161
+ "preset": {
162
+ "name": "angular"
163
+ }
164
+ }
165
+ }
166
+ },
167
+ "create-react-native-library": {
168
+ "type": "fabric-view",
169
+ "languages": "kotlin-objc",
170
+ "tools": [
171
+ "eslint",
172
+ "jest",
173
+ "lefthook",
174
+ "release-it"
175
+ ],
176
+ "version": "0.56.0"
177
+ }
178
+ }
@@ -0,0 +1,11 @@
1
+ import { NativeModules } from 'react-native';
2
+ import type { DeviceCameraInfo, CurrentCameraInfo } from './types';
3
+
4
+ const { CameraInfoModule } = NativeModules;
5
+
6
+ export interface CameraInfoModuleInterface {
7
+ getCameraInfo(): Promise<DeviceCameraInfo>;
8
+ getCurrentCameraInfo(): Promise<CurrentCameraInfo>;
9
+ }
10
+
11
+ export default CameraInfoModule as CameraInfoModuleInterface;
@@ -0,0 +1,121 @@
1
+ import {
2
+ codegenNativeComponent,
3
+ type ViewProps,
4
+ type NativeSyntheticEvent,
5
+ } from 'react-native';
6
+ import type {
7
+ DirectEventHandler,
8
+ Double,
9
+ } from 'react-native/Libraries/Types/CodegenTypesNamespace';
10
+
11
+ // Define codegen types locally (no longer exported from react-native in 0.83)
12
+
13
+ // Event payload types for better TypeScript inference
14
+ export interface BarcodeScannedEventPayload {
15
+ barcodes: {
16
+ data: string;
17
+ format: string;
18
+ timestamp: Double;
19
+ boundingBox?: {
20
+ left: Double;
21
+ top: Double;
22
+ right: Double;
23
+ bottom: Double;
24
+ };
25
+ area?: Double;
26
+ }[];
27
+ }
28
+
29
+ export interface ScannerErrorEventPayload {
30
+ error: string;
31
+ code: string;
32
+ }
33
+
34
+ export interface OnLoadEventPayload {
35
+ success: boolean;
36
+ error?: string;
37
+ }
38
+
39
+ // Event types for use in handlers
40
+ export type BarcodeScannedEvent =
41
+ NativeSyntheticEvent<BarcodeScannedEventPayload>;
42
+ export type ScannerErrorEvent = NativeSyntheticEvent<ScannerErrorEventPayload>;
43
+ export type OnLoadEvent = NativeSyntheticEvent<OnLoadEventPayload>;
44
+
45
+ // Nested object types for better codegen compatibility
46
+ export interface FocusAreaSize {
47
+ width: Double;
48
+ height: Double;
49
+ }
50
+
51
+ export interface FocusAreaPosition {
52
+ x: Double; // 0-100
53
+ y: Double; // 0-100
54
+ }
55
+
56
+ export interface FocusAreaConfig {
57
+ enabled?: boolean;
58
+ showOverlay?: boolean;
59
+ borderColor?: string;
60
+ tintColor?: string;
61
+ // NOTE: Codegen does not support mixed types (number OR object), so we always pass {width,height}.
62
+ size?: FocusAreaSize;
63
+ position?: FocusAreaPosition;
64
+ }
65
+
66
+ export interface BarcodeFramesConfig {
67
+ enabled?: boolean;
68
+ color?: string;
69
+ onlyInFocusArea?: boolean;
70
+ }
71
+
72
+ export interface BoundingBox {
73
+ left: Double;
74
+ top: Double;
75
+ right: Double;
76
+ bottom: Double;
77
+ }
78
+
79
+ export interface BarcodeData {
80
+ data: string;
81
+ format: string;
82
+ timestamp: Double;
83
+ boundingBox?: BoundingBox;
84
+ area?: Double;
85
+ }
86
+
87
+ export interface NativeProps extends ViewProps {
88
+ barcodeTypes?: string[];
89
+
90
+ /**
91
+ * Focus area configuration (Android: drives overlay + optional filtering).
92
+ * - `showOverlay` controls whether the scanning region is drawn.
93
+ * - `enabled` controls whether scanning is restricted to that region.
94
+ */
95
+ focusArea?: FocusAreaConfig;
96
+
97
+ /**
98
+ * Barcode frames configuration (draw rectangles around detected barcodes).
99
+ */
100
+ barcodeFrames?: BarcodeFramesConfig;
101
+
102
+ torch?: boolean;
103
+ zoom?: Double;
104
+ pauseScanning?: boolean;
105
+
106
+ barcodeScanStrategy?: string;
107
+ keepScreenOn?: boolean;
108
+
109
+ /**
110
+ * Minimum interval (in seconds) between barcode emission events.
111
+ * Prevents rapid duplicate detections. Set to 0 to disable debouncing.
112
+ * @default 0.5
113
+ */
114
+ barcodeEmissionInterval?: Double;
115
+
116
+ onBarcodeScanned?: DirectEventHandler<BarcodeScannedEventPayload>;
117
+ onScannerError?: DirectEventHandler<ScannerErrorEventPayload>;
118
+ onLoad?: DirectEventHandler<OnLoadEventPayload>;
119
+ }
120
+
121
+ export default codegenNativeComponent<NativeProps>('ScannerView');
@@ -0,0 +1,190 @@
1
+ import { useState, useEffect, useCallback, useMemo } from 'react';
2
+ import CameraInfoModule from '../CameraInfoModule';
3
+ import type {
4
+ DeviceCameraInfo,
5
+ CurrentCameraInfo,
6
+ CameraInfo,
7
+ CameraFacing,
8
+ } from '../types';
9
+
10
+ export interface UseCameraInfoReturn {
11
+ // Device information
12
+ deviceInfo: DeviceCameraInfo | null;
13
+ currentCameraInfo: CurrentCameraInfo | null;
14
+
15
+ // Camera lists
16
+ allCameras: CameraInfo[];
17
+ backCameras: CameraInfo[];
18
+ frontCameras: CameraInfo[];
19
+ macroCameras: CameraInfo[];
20
+
21
+ // Quick access properties
22
+ hasMultipleCameras: boolean;
23
+ hasBackCamera: boolean;
24
+ hasFrontCamera: boolean;
25
+ hasMacroCamera: boolean;
26
+ hasTorch: boolean;
27
+
28
+ // Default cameras
29
+ defaultBackCamera: CameraInfo | null;
30
+ defaultFrontCamera: CameraInfo | null;
31
+
32
+ // Zoom information
33
+ maxZoom: number;
34
+ minZoom: number;
35
+
36
+ // Loading and error states
37
+ isLoading: boolean;
38
+ error: string | null;
39
+
40
+ // Actions
41
+ refreshInfo: () => Promise<void>;
42
+ getCameraById: (id: string) => CameraInfo | null;
43
+ getCamerasByFacing: (facing: CameraFacing) => CameraInfo[];
44
+ }
45
+
46
+ export function useCameraInfo(): UseCameraInfoReturn {
47
+ const [deviceInfo, setDeviceInfo] = useState<DeviceCameraInfo | null>(null);
48
+ const [currentCameraInfo, setCurrentCameraInfo] =
49
+ useState<CurrentCameraInfo | null>(null);
50
+ const [isLoading, setIsLoading] = useState(true);
51
+ const [error, setError] = useState<string | null>(null);
52
+
53
+ const loadCameraInfo = useCallback(async () => {
54
+ try {
55
+ setIsLoading(true);
56
+ setError(null);
57
+
58
+ const info = await CameraInfoModule.getCameraInfo();
59
+ setDeviceInfo(info);
60
+
61
+ // Try to get current camera info if available
62
+ try {
63
+ const currentInfo = await CameraInfoModule.getCurrentCameraInfo();
64
+ setCurrentCameraInfo(currentInfo);
65
+ } catch (e) {
66
+ // Current camera info might not be available if no camera is bound
67
+ console.log('Current camera info not available:', e);
68
+ }
69
+ } catch (e: any) {
70
+ let errorMessage = 'Failed to load camera information';
71
+
72
+ // Handle specific error types
73
+ if (e?.code === 'PERMISSION_ERROR') {
74
+ errorMessage =
75
+ 'Camera permission not granted. Please grant camera permission in app settings.';
76
+ } else if (e?.code === 'NO_CAMERAS_ERROR') {
77
+ errorMessage = 'No cameras found on this device.';
78
+ } else if (e?.code === 'CAMERA_ACCESS_ERROR') {
79
+ errorMessage = 'Unable to access camera information. Please try again.';
80
+ } else if (e?.message) {
81
+ errorMessage = e.message;
82
+ }
83
+
84
+ setError(errorMessage);
85
+ console.error('Error loading camera info:', e);
86
+ } finally {
87
+ setIsLoading(false);
88
+ }
89
+ }, []);
90
+
91
+ const refreshInfo = useCallback(async () => {
92
+ await loadCameraInfo();
93
+ }, [loadCameraInfo]);
94
+
95
+ useEffect(() => {
96
+ loadCameraInfo();
97
+ }, [loadCameraInfo]);
98
+ // Computed properties
99
+ const allCameras = useMemo(
100
+ () => deviceInfo?.cameras || [],
101
+ [deviceInfo?.cameras]
102
+ );
103
+ const backCameras = useMemo(
104
+ () => allCameras.filter((camera) => camera.facing === 'back'),
105
+ [allCameras]
106
+ );
107
+ const frontCameras = useMemo(
108
+ () => allCameras.filter((camera) => camera.facing === 'front'),
109
+ [allCameras]
110
+ );
111
+ const macroCameras = useMemo(
112
+ () => allCameras.filter((camera) => camera.isMacroCamera),
113
+ [allCameras]
114
+ );
115
+
116
+ const hasMultipleCameras = allCameras.length > 1;
117
+ const hasBackCamera = backCameras.length > 0;
118
+ const hasFrontCamera = frontCameras.length > 0;
119
+ const hasMacroCamera = macroCameras.length > 0;
120
+ const hasTorch = allCameras.some((camera) => camera.hasFlash);
121
+
122
+ const defaultBackCamera = deviceInfo?.defaultBackCamera
123
+ ? allCameras.find((camera) => camera.id === deviceInfo.defaultBackCamera) ||
124
+ null
125
+ : backCameras[0] || null;
126
+
127
+ const defaultFrontCamera = deviceInfo?.defaultFrontCamera
128
+ ? allCameras.find(
129
+ (camera) => camera.id === deviceInfo.defaultFrontCamera
130
+ ) || null
131
+ : frontCameras[0] || null;
132
+
133
+ // Zoom range from all cameras
134
+ const allZoomRanges = allCameras.map((camera) => ({
135
+ min: camera.zoomMin,
136
+ max: camera.zoomMax,
137
+ }));
138
+ const maxZoom = Math.max(...allZoomRanges.map((range) => range.max), 1);
139
+ const minZoom = Math.min(...allZoomRanges.map((range) => range.min), 1);
140
+
141
+ const getCameraById = useCallback(
142
+ (id: string): CameraInfo | null => {
143
+ return allCameras.find((camera) => camera.id === id) || null;
144
+ },
145
+ [allCameras]
146
+ );
147
+
148
+ const getCamerasByFacing = useCallback(
149
+ (facing: CameraFacing): CameraInfo[] => {
150
+ return allCameras.filter((camera) => camera.facing === facing);
151
+ },
152
+ [allCameras]
153
+ );
154
+
155
+ return {
156
+ // Device information
157
+ deviceInfo,
158
+ currentCameraInfo,
159
+
160
+ // Camera lists
161
+ allCameras,
162
+ backCameras,
163
+ frontCameras,
164
+ macroCameras,
165
+
166
+ // Quick access properties
167
+ hasMultipleCameras,
168
+ hasBackCamera,
169
+ hasFrontCamera,
170
+ hasMacroCamera,
171
+ hasTorch,
172
+
173
+ // Default cameras
174
+ defaultBackCamera,
175
+ defaultFrontCamera,
176
+
177
+ // Zoom information
178
+ maxZoom,
179
+ minZoom,
180
+
181
+ // Loading and error states
182
+ isLoading,
183
+ error,
184
+
185
+ // Actions
186
+ refreshInfo,
187
+ getCameraById,
188
+ getCamerasByFacing,
189
+ };
190
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,30 @@
1
+ export { BarcodeFormat, BarcodeScanStrategy } from './types';
2
+ export type {
3
+ FrameSize,
4
+ FocusAreaConfig,
5
+ BarcodeFramesConfig,
6
+ BarcodeScannedEventPayload,
7
+ ScannerErrorEventPayload,
8
+ OnLoadEventPayload,
9
+ DeviceCameraInfo,
10
+ CurrentCameraInfo,
11
+ CameraInfo,
12
+ CameraFacing,
13
+ } from './types';
14
+
15
+ // Export the camera info hook
16
+ export { useCameraInfo } from './hooks/useCameraInfo';
17
+ export type { UseCameraInfoReturn } from './hooks/useCameraInfo';
18
+
19
+ // Re-export the native component and event types
20
+
21
+ export { default as ScannerView } from './ScannerViewNativeComponent';
22
+ export * from './ScannerViewNativeComponent';
23
+
24
+ // Export event types for better TypeScript inference
25
+ // These are the wrapped NativeSyntheticEvent types that users should use in their handlers
26
+ export type {
27
+ BarcodeScannedEvent,
28
+ ScannerErrorEvent,
29
+ OnLoadEvent,
30
+ } from './ScannerViewNativeComponent';
package/src/types.ts ADDED
@@ -0,0 +1,177 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+
3
+ // Barcode format enum
4
+ export enum BarcodeFormat {
5
+ QR_CODE = 'QR_CODE',
6
+ CODE_128 = 'CODE_128',
7
+ CODE_39 = 'CODE_39',
8
+ EAN_13 = 'EAN_13',
9
+ EAN_8 = 'EAN_8',
10
+ UPC_A = 'UPC_A',
11
+ UPC_E = 'UPC_E',
12
+ DATA_MATRIX = 'DATA_MATRIX',
13
+ PDF_417 = 'PDF_417',
14
+ AZTEC = 'AZTEC',
15
+ ITF = 'ITF',
16
+ }
17
+
18
+ // Barcode scan strategy enum
19
+ export enum BarcodeScanStrategy {
20
+ ONE = 'ONE',
21
+ ALL = 'ALL',
22
+ BIGGEST = 'BIGGEST',
23
+ SORT_BY_BIGGEST = 'SORT_BY_BIGGEST',
24
+ }
25
+
26
+ // Frame size configuration - can be a number (square) or object (rectangle)
27
+ export type FrameSize = number | { width: number; height: number };
28
+
29
+ // Focus area configuration
30
+ export type FocusAreaConfig = {
31
+ /**
32
+ * Whether to restrict scanning to focus area only
33
+ * @default false
34
+ */
35
+ enabled?: boolean;
36
+ /**
37
+ * Size of the focus area
38
+ * @default 300
39
+ */
40
+ size?: FrameSize;
41
+ /**
42
+ * Color of the focus area border
43
+ * @default transparent (no border) when not provided
44
+ */
45
+ borderColor?: string;
46
+ /**
47
+ * Color of the semi-transparent overlay (tint) around the focus area
48
+ * @default '#000000' with 50% opacity when not provided
49
+ */
50
+ tintColor?: string;
51
+ /**
52
+ * Whether to draw the focus area overlay
53
+ * @default false
54
+ */
55
+ showOverlay?: boolean;
56
+ /**
57
+ * Position of the focus area (percentage from 0-100)
58
+ * @default center (50, 50) when not provided
59
+ */
60
+ position?: {
61
+ x: number;
62
+ y: number;
63
+ };
64
+ };
65
+
66
+ // Barcode frame configuration
67
+ export type BarcodeFramesConfig = {
68
+ enabled?: boolean; // Whether to draw frames around detected barcodes
69
+ color?: string; // Color of barcode frames
70
+ onlyInFocusArea?: boolean; // Only show frames for barcodes in focus area
71
+ };
72
+
73
+ // Camera information types
74
+ export type CameraFacing = 'front' | 'back' | 'unknown';
75
+
76
+ export type ZoomRange = {
77
+ min: number;
78
+ max: number;
79
+ };
80
+
81
+ export type CameraInfo = {
82
+ id: string;
83
+ facing: CameraFacing;
84
+ sensorOrientation: number;
85
+ minFocusDistance: number;
86
+ hasFlash: boolean;
87
+ isMacroCamera: boolean;
88
+ zoomMin: number;
89
+ zoomMax: number;
90
+ focalLengths: string[];
91
+ aeModes: string[];
92
+ afModes: string[];
93
+ };
94
+
95
+ export type DeviceCameraInfo = {
96
+ cameras: CameraInfo[];
97
+ defaultBackCamera: string;
98
+ defaultFrontCamera: string;
99
+ };
100
+
101
+ export type CurrentCameraInfo = {
102
+ status: string;
103
+ message: string;
104
+ // Additional properties when camera is bound
105
+ currentZoom?: number;
106
+ isTorchEnabled?: boolean;
107
+ focusMode?: string;
108
+ };
109
+
110
+ // Barcode scanned event payload
111
+ export type BarcodeScannedEventPayload = {
112
+ data: string;
113
+ format: BarcodeFormat;
114
+ timestamp: number;
115
+ boundingBox?: {
116
+ left: number;
117
+ top: number;
118
+ right: number;
119
+ bottom: number;
120
+ };
121
+ area?: number;
122
+ };
123
+
124
+ // Scanner error event payload
125
+ export type ScannerErrorEventPayload = {
126
+ error: string;
127
+ code: string;
128
+ };
129
+
130
+ // On load event payload (for camera initialization)
131
+ export type OnLoadEventPayload = {
132
+ success: boolean;
133
+ error?: string;
134
+ };
135
+
136
+ // Event types
137
+ export type CameraNativeModuleEvents = {
138
+ onBarcodeScanned: (params: BarcodeScannedEventPayload) => void;
139
+ onScannerError: (params: ScannerErrorEventPayload) => void;
140
+ onLoad: (params: OnLoadEventPayload) => void;
141
+ };
142
+
143
+ // Props interface for the scanner view
144
+ export type CameraNativeModuleViewProps = {
145
+ // Barcode configuration
146
+ barcodeTypes?: BarcodeFormat[];
147
+
148
+ // Focus area configuration
149
+ focusArea?: FocusAreaConfig;
150
+
151
+ // Barcode frame configuration
152
+ barcodeFrames?: BarcodeFramesConfig;
153
+
154
+ // Camera configuration
155
+ torch?: boolean;
156
+ zoom?: number;
157
+ pauseScanning?: boolean;
158
+ keepScreenOn?: boolean;
159
+
160
+ // Event handlers
161
+ onBarcodeScanned?: (event: {
162
+ nativeEvent: BarcodeScannedEventPayload;
163
+ }) => void;
164
+ onScannerError?: (event: { nativeEvent: ScannerErrorEventPayload }) => void;
165
+ onLoad?: (event: { nativeEvent: OnLoadEventPayload }) => void;
166
+
167
+ // Styling
168
+ style?: StyleProp<ViewStyle>;
169
+ };
170
+
171
+ // Method invokers for controlling the scanner
172
+ export type CameraNativeModuleMethods = {
173
+ toggleTorch: () => Promise<boolean>;
174
+ startScanning: () => Promise<void>;
175
+ stopScanning: () => Promise<void>;
176
+ isTorchAvailable: () => Promise<boolean>;
177
+ };