wcz-layout
Version:
68 lines (59 loc) • 2.93 kB
Markdown
---
name: scanning
description: "Use when a feature reads barcodes or QR codes, from a handheld laser scanner (keystrokes) via useScanDetection or from the device camera via @yudiel/react-qr-scanner."
metadata:
type: convention
library: wcz-layout
---
## Rules
- Laser scanners type the code as fast keystrokes. Catch them with `useScanDetection` from
`wcz-layout/hooks`, never a hidden input or an own `keydown` listener. It listens on
`document`, so nothing needs focus.
- `useScanDetection({ onComplete, ... })` options (defaults): `minLength` (1),
`averageWaitTime` (50 ms between keys, slower input counts as typing), `timeToEvaluate`
(100 ms), `startCharacter` (`[]`), `endCharacter` (`["Enter", "Escape"]`), `onError`,
`container` (`document`), `ignoreIfFocusOn`, `preventDefault` / `stopPropagation` (`false`),
`enabled` (`true`). Set `minLength` to the shortest valid code; use `enabled: false` while
scans must be ignored.
- Camera scanning always uses `Scanner` from `/react-qr-scanner` (install if missing),
never another QR/barcode library. Rear camera, finder and torch are on by default. Always set:
- `constraints={{ width: { ideal: 1920 }, height: { ideal: 1080 } }}`: Full HD, the default
720p misses small and dense codes.
- `formats`: only the symbologies the feature expects (`qr_code`, `code_128`, `ean_13`, …).
All formats are scanned by default, which is slower and misreads more.
- `onError`: alert `error.message` (permission denied, no camera, camera in use).
- Open the camera in a custom dialog that resolves with the first scanned value (see `dialogs`).
It needs HTTPS or `localhost`; the component is SSR-safe.
- Where both scanners may be used, keep `useScanDetection` on the page, add a camera button,
and send both results to the same handler.
## Examples
```tsx
import { Dialog, DialogContent, DialogTitle } from "@mui/material";
import { Scanner } from "@yudiel/react-qr-scanner";
import type { DialogProps } from "wcz-layout/hooks";
import { useDialogs, useScanDetection, useTranslation } from "wcz-layout/hooks";
// laser scanner
useScanDetection({ onComplete: handleCode, minLength: 8 });
// camera button
const { open } = useDialogs();
const code = await open(ScanDialog);
if (code) await handleCode(code);
// camera dialog
export const ScanDialog = ({ open, onClose }: DialogProps<undefined, string | undefined>) => {
const { t } = useTranslation();
const { alert } = useDialogs();
return (
<Dialog fullWidth open={open} onClose={() => onClose(undefined)}>
<DialogTitle>{t("Scan")}</DialogTitle>
<DialogContent>
<Scanner
constraints={{ width: { ideal: 1920 }, height: { ideal: 1080 } }}
formats={["qr_code", "code_128"]}
onScan={([code]) => onClose(code.rawValue)}
onError={(error) => alert(error.message)}
/>
</DialogContent>
</Dialog>
);
};
```