# The barcode kit — a QR and barcode scanner you opt into

> A live camera scanner for QR codes and barcodes, shipped as an optional KIT you depend on with one line. It owns the camera and the decode loop and raises `scanned(text, format)`; your app supplies a box to draw in and an action to run. It is also the platform's proof that a control may ship a WebAssembly module.

<!-- id: ui-barcode-kit · area: ui · stability: preview · html: https://osysharp.com/reference/ui/barcode-kit/ -->

## Summary        {#summary}

The platform ships **mechanism**, never components. `Osysharp.Barcode` is a complete barcode and QR scanner built on
that mechanism, distributed as an ordinary kit — you depend on it in one line and nothing is copied into your
project:

```osy syntax
app Warehouse {
  use Osysharp.Barcode@1;
  model "model/**/*.osy";
}
```

It opens the camera, watches the picture, and raises `scanned(text, format)` when it reads a code. Everything about
*reading a symbol* — the camera, the frame loop, the decoder — is inside the control.

⚠️ **This is not the same thing as [camera and microphone](https://osysharp.com/reference/ui/capture/).** `Camera.Start()` / `Camera.Capture()` are for taking a
photograph or a recording and keeping the file. This is for reading what a picture *says* and keeping the text. An
app can use both; they do not interfere.

## Signature      {#signature}

```osy syntax
BarcodeScanner(scanned: Found)                       // everything, back camera, four looks a second
BarcodeScanner(scanned: Found, formats: qr)          // QR only — materially faster on a phone
BarcodeScanner(scanned: Found, active: armed)        // false releases the camera
```

`scanned` is an event, so it binds to an action taking `(string text, string format)`. The control has no default
size: put it in a box that has one.

## Description    {#description}

### The whole thing, at a call site   {#app-side}

```osy title="a page that reads a code and shows it" test app=ui-barcode-kit
// ⚠ This example DECLARES the control inline, because a documentation example compiles on its own with no manifest
// to carry a `use`. In your app you write `use Osysharp.Barcode@1;` instead and delete this block — the declaration
// arrives with the kit. What follows is `scan.osy`, trimmed to what this page uses.
control BarcodeScanner {
  contractVersion "1.1"
  participation headless
  props {
    bool active = true;
    [Values(any, qr, linear)] string formats = "any";
    [Values(back, front)] string facing = "back";
    int intervalMs = 250;
    int repeatAfterMs = 2000;
  }
  events {
    scanned(string text, string format);
    failed(string reason);
  }
  chunks { Core; Wasm; }
  probe { bool scanning; int scans; string? last; string? failure; }
}

[Page("/scan")] [AllowAnonymous]
component ScanPage() {
  string code = "";
  string problem = "";
  bool armed = true;

  action Found(string text, string format) { code = text; armed = false; }
  action Broke(string reason) { problem = reason; }
  action Again() { code = ""; problem = ""; armed = true; }

  render {
    Stack(gap: 3, p: 4) {
      Stack(h: "16rem") {
        BarcodeScanner(scanned: Found, failed: Broke, active: armed, formats: qr);
      }
      if (problem != "") { Text(problem); }
      if (code != "") {
        Text(code);
        Button("Scan another", onPress: Again);
      }
    }
  }
}
```

Note `active: armed`. A scanner that cannot be switched off is a camera that is always on — turning it off after a
read is both the polite thing and the thing that puts the browser's recording indicator out.

### `repeatAfterMs` is the prop that makes it usable   {#repeats}

A label held in front of the camera is read on **every** pass — four times a second at the default interval. So the
same text is reported once and then suppressed for `repeatAfterMs` (2 seconds by default). Without that, one label
held for ten seconds produces forty events, and an app that appends a row per scan collects forty rows.

Set it to `0` if you genuinely want every read — a counter, or a diagnostic.

### Narrowing `formats` is a real speed-up   {#formats}

| value | what it looks for |
|---|---|
| `any` | every format the decoder knows |
| `qr` | QR and Micro QR |
| `linear` | the retail and logistics 1-D family — EAN, UPC, Code 39/93/128, ITF, Codabar, DataBar |

The decoder spends time proportional to how many families it must try, so `qr` on a phone is noticeably faster than
`any`. `format` on the `scanned` event names the exact symbology it found (`QRCode`, `EAN-13`, …), not the family
you asked for.

### When it cannot run, it says so   {#failure}

`failed(reason)` carries words meant for a person: the camera was refused, there is no camera, another app holds it,
the decoder would not load. It is raised **once per cause**, not once per frame — so an app can show it as a message
without four of them arriving a second.

Like [camera and microphone](https://osysharp.com/reference/ui/capture/), this needs a **secure page**: browsers give no camera to plain `http://` beyond localhost.

### What it costs, and when   {#cost}

| | Size | When it loads |
|---|---|---|
| the control | 3 KB | on mount |
| the decoder glue | 37 KB | the first time a scanner is **activated** |
| the decoder itself | 1.07 MB | the same moment, as WebAssembly |

A page that mounts a scanner with `active: false` and never arms it downloads neither chunk. An app that never
writes the `use` carries nothing at all.

### It is also the proof that a control may ship WebAssembly   {#wasm}

The decoder is ZXing's C++ library compiled to WebAssembly, and it reaches the browser through nothing special: a
`.wasm` is an ordinary control asset, pinned by content address, served same-origin, and reached through the ordinary
[chunks — assets a control loads on demand](https://osysharp.com/reference/ui/control-chunks/) mechanism. If you are shipping a control of your own around a native library, this kit is the
worked example — see its `README.md` for the one function everything turns on.

## See also       {#see-also}

- [camera and microphone](https://osysharp.com/reference/ui/capture/) — the camera and microphone as verbs, for taking a photograph or a recording
- [chunks — assets a control loads on demand](https://osysharp.com/reference/ui/control-chunks/) — how an asset a control loads on demand is declared and served
- [control — foreign UI controls (charts, grids, maps)](https://osysharp.com/reference/ui/controls/) — declaring a foreign control of your own
- [The markdown editor kit — a rich editor you opt into](https://osysharp.com/reference/ui/markdown-editor-kit/) — the other bundled control kit, and the first one
- [upload](https://osysharp.com/reference/ui/upload/) — a file a person chooses, which is the other way bytes arrive from a browser
