pi-kiosk-shared 2.3.3 → 2.3.6

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 (75) hide show
  1. package/README.md +18 -48
  2. package/dist/analyticsPiiTags.d.ts +6 -0
  3. package/dist/analyticsPiiTags.d.ts.map +1 -0
  4. package/dist/api.d.ts +129 -0
  5. package/dist/api.d.ts.map +1 -0
  6. package/dist/api.js +305 -0
  7. package/dist/api.js.map +1 -0
  8. package/dist/auditEventCodes.d.ts +8 -0
  9. package/dist/auditEventCodes.d.ts.map +1 -0
  10. package/dist/auditEventCodes.js +180 -0
  11. package/dist/auditEventCodes.js.map +1 -0
  12. package/dist/auditEventDescriptions.d.ts +5 -0
  13. package/dist/auditEventDescriptions.d.ts.map +1 -0
  14. package/dist/auditEventDescriptions.js +849 -0
  15. package/dist/auditEventDescriptions.js.map +1 -0
  16. package/dist/auditEventLabels.d.ts +4 -0
  17. package/dist/auditEventLabels.d.ts.map +1 -0
  18. package/dist/auditEventLabels.js +858 -0
  19. package/dist/auditEventLabels.js.map +1 -0
  20. package/dist/auditMetadataDisplayFields.d.ts +9 -0
  21. package/dist/auditMetadataDisplayFields.d.ts.map +1 -0
  22. package/dist/auditMetadataDisplayFields.js +273 -0
  23. package/dist/auditMetadataDisplayFields.js.map +1 -0
  24. package/dist/barcode/normalizeScanPayload.d.ts +17 -0
  25. package/dist/barcode/normalizeScanPayload.d.ts.map +1 -0
  26. package/dist/barcode/normalizeScanPayload.js +100 -0
  27. package/dist/barcode/normalizeScanPayload.js.map +1 -0
  28. package/dist/checkout/sessionMetadataV3.d.ts +36 -0
  29. package/dist/checkout/sessionMetadataV3.d.ts.map +1 -0
  30. package/dist/checkout/sessionMetadataV3.js +6 -0
  31. package/dist/checkout/sessionMetadataV3.js.map +1 -0
  32. package/dist/checkout/sessionMetadataV4.d.ts +19 -0
  33. package/dist/checkout/sessionMetadataV4.d.ts.map +1 -0
  34. package/dist/checkout/sessionMetadataV4.js +33 -0
  35. package/dist/checkout/sessionMetadataV4.js.map +1 -0
  36. package/dist/checkout/sessionMetadataV5.d.ts +46 -0
  37. package/dist/checkout/sessionMetadataV5.d.ts.map +1 -0
  38. package/dist/checkout/sessionMetadataV5.js +40 -0
  39. package/dist/checkout/sessionMetadataV5.js.map +1 -0
  40. package/dist/errors/pickLocalizedApiMessage.d.ts +6 -0
  41. package/dist/errors/pickLocalizedApiMessage.d.ts.map +1 -0
  42. package/dist/errors/pickLocalizedApiMessage.js +31 -0
  43. package/dist/errors/pickLocalizedApiMessage.js.map +1 -0
  44. package/dist/hooks/scannerCameraConstraints.d.ts +57 -0
  45. package/dist/hooks/scannerCameraConstraints.d.ts.map +1 -0
  46. package/dist/hooks/scannerCameraConstraints.js +195 -0
  47. package/dist/hooks/scannerCameraConstraints.js.map +1 -0
  48. package/dist/hooks/scannerFormats.d.ts +11 -0
  49. package/dist/hooks/scannerFormats.d.ts.map +1 -0
  50. package/dist/hooks/scannerFormats.js +39 -0
  51. package/dist/hooks/scannerFormats.js.map +1 -0
  52. package/dist/hooks/scannerNativeTypes.d.ts +18 -0
  53. package/dist/hooks/scannerNativeTypes.d.ts.map +1 -0
  54. package/dist/hooks/scannerNativeTypes.js +2 -0
  55. package/dist/hooks/scannerNativeTypes.js.map +1 -0
  56. package/dist/hooks/scannerPlatformProfile.d.ts +23 -0
  57. package/dist/hooks/scannerPlatformProfile.d.ts.map +1 -0
  58. package/dist/hooks/scannerPlatformProfile.js +86 -0
  59. package/dist/hooks/scannerPlatformProfile.js.map +1 -0
  60. package/dist/hooks/scannerScanPasses.d.ts +23 -0
  61. package/dist/hooks/scannerScanPasses.d.ts.map +1 -0
  62. package/dist/hooks/scannerScanPasses.js +66 -0
  63. package/dist/hooks/scannerScanPasses.js.map +1 -0
  64. package/dist/hooks/selectEngine.d.ts +14 -0
  65. package/dist/hooks/selectEngine.d.ts.map +1 -0
  66. package/dist/hooks/selectEngine.js +2 -0
  67. package/dist/hooks/selectEngine.js.map +1 -0
  68. package/dist/hooks/zxingJsSensitiveDecode.d.ts +13 -0
  69. package/dist/hooks/zxingJsSensitiveDecode.d.ts.map +1 -0
  70. package/dist/hooks/zxingJsSensitiveDecode.js +54 -0
  71. package/dist/hooks/zxingJsSensitiveDecode.js.map +1 -0
  72. package/dist/labels/localizedNameMap.d.ts +37 -0
  73. package/dist/ui/FormField/FormField.js +2 -2
  74. package/dist/ui/FormField/FormField.js.map +1 -1
  75. package/package.json +3 -2
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Read-only v5 session-metadata contract for kiosk/customer/PWA consumers.
3
+ *
4
+ * SSOT for upgrade/merge/payment resolution: `up-backend/src/application/services/checkout/sessionMetadataCompat.ts`
5
+ * and `up-backend/src/domain/types/checkout/sessionMetadataV5.ts` (domain guard only).
6
+ * Shared package = type mirror for future consumers; kiosk/customer re-export via `pi-kiosk-shared`.
7
+ * Keep field names and optionality in sync with ADR-006 when backend evolves.
8
+ */
9
+ import type { SessionMetadataCheckoutMode, SessionMetadataCollect, SessionMetadataShopLine } from './sessionMetadataV3.js';
10
+ import type { SessionMetadataLoyaltyV4 } from './sessionMetadataV4.js';
11
+ export type PromoStackingMode = 'EXCLUSIVE' | 'STACK_PROMO_THEN_LOYALTY';
12
+ /**
13
+ * How the activated promo reward entered checkout.
14
+ * MANUAL_CODE = typed apply-code path (reward metadata.source mirror).
15
+ * WALLET_REWARD = customer/kiosk wallet activate path.
16
+ */
17
+ export type PromoActivationSource = 'MANUAL_CODE' | 'WALLET_REWARD';
18
+ export interface SessionMetadataShopV5 {
19
+ salesPointId: number;
20
+ lines: SessionMetadataShopLine[];
21
+ }
22
+ export interface SessionMetadataPromotionsV5 {
23
+ readonly activatedPromoRewardId?: string | null;
24
+ readonly stackingMode?: PromoStackingMode;
25
+ readonly activatedAt?: string | null;
26
+ readonly ruleVersionId?: string | null;
27
+ /** Typed apply-code vs wallet activation (plan MANUAL_CODE instrument bridge). */
28
+ readonly source?: PromoActivationSource | null;
29
+ /** Bound promo event when known (display / AUTO_DEAL suppress). */
30
+ readonly eventId?: string | null;
31
+ }
32
+ export interface SessionMetadataEnvelopeV5 {
33
+ version: 5;
34
+ collect?: SessionMetadataCollect;
35
+ checkoutMode?: SessionMetadataCheckoutMode;
36
+ shop?: SessionMetadataShopV5;
37
+ loyalty?: SessionMetadataLoyaltyV4;
38
+ promotions?: SessionMetadataPromotionsV5;
39
+ }
40
+ export declare function isSessionMetadataV5(value: unknown): value is SessionMetadataEnvelopeV5;
41
+ /** Channel/mode matrix — throws on invalid combinations (inherits v4 rules). */
42
+ export declare function assertSessionMetadataV5ChannelRules(envelope: SessionMetadataEnvelopeV5): void;
43
+ export declare function upgradeSessionMetadataV4ToV5(envelope: {
44
+ version: 4;
45
+ } & Omit<SessionMetadataEnvelopeV5, 'version'>): SessionMetadataEnvelopeV5;
46
+ //# sourceMappingURL=sessionMetadataV5.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionMetadataV5.d.ts","sourceRoot":"","sources":["../../src/checkout/sessionMetadataV5.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,0BAA0B,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,eAAe,CAAC;AAEpE,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,uBAAuB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC/C,mEAAmE;IACnE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,YAAY,CAAC,EAAE,2BAA2B,CAAC;IAC3C,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC,UAAU,CAAC,EAAE,2BAA2B,CAAC;CAC1C;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,yBAAyB,CAMtF;AAED,gFAAgF;AAChF,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI,CA+B7F;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,GAAG,IAAI,CAAC,yBAAyB,EAAE,SAAS,CAAC,GACpE,yBAAyB,CAM3B"}
@@ -0,0 +1,40 @@
1
+ export function isSessionMetadataV5(value) {
2
+ return (typeof value === 'object' &&
3
+ value !== null &&
4
+ value.version === 5);
5
+ }
6
+ /** Channel/mode matrix — throws on invalid combinations (inherits v4 rules). */
7
+ export function assertSessionMetadataV5ChannelRules(envelope) {
8
+ const mode = envelope.checkoutMode;
9
+ if (mode === undefined) {
10
+ return;
11
+ }
12
+ if (mode.channel === 'MOBILE_FIRST' &&
13
+ mode.selectedMode !== 'PREPAY_COLLECT_LATER' &&
14
+ mode.selectedMode !== 'PAY_NOW_SELF_SERVICE') {
15
+ throw new Error('SESSION_METADATA_V5_MOBILE_MODE_INVALID');
16
+ }
17
+ if (mode.channel === 'KIOSK_FIRST' && mode.selectedMode === 'PREPAY_COLLECT_LATER') {
18
+ throw new Error('SESSION_METADATA_V5_KIOSK_MODE_INVALID');
19
+ }
20
+ if (envelope.collect !== undefined) {
21
+ if (mode.channel === 'MOBILE_FIRST' &&
22
+ mode.selectedMode === 'PREPAY_COLLECT_LATER' &&
23
+ envelope.collect.timing !== 'LATER') {
24
+ throw new Error('SESSION_METADATA_V5_MOBILE_COLLECT_TIMING_INVALID');
25
+ }
26
+ if (mode.channel === 'MOBILE_FIRST' &&
27
+ mode.selectedMode === 'PAY_NOW_SELF_SERVICE' &&
28
+ envelope.collect.timing !== 'NOW') {
29
+ throw new Error('SESSION_METADATA_V5_MOBILE_COLLECT_TIMING_INVALID');
30
+ }
31
+ }
32
+ }
33
+ export function upgradeSessionMetadataV4ToV5(envelope) {
34
+ return {
35
+ ...envelope,
36
+ version: 5,
37
+ promotions: envelope.promotions ?? {},
38
+ };
39
+ }
40
+ //# sourceMappingURL=sessionMetadataV5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionMetadataV5.js","sourceRoot":"","sources":["../../src/checkout/sessionMetadataV5.ts"],"names":[],"mappings":"AAiDA,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAAmC,CAAC,OAAO,KAAK,CAAC,CACnD,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,mCAAmC,CAAC,QAAmC;IACrF,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,IACE,IAAI,CAAC,OAAO,KAAK,cAAc;QAC/B,IAAI,CAAC,YAAY,KAAK,sBAAsB;QAC5C,IAAI,CAAC,YAAY,KAAK,sBAAsB,EAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,aAAa,IAAI,IAAI,CAAC,YAAY,KAAK,sBAAsB,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,IACE,IAAI,CAAC,OAAO,KAAK,cAAc;YAC/B,IAAI,CAAC,YAAY,KAAK,sBAAsB;YAC5C,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,OAAO,EACnC,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,IACE,IAAI,CAAC,OAAO,KAAK,cAAc;YAC/B,IAAI,CAAC,YAAY,KAAK,sBAAsB;YAC5C,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK,EACjC,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,QAAqE;IAErE,OAAO;QACL,GAAG,QAAQ;QACX,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,EAAE;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Pick one language from CS-first API messages shaped as `CS / EN` or `CS / SK / EN`.
3
+ * Non-matching strings (no slash segments, or >3 parts) are returned unchanged.
4
+ */
5
+ export declare function pickLocalizedApiMessage(message: string, locale: string | undefined): string;
6
+ //# sourceMappingURL=pickLocalizedApiMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pickLocalizedApiMessage.d.ts","sourceRoot":"","sources":["../../src/errors/pickLocalizedApiMessage.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CA2BR"}
@@ -0,0 +1,31 @@
1
+ import { normalizeLabelLocale } from '../labels/localizedLabel.js';
2
+ /**
3
+ * Pick one language from CS-first API messages shaped as `CS / EN` or `CS / SK / EN`.
4
+ * Non-matching strings (no slash segments, or >3 parts) are returned unchanged.
5
+ */
6
+ export function pickLocalizedApiMessage(message, locale) {
7
+ const trimmed = message.trim();
8
+ if (trimmed.length === 0) {
9
+ return message;
10
+ }
11
+ const parts = trimmed.split(' / ').map((part) => part.trim()).filter((part) => part.length > 0);
12
+ if (parts.length < 2 || parts.length > 3) {
13
+ return message;
14
+ }
15
+ const loc = normalizeLabelLocale(locale);
16
+ if (parts.length === 3) {
17
+ if (loc === 'cs') {
18
+ return parts[0];
19
+ }
20
+ if (loc === 'sk') {
21
+ return parts[1];
22
+ }
23
+ return parts[2];
24
+ }
25
+ // Legacy bilingual `CS / EN`
26
+ if (loc === 'en') {
27
+ return parts[1];
28
+ }
29
+ return parts[0];
30
+ }
31
+ //# sourceMappingURL=pickLocalizedApiMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pickLocalizedApiMessage.js","sourceRoot":"","sources":["../../src/errors/pickLocalizedApiMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,6BAA6B,CAAC;AAErF;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAe,EACf,MAA0B;IAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChG,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,GAAG,GAAgB,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC;QACnB,CAAC;QACD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC;QACnB,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC;IACnB,CAAC;IAED,6BAA6B;IAC7B,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * High-sensitivity camera constraints for live barcode / QR decode.
3
+ * Prefer rear camera + high ideal resolution so small symbols fill pixels.
4
+ *
5
+ * Do not set hard `min` width/height - Android Chrome often rejects those with
6
+ * OverconstrainedError. Some Android builds also surface soft-constraint failure
7
+ * as NotAllowedError; the ladder retries NotAllowed only until the final
8
+ * `video: true` rung (a true user deny there is not retried).
9
+ */
10
+ export declare const SCANNER_VIDEO_CONSTRAINTS: MediaTrackConstraints;
11
+ /**
12
+ * Progressive getUserMedia ladder for mobile browsers.
13
+ * Soften resolution first, then facingMode-only, then any camera.
14
+ */
15
+ export declare const SCANNER_VIDEO_CONSTRAINT_FALLBACKS: ReadonlyArray<MediaTrackConstraints | true>;
16
+ /**
17
+ * Optical zoom policy for scanner tracks: use the device's capability max
18
+ * (not a hard 2x ceiling). Documented for callers; resolution is via
19
+ * resolvePreferredOpticalZoom.
20
+ */
21
+ export declare const SCANNER_OPTICAL_ZOOM_POLICY: "max";
22
+ /**
23
+ * Resolve preferred optical zoom from MediaTrackCapabilities.zoom bounds.
24
+ * Targets device max (G2) - no fixed 2x ceiling. Snaps down to a valid step
25
+ * when `step` is provided.
26
+ */
27
+ export declare function resolvePreferredOpticalZoom(min: number, max: number, step?: number): number;
28
+ /**
29
+ * Midpoint zoom for a stepped ladder toward max (G4 distance lever).
30
+ * Snaps to step when provided.
31
+ */
32
+ export declare function resolveMidOpticalZoom(min: number, maxTarget: number, step?: number): number;
33
+ /**
34
+ * Open a camera stream with progressive constraint fallbacks.
35
+ *
36
+ * Overconstrained / NotFound / NotReadable / Abort -> next rung.
37
+ * NotAllowedError -> next rung only while `video` is not yet the final `true`
38
+ * (any-camera) rung; on that last rung NotAllowed is a real deny and is rethrown.
39
+ * Other failures (SecurityError, etc.) are rethrown immediately.
40
+ */
41
+ export declare function openScannerMediaStream(getUserMedia: MediaDevices['getUserMedia']): Promise<MediaStream>;
42
+ /**
43
+ * Best-effort continuous autofocus + torch after getUserMedia.
44
+ * Optical zoom is NOT applied here — max zoom on open blurs/crops close barcodes
45
+ * (camera shows a sharp code but @zxing never locks). The hook applies
46
+ * {@link applyScannerDistanceZoom} only after multi-pass has already started
47
+ * (second assist window), never at open and never at the first assist tick.
48
+ */
49
+ export declare function applyScannerTrackEnhancements(track: MediaStreamTrack): Promise<void>;
50
+ /**
51
+ * Delayed distance lever (G2/G4): mid → max optical zoom from capabilities.
52
+ * Hook policy: call only after SCANNER_DISTANCE_ASSIST_DELAY_MS (multi-pass first)
53
+ * plus SCANNER_DISTANCE_ZOOM_DELAY_MS — never on open and never at the first
54
+ * assist tick, so close codes with slow AF are not forced into max zoom.
55
+ */
56
+ export declare function applyScannerDistanceZoom(track: MediaStreamTrack): Promise<void>;
57
+ //# sourceMappingURL=scannerCameraConstraints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerCameraConstraints.d.ts","sourceRoot":"","sources":["../../src/hooks/scannerCameraConstraints.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,qBAKvC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kCAAkC,EAAE,aAAa,CAAC,qBAAqB,GAAG,IAAI,CAS1F,CAAC;AAqBF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAG,KAAc,CAAC;AAE1D;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CASR;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CAWR;AAmBD;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,GACzC,OAAO,CAAC,WAAW,CAAC,CAqBtB;AAED;;;;;;GAMG;AACH,wBAAsB,6BAA6B,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4B1F;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDrF"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * High-sensitivity camera constraints for live barcode / QR decode.
3
+ * Prefer rear camera + high ideal resolution so small symbols fill pixels.
4
+ *
5
+ * Do not set hard `min` width/height - Android Chrome often rejects those with
6
+ * OverconstrainedError. Some Android builds also surface soft-constraint failure
7
+ * as NotAllowedError; the ladder retries NotAllowed only until the final
8
+ * `video: true` rung (a true user deny there is not retried).
9
+ */
10
+ export const SCANNER_VIDEO_CONSTRAINTS = {
11
+ facingMode: { ideal: 'environment' },
12
+ width: { ideal: 1920 },
13
+ height: { ideal: 1080 },
14
+ frameRate: { ideal: 30 },
15
+ };
16
+ /**
17
+ * Progressive getUserMedia ladder for mobile browsers.
18
+ * Soften resolution first, then facingMode-only, then any camera.
19
+ */
20
+ export const SCANNER_VIDEO_CONSTRAINT_FALLBACKS = [
21
+ SCANNER_VIDEO_CONSTRAINTS,
22
+ {
23
+ facingMode: { ideal: 'environment' },
24
+ width: { ideal: 1280 },
25
+ height: { ideal: 720 },
26
+ },
27
+ { facingMode: { ideal: 'environment' } },
28
+ true,
29
+ ];
30
+ /**
31
+ * Optical zoom policy for scanner tracks: use the device's capability max
32
+ * (not a hard 2x ceiling). Documented for callers; resolution is via
33
+ * resolvePreferredOpticalZoom.
34
+ */
35
+ export const SCANNER_OPTICAL_ZOOM_POLICY = 'max';
36
+ /**
37
+ * Resolve preferred optical zoom from MediaTrackCapabilities.zoom bounds.
38
+ * Targets device max (G2) - no fixed 2x ceiling. Snaps down to a valid step
39
+ * when `step` is provided.
40
+ */
41
+ export function resolvePreferredOpticalZoom(min, max, step) {
42
+ if (!(max > min)) {
43
+ return min;
44
+ }
45
+ if (step !== undefined && step > 0) {
46
+ const stepsFromMin = Math.floor((max - min) / step + Number.EPSILON);
47
+ return min + stepsFromMin * step;
48
+ }
49
+ return max;
50
+ }
51
+ /**
52
+ * Midpoint zoom for a stepped ladder toward max (G4 distance lever).
53
+ * Snaps to step when provided.
54
+ */
55
+ export function resolveMidOpticalZoom(min, maxTarget, step) {
56
+ if (!(maxTarget > min)) {
57
+ return min;
58
+ }
59
+ const mid = (min + maxTarget) / 2;
60
+ if (step !== undefined && step > 0) {
61
+ const stepsFromMin = Math.round((mid - min) / step);
62
+ const snapped = min + stepsFromMin * step;
63
+ return Math.min(maxTarget, Math.max(min, snapped));
64
+ }
65
+ return mid;
66
+ }
67
+ function isConstraintRetryableError(err) {
68
+ if (!(err instanceof DOMException)) {
69
+ return false;
70
+ }
71
+ return (err.name === 'OverconstrainedError' ||
72
+ err.name === 'ConstraintNotSatisfiedError' ||
73
+ err.name === 'NotFoundError' ||
74
+ err.name === 'NotReadableError' ||
75
+ err.name === 'AbortError');
76
+ }
77
+ function isNotAllowedError(err) {
78
+ return err instanceof DOMException && err.name === 'NotAllowedError';
79
+ }
80
+ /**
81
+ * Open a camera stream with progressive constraint fallbacks.
82
+ *
83
+ * Overconstrained / NotFound / NotReadable / Abort -> next rung.
84
+ * NotAllowedError -> next rung only while `video` is not yet the final `true`
85
+ * (any-camera) rung; on that last rung NotAllowed is a real deny and is rethrown.
86
+ * Other failures (SecurityError, etc.) are rethrown immediately.
87
+ */
88
+ export async function openScannerMediaStream(getUserMedia) {
89
+ let lastError;
90
+ for (let i = 0; i < SCANNER_VIDEO_CONSTRAINT_FALLBACKS.length; i++) {
91
+ const video = SCANNER_VIDEO_CONSTRAINT_FALLBACKS[i];
92
+ try {
93
+ return await getUserMedia({ video, audio: false });
94
+ }
95
+ catch (err) {
96
+ lastError = err;
97
+ if (isConstraintRetryableError(err)) {
98
+ continue;
99
+ }
100
+ // Soft-constraint NotAllowed: retry until final any-camera rung only.
101
+ if (isNotAllowedError(err) && video !== true) {
102
+ continue;
103
+ }
104
+ throw err;
105
+ }
106
+ }
107
+ throw lastError instanceof Error
108
+ ? lastError
109
+ : new Error('Could not open scanner camera', { cause: lastError });
110
+ }
111
+ /**
112
+ * Best-effort continuous autofocus + torch after getUserMedia.
113
+ * Optical zoom is NOT applied here — max zoom on open blurs/crops close barcodes
114
+ * (camera shows a sharp code but @zxing never locks). The hook applies
115
+ * {@link applyScannerDistanceZoom} only after multi-pass has already started
116
+ * (second assist window), never at open and never at the first assist tick.
117
+ */
118
+ export async function applyScannerTrackEnhancements(track) {
119
+ const getCapabilities = track.getCapabilities;
120
+ if (getCapabilities === undefined) {
121
+ return;
122
+ }
123
+ const capabilities = getCapabilities.call(track);
124
+ const hasContinuousFocus = capabilities.focusMode?.includes('continuous') === true;
125
+ const hasTorch = capabilities.torch === true;
126
+ if (!hasContinuousFocus && !hasTorch) {
127
+ return;
128
+ }
129
+ const advanced = [];
130
+ if (hasContinuousFocus) {
131
+ advanced.push({ focusMode: 'continuous' });
132
+ }
133
+ if (hasTorch) {
134
+ advanced.push({ torch: true });
135
+ }
136
+ try {
137
+ const next = { advanced };
138
+ await track.applyConstraints(next);
139
+ }
140
+ catch {
141
+ // Device rejected advanced focus/torch — keep the stream as opened.
142
+ }
143
+ }
144
+ /**
145
+ * Delayed distance lever (G2/G4): mid → max optical zoom from capabilities.
146
+ * Hook policy: call only after SCANNER_DISTANCE_ASSIST_DELAY_MS (multi-pass first)
147
+ * plus SCANNER_DISTANCE_ZOOM_DELAY_MS — never on open and never at the first
148
+ * assist tick, so close codes with slow AF are not forced into max zoom.
149
+ */
150
+ export async function applyScannerDistanceZoom(track) {
151
+ const getCapabilities = track.getCapabilities;
152
+ if (getCapabilities === undefined) {
153
+ return;
154
+ }
155
+ const capabilities = getCapabilities.call(track);
156
+ const zoomCap = capabilities.zoom;
157
+ if (zoomCap === undefined) {
158
+ return;
159
+ }
160
+ const zoomMin = zoomCap.min ?? 1;
161
+ const zoomMax = zoomCap.max ?? 1;
162
+ const zoomStep = zoomCap.step;
163
+ if (!(zoomMax > zoomMin)) {
164
+ return;
165
+ }
166
+ const preferredZoom = resolvePreferredOpticalZoom(zoomMin, zoomMax, zoomStep);
167
+ if (!(preferredZoom > zoomMin)) {
168
+ return;
169
+ }
170
+ const midZoom = resolveMidOpticalZoom(zoomMin, preferredZoom, zoomStep);
171
+ const useZoomLadder = midZoom > zoomMin && midZoom < preferredZoom;
172
+ try {
173
+ if (useZoomLadder) {
174
+ await track.applyConstraints({
175
+ advanced: [{ zoom: midZoom }],
176
+ });
177
+ try {
178
+ await track.applyConstraints({
179
+ advanced: [{ zoom: preferredZoom }],
180
+ });
181
+ }
182
+ catch {
183
+ // Max rejected after mid — keep mid.
184
+ }
185
+ return;
186
+ }
187
+ await track.applyConstraints({
188
+ advanced: [{ zoom: preferredZoom }],
189
+ });
190
+ }
191
+ catch {
192
+ // Zoom unsupported after open — keep current stream.
193
+ }
194
+ }
195
+ //# sourceMappingURL=scannerCameraConstraints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerCameraConstraints.js","sourceRoot":"","sources":["../../src/hooks/scannerCameraConstraints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { BarcodeFormat } from '@zxing/library';
2
+ export type BarcodeScannerFormatProfile = 'retail' | 'qr-only' | 'all';
3
+ export declare const REQUIRED_NATIVE_FORMATS_RETAIL: readonly ["code_128", "ean_13", "ean_8", "upc_a"];
4
+ export declare const REQUIRED_NATIVE_FORMATS_QR_ONLY: readonly ["qr_code"];
5
+ export declare const REQUIRED_NATIVE_FORMATS_ALL: readonly ["code_128", "ean_13", "ean_8", "upc_a", "qr_code"];
6
+ export interface ScannerFormatConfig {
7
+ readonly nativeFormats: readonly string[];
8
+ readonly zxingFormats: readonly BarcodeFormat[];
9
+ }
10
+ export declare function resolveScannerFormatConfig(formatProfile?: BarcodeScannerFormatProfile): ScannerFormatConfig;
11
+ //# sourceMappingURL=scannerFormats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerFormats.d.ts","sourceRoot":"","sources":["../../src/hooks/scannerFormats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,MAAM,2BAA2B,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;AAEvE,eAAO,MAAM,8BAA8B,mDAKjC,CAAC;AAEX,eAAO,MAAM,+BAA+B,sBAAuB,CAAC;AAEpE,eAAO,MAAM,2BAA2B,8DAG9B,CAAC;AAaX,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,YAAY,EAAE,SAAS,aAAa,EAAE,CAAC;CACjD;AAED,wBAAgB,0BAA0B,CACxC,aAAa,GAAE,2BAAsC,GACpD,mBAAmB,CAiBrB"}
@@ -0,0 +1,39 @@
1
+ import { BarcodeFormat } from '@zxing/library';
2
+ export const REQUIRED_NATIVE_FORMATS_RETAIL = [
3
+ 'code_128',
4
+ 'ean_13',
5
+ 'ean_8',
6
+ 'upc_a',
7
+ ];
8
+ export const REQUIRED_NATIVE_FORMATS_QR_ONLY = ['qr_code'];
9
+ export const REQUIRED_NATIVE_FORMATS_ALL = [
10
+ ...REQUIRED_NATIVE_FORMATS_RETAIL,
11
+ 'qr_code',
12
+ ];
13
+ const ZXING_RETAIL_FORMATS = [
14
+ BarcodeFormat.CODE_128,
15
+ BarcodeFormat.EAN_13,
16
+ BarcodeFormat.EAN_8,
17
+ BarcodeFormat.UPC_A,
18
+ ];
19
+ const ZXING_QR_ONLY_FORMATS = [BarcodeFormat.QR_CODE];
20
+ const ZXING_ALL_FORMATS = [...ZXING_RETAIL_FORMATS, BarcodeFormat.QR_CODE];
21
+ export function resolveScannerFormatConfig(formatProfile = 'retail') {
22
+ if (formatProfile === 'qr-only') {
23
+ return {
24
+ nativeFormats: REQUIRED_NATIVE_FORMATS_QR_ONLY,
25
+ zxingFormats: ZXING_QR_ONLY_FORMATS,
26
+ };
27
+ }
28
+ if (formatProfile === 'all') {
29
+ return {
30
+ nativeFormats: REQUIRED_NATIVE_FORMATS_ALL,
31
+ zxingFormats: ZXING_ALL_FORMATS,
32
+ };
33
+ }
34
+ return {
35
+ nativeFormats: REQUIRED_NATIVE_FORMATS_RETAIL,
36
+ zxingFormats: ZXING_RETAIL_FORMATS,
37
+ };
38
+ }
39
+ //# sourceMappingURL=scannerFormats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerFormats.js","sourceRoot":"","sources":["../../src/hooks/scannerFormats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI/C,MAAM,CAAC,MAAM,8BAA8B,GAAG;IAC5C,UAAU;IACV,QAAQ;IACR,OAAO;IACP,OAAO;CACC,CAAC;AAEX,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,SAAS,CAAU,CAAC;AAEpE,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,GAAG,8BAA8B;IACjC,SAAS;CACD,CAAC;AAEX,MAAM,oBAAoB,GAAoB;IAC5C,aAAa,CAAC,QAAQ;IACtB,aAAa,CAAC,MAAM;IACpB,aAAa,CAAC,KAAK;IACnB,aAAa,CAAC,KAAK;CACpB,CAAC;AAEF,MAAM,qBAAqB,GAAoB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvE,MAAM,iBAAiB,GAAoB,CAAC,GAAG,oBAAoB,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;AAO5F,MAAM,UAAU,0BAA0B,CACxC,gBAA6C,QAAQ;IAErD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO;YACL,aAAa,EAAE,+BAA+B;YAC9C,YAAY,EAAE,qBAAqB;SACpC,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;QAC5B,OAAO;YACL,aAAa,EAAE,2BAA2B;YAC1C,YAAY,EAAE,iBAAiB;SAChC,CAAC;IACJ,CAAC;IACD,OAAO;QACL,aAAa,EAAE,8BAA8B;QAC7C,YAAY,EAAE,oBAAoB;KACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface NativeBarcodeDetector {
2
+ detect: (source: CanvasImageSource) => Promise<Array<{
3
+ rawValue: string;
4
+ }>>;
5
+ }
6
+ export interface NativeBarcodeDetectorConstructor {
7
+ new (init?: {
8
+ formats?: string[];
9
+ }): NativeBarcodeDetector;
10
+ getSupportedFormats: () => Promise<string[]>;
11
+ }
12
+ declare global {
13
+ interface Window {
14
+ BarcodeDetector?: NativeBarcodeDetectorConstructor;
15
+ }
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=scannerNativeTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerNativeTypes.d.ts","sourceRoot":"","sources":["../../src/hooks/scannerNativeTypes.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,gCAAgC;IAC/C,KAAK,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,qBAAqB,CAAC;IAC3D,mBAAmB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC9C;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,eAAe,CAAC,EAAE,gCAAgC,CAAC;KACpD;CACF;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scannerNativeTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerNativeTypes.js","sourceRoot":"","sources":["../../src/hooks/scannerNativeTypes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Platform-specific scanner engine ordering and UX hints.
3
+ * Firefox: ZBar WASM + @zxing only — no @undecaf/barcode-detector-polyfill package.
4
+ */
5
+ export type ScannerPlatformProfileId = 'chrome-android' | 'chrome-desktop' | 'ios-safari' | 'crios-ios' | 'firefox-desktop' | 'generic';
6
+ export interface ScannerPlatformProfile {
7
+ readonly id: ScannerPlatformProfileId;
8
+ /** Prefer preview snap CTA over live-only decode (PC webcams). */
9
+ readonly preferPreviewSnap: boolean;
10
+ /** Run Chromium BarcodeDetector when probe succeeds. */
11
+ readonly nativeEnabled: boolean;
12
+ /** ZBar full pass every frame (desktop); mobile uses budget backoff in hook. */
13
+ readonly zbarFullPassEveryFrame: boolean;
14
+ /** @zxing assist starts on frame 0 (always true in v2.2). */
15
+ readonly zxingFrameZero: boolean;
16
+ }
17
+ /**
18
+ * Resolve scanner platform profile from UA + feature hints.
19
+ * Safe in SSR (returns `generic`).
20
+ */
21
+ export declare function resolveScannerPlatformProfile(): ScannerPlatformProfile;
22
+ export { resolveScannerPlatformProfile as getScannerPlatformProfile };
23
+ //# sourceMappingURL=scannerPlatformProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerPlatformProfile.d.ts","sourceRoot":"","sources":["../../src/hooks/scannerPlatformProfile.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,wBAAwB,GAChC,gBAAgB,GAChB,gBAAgB,GAChB,YAAY,GACZ,WAAW,GACX,iBAAiB,GACjB,SAAS,CAAC;AAEd,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,kEAAkE;IAClE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,wDAAwD;IACxD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAsBD;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,sBAAsB,CAyDtE;AAYD,OAAO,EAAE,6BAA6B,IAAI,yBAAyB,EAAE,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Platform-specific scanner engine ordering and UX hints.
3
+ * Firefox: ZBar WASM + @zxing only — no @undecaf/barcode-detector-polyfill package.
4
+ */
5
+ function isIosDevice(ua) {
6
+ return /iPad|iPhone|iPod/.test(ua) || (ua.includes('Mac') && typeof document !== 'undefined' && 'ontouchend' in document);
7
+ }
8
+ function isCriOs(ua) {
9
+ return /CriOS/.test(ua);
10
+ }
11
+ function isFirefox(ua) {
12
+ return /Firefox\//.test(ua) && !/Seamonkey|Waterfox/.test(ua);
13
+ }
14
+ function isChromeDesktop(ua) {
15
+ return /Chrome\//.test(ua) && !/Edg\/|OPR\/|CriOS|Mobile/.test(ua);
16
+ }
17
+ function isChromeAndroid(ua) {
18
+ return /Android/.test(ua) && /Chrome\//.test(ua) && !/Edg\//.test(ua);
19
+ }
20
+ /**
21
+ * Resolve scanner platform profile from UA + feature hints.
22
+ * Safe in SSR (returns `generic`).
23
+ */
24
+ export function resolveScannerPlatformProfile() {
25
+ if (typeof navigator === 'undefined') {
26
+ return genericProfile();
27
+ }
28
+ const ua = navigator.userAgent;
29
+ if (isFirefox(ua)) {
30
+ return {
31
+ id: 'firefox-desktop',
32
+ preferPreviewSnap: true,
33
+ nativeEnabled: false,
34
+ zbarFullPassEveryFrame: true,
35
+ zxingFrameZero: true,
36
+ };
37
+ }
38
+ if (isCriOs(ua) && isIosDevice(ua)) {
39
+ return {
40
+ id: 'crios-ios',
41
+ preferPreviewSnap: false,
42
+ nativeEnabled: false,
43
+ zbarFullPassEveryFrame: false,
44
+ zxingFrameZero: true,
45
+ };
46
+ }
47
+ if (isIosDevice(ua)) {
48
+ return {
49
+ id: 'ios-safari',
50
+ preferPreviewSnap: false,
51
+ nativeEnabled: false,
52
+ zbarFullPassEveryFrame: false,
53
+ zxingFrameZero: true,
54
+ };
55
+ }
56
+ if (isChromeDesktop(ua)) {
57
+ return {
58
+ id: 'chrome-desktop',
59
+ preferPreviewSnap: true,
60
+ nativeEnabled: true,
61
+ zbarFullPassEveryFrame: true,
62
+ zxingFrameZero: true,
63
+ };
64
+ }
65
+ if (isChromeAndroid(ua)) {
66
+ return {
67
+ id: 'chrome-android',
68
+ preferPreviewSnap: false,
69
+ nativeEnabled: true,
70
+ zbarFullPassEveryFrame: true,
71
+ zxingFrameZero: true,
72
+ };
73
+ }
74
+ return genericProfile();
75
+ }
76
+ function genericProfile() {
77
+ return {
78
+ id: 'generic',
79
+ preferPreviewSnap: false,
80
+ nativeEnabled: typeof window !== 'undefined' && window.BarcodeDetector !== undefined,
81
+ zbarFullPassEveryFrame: false,
82
+ zxingFrameZero: true,
83
+ };
84
+ }
85
+ export { resolveScannerPlatformProfile as getScannerPlatformProfile };
86
+ //# sourceMappingURL=scannerPlatformProfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scannerPlatformProfile.js","sourceRoot":"","sources":["../../src/hooks/scannerPlatformProfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Digital-zoom scan regions for distant / small barcodes.
3
+ * Used by the pure-JS @zxing multi-pass decoder.
4
+ */
5
+ export interface ScanPass {
6
+ readonly sx: number;
7
+ readonly sy: number;
8
+ readonly sw: number;
9
+ readonly sh: number;
10
+ /** Upscale factor when drawing the crop into the decode canvas. */
11
+ readonly scale: number;
12
+ }
13
+ /**
14
+ * Full frame + center zooms + mid-band (1D) + four corner crops + optional tight center.
15
+ * Covers off-center / distant codes that are not in the viewfinder center.
16
+ *
17
+ * CPU bound: at most 10 passes (1 full + 3 center + 1 mid-band + 4 corners + 1 tight center).
18
+ * Do not add more regions without raising this documented ceiling (~10–12 max).
19
+ */
20
+ /** Full-frame only — cheap first pass (~1 crop per tick; G9 CPU bound). */
21
+ export declare function buildQuickScanPass(videoWidth: number, videoHeight: number): ScanPass[];
22
+ export declare function buildMaxSensitivityScanPasses(videoWidth: number, videoHeight: number): ScanPass[];
23
+ //# sourceMappingURL=scannerScanPasses.d.ts.map