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

@bnnx/react-native-label-printer

v0.4.0

Published

React Native library for printing labels via Bluetooth on Android and iOS, with support for TSPL and CPCL thermal printers.

Readme

@bnnx/react-native-label-printer

A React Native library for discovering, connecting to, and printing labels on Bluetooth Low Energy (BLE) thermal printers. Built on the New Architecture (TurboModules) with native support for TSPL commands.

Key Features

  • TurboModule Architecture — High-performance JSI bridge, no legacy Bridge overhead.
  • Cross-Platform BLE — Full Bluetooth LE implementation for both iOS (CoreBluetooth) and Android (BluetoothGatt).
  • MTU-Aware Chunking — Android transmissions are natively paced and chunked to prevent buffer overflows.
  • Automatic Disconnection Detection — Native event emitters notify when the printer goes out of range or is powered off.
  • Modern Permissions — Ready for Android 12+ (neverForLocation), no GPS permission needed to print.
  • Built-in TSPL Builder — Chainable API for text, barcodes, QR codes, and more.
  • React HookuseLabelPrinter hook manages scanning, connection state, and device cleanup automatically.

Tech Stack

  • Framework: React Native 0.73+ (TurboModules / New Architecture)
  • TypeScript: Full type definitions
  • Android: Kotlin, BluetoothLeScanner + BluetoothGatt
  • iOS: Objective-C++, CoreBluetooth

Prerequisites

  • React Native 0.73.0 or higher with New Architecture enabled
  • iOS 13+ / Android 6+ (API 23)

Getting Started

1. Installation

yarn add @bnnx/react-native-label-printer

2. iOS Setup

Add the following to ios/YourAppName/Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app requires Bluetooth to connect to and print labels.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app requires Bluetooth to connect to and print labels.</string>

Install CocoaPods:

cd ios
RCT_NEW_ARCH_ENABLED=1 pod install
cd ..

3. Android Setup

Add the following permissions to android/app/src/main/AndroidManifest.xml:

<!-- Android 11 and lower -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />

<!-- Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Make sure your app requests these runtime permissions before scanning. A library like react-native-permissions is recommended.


API Reference

Native Functions

| Function | Description | | --- | --- | | startScan() | Starts BLE scanning for nearby thermal printers. Matches by known name prefixes and service UUIDs. | | stopScan() | Stops the current BLE scan. | | connect(address: string): Promise<void> | Connects to a printer by its address (MAC on Android, UUID on iOS). Handles MTU negotiation and characteristic discovery automatically. Times out after 5 seconds. | | disconnect(): Promise<void> | Disconnects from the currently connected printer. | | sendRaw(data: string): Promise<void> | Sends a raw UTF-8 string to the connected printer. Automatically chunks data based on the negotiated MTU. |

Events

| Event | Callback | Description | | --- | --- | --- | | onPrinterFound | (printer: { name: string; address: string }) => void | Fired when a printer is discovered during scanning. | | onPrinterDisconnected | (address: string) => void | Fired when the connected printer is turned off or goes out of range. |

useLabelPrinter Hook

The recommended way to use this library. Manages scanning, connection, and device lifecycle automatically.

import { useLabelPrinter } from '@bnnx/react-native-label-printer';

const {
  devices,          // Device[] — discovered printers
  isScanning,       // boolean
  connectedDevice,  // Device | null
  isConnecting,     // boolean
  startScan,        // () => void — clears list and starts scanning
  stopScan,         // () => void
  connect,          // (address: string) => Promise<void>
  disconnect,       // () => Promise<void>
} = useLabelPrinter({
  cleanupIntervalMs: 2000,  // How often stale devices are removed (default: 2000)
  deviceTimeoutMs: 10000,   // Max age before a device is removed. 0 to disable (default: 10000)
});

Device type:

type Device = {
  name: string;
  address: string;
  lastSeen?: number;
};

Usage Example

A complete scanning, connecting, and printing flow:

import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { sendRaw, TSPLBuilder, useLabelPrinter } from '@bnnx/react-native-label-printer';

export default function PrinterDemo() {
  const { devices, connectedDevice, startScan, connect, disconnect } = useLabelPrinter();

  const handleConnect = async (address: string) => {
    if (connectedDevice) await disconnect();
    await connect(address);
  };

  const handlePrint = async () => {
    const payload = new TSPLBuilder()
      .size(50, 30)
      .gap(2)
      .clear()
      .text(10, 10, 'Hello World!')
      .barcode(10, 50, '12345678', '128', 40)
      .qrCode(250, 10, 'https://example.com', { cellWidth: 4 })
      .print(1)
      .build();

    await sendRaw(payload);
  };

  return (
    <View style={{ flex: 1, paddingTop: 50 }}>
      <TouchableOpacity onPress={() => startScan()}>
        <Text>SCAN</Text>
      </TouchableOpacity>

      <TouchableOpacity onPress={handlePrint} disabled={!connectedDevice}>
        <Text>PRINT LABEL</Text>
      </TouchableOpacity>

      {devices.map((p) => (
        <TouchableOpacity key={p.address} onPress={() => handleConnect(p.address)}>
          <Text>{p.name} - {p.address}</Text>
        </TouchableOpacity>
      ))}
    </View>
  );
}

TSPLBuilder

Chainable builder for constructing TSPL command payloads.

const payload = new TSPLBuilder()
  .size(width, height)                          // Label dimensions (mm)
  .gap(gapSize, offsetMm?)                      // Gap between labels (mm)
  .cls()                                        // Clear image buffer (alias: .clear())
  .codePage(value)                              // Set code page (e.g. "1252" for Latin-1)
  .direction(0 | 1)                             // Print direction
  .reference(x, y)                              // Reference point
  .density(0-15)                                // Print density
  .speed(value)                                 // Print speed
  .feed(mm)                                     // Feed paper
  .text(x, y, content, options?)                // Draw text
  .barcode(x, y, content, type?, height?, options?)  // Draw barcode
  .qrCode(x, y, content, options?)              // Draw QR code
  .box(x, y, xEnd, yEnd, thickness?)            // Draw box
  .print(copies)                                // Print command
  .build();                                     // Build final string

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT