@unif/react-native-hms-scan 0.6.1 → 1.0.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.
Files changed (168) hide show
  1. package/README.md +24 -72
  2. package/android/src/main/AndroidManifest.xml +0 -9
  3. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanImage.kt +135 -0
  4. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanModule.kt +163 -147
  5. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanResultMapper.kt +17 -9
  6. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanView.kt +57 -19
  7. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanViewManager.kt +1 -1
  8. package/ios/HmsScanModule.mm +13 -37
  9. package/ios/HmsScanResultMapper.h +4 -3
  10. package/ios/HmsScanResultMapper.mm +31 -19
  11. package/ios/HmsScanView.h +1 -1
  12. package/ios/HmsScanView.mm +140 -25
  13. package/lib/module/HmsScanView/HmsScanView.js +66 -0
  14. package/lib/module/HmsScanView/HmsScanView.js.map +1 -0
  15. package/lib/module/HmsScanView/HmsScanView.web.js +26 -0
  16. package/lib/module/HmsScanView/HmsScanView.web.js.map +1 -0
  17. package/lib/module/HmsScanView/types.js +4 -0
  18. package/lib/module/HmsScanView/types.js.map +1 -0
  19. package/lib/module/HmsScanViewNativeComponent.ts +7 -5
  20. package/lib/module/NativeHmsScan.js +1 -1
  21. package/lib/module/NativeHmsScan.js.map +1 -1
  22. package/lib/module/ScanError.js +12 -0
  23. package/lib/module/ScanError.js.map +1 -0
  24. package/lib/module/Scanner/DeniedOverlay.js +1 -1
  25. package/lib/module/Scanner/DeniedOverlay.js.map +1 -1
  26. package/lib/module/Scanner/ResultFail.js +3 -2
  27. package/lib/module/Scanner/ResultFail.js.map +1 -1
  28. package/lib/module/Scanner/ResultFocus/ResultFocus.js +56 -0
  29. package/lib/module/Scanner/ResultFocus/ResultFocus.js.map +1 -0
  30. package/lib/module/Scanner/ResultFocus/styles.js +39 -0
  31. package/lib/module/Scanner/ResultFocus/styles.js.map +1 -0
  32. package/lib/module/Scanner/ResultFocus/types.js +4 -0
  33. package/lib/module/Scanner/ResultFocus/types.js.map +1 -0
  34. package/lib/module/Scanner/ScanHint.js +6 -3
  35. package/lib/module/Scanner/ScanHint.js.map +1 -1
  36. package/lib/module/Scanner/ScanToolbar.js +6 -3
  37. package/lib/module/Scanner/ScanToolbar.js.map +1 -1
  38. package/lib/module/Scanner/ScanTopBar.js +6 -3
  39. package/lib/module/Scanner/ScanTopBar.js.map +1 -1
  40. package/lib/module/Scanner/Scanner.js +9 -311
  41. package/lib/module/Scanner/Scanner.js.map +1 -1
  42. package/lib/module/Scanner/Scanner.web.js +29 -0
  43. package/lib/module/Scanner/Scanner.web.js.map +1 -0
  44. package/lib/module/Scanner/ScannerInner.js +310 -0
  45. package/lib/module/Scanner/ScannerInner.js.map +1 -0
  46. package/lib/module/Scanner/styles.js +11 -0
  47. package/lib/module/Scanner/styles.js.map +1 -0
  48. package/lib/module/Scanner/types.js +4 -0
  49. package/lib/module/Scanner/types.js.map +1 -0
  50. package/lib/module/constants.js +20 -0
  51. package/lib/module/constants.js.map +1 -0
  52. package/lib/module/decodeImage.js +29 -24
  53. package/lib/module/decodeImage.js.map +1 -1
  54. package/lib/module/decodeImage.web.js +7 -0
  55. package/lib/module/decodeImage.web.js.map +1 -0
  56. package/lib/module/errors.js +24 -0
  57. package/lib/module/errors.js.map +1 -0
  58. package/lib/module/format.js +53 -47
  59. package/lib/module/format.js.map +1 -1
  60. package/lib/module/index.js +5 -19
  61. package/lib/module/index.js.map +1 -1
  62. package/lib/module/index.web.js +8 -0
  63. package/lib/module/index.web.js.map +1 -0
  64. package/lib/module/mock.js +2 -23
  65. package/lib/module/mock.js.map +1 -1
  66. package/lib/module/permissions.js +24 -20
  67. package/lib/module/permissions.js.map +1 -1
  68. package/lib/module/permissions.web.js +10 -0
  69. package/lib/module/permissions.web.js.map +1 -0
  70. package/lib/module/types.js +1 -45
  71. package/lib/module/types.js.map +1 -1
  72. package/lib/typescript/src/HmsScanView/HmsScanView.d.ts +3 -0
  73. package/lib/typescript/src/HmsScanView/HmsScanView.d.ts.map +1 -0
  74. package/lib/typescript/src/HmsScanView/HmsScanView.web.d.ts +3 -0
  75. package/lib/typescript/src/HmsScanView/HmsScanView.web.d.ts.map +1 -0
  76. package/lib/typescript/src/HmsScanView/types.d.ts +12 -0
  77. package/lib/typescript/src/HmsScanView/types.d.ts.map +1 -0
  78. package/lib/typescript/src/HmsScanViewNativeComponent.d.ts +6 -4
  79. package/lib/typescript/src/HmsScanViewNativeComponent.d.ts.map +1 -1
  80. package/lib/typescript/src/NativeHmsScan.d.ts +3 -5
  81. package/lib/typescript/src/NativeHmsScan.d.ts.map +1 -1
  82. package/lib/typescript/src/ScanError.d.ts +7 -0
  83. package/lib/typescript/src/ScanError.d.ts.map +1 -0
  84. package/lib/typescript/src/Scanner/DeniedOverlay.d.ts.map +1 -1
  85. package/lib/typescript/src/Scanner/ResultFail.d.ts +2 -1
  86. package/lib/typescript/src/Scanner/ResultFail.d.ts.map +1 -1
  87. package/lib/typescript/src/Scanner/ResultFocus/ResultFocus.d.ts +4 -0
  88. package/lib/typescript/src/Scanner/ResultFocus/ResultFocus.d.ts.map +1 -0
  89. package/lib/typescript/src/Scanner/ResultFocus/styles.d.ts +36 -0
  90. package/lib/typescript/src/Scanner/ResultFocus/styles.d.ts.map +1 -0
  91. package/lib/typescript/src/Scanner/ResultFocus/types.d.ts +8 -0
  92. package/lib/typescript/src/Scanner/ResultFocus/types.d.ts.map +1 -0
  93. package/lib/typescript/src/Scanner/ScanHint.d.ts.map +1 -1
  94. package/lib/typescript/src/Scanner/ScanToolbar.d.ts.map +1 -1
  95. package/lib/typescript/src/Scanner/ScanTopBar.d.ts.map +1 -1
  96. package/lib/typescript/src/Scanner/Scanner.d.ts +2 -45
  97. package/lib/typescript/src/Scanner/Scanner.d.ts.map +1 -1
  98. package/lib/typescript/src/Scanner/Scanner.web.d.ts +3 -0
  99. package/lib/typescript/src/Scanner/Scanner.web.d.ts.map +1 -0
  100. package/lib/typescript/src/Scanner/ScannerInner.d.ts +3 -0
  101. package/lib/typescript/src/Scanner/ScannerInner.d.ts.map +1 -0
  102. package/lib/typescript/src/Scanner/styles.d.ts +7 -0
  103. package/lib/typescript/src/Scanner/styles.d.ts.map +1 -0
  104. package/lib/typescript/src/Scanner/types.d.ts +20 -0
  105. package/lib/typescript/src/Scanner/types.d.ts.map +1 -0
  106. package/lib/typescript/src/constants.d.ts +8 -0
  107. package/lib/typescript/src/constants.d.ts.map +1 -0
  108. package/lib/typescript/src/decodeImage.d.ts +2 -12
  109. package/lib/typescript/src/decodeImage.d.ts.map +1 -1
  110. package/lib/typescript/src/decodeImage.web.d.ts +3 -0
  111. package/lib/typescript/src/decodeImage.web.d.ts.map +1 -0
  112. package/lib/typescript/src/errors.d.ts +6 -0
  113. package/lib/typescript/src/errors.d.ts.map +1 -0
  114. package/lib/typescript/src/format.d.ts +15 -12
  115. package/lib/typescript/src/format.d.ts.map +1 -1
  116. package/lib/typescript/src/index.d.ts +6 -7
  117. package/lib/typescript/src/index.d.ts.map +1 -1
  118. package/lib/typescript/src/index.web.d.ts +9 -0
  119. package/lib/typescript/src/index.web.d.ts.map +1 -0
  120. package/lib/typescript/src/mock.d.ts +9 -8
  121. package/lib/typescript/src/mock.d.ts.map +1 -1
  122. package/lib/typescript/src/permissions.d.ts +4 -8
  123. package/lib/typescript/src/permissions.d.ts.map +1 -1
  124. package/lib/typescript/src/permissions.web.d.ts +4 -0
  125. package/lib/typescript/src/permissions.web.d.ts.map +1 -0
  126. package/lib/typescript/src/types.d.ts +31 -56
  127. package/lib/typescript/src/types.d.ts.map +1 -1
  128. package/package.json +9 -2
  129. package/src/HmsScanView/HmsScanView.tsx +67 -0
  130. package/src/HmsScanView/HmsScanView.web.tsx +22 -0
  131. package/src/HmsScanView/types.ts +17 -0
  132. package/src/HmsScanViewNativeComponent.ts +7 -5
  133. package/src/NativeHmsScan.ts +3 -5
  134. package/src/ScanError.ts +13 -0
  135. package/src/Scanner/DeniedOverlay.tsx +4 -2
  136. package/src/Scanner/ResultFail.tsx +23 -5
  137. package/src/Scanner/ResultFocus/ResultFocus.tsx +43 -0
  138. package/src/Scanner/ResultFocus/styles.ts +25 -0
  139. package/src/Scanner/ResultFocus/types.ts +8 -0
  140. package/src/Scanner/ScanHint.tsx +16 -11
  141. package/src/Scanner/ScanToolbar.tsx +35 -13
  142. package/src/Scanner/ScanTopBar.tsx +20 -12
  143. package/src/Scanner/Scanner.tsx +13 -436
  144. package/src/Scanner/Scanner.web.tsx +26 -0
  145. package/src/Scanner/ScannerInner.tsx +391 -0
  146. package/src/Scanner/styles.ts +6 -0
  147. package/src/Scanner/types.ts +36 -0
  148. package/src/constants.ts +55 -0
  149. package/src/decodeImage.ts +35 -29
  150. package/src/decodeImage.web.ts +8 -0
  151. package/src/errors.ts +26 -0
  152. package/src/format.ts +77 -76
  153. package/src/index.tsx +17 -32
  154. package/src/index.web.tsx +22 -0
  155. package/src/mock.ts +21 -29
  156. package/src/permissions.ts +33 -20
  157. package/src/permissions.web.ts +9 -0
  158. package/src/types.ts +38 -126
  159. package/lib/module/HmsScanView.js +0 -43
  160. package/lib/module/HmsScanView.js.map +0 -1
  161. package/lib/module/Scanner/ResultFocus.js +0 -171
  162. package/lib/module/Scanner/ResultFocus.js.map +0 -1
  163. package/lib/typescript/src/HmsScanView.d.ts +0 -33
  164. package/lib/typescript/src/HmsScanView.d.ts.map +0 -1
  165. package/lib/typescript/src/Scanner/ResultFocus.d.ts +0 -14
  166. package/lib/typescript/src/Scanner/ResultFocus.d.ts.map +0 -1
  167. package/src/HmsScanView.tsx +0 -87
  168. package/src/Scanner/ResultFocus.tsx +0 -122
@@ -0,0 +1,8 @@
1
+ import type { ScanFailure } from './types';
2
+ /** The one source for public scan formats and input validation. */
3
+ export declare const SCAN_FORMATS: readonly ["QR_CODE", "AZTEC", "DATA_MATRIX", "PDF417", "CODABAR", "CODE_39", "CODE_93", "CODE_128", "EAN_8", "EAN_13", "UPC_A", "UPC_E", "ITF14", "MULTI_FUNCTIONAL", "UNKNOWN"];
4
+ export declare const SCAN_CONTENT_TYPES: readonly ["TEXT", "URL", "EMAIL", "PHONE", "SMS", "WIFI", "CONTACT", "EVENT", "LOCATION", "DRIVER", "ISBN", "ARTICLE", "OTHER"];
5
+ export declare const SCAN_FORMAT_SET: ReadonlySet<string>;
6
+ export declare const SCAN_CONTENT_TYPE_SET: ReadonlySet<string>;
7
+ export declare const SCAN_ERROR_REASONS: Readonly<Record<string, ScanFailure['reason']>>;
8
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,mEAAmE;AACnE,eAAO,MAAM,YAAY,kLAgBf,CAAC;AACX,eAAO,MAAM,kBAAkB,iIAcrB,CAAC;AAEX,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAAyB,CAAC;AAC1E,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,CAErD,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAYtC,CAAC"}
@@ -1,13 +1,3 @@
1
- import { type DecodeImageOptions, type ScanResult } from './types';
2
- /**
3
- * 从本地图片解码条码 / 二维码(华为 Bitmap 模式)。
4
- *
5
- * @param uri 本地图片。iOS 支持 file://、绝对路径、data:;Android 支持
6
- * file://、绝对路径、content://、android.resource://。
7
- * 两端都不下载远程 URL,也不支持 ph:// / assets-library://。
8
- * @param options 可选;formats 限定码制,不传 = 全部。
9
- * @returns 命中的结果数组(可能为空)。
10
- * @throws HmsScanError 图片加载失败 / 读权限缺失等。
11
- */
12
- export declare function decodeImage(uri: string, options?: DecodeImageOptions): Promise<ScanResult[]>;
1
+ import type { DecodeScanImageInput, ScanResult } from './types';
2
+ export declare function decodeImage(input: Readonly<DecodeScanImageInput>): Promise<readonly ScanResult[]>;
13
3
  //# sourceMappingURL=decodeImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decodeImage.d.ts","sourceRoot":"","sources":["../../../src/decodeImage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,kBAAkB,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAEjF;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,UAAU,EAAE,CAAC,CAmBvB"}
1
+ {"version":3,"file":"decodeImage.d.ts","sourceRoot":"","sources":["../../../src/decodeImage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAsB,WAAW,CAC/B,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GACpC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAkChC"}
@@ -0,0 +1,3 @@
1
+ import type { DecodeScanImageInput, ScanResult } from './types';
2
+ export declare function decodeImage(_input: Readonly<DecodeScanImageInput>): Promise<readonly ScanResult[]>;
3
+ //# sourceMappingURL=decodeImage.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decodeImage.web.d.ts","sourceRoot":"","sources":["../../../src/decodeImage.web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GACrC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAEhC"}
@@ -0,0 +1,6 @@
1
+ import { ScanError } from './ScanError';
2
+ import type { ScanFailure } from './types';
3
+ /** Native boundary normalization; Scanner only uses this for its external picker. */
4
+ export declare function scanError(error: unknown, fallback: Readonly<ScanFailure>): ScanError;
5
+ export declare function unsupportedScanError(): ScanError;
6
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,SAAS,CAAC;AAE9D,qFAAqF;AACrF,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC9B,SAAS,CAUX;AAED,wBAAgB,oBAAoB,IAAI,SAAS,CAKhD"}
@@ -1,13 +1,16 @@
1
- import { type BarcodeContentType, type BarcodeFormat, type ScanResult } from './types';
2
- /** 把任意字符串安全收敛成 BarcodeFormat(未知归 UNKNOWN)。 */
3
- export declare function coerceFormat(value: unknown): BarcodeFormat;
4
- /** 把任意字符串安全收敛成 BarcodeContentType(未知/缺省 → undefined)。 */
5
- export declare function coerceContentType(value: unknown): BarcodeContentType | undefined;
6
- /** formats[] → 逗号分隔 CSV(传给原生);空/未传 → ''(= 全部码制)。 */
7
- export declare function formatsToCsv(formats?: readonly BarcodeFormat[]): string;
8
- /**
9
- * 解析原生回传的 JSON 字符串 → 强类型 ScanResult[]。
10
- * 任何脏数据都被安全过滤;解析失败返回空数组而非抛错。
11
- */
12
- export declare function parseResultsJson(json: string): ScanResult[];
1
+ import { ScanError } from './ScanError';
2
+ import type { RequestedScanFormat, ScanContentType, ScanFormat, ScanResult } from './types';
3
+ export declare function coerceFormat(value: unknown): ScanFormat;
4
+ export declare function coerceContentType(value: unknown): ScanContentType | undefined;
5
+ /** Empty means no extra filter. Order and duplicates do not change the filter. */
6
+ export declare function formatsToCsv(value?: readonly RequestedScanFormat[]): string;
7
+ export declare function formatConfiguration(value?: readonly RequestedScanFormat[]): {
8
+ csv: string;
9
+ error: undefined;
10
+ } | {
11
+ csv: string;
12
+ error: ScanError;
13
+ };
14
+ /** Malformed bridge data is distinct from a successfully decoded empty batch. */
15
+ export declare function parseResultsJson(json: unknown): readonly ScanResult[];
13
16
  //# sourceMappingURL=format.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAElB,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AAqBjB,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAI1D;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CAIhF;AAED,oDAAoD;AACpD,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAEvE;AA6BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAe3D"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/format.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,UAAU,EAEV,UAAU,EACX,MAAM,SAAS,CAAC;AACjB,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAIvD;AACD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAI7E;AACD,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,CAiB3E;AACD,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,SAAS,mBAAmB,EAAE;;;;;WAIpC,SAAS;EAE9C;AAqBD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,UAAU,EAAE,CA2BrE"}
@@ -1,10 +1,9 @@
1
- export { ALL_BARCODE_FORMATS, HmsScanError, } from './types';
2
- export type { BarcodeFormat, BarcodeContentType, ScanCornerPoint, ScanResult, ScanError, DecodeImageOptions, CameraPermissionStatus, HmsScanErrorCode, ScanProduct, } from './types';
3
- export { coerceFormat, coerceContentType, formatsToCsv } from './format';
4
- export { HmsScanView } from './HmsScanView';
5
- export type { HmsScanViewProps, TorchStatus } from './HmsScanView';
1
+ export { ScanError } from './ScanError';
2
+ export type { ScanFormat, RequestedScanFormat, ScanContentType, ScanPoint, ScanResult, ScanFailure, DecodeScanImageInput, ScanCameraPermission, ScanTorchState, ScannerImage, } from './types';
3
+ export { HmsScanView } from './HmsScanView/HmsScanView';
4
+ export type { HmsScanViewProps } from './HmsScanView/types';
6
5
  export { decodeImage } from './decodeImage';
7
- export { getCameraPermissionStatus, requestCameraPermission } from './permissions';
6
+ export { getCameraPermissionStatus, requestCameraPermission, } from './permissions';
8
7
  export { Scanner } from './Scanner/Scanner';
9
- export type { ScannerProps } from './Scanner/Scanner';
8
+ export type { ScannerProps } from './Scanner/types';
10
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAKA,OAAO,EACL,mBAAmB,EACnB,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,GACZ,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGzE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGnF,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { ScanError } from './ScanError';
2
+ export type { ScanFormat, RequestedScanFormat, ScanContentType, ScanPoint, ScanResult, ScanFailure, DecodeScanImageInput, ScanCameraPermission, ScanTorchState, ScannerImage, } from './types';
3
+ export { HmsScanView } from './HmsScanView/HmsScanView.web';
4
+ export type { HmsScanViewProps } from './HmsScanView/types';
5
+ export { decodeImage } from './decodeImage.web';
6
+ export { getCameraPermissionStatus, requestCameraPermission, } from './permissions.web';
7
+ export { Scanner } from './Scanner/Scanner.web';
8
+ export type { ScannerProps } from './Scanner/types';
9
+ //# sourceMappingURL=index.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../src/index.web.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,12 +1,13 @@
1
1
  import type { FC } from 'react';
2
- import type { CameraPermissionStatus, DecodeImageOptions, ScanResult } from './types';
3
- import type { HmsScanViewProps } from './HmsScanView';
4
- import type { ScannerProps } from './Scanner/Scanner';
5
- export * from './types';
6
- export { coerceFormat, coerceContentType, formatsToCsv } from './format';
7
- export declare const decodeImage: jest.Mock<Promise<ScanResult[]>, [_uri: string, _options?: DecodeImageOptions | undefined], any>;
8
- export declare const getCameraPermissionStatus: jest.Mock<Promise<CameraPermissionStatus>, [], any>;
9
- export declare const requestCameraPermission: jest.Mock<Promise<CameraPermissionStatus>, [], any>;
2
+ import type { DecodeScanImageInput, ScanCameraPermission, ScanResult } from './types';
3
+ import type { HmsScanViewProps } from './HmsScanView/types';
4
+ import type { ScannerProps } from './Scanner/types';
5
+ export { ScanError } from './ScanError';
6
+ export type { ScanFormat, RequestedScanFormat, ScanContentType, ScanPoint, ScanResult, ScanFailure, DecodeScanImageInput, ScanCameraPermission, ScanTorchState, ScannerImage, } from './types';
7
+ export type { HmsScanViewProps, ScannerProps };
8
+ export declare const decodeImage: jest.Mock<Promise<readonly ScanResult[]>, [_input: Readonly<DecodeScanImageInput>], any>;
9
+ export declare const getCameraPermissionStatus: jest.Mock<Promise<ScanCameraPermission>, [], any>;
10
+ export declare const requestCameraPermission: jest.Mock<Promise<ScanCameraPermission>, [], any>;
10
11
  export declare const HmsScanView: FC<HmsScanViewProps>;
11
12
  export declare const Scanner: FC<ScannerProps>;
12
13
  //# sourceMappingURL=mock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../../src/mock.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,EACX,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGzE,eAAO,MAAM,WAAW,kGAGvB,CAAC;AAGF,eAAO,MAAM,yBAAyB,qDAErC,CAAC;AACF,eAAO,MAAM,uBAAuB,qDAEnC,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAAc,CAAC;AAC5D,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAAc,CAAC"}
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../../src/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,UAAU,EACX,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC;AAC/C,eAAO,MAAM,WAAW,0FAGvB,CAAC;AACF,eAAO,MAAM,yBAAyB,mDAErC,CAAC;AACF,eAAO,MAAM,uBAAuB,mDAEnC,CAAC;AACF,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAAc,CAAC;AAC5D,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAAc,CAAC"}
@@ -1,9 +1,5 @@
1
- import type { CameraPermissionStatus } from './types';
2
- /** 查询当前相机权限状态(不弹窗)。 */
3
- export declare function getCameraPermissionStatus(): Promise<CameraPermissionStatus>;
4
- /**
5
- * 发起相机权限请求(必要时弹系统授权框),返回请求后的状态。
6
- * 若用户已永久拒绝(blocked),需引导去系统设置开启。
7
- */
8
- export declare function requestCameraPermission(): Promise<CameraPermissionStatus>;
1
+ import type { ScanCameraPermission } from './types';
2
+ /** Reads the actual status without presenting a system permission prompt. */
3
+ export declare function getCameraPermissionStatus(): Promise<ScanCameraPermission>;
4
+ export declare function requestCameraPermission(): Promise<ScanCameraPermission>;
9
5
  //# sourceMappingURL=permissions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AActD,uBAAuB;AACvB,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAEjF;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAE/E"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/permissions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AA8BpD,6EAA6E;AAC7E,wBAAgB,yBAAyB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAEzE;AACD,wBAAgB,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAEvE"}
@@ -0,0 +1,4 @@
1
+ import type { ScanCameraPermission } from './types';
2
+ export declare function getCameraPermissionStatus(): Promise<ScanCameraPermission>;
3
+ export declare function requestCameraPermission(): Promise<ScanCameraPermission>;
4
+ //# sourceMappingURL=permissions.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.web.d.ts","sourceRoot":"","sources":["../../../src/permissions.web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAE/E;AACD,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAE7E"}
@@ -1,67 +1,42 @@
1
- /** 统一码制枚举(两端归一)。 */
2
- export type BarcodeFormat = 'QR_CODE' | 'AZTEC' | 'DATA_MATRIX' | 'PDF417' | 'CODABAR' | 'CODE_39' | 'CODE_93' | 'CODE_128' | 'EAN_8' | 'EAN_13' | 'UPC_A' | 'UPC_E' | 'ITF14' | 'MULTI_FUNCTIONAL' | 'UNKNOWN';
3
- /** 所有可用码制(不含 UNKNOWN)。传给原生即"识别全部码制"。 */
4
- export declare const ALL_BARCODE_FORMATS: readonly BarcodeFormat[];
5
- /**
6
- * 码内容语义类型(尽力归一)。
7
- * Android 来自 HmsScan.getScanTypeForm(),iOS 来自 sceneType(精度有限,未知归 OTHER)。
8
- */
9
- export type BarcodeContentType = 'TEXT' | 'URL' | 'EMAIL' | 'PHONE' | 'SMS' | 'WIFI' | 'CONTACT' | 'EVENT' | 'LOCATION' | 'DRIVER' | 'ISBN' | 'ARTICLE' | 'OTHER';
10
- /** 取景框/解码命中的角点(图像坐标系,单位 px)。 */
11
- export interface ScanCornerPoint {
1
+ import type { SCAN_FORMATS, SCAN_CONTENT_TYPES } from './constants';
2
+ export type ScanFormat = (typeof SCAN_FORMATS)[number];
3
+ export type RequestedScanFormat = Exclude<ScanFormat, 'UNKNOWN'>;
4
+ export type ScanContentType = (typeof SCAN_CONTENT_TYPES)[number];
5
+ export interface ScanPoint {
12
6
  x: number;
13
7
  y: number;
14
8
  }
15
- /** 一次扫码/解码命中的结果。 */
16
9
  export interface ScanResult {
17
- /** 原始解码文本(Android getOriginalValue / iOS text)。 */
10
+ /** Unmodified decoded text. */
18
11
  value: string;
19
- /** 码制。 */
20
- format: BarcodeFormat;
21
- /** 内容语义类型(可能缺省)。 */
22
- contentType?: BarcodeContentType;
23
- /** 条码四角点(可能缺省)。 */
24
- cornerPoints?: ScanCornerPoint[];
12
+ format: ScanFormat;
13
+ contentType?: ScanContentType;
14
+ /** Coordinates in the recognition image, not screen coordinates. */
15
+ cornerPoints?: readonly ScanPoint[];
25
16
  }
26
- /** decodeImage 选项。 */
27
- export interface DecodeImageOptions {
28
- /** 限定识别码制;不传 = 全部。 */
29
- formats?: readonly BarcodeFormat[];
30
- }
31
- /** `<HmsScanView>` / `<Scanner>` 通过回调上报的普通错误对象。 */
32
- export interface ScanError {
33
- code: string;
17
+ export interface ScanFailure {
18
+ reason: 'invalid_input' | 'permission_denied' | 'image_unavailable' | 'decode_failed' | 'invalid_response' | 'unavailable' | 'unsupported';
34
19
  message: string;
20
+ sourceCode?: string;
21
+ }
22
+ export interface DecodeScanImageInput {
23
+ /** A readable local file URI, borrowed until this operation settles. */
24
+ uri: string;
25
+ formats?: readonly RequestedScanFormat[];
26
+ }
27
+ export type ScanCameraPermission = 'granted' | 'denied' | 'blocked' | 'undetermined';
28
+ export interface ScanTorchState {
29
+ on: boolean;
30
+ available?: boolean;
31
+ lowLight?: boolean;
35
32
  }
36
- /** 相机权限状态。 */
37
- export type CameraPermissionStatus = 'granted' | 'denied' | 'blocked' | 'undetermined';
38
- /** 错误码。 */
39
- export type HmsScanErrorCode = 'E_NO_CAMERA_PERMISSION' | 'E_NO_READ_PERMISSION' | 'E_CAMERA_INIT' | 'E_DECODE_FAILED' | 'E_IMAGE_LOAD_FAILED' | 'E_NO_RESULT' | 'E_UNKNOWN';
40
- /** 库统一抛出的错误类型。 */
41
- export declare class HmsScanError extends Error {
42
- readonly code: HmsScanErrorCode;
43
- constructor(code: HmsScanErrorCode, message?: string);
33
+ export interface ScannerImage {
34
+ uri: string;
35
+ onSourceReleased?(): void;
44
36
  }
45
- /**
46
- * 业务层商品信息——`<Scanner>` 扫到条码后,由宿主通过 resolveProduct 解析返回,
47
- * 用于聚焦款"浮层确认卡"展示。仅 name 必填,其余可缺省。
48
- */
49
- export interface ScanProduct {
50
- /** 商品名(必填)。 */
51
- name: string;
52
- /** 品牌(如 "统一")。 */
53
- brand?: string;
54
- /** 字母牌字符;缺省时取 brand 或 name 的首字。 */
55
- brandChar?: string;
56
- /** 条码;缺省时取扫到的 value。 */
57
- barcode?: string;
58
- /** 规格(如 "500ml × 15 瓶/箱")。 */
59
- spec?: string;
60
- /** 库存短描述(如 "充足")。 */
61
- stockShort?: string;
62
- /** 价格展示串(如 "¥5.50")。 */
63
- price?: string;
64
- /** 价格下方副标题,默认 "建议零售"。 */
65
- priceCaption?: string;
37
+ /** Native rejection payload; internal to the capability boundary. */
38
+ export interface NativeScanFailure {
39
+ code?: unknown;
40
+ message?: unknown;
66
41
  }
67
42
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAQA,oBAAoB;AACpB,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,OAAO,GACP,aAAa,GACb,QAAQ,GACR,SAAS,GACT,SAAS,GACT,SAAS,GACT,UAAU,GACV,OAAO,GACP,QAAQ,GACR,OAAO,GACP,OAAO,GACP,OAAO,GACP,kBAAkB,GAClB,SAAS,CAAC;AAEd,wCAAwC;AACxC,eAAO,MAAM,mBAAmB,EAAE,SAAS,aAAa,EAe9C,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,KAAK,GACL,OAAO,GACP,OAAO,GACP,KAAK,GACL,MAAM,GACN,SAAS,GACT,OAAO,GACP,UAAU,GACV,QAAQ,GACR,MAAM,GACN,SAAS,GACT,OAAO,CAAC;AAEZ,gCAAgC;AAChC,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,oBAAoB;AACpB,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU;IACV,MAAM,EAAE,aAAa,CAAC;IACtB,oBAAoB;IACpB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,mBAAmB;IACnB,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;CAClC;AAED,sBAAsB;AACtB,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACpC;AAED,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,cAAc;AACd,MAAM,MAAM,sBAAsB,GAC9B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,cAAc,CAAC;AAEnB,WAAW;AACX,MAAM,MAAM,gBAAgB,GACxB,wBAAwB,GACxB,sBAAsB,GACtB,eAAe,GACf,iBAAiB,GACjB,qBAAqB,GACrB,aAAa,GACb,WAAW,CAAC;AAEhB,kBAAkB;AAClB,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;gBACpB,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM;CAOrD;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAEjE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AACD,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,oEAAoE;IACpE,YAAY,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC;AACD,MAAM,WAAW,WAAW;IAC1B,MAAM,EACF,eAAe,GACf,mBAAmB,GACnB,mBAAmB,GACnB,eAAe,GACf,kBAAkB,GAClB,aAAa,GACb,aAAa,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC1C;AACD,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,cAAc,CAAC;AACnB,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,IAAI,IAAI,CAAC;CAC3B;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "@unif/react-native-hms-scan",
3
- "version": "0.6.1",
4
- "description": "华为 HMS 统一扫码服务 React Native bridge:定制视图扫码 + 图片识别 (Scan SDK-Plus / ScanKitFrameWork,@unif 私有)",
3
+ "version": "1.0.0",
4
+ "description": "Unif React Native 扫码:实时预览、二维码、条码和本地图片识别",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
7
7
  "exports": {
8
8
  ".": {
9
+ "browser": {
10
+ "source": "./src/index.web.tsx",
11
+ "types": "./lib/typescript/src/index.web.d.ts",
12
+ "default": "./lib/module/index.web.js"
13
+ },
9
14
  "source": "./src/index.tsx",
10
15
  "types": "./lib/typescript/src/index.d.ts",
11
16
  "default": "./lib/module/index.js"
@@ -41,6 +46,8 @@
41
46
  "prepare": "bob build",
42
47
  "typecheck": "tsc",
43
48
  "test": "yarn verify:integration-contracts && yarn verify:android-integration && yarn verify:ios-integration && jest",
49
+ "test:native:android": "python3 scripts/test-android-native.py",
50
+ "test:native:ios": "bash scripts/test-ios-native.sh",
44
51
  "verify:integration-contracts": "node --test scripts/__tests__/integration-contract.test.mjs",
45
52
  "verify:android-integration": "node scripts/verify-android-integration.mjs",
46
53
  "verify:ios-integration": "node scripts/verify-ios-integration.mjs",
@@ -0,0 +1,67 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { View } from 'react-native';
3
+ import NativeHmsScanView from '../HmsScanViewNativeComponent';
4
+ import { formatConfiguration, parseResultsJson } from '../format';
5
+ import { scanError } from '../errors';
6
+ import type { ScanResult } from '../types';
7
+ import type { HmsScanViewProps } from './types';
8
+
9
+ export function HmsScanView({
10
+ formats,
11
+ continuous = true,
12
+ paused = false,
13
+ torch = false,
14
+ onScanResult,
15
+ onScanError,
16
+ onTorchState,
17
+ ...viewProps
18
+ }: HmsScanViewProps) {
19
+ const config = formatConfiguration(formats);
20
+ const invalid = config.error;
21
+ const errorRef = useRef(onScanError);
22
+ errorRef.current = onScanError;
23
+ useEffect(() => {
24
+ if (invalid) errorRef.current?.(invalid);
25
+ }, [invalid?.message]);
26
+ if (invalid) return <View {...viewProps} />;
27
+ return (
28
+ <NativeHmsScanView
29
+ {...viewProps}
30
+ formatsCsv={config.csv}
31
+ continuous={continuous}
32
+ paused={paused}
33
+ torch={torch}
34
+ onScanResult={(event) => {
35
+ let results: readonly ScanResult[];
36
+ try {
37
+ results = parseResultsJson(event.nativeEvent.resultsJson);
38
+ } catch (error) {
39
+ onScanError?.(
40
+ scanError(error, {
41
+ reason: 'invalid_response',
42
+ message: '扫码结果无法识别',
43
+ })
44
+ );
45
+ return;
46
+ }
47
+ onScanResult?.(results);
48
+ }}
49
+ onScanError={(event) =>
50
+ onScanError?.(
51
+ scanError(event.nativeEvent, {
52
+ reason: 'unavailable',
53
+ message: '扫码相机不可用',
54
+ })
55
+ )
56
+ }
57
+ onTorchState={(event) => {
58
+ const state = event.nativeEvent;
59
+ onTorchState?.({
60
+ on: state.on,
61
+ ...(state.hasAvailable ? { available: state.available } : {}),
62
+ ...(state.hasLowLight ? { lowLight: state.lowLight } : {}),
63
+ });
64
+ }}
65
+ />
66
+ );
67
+ }
@@ -0,0 +1,22 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { View } from 'react-native';
3
+ import { unsupportedScanError } from '../errors';
4
+ import type { HmsScanViewProps } from './types';
5
+
6
+ export function HmsScanView({
7
+ onScanError,
8
+ formats: _formats,
9
+ paused: _paused,
10
+ torch: _torch,
11
+ continuous: _continuous,
12
+ onScanResult: _onScanResult,
13
+ onTorchState: _onTorchState,
14
+ ...props
15
+ }: HmsScanViewProps) {
16
+ const callback = useRef(onScanError);
17
+ callback.current = onScanError;
18
+ useEffect(() => {
19
+ callback.current?.(unsupportedScanError());
20
+ }, []);
21
+ return <View {...props} />;
22
+ }
@@ -0,0 +1,17 @@
1
+ import type { ViewProps } from 'react-native';
2
+ import type {
3
+ RequestedScanFormat,
4
+ ScanFailure,
5
+ ScanResult,
6
+ ScanTorchState,
7
+ } from '../types';
8
+
9
+ export interface HmsScanViewProps extends ViewProps {
10
+ formats?: readonly RequestedScanFormat[];
11
+ continuous?: boolean;
12
+ paused?: boolean;
13
+ torch?: boolean;
14
+ onScanResult?(results: readonly ScanResult[]): void;
15
+ onScanError?(error: Readonly<ScanFailure>): void;
16
+ onTorchState?(state: Readonly<ScanTorchState>): void;
17
+ }
@@ -7,7 +7,7 @@ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNati
7
7
 
8
8
  // RN codegen Fabric 组件规范(注册名 "HmsScanView")。
9
9
  // 事件 payload 都用基础类型 / 单字符串,绕开 codegen 对复杂事件结构的限制:
10
- // 扫码结果以 JSON 字符串回传(由 src/HmsScanView.tsx 解析成 ScanResult[])。
10
+ // 扫码结果以 JSON 字符串回传(由 HmsScanView/HmsScanView.tsx 解析成 ScanResult[])。
11
11
 
12
12
  type ScanResultEvent = Readonly<{
13
13
  /** JSON 编码的 ScanResult[]。 */
@@ -19,15 +19,17 @@ type ScanErrorEvent = Readonly<{
19
19
  message: string;
20
20
  }>;
21
21
 
22
- type TorchStatusEvent = Readonly<{
23
- /** 环境是否暗到建议显示手电按钮(Android OnLightVisibleCallBack)。 */
22
+ type TorchStateEvent = Readonly<{
24
23
  available: boolean;
24
+ hasAvailable: boolean;
25
+ lowLight: boolean;
26
+ hasLowLight: boolean;
25
27
  /** 手电当前是否点亮。 */
26
28
  on: boolean;
27
29
  }>;
28
30
 
29
31
  export interface NativeProps extends ViewProps {
30
- /** 限定码制(逗号分隔的 BarcodeFormat),空串 = 全部。 */
32
+ /** 限定码制(逗号分隔的 ScanFormat),空串 = 全部。 */
31
33
  formatsCsv?: WithDefault<string, ''>;
32
34
  /** 连续扫码(命中后继续,不自动停)。 */
33
35
  continuous?: WithDefault<boolean, true>;
@@ -38,7 +40,7 @@ export interface NativeProps extends ViewProps {
38
40
 
39
41
  onScanResult?: DirectEventHandler<ScanResultEvent>;
40
42
  onScanError?: DirectEventHandler<ScanErrorEvent>;
41
- onTorchStatus?: DirectEventHandler<TorchStatusEvent>;
43
+ onTorchState?: DirectEventHandler<TorchStateEvent>;
42
44
  }
43
45
 
44
46
  export default codegenNativeComponent<NativeProps>('HmsScanView');
@@ -8,10 +8,8 @@ import { TurboModuleRegistry } from 'react-native';
8
8
  export interface Spec extends TurboModule {
9
9
  /**
10
10
  * 解码本地图片里的条码 / 二维码。
11
- * @param uri 本地图片。iOS 支持 file://、绝对路径、data:;Android 支持
12
- * file://、绝对路径、content://、android.resource://。
13
- * 两端都不下载远程 URL,也不支持 ph:// / assets-library://。
14
- * @param formatsCsv 限定码制(逗号分隔的 BarcodeFormat),空串 = 全部。
11
+ * @param uri 本地图片 file URI,由公共能力边界校验。
12
+ * @param formatsCsv 限定码制(逗号分隔的 ScanFormat),空串 = 全部。
15
13
  * @returns JSON 编码的 ScanResult[](可能为空数组)。
16
14
  */
17
15
  decodeImage(uri: string, formatsCsv: string): Promise<string>;
@@ -23,4 +21,4 @@ export interface Spec extends TurboModule {
23
21
  requestCameraPermission(): Promise<string>;
24
22
  }
25
23
 
26
- export default TurboModuleRegistry.getEnforcing<Spec>('HmsScan');
24
+ export default TurboModuleRegistry.get<Spec>('HmsScan');
@@ -0,0 +1,13 @@
1
+ import type { ScanFailure } from './types';
2
+
3
+ export class ScanError extends Error implements ScanFailure {
4
+ readonly reason: ScanFailure['reason'];
5
+ readonly sourceCode?: string;
6
+ constructor(error: Readonly<ScanFailure>) {
7
+ super(error.message);
8
+ this.name = 'ScanError';
9
+ this.reason = error.reason;
10
+ this.sourceCode = error.sourceCode;
11
+ Object.setPrototypeOf(this, ScanError.prototype);
12
+ }
13
+ }
@@ -20,12 +20,14 @@ export function DeniedOverlay({ onClose, onSettings }: DeniedOverlayProps) {
20
20
  <Empty
21
21
  icon="permission-denied"
22
22
  title="需要相机权限"
23
- desc="开启相机后,才能扫描商品条码与门店二维码。请前往系统设置授权。"
23
+ desc="开启相机后,才能扫描条码与二维码。请前往系统设置授权。"
24
24
  />
25
25
  {/* block(flexGrow:1)而非 flex:1:ButtonBase 非 block 时硬编码 flexGrow:0,
26
26
  会压过 style 里的 flex:1 → 按钮塌成 padding 宽、label 被裁(同 ResultFocus)。 */}
27
27
  <View style={styles.row}>
28
- {onClose && <Button label="取消" variant="ghost" block onPress={onClose} />}
28
+ {onClose && (
29
+ <Button label="取消" variant="ghost" block onPress={onClose} />
30
+ )}
29
31
  <Button
30
32
  label="去设置开启"
31
33
  variant="primary"
@@ -11,32 +11,50 @@ import {
11
11
 
12
12
  interface ResultFailProps {
13
13
  bottomInset: number;
14
+ failed?: boolean;
14
15
  /** 重扫:回到取景重新扫描。(退出扫码页是外层工具栏「返回」的事。) */
15
16
  onRescan: () => void;
16
17
  }
17
18
 
18
19
  // 未识别失败的底部弹层:design 的 Empty(error-alert)+ Button(重扫)。
19
20
  // 聚焦款不加背景遮罩,与浮层确认卡保持一致。
20
- export function ResultFail({ bottomInset, onRescan }: ResultFailProps) {
21
+ export function ResultFail({ bottomInset, failed, onRescan }: ResultFailProps) {
21
22
  const s = useThemedStyles(makeStyles);
22
23
  const anim = useRef(new Animated.Value(0)).current;
23
24
  useEffect(() => {
24
- Animated.timing(anim, { toValue: 1, duration: 320, useNativeDriver: true }).start();
25
+ Animated.timing(anim, {
26
+ toValue: 1,
27
+ duration: 320,
28
+ useNativeDriver: true,
29
+ }).start();
25
30
  }, [anim]);
26
31
 
27
32
  return (
28
33
  <Animated.View
29
34
  style={[
30
35
  s.sheet,
31
- { transform: [{ translateY: anim.interpolate({ inputRange: [0, 1], outputRange: [r(320), 0] }) }] },
36
+ {
37
+ transform: [
38
+ {
39
+ translateY: anim.interpolate({
40
+ inputRange: [0, 1],
41
+ outputRange: [r(320), 0],
42
+ }),
43
+ },
44
+ ],
45
+ },
32
46
  ]}
33
47
  >
34
48
  <View style={s.grabber} />
35
49
  <View style={[styles.inner, { paddingBottom: bottomInset + r(14) }]}>
36
50
  <Empty
37
51
  icon="error-alert"
38
- title="未识别到条码"
39
- desc="请将条码完整置于框内、保持平整并对准光线后重试。"
52
+ title={failed ? '图片识别失败' : '未识别到条码'}
53
+ desc={
54
+ failed
55
+ ? '无法读取或解码图片,请重试。'
56
+ : '请将条码完整置于框内、保持平整并对准光线后重试。'
57
+ }
40
58
  />
41
59
  <Button label="重扫" variant="primary" block onPress={onRescan} />
42
60
  </View>