Documents the intended API, template loading strategy, scan modes, ZXing bundling approach, and project structure for the reusable barcode scanner library. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
140 lines
4.0 KiB
Markdown
140 lines
4.0 KiB
Markdown
# Phone Barcode Scanner — Library Refactor Plan
|
|
|
|
## Goal
|
|
|
|
Refactor the current monolithic app into a reusable library that can be embedded
|
|
as a feature in other applications, with a clean API and self-contained UI.
|
|
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
phone-barcode/
|
|
lib/
|
|
scanner.mjs — camera, decode pipeline, ZXing wrapper (no DOM)
|
|
scanner-ui.mjs — clones template node into a container, wires controls
|
|
template.html — UI markup fragment (no <html>/<body>, just the widget)
|
|
style.css — scoped styles for the widget
|
|
index.mjs — public API (re-exports)
|
|
vendor/
|
|
zxing.min.js — bundled, populated by `make build`
|
|
demo/
|
|
index.html — demo app, built as a consumer of the library
|
|
app.mjs
|
|
Makefile
|
|
package.json
|
|
```
|
|
|
|
|
|
## API
|
|
|
|
### Low-level: bring your own container
|
|
|
|
```javascript
|
|
import { Barcode_Scanner } from './phone-barcode/index.mjs';
|
|
|
|
const scanner = new Barcode_Scanner(container_el, {
|
|
mode: 'continuous', // 'continuous' | 'single' | 'aim-tap'
|
|
on_scan(text, format) {}, // called on each successful decode
|
|
on_close() {}, // called when user dismisses
|
|
});
|
|
|
|
await scanner.start();
|
|
scanner.stop();
|
|
```
|
|
|
|
The scanner clones the UI template into `container_el` and takes it over.
|
|
Caller is responsible for showing/hiding the container.
|
|
|
|
### High-level: managed dialog
|
|
|
|
```javascript
|
|
import { scan_once, scan_continuous } from './phone-barcode/index.mjs';
|
|
|
|
// Creates a <dialog>, runs scanner, resolves on first scan, cleans up
|
|
const result = await scan_once();
|
|
// → { text: '...', format: 'CODE_128' } | null (if dismissed)
|
|
|
|
// Same but keeps scanning; on_scan called for each result
|
|
const handle = await scan_continuous({ on_scan(text, format) {} });
|
|
handle.close();
|
|
```
|
|
|
|
Both functions create a `<dialog>` internally, inject the scanner, and manage
|
|
the full lifecycle. They accept an optional `dialog_el` parameter if the caller
|
|
wants to provide their own dialog element instead.
|
|
|
|
|
|
## Template Loading
|
|
|
|
The UI template (`template.html`) is a plain HTML fragment — no `<html>` or
|
|
`<body>`, just the widget markup.
|
|
|
|
Two ways to get the template node:
|
|
|
|
```javascript
|
|
// 1. Library fetches it (convenience)
|
|
import { load_template } from './phone-barcode/index.mjs';
|
|
const tmpl = await load_template(); // fetches template.html relative to lib
|
|
|
|
// 2. Caller provides it (e.g. already in the DOM, or loaded differently)
|
|
const tmpl = document.getElementById('barcode-scanner-template');
|
|
const scanner = new Barcode_Scanner(container, { template: tmpl });
|
|
```
|
|
|
|
`Barcode_Scanner` accepts either a `<template>` element or a plain node. If no
|
|
`template` option is given, it calls `load_template()` automatically.
|
|
|
|
|
|
## Scan Modes
|
|
|
|
| Mode | Behaviour |
|
|
|--------------|--------------------------------------------------------|
|
|
| `continuous` | Scans forever, fires `on_scan` for each new code |
|
|
| `single` | Resolves/fires once then stops; UI shows result briefly |
|
|
| `aim-tap` | Scanning paused; user taps shutter button to attempt |
|
|
|
|
|
|
## ZXing Bundling
|
|
|
|
`vendor/zxing.min.js` is committed to the repo (populated by `make build`).
|
|
The library loads it via a `<script>` tag injected into the document if
|
|
`window.ZXing` is not already present, so the caller does not need to think
|
|
about it.
|
|
|
|
|
|
## Styling
|
|
|
|
`style.css` uses a scoped class prefix (`bcs-`) on all elements to avoid
|
|
collisions with host app styles. The host can override via CSS custom properties:
|
|
|
|
```css
|
|
.bcs-root {
|
|
--bcs-accent: #00e87a;
|
|
--bcs-bg: #0a0c0f;
|
|
}
|
|
```
|
|
|
|
|
|
## Lifecycle
|
|
|
|
```
|
|
Barcode_Scanner.start()
|
|
→ inject template into container
|
|
→ inject ZXing if needed
|
|
→ start camera (auto-select main back camera)
|
|
→ start decode loop
|
|
|
|
Barcode_Scanner.stop()
|
|
→ stop camera tracks
|
|
→ cancel decode loop
|
|
→ remove injected nodes from container
|
|
```
|
|
|
|
|
|
## Demo App
|
|
|
|
`demo/` contains a minimal page that exercises both the low-level and
|
|
high-level APIs — a persistent embedded scanner plus a "Scan once" button
|
|
that opens the managed dialog.
|