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 | Uint8ArrayPayload; Uint8Array implies byte mode
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, modules, 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.labelstring<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.videoHTMLVideoElementElement 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.signalAbortSignalAbort → 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()() => voidStop the loop and tracks; 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' | 'stopped' | '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' | 'stopped' | 'disposed';

interface QrMatrix {
  readonly errorCorrection: QrErrorCorrection;
  readonly mask: number;
  readonly mode: QrMode;
  readonly modules: ReadonlyArray<ReadonlyArray<boolean>>; // frozen, row-major
  readonly size: number;    // 17 + 4 * version
  readonly version: number; // 1–40
  get(x: number, y: number): boolean; // 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 errors
SigilCapacityErrorPayload exceeds the version/mode limitbytes, maxBytes, version
SigilOptionErrorInvalid option combination (forced mode can't represent input, bad mask/version)
SigilUnsupportedErrorBarcodeDetector/getUserMedia missing
SigilPermissionErrorCamera NotAllowedError
SigilDisposedErrorstart() on a disposed scanner

All carry cause when wrapping a platform error.