Skip to content

API Overview ​

SymbolPurposeExecutionCommon gotcha
encodeQrEncode a payload into a QrMatrixSyncThrows SigilCapacityError over capacity
qrCapacityPayload limit for a version/level/modeSyncReturns characters for numeric/alphanumeric, bytes for byte mode
toSvgRender a matrix as an SVG stringSyncEscapes dark/light as raw CSS: pass values, not markup
drawToCanvasPaint a matrix onto a canvasSyncBrowser only; resizes the canvas for DPR
detectQrOne-shot detection on an image sourceAsyncThrows SigilUnsupportedError without BarcodeDetector
createQrScannerCamera scan loopAsync (start)Must dispose(); camera tracks persist otherwise
isQrScanSupportedSync feature checkSyncConstructor exists ≠ qr_code supported: prefer qrScanSupport()
qrScanSupportAsync feature check incl. formatsAsyncNever assume support per browser/version

Package Entry Point ​

ImportPurpose
@vielzeug/sigilComplete public Sigil API

Encoding ​

encodeQr(data, options?) ​

ts
function encodeQr(data: string | Uint8Array, options?: QrEncodeOptions): QrMatrix;

Encodes data into a QR symbol. Picks the most compact mode covering the whole input, the smallest fitting version, and the lowest-penalty mask.

ParameterTypeDefaultDescription
datastring | Uint8ArrayN/APayload; Uint8Array is raw binary and always byte mode (no UTF-8 round-trip)
options.errorCorrection'L' | 'M' | 'Q' | 'H''M'Error-correction level
options.version1–40autoPin the version; throws if payload can't fit
options.minVersion1–401Smallest acceptable version
options.modeQrModeautoForce a segment mode
options.mask0–7autoForce the mask (test vectors only)

Returns a frozen QrMatrix with size, version, mode, errorCorrection, mask, and get(x, y).

Throws SigilCapacityError (payload exceeds capacity), SigilOptionError (invalid mode/version/mask combination).

ts
import { encodeQr } from '@vielzeug/sigil';

const matrix = encodeQr('HELLO WORLD', { errorCorrection: 'Q' });
matrix.size; // 21 (v1)
matrix.get(0, 0); // finder pattern → true

qrCapacity(version, errorCorrection, mode) ​

ts
function qrCapacity(version: number, errorCorrection: QrErrorCorrection, mode: QrMode): number;

Returns the payload limit: characters for numeric/alphanumeric, bytes for byte.

ts
qrCapacity(1, 'M', 'byte'); // → 14
qrCapacity(40, 'L', 'numeric'); // → 7089

Rendering ​

toSvg(matrix, options?) ​

ts
function toSvg(matrix: QrMatrix, options?: QrSvgOptions): string;

Returns a complete <svg> string. Runs in any environment: no DOM required.

ParameterTypeDefaultDescription
options.darkstring'currentColor'Dark module color
options.lightstring'transparent'Background color
options.marginnumber4Quiet-zone modules
options.scalenumber1User units per module
options.optimizePathbooleantrueMerge dark runs into one <path>
options.labelstringN/A<title> + aria-label; enables role="img"
ts
const svg = toSvg(matrix, { label: 'Pairing code', dark: 'var(--qr-dark)' });

drawToCanvas(matrix, canvas, options?): browser only ​

ts
function drawToCanvas(matrix: QrMatrix, canvas: HTMLCanvasElement, options?: QrCanvasOptions): number;

Paints the matrix and returns the CSS-pixel edge length. Sizes the backing store for devicePixelRatio so output stays crisp on retina displays.

ParameterTypeDefaultDescription
options.scalenumber1CSS px per module
options.marginnumber4Quiet-zone modules
options.dark / options.lightstring'#000' / '#fff'Fill colors

Scanning (browser only) ​

createQrScanner(options) ​

ts
function createQrScanner(options: QrScannerOptions): QrScanner;

Creates a camera scan loop around the native BarcodeDetector.

ParameterTypeDefaultDescription
options.videoHTMLVideoElementN/AElement the stream attaches to (needs autoplay playsinline muted)
options.constraintsMediaTrackConstraints{ facingMode: 'environment' }getUserMedia video constraints
options.intervalMsnumber200Minimum ms between detect passes
options.oncebooleantrueStop after the first result
options.signalAbortSignalN/AAbort → stop()
options.detectorQrDetectornativeInjected detector for tests
options.mediaDevicesPick<MediaDevices, 'getUserMedia'>navigator.mediaDevicesInjected media for tests

Returns a QrScanner:

MemberSignatureDescription
start()() => Promise<void>Request camera, attach stream, run the detect loop. Rejects with SigilUnsupportedError / SigilPermissionError. stop()/dispose() while the camera prompt is pending win: the late stream is released and the call resolves
stop()() => voidStop the loop and tracks, return to 'idle'; instance stays usable
onResult(handler)(handler) => () => voidDecode results; returns unsubscribe
tap(handler, options?)(handler, { signal? }) => () => voidObserve SigilEvents; handler errors are swallowed
statusQrScannerStatus'idle' | 'starting' | 'scanning' | 'disposed'
dispose() / [Symbol.dispose]() => voidTerminal teardown; disposalSignal aborts
disposedbooleanWhether dispose() ran
ts
const scanner = createQrScanner({ video });
const off = scanner.onResult(({ value }) => console.log(value));
await scanner.start();

detectQr(source, options?) ​

ts
function detectQr(
  source: ImageBitmapSource,
  options?: { signal?: AbortSignal; detector?: QrDetector },
): Promise<QrScanResult | null>;

Single-pass detection on an image source. Returns the first result's { value, cornerPoints }, or null when nothing decodes. Throws SigilUnsupportedError when no detector is available.


isQrScanSupported() / qrScanSupport() ​

ts
function isQrScanSupported(): boolean;
function qrScanSupport(): Promise<boolean>;

isQrScanSupported checks the BarcodeDetector constructor synchronously. qrScanSupport additionally asks getSupportedFormats() for 'qr_code': use it before showing scan affordances.

Types ​

ts
type QrErrorCorrection = 'L' | 'M' | 'Q' | 'H';
type QrMode = 'numeric' | 'alphanumeric' | 'byte';
type QrScannerStatus = 'idle' | 'starting' | 'scanning' | 'disposed';

interface QrMatrix {
  readonly errorCorrection: QrErrorCorrection;
  readonly mask: number;
  readonly mode: QrMode;
  readonly size: number;    // 17 + 4 * version
  readonly version: number; // 1–40
  get(x: number, y: number): boolean; // true = dark; false outside bounds
}

interface QrScanResult {
  readonly cornerPoints?: ReadonlyArray<{ readonly x: number; readonly y: number }>;
  readonly value: string;
}

interface QrDetector {
  detect(source: ImageBitmapSource): Promise<
    ReadonlyArray<{ rawValue: string; cornerPoints?: ReadonlyArray<{ x: number; y: number }> }>
  >;
}

type SigilEvent =
  | { readonly type: 'status-change'; readonly status: QrScannerStatus }
  | { readonly type: 'detect'; readonly value: string; readonly elapsedMs: number }
  | { readonly type: 'frame-skipped'; readonly reason: 'not-ready' | 'busy' }
  | { readonly type: 'error'; readonly error: SigilError }
  | { readonly type: 'dispose' };

QrEncodeOptions, QrSvgOptions, QrCanvasOptions, QrScannerOptions, and QrScanner are documented under their factories above.

Errors ​

ClassTriggerNotable members
SigilErrorBase class for all sigil errorsN/A
SigilCapacityErrorPayload exceeds the version/mode limitbytes, maxBytes, version
SigilOptionErrorInvalid option combination (forced mode can't represent input, bad mask/version)N/A
SigilUnsupportedErrorBarcodeDetector/getUserMedia/canvas 2D context missingN/A
SigilPermissionErrorCamera NotAllowedErrorN/A
SigilDisposedErrorstart() on a disposed scannerN/A

All carry cause when wrapping a platform error.