npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vision-camera-smart-scan

v1.1.0

Published

Drop-in barcode scanning upgrade for react-native-vision-camera. ~60% to 90%+ scan success rate with zero native code.

Readme

vision-camera-smart-scan

Drop-in barcode scanning upgrade for react-native-vision-camera. Takes scan success rate from ~60% to 90%+ with zero native code changes.

The Problem

Default useCodeScanner in react-native-vision-camera works, but in real-world conditions — dim grocery stores, angled barcodes, small cosmetic labels, iPhone 14 Pro+ close-focus issues — success rate drops to ~60%. Users have to carefully align barcodes and hold perfectly still.

Every production barcode app rebuilds the same camera pipeline fixes from scratch. This package bundles them into a single hook.

What It Does

| Technique | What it solves | |-----------|---------------| | Multi-camera device selection | iPhone 14 Pro+ can't focus closer than ~20cm on the main lens. Multi-cam enables automatic ultra-wide fallback for close shots. | | Temporal fusion | Requires the same barcode across N consecutive frames before accepting. Eliminates phantom reads from partially-decoded frames. | | Region of interest | Restricts detection to the center of the frame. Kills adjacent-barcode misreads and speeds up decode. | | Low-light boost | Enables platform-native low-light enhancement. Essential for fluorescent-lit store aisles. | | Smart zoom | Starts at device.neutralZoom so multi-cam devices begin on the wide-angle lens, not ultra-wide. | | Haptic feedback | Configurable haptic tap on confirmed scan. Light impact feels instant vs. heavy notification vibration. |

Install

npm install vision-camera-smart-scan react-native-vision-camera

# Optional: haptic feedback
npm install expo-haptics

Quick Start

import { Camera } from 'react-native-vision-camera';
import { useSmartScan } from 'vision-camera-smart-scan';

function Scanner() {
  const { device, cameraProps, cameraRef, codeScanner } = useSmartScan({
    onScan: (value) => {
      console.log('Scanned:', value);
    },
  });

  if (!device) return <Text>No camera available</Text>;

  return (
    <Camera
      ref={cameraRef}
      style={StyleSheet.absoluteFill}
      device={device}
      isActive={true}
      {...cameraProps}
      codeScanner={codeScanner}
    />
  );
}

Full Example

import { useState, useCallback } from 'react';
import { View, Text, StyleSheet, Pressable } from 'react-native';
import { Camera } from 'react-native-vision-camera';
import { useFocusEffect } from 'expo-router';
import { useSmartScan } from 'vision-camera-smart-scan';

function BarcodeScanner() {
  const [isActive, setIsActive] = useState(true);
  const [lastBarcode, setLastBarcode] = useState<string | null>(null);

  const { device, cameraProps, cameraRef, codeScanner, reset } = useSmartScan({
    onScan: (value) => {
      setIsActive(false);
      setLastBarcode(value);
    },
    codeTypes: ['ean-13', 'ean-8', 'upc-a', 'upc-e', 'qr'],
    confirmFrames: 2,
    cooldownMs: 2000,
    scanRegion: 'center',
    haptic: 'light',
  });

  // Reset when screen regains focus
  useFocusEffect(
    useCallback(() => {
      setIsActive(true);
      reset();
    }, [reset])
  );

  function dismiss() {
    setLastBarcode(null);
    setIsActive(true);
    reset();
  }

  if (!device) return <Text>No camera available</Text>;

  return (
    <View style={StyleSheet.absoluteFill}>
      <Camera
        ref={cameraRef}
        style={StyleSheet.absoluteFill}
        device={device}
        isActive={isActive}
        {...cameraProps}
        codeScanner={codeScanner}
      />
      {lastBarcode && (
        <Pressable style={styles.result} onPress={dismiss}>
          <Text style={styles.barcode}>{lastBarcode}</Text>
          <Text style={styles.hint}>Tap to scan again</Text>
        </Pressable>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  result: {
    position: 'absolute',
    bottom: 100,
    alignSelf: 'center',
    backgroundColor: 'rgba(0,0,0,0.8)',
    padding: 20,
    borderRadius: 12,
    alignItems: 'center',
  },
  barcode: { color: '#fff', fontSize: 20, fontWeight: '600' },
  hint: { color: 'rgba(255,255,255,0.6)', fontSize: 14, marginTop: 4 },
});

API

useSmartScan(options)

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | onScan | (value: string, code: Code) => void | required | Called when a barcode is confirmed | | codeTypes | CodeType[] | ['ean-13', 'ean-8', 'upc-a', 'upc-e'] | Barcode symbologies to detect | | confirmFrames | number | 2 | Consecutive matching frames required | | cooldownMs | number | 2000 | Minimum ms between accepted scans | | scanRegion | 'center' \| 'narrow' \| 'wide' \| 'full' \| Region | 'center' | Detection area (iOS only) | | haptic | 'light' \| 'medium' \| 'heavy' \| 'none' | 'light' | Haptic feedback style | | lowLightBoost | boolean | true | Enable low-light enhancement | | smartZoom | boolean | true | Start at optimal zoom level | | enableZoomGesture | boolean | true | Enable native pinch-to-zoom | | tapToFocus | boolean | true | Tap a point to focus there | | physicalDevices | PhysicalCameraDeviceType[] | ['ultra-wide-angle-camera', 'wide-angle-camera', 'telephoto-camera'] | Camera lens preference |

Region Presets

| Preset | Area | Best for | |--------|------|----------| | 'center' | 80% x 40% centered | General barcode scanning | | 'narrow' | 70% x 30% centered | Dense shelves, adjacent products | | 'wide' | 90% x 60% centered | Large labels, QR codes | | 'full' | Entire frame | No restriction |

Returns

| Property | Type | Description | |----------|------|-------------| | device | CameraDevice \| undefined | Selected camera device (multi-cam optimized) | | cameraProps | { zoom?, lowLightBoost?, enableZoomGesture?, onTouchEnd? } | Spread onto <Camera> | | cameraRef | RefObject<Camera> | Pass as ref to <Camera> (required for tap-to-focus) | | codeScanner | CodeScanner | Pass to Camera's codeScanner prop | | reset() | () => void | Reset temporal fusion state |

How It Works

Multi-Camera Device Selection

On iPhones with multiple back cameras (11+), the hook requests a multi-camera device. This lets iOS automatically switch between lenses based on subject distance. The iPhone 14 Pro and later have a minimum focus distance of ~20cm on the main (wide-angle) lens. Without multi-cam, barcodes held closer than 20cm simply won't focus. With multi-cam enabled, the system falls back to the ultra-wide camera which can focus at ~2cm.

Temporal Fusion

Instead of accepting the first decoded barcode, useSmartScan requires the same value across N consecutive onCodeScanned callbacks (default: 2). This eliminates:

  • Phantom reads from partially-visible barcodes at frame edges
  • Transient misreads when the camera is in motion
  • Incorrect decodes from damaged or low-contrast labels

The overhead is one extra frame (~33ms at 30fps). Unnoticeable to the user, but eliminates the #1 source of wrong-product lookups.

Region of Interest

The center preset restricts barcode detection to the middle 80% x 40% of the camera frame. Benefits:

  • Adjacent products on a grocery shelf won't trigger false scans
  • The decoder processes less of each frame, improving throughput
  • Users intuitively point the center of their phone at the barcode anyway

regionOfInterest is iOS-only in react-native-vision-camera v4. On Android, the full frame is always scanned.

Requirements

  • react-native-vision-camera v4.0+
  • React Native 0.73+
  • React 18+
  • expo-haptics (optional, for haptic feedback)

Tested In Production

This package powers barcode scanning in Melu, a food safety scanner app used by parents to check products at the grocery store. The techniques were developed and validated through real-world testing across hundreds of products in varying lighting conditions.

License

MIT © Aashish Takkala