{"version":3,"file":"barcode.cjs","names":[],"sources":["../../src/capture/barcode.ts"],"sourcesContent":["/**\n * Symbologies the `BarcodeDetector` API names.\n *\n * Three of them carry the weight in Brazil: `ean_13` is the retail barcode on every\n * packaged product, `qr_code` is what a Pix \"copia e cola\" payload travels in, and\n * `code_128` is the label on a shipment. The rest are here because the spec has them\n * and asking for one costs nothing.\n */\nexport type BarcodeFormat =\n    | \"aztec\"\n    | \"codabar\"\n    | \"code_128\"\n    | \"code_39\"\n    | \"code_93\"\n    | \"data_matrix\"\n    | \"ean_13\"\n    | \"ean_8\"\n    | \"itf\"\n    | \"pdf417\"\n    | \"qr_code\"\n    | \"upc_a\"\n    | \"upc_e\"\n    | \"unknown\";\n\n/** Every symbology in the spec, used to validate what a detector reports back. */\nexport const ALL_BARCODE_FORMATS: readonly BarcodeFormat[] = [\n    \"aztec\",\n    \"codabar\",\n    \"code_128\",\n    \"code_39\",\n    \"code_93\",\n    \"data_matrix\",\n    \"ean_13\",\n    \"ean_8\",\n    \"itf\",\n    \"pdf417\",\n    \"qr_code\",\n    \"upc_a\",\n    \"upc_e\",\n    \"unknown\",\n];\n\n/**\n * What a scanner looks for when you do not say.\n *\n * Deliberately three formats, not all fourteen. Every extra symbology is more work\n * per frame, and on a mid-range phone the difference between three and fourteen is the\n * difference between a scanner that locks on instantly and one that feels broken.\n */\nexport const DEFAULT_BARCODE_FORMATS: readonly BarcodeFormat[] = [\"qr_code\", \"ean_13\", \"code_128\"];\n\n/** A corner of a detected symbol, in the source's pixel coordinates. */\nexport interface BarcodePoint {\n    x: number;\n    y: number;\n}\n\n/** One decoded symbol, normalised. */\nexport interface BarcodeScanResult {\n    /** The decoded payload — a GTIN, a URL, a Pix BR Code. */\n    rawValue: string;\n    /** Which symbology it was read as. `\"unknown\"` when the engine does not say. */\n    format: BarcodeFormat;\n    /** Box in source pixels, or `null` when the engine reports none. */\n    boundingBox: DOMRectReadOnly | null;\n    /** Corners in source pixels, clockwise from top-left. Empty when unreported. */\n    cornerPoints: readonly BarcodePoint[];\n}\n\n/**\n * The shape a detector resolves with, before normalisation.\n *\n * Every field is optional because a polyfill is allowed to report the value and no\n * geometry at all, and the native engines differ on `cornerPoints`.\n */\nexport interface DetectedBarcodeLike {\n    rawValue?: string;\n    format?: string;\n    boundingBox?: DOMRectReadOnly;\n    cornerPoints?: readonly BarcodePoint[];\n}\n\n/**\n * The slice of `BarcodeDetector` this SDK uses.\n *\n * Exported so a consumer can **inject a polyfill** where the native API is missing —\n * see {@link isBarcodeDetectionSupported} for why that matters — and so tests can hand\n * in a decoder without a camera. Anything with a `detect()` that resolves to objects\n * carrying a `rawValue` will do.\n */\nexport interface BarcodeDetectorLike {\n    /**\n     * Decode every symbol visible in the source.\n     *\n     * @param source - A `<video>`, a `<canvas>`, an `ImageBitmap`, a `Blob`…\n     * @returns Every symbol found, or an empty array — finding nothing is not an error.\n     */\n    detect: (source: ImageBitmapSource) => Promise<readonly DetectedBarcodeLike[]>;\n}\n\n/** The constructor, as Chromium exposes it on the global scope. */\ninterface BarcodeDetectorConstructorLike {\n    new (options?: { formats?: readonly string[] }): BarcodeDetectorLike;\n    getSupportedFormats?: () => Promise<readonly string[]>;\n}\n\n/**\n * Read the constructor off the global scope, or `null` when the engine has none.\n *\n * Kept private: everything a consumer needs is covered by\n * {@link isBarcodeDetectionSupported}, {@link getSupportedBarcodeFormats} and\n * {@link createBarcodeDetector}.\n */\nfunction barcodeDetectorConstructor(): BarcodeDetectorConstructorLike | null {\n    const candidate = (globalThis as { BarcodeDetector?: unknown }).BarcodeDetector;\n    return typeof candidate === \"function\" ? (candidate as BarcodeDetectorConstructorLike) : null;\n}\n\n/**\n * Whether this browser can decode barcodes on its own.\n *\n * **Expect `false` on a lot of real devices, and design for it.** `BarcodeDetector` is\n * a Chromium-only API backed by a platform decoder, so it is there on Android and\n * ChromeOS, usually there on macOS, and **absent** on Chromium for Windows and Linux,\n * in Firefox, and in every browser on iOS (all of which are WebKit underneath,\n * including Chrome for iOS).\n *\n * This SDK ships **no** decoder of its own and no bundled fallback: a QR reader is\n * Reed–Solomon error correction plus perspective correction plus a finder-pattern\n * search, and the honest options are a WASM build every consumer of this SDK would pay\n * for, or nothing. So the escape hatch is injection instead — pass any\n * {@link BarcodeDetectorLike} (the `barcode-detector` polyfill, your own `zxing-wasm`\n * wrapper) as `detector` to `useBarcodeScanner`, and the SDK drives it exactly like\n * the native one.\n *\n * @returns `true` when `new BarcodeDetector()` will work.\n */\nexport function isBarcodeDetectionSupported(): boolean {\n    return barcodeDetectorConstructor() !== null;\n}\n\n/**\n * Which symbologies this engine will actually decode.\n *\n * Worth asking rather than assuming: the format list belongs to the platform decoder,\n * not to the browser, so two Chromium builds on two operating systems answer\n * differently — and asking for a format the engine does not have makes the constructor\n * throw `NotSupportedError`, which reads like a bug in your code.\n *\n * @returns The supported formats, or an empty array when there is no detector.\n */\nexport async function getSupportedBarcodeFormats(): Promise<readonly BarcodeFormat[]> {\n    const constructor = barcodeDetectorConstructor();\n    if (!constructor || typeof constructor.getSupportedFormats !== \"function\") return [];\n    try {\n        const formats = await constructor.getSupportedFormats();\n        return formats.filter((format): format is BarcodeFormat =>\n            ALL_BARCODE_FORMATS.includes(format as BarcodeFormat),\n        );\n    } catch {\n        return [];\n    }\n}\n\n/**\n * Build a native detector for the given formats.\n *\n * @param formats - Symbologies to look for. Must be ones the engine supports.\n * @returns The detector, or `null` when the API is missing or refused the formats.\n */\nexport function createBarcodeDetector(\n    formats: readonly BarcodeFormat[] = DEFAULT_BARCODE_FORMATS,\n): BarcodeDetectorLike | null {\n    const constructor = barcodeDetectorConstructor();\n    if (!constructor) return null;\n    try {\n        return new constructor({ formats: [...formats] });\n    } catch {\n        return null;\n    }\n}\n\n/**\n * Turn one raw detection into a {@link BarcodeScanResult}.\n *\n * An unrecognised `format` string becomes `\"unknown\"` rather than being passed through\n * as a lie about the union, and missing geometry becomes `null`/`[]` rather than\n * `undefined`, so a consumer never has to branch on three kinds of absence.\n *\n * @param raw - What the detector resolved with.\n * @param known - The formats considered valid. Defaults to the whole spec list.\n * @returns The normalised result.\n */\nexport function normalizeBarcode(\n    raw: DetectedBarcodeLike,\n    known: readonly BarcodeFormat[] = ALL_BARCODE_FORMATS,\n): BarcodeScanResult {\n    const format = raw.format as BarcodeFormat | undefined;\n    return {\n        rawValue: raw.rawValue ?? \"\",\n        format: format !== undefined && known.includes(format) ? format : \"unknown\",\n        boundingBox: raw.boundingBox ?? null,\n        cornerPoints: raw.cornerPoints ?? [],\n    };\n}\n"],"mappings":"AAyBA,IAAa,EAAgD,CACzD,QACA,UACA,WACA,UACA,UACA,cACA,SACA,QACA,MACA,SACA,UACA,QACA,QACA,SACJ,EASa,EAAoD,CAAC,UAAW,SAAU,UAAU,EAgEjG,SAAS,GAAoE,CACzE,IAAM,EAAa,WAA6C,gBAChE,OAAO,OAAO,GAAc,WAAc,EAA+C,IAC7F,CAqBA,SAAgB,GAAuC,CACnD,OAAO,EAA2B,IAAM,IAC5C,CAYA,eAAsB,GAAgE,CAClF,IAAM,EAAc,EAA2B,EAC/C,GAAI,CAAC,GAAe,OAAO,EAAY,qBAAwB,WAAY,MAAO,CAAC,EACnF,GAAI,CAEA,OAAO,MADe,EAAY,oBAAoB,EAAA,CACvC,OAAQ,GACnB,EAAoB,SAAS,CAAuB,CACxD,CACJ,MAAQ,CACJ,MAAO,CAAC,CACZ,CACJ,CAQA,SAAgB,EACZ,EAAoC,EACV,CAC1B,IAAM,EAAc,EAA2B,EAC/C,GAAI,CAAC,EAAa,OAAO,KACzB,GAAI,CACA,OAAO,IAAI,EAAY,CAAE,QAAS,CAAC,GAAG,CAAO,CAAE,CAAC,CACpD,MAAQ,CACJ,OAAO,IACX,CACJ,CAaA,SAAgB,EACZ,EACA,EAAkC,EACjB,CACjB,IAAM,EAAS,EAAI,OACnB,MAAO,CACH,SAAU,EAAI,UAAY,GAC1B,OAAQ,IAAW,IAAA,IAAa,EAAM,SAAS,CAAM,EAAI,EAAS,UAClE,YAAa,EAAI,aAAe,KAChC,aAAc,EAAI,cAAgB,CAAC,CACvC,CACJ"}