@rejaul/react-native-printer-kit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rejaul Karim
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,199 @@
1
+ # react-native-printer-kit
2
+
3
+ A professional-grade React Native module for printing directly to Bluetooth POS/thermal (ESC/POS) printers on **Android devices only** — no third-party printer app, no OS print dialog. Print raw text, images, PDFs, and full HTML/CSS content, including **Bangla and other non-Latin scripts** that ESC/POS printer fonts don't support natively.
4
+
5
+ > **Important:** This library is **exclusively for Android**. Bluetooth Classic SPP + ESC/POS is an Android-specific integration; iOS does not expose the APIs this relies on.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@rejaul/react-native-printer-kit.svg)](https://www.npmjs.com/package/@rejaul/react-native-printer-kit)
8
+ [![license](https://img.shields.io/npm/l/@rejaul/react-native-printer-kit.svg)](LICENSE)
9
+ [![Platform - Android Only](https://img.shields.io/badge/Platform-Android%20Only-green)]()
10
+ [![Kotlin](https://img.shields.io/badge/Language-Kotlin-purple)]()
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Supported-blue)]()
12
+
13
+ ## Why this exists
14
+
15
+ Most ESC/POS printer libraries only send raw text or a single pre-made image. They can't render real content — an actual HTML/CSS receipt layout, a PDF, or text in a script the printer's built-in font doesn't have (Bangla, Arabic, Hindi, etc.). This library renders your HTML/PDF to a bitmap on-device (Android's own `WebView` and `PdfRenderer` — no external rendering library) and sends it to the printer as a dithered ESC/POS raster image.
16
+
17
+ It's a thin React Native bridge over [`android-printer-kit`](https://github.com/DeveloperRejaul/android-printer-kit), the native Kotlin library that does the actual work.
18
+
19
+ ## Features
20
+
21
+ - **Direct Bluetooth Classic (SPP) connection** to any paired ESC/POS printer.
22
+ - **HTML → PDF → print** pipeline, so you can print an actual styled receipt/report.
23
+ - **PDF → image → print** pipeline via Android's built-in `PdfRenderer`.
24
+ - **Non-Latin text support** (Bangla and others) via image-based rendering.
25
+ - **Persistent connection**: the printer stays connected even if the app is swiped away from Recents (a foreground service keeps it alive).
26
+ - **Auto-reconnect**: remembers the last connected printer and reconnects automatically next time the app starts.
27
+ - **Banded raster printing**: images are sent in small, paced chunks, since many cheap ESC/POS boards silently drop large single print commands.
28
+ - **Type-safe**: full TypeScript definitions, backed by a New Architecture TurboModule.
29
+
30
+ ## Platform Support
31
+
32
+ | Platform | Status | Details |
33
+ |----------|--------|---------|
34
+ | **Android** | **Fully Supported** | API Level 24+ required |
35
+ | **iOS** | **Not Supported** | No Bluetooth Classic SPP / ESC/POS API equivalent |
36
+
37
+ ## Scope
38
+
39
+ This library speaks **Bluetooth Classic SPP + ESC/POS** — the standard used by virtually all budget Bluetooth receipt/thermal printers. It does not support Bluetooth LE printers, WiFi/network printers, USB-connected printers, or non-ESC/POS protocols (PCL/PostScript inkjet & laser printers).
40
+
41
+ ## Minimum Requirements
42
+
43
+ - **React Native** >= 0.76 (New Architecture / TurboModules)
44
+ - **Android API Level** >= 24 (Android 7.0+)
45
+ - **Kotlin** 2.0.21+ (included in the build system)
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ npm install @rejaul/react-native-printer-kit
51
+ # or
52
+ yarn add @rejaul/react-native-printer-kit
53
+ ```
54
+
55
+ Nothing to configure manually — all required Bluetooth and foreground-service permissions are declared by the underlying native library's manifest and merge in automatically. You still need to request the runtime `BLUETOOTH_CONNECT` (Android 12+) and `POST_NOTIFICATIONS` (Android 13+) permissions at runtime — `requestBluetoothPermission()` handles both in one call; see [Permissions](#permissions) below.
56
+
57
+ ## Quick Start
58
+
59
+ ```typescript
60
+ import {
61
+ hasBluetoothPermission,
62
+ requestBluetoothPermission,
63
+ getBondedBluetoothPrinters,
64
+ connectPrinter,
65
+ printText,
66
+ printHtml,
67
+ } from '@rejaul/react-native-printer-kit';
68
+
69
+ async function printReceipt() {
70
+ // 1. Make sure Bluetooth permission is granted (Android 12+)
71
+ if (!hasBluetoothPermission()) {
72
+ const granted = await requestBluetoothPermission();
73
+ if (!granted) return;
74
+ }
75
+
76
+ // 2. List paired printers and connect to one
77
+ const printers = getBondedBluetoothPrinters();
78
+ if (printers.length === 0) return;
79
+ await connectPrinter(printers[0]!.address);
80
+
81
+ // 3a. Print plain text
82
+ await printText('Hello from PrinterKit');
83
+
84
+ // 3b. Or print a full HTML receipt (Bangla, styling, everything)
85
+ const ok = await printHtml(myReceiptHtml);
86
+ console.log('Printed:', ok);
87
+ }
88
+ ```
89
+
90
+ ## Permissions
91
+
92
+ ```typescript
93
+ import {
94
+ hasBluetoothPermission,
95
+ requestBluetoothPermission,
96
+ } from '@rejaul/react-native-printer-kit';
97
+
98
+ // Synchronous check - always true below Android 12
99
+ const granted = hasBluetoothPermission();
100
+
101
+ // Shows the system permission dialog if needed (no-op if already granted,
102
+ // or not required on this Android version)
103
+ const result = await requestBluetoothPermission();
104
+ ```
105
+
106
+ ## API Reference
107
+
108
+ ### Permissions
109
+
110
+ #### `hasBluetoothPermission(): boolean`
111
+ Whether `BLUETOOTH_CONNECT` specifically is already granted (always `true` below Android 12) — the permission that actually gates connect/print.
112
+
113
+ #### `requestBluetoothPermission(): Promise<boolean>`
114
+ Shows the system permission dialog(s) for whatever's needed on this Android version — `BLUETOOTH_CONNECT` (12+) and `POST_NOTIFICATIONS` (13+, for the persistent-connection notification's visibility) — and resolves based on `BLUETOOTH_CONNECT`'s result specifically. A denied `POST_NOTIFICATIONS` alone doesn't make this resolve `false`: printing still works, the notification just won't show.
115
+
116
+ ### Connection
117
+
118
+ #### `getBondedBluetoothPrinters(): BluetoothPrinterDevice[]`
119
+ Lists Bluetooth devices already paired with the phone via Android's own Bluetooth settings.
120
+
121
+ #### `connectPrinter(address: string): Promise<boolean>`
122
+ Opens an RFCOMM/SPP connection to the paired printer. Closes any existing connection first, and remembers the address for auto-reconnect on the next app launch.
123
+
124
+ #### `disconnectPrinter(): Promise<void>`
125
+ Closes the current connection and forgets it for auto-reconnect.
126
+
127
+ #### `isConnectedPrinter(): Promise<boolean>`
128
+ Whether a printer connection is currently open.
129
+
130
+ #### `getConnectedPrinter(): Promise<BluetoothPrinterDevice | null>`
131
+ The currently connected printer, if any.
132
+
133
+ ### Printing
134
+
135
+ #### `printText(text: string, feedLines?: number): Promise<void>`
136
+ Prints raw text using the printer's built-in font. **ASCII only** — use `printHtml()` for Bangla or other non-Latin scripts.
137
+
138
+ #### `printImage(imagePath: string, printerWidthDots?: number, feedLines?: number): Promise<void>`
139
+ Prints an image file as a dithered ESC/POS raster image. `printerWidthDots`: 384 for 58mm printers, 576 for 80mm printers (default 384).
140
+
141
+ #### `printImageBase64(base64: string, printerWidthDots?: number, feedLines?: number): Promise<void>`
142
+ Same as above, from a base64-encoded image string.
143
+
144
+ #### `pdfToImage(pdfPath: string, imageType?: 'PNG' | 'JPEG', page?: number, targetWidthPx?: number): Promise<string>`
145
+ Renders one PDF page to an image file and returns its path.
146
+
147
+ #### `printPdf(pdfPath: string, printerWidthDots?: number, page?: number, feedLines?: number): Promise<void>`
148
+ `pdfToImage` + print, in one call.
149
+
150
+ #### `htmlToPdf(html: string, pageWidthDp?: number, heightDp?: number, minPageHeightDp?: number): Promise<string | null>`
151
+ Renders HTML to a PDF file using an off-screen `WebView` and returns its path, or `null` on failure. `pageWidthDp` controls how large the content renders (like a CSS viewport width), independent of the final printed width. Leave `heightDp` unset to auto-measure the real content height (recommended).
152
+
153
+ #### `printHtml(html: string, printerWidthDots?: number, pageWidthDp?: number, heightDp?: number, minPageHeightDp?: number): Promise<boolean>`
154
+ Full pipeline: `htmlToPdf` → `printPdf`. This is how you print Bangla (or other non-Latin) text or any real HTML/CSS layout.
155
+
156
+ ## Type Definitions
157
+
158
+ ```typescript
159
+ type BluetoothPrinterDevice = {
160
+ name: string | null;
161
+ address: string;
162
+ };
163
+
164
+ type PrinterImageType = 'PNG' | 'JPEG';
165
+ ```
166
+
167
+ ## Persistent connection & auto-reconnect
168
+
169
+ Connecting through this library keeps the printer connected even if the app is swiped away from Recents — the native side runs a foreground service that outlives the Activity/JS runtime. Every successful `connectPrinter()` call also remembers the device, so the next time the app is opened (even after being fully killed) it reconnects automatically without the user having to pick the printer again.
170
+
171
+ ## Printing Bangla / other non-Latin text
172
+
173
+ ESC/POS printer firmware fonts only cover ASCII, so `printText()` can't render Bangla. For anything with non-Latin text, render it as an image instead — build a bitmap yourself and use `printImage()`/`printImageBase64()`, or write it as HTML/CSS and call `printHtml()`, which renders it with a real font via `WebView` and prints the result as a dithered raster image.
174
+
175
+ ## Example Application
176
+
177
+ See the [`example`](./example) directory for a complete React Native application demonstrating permission handling, printer pairing/connection, and every print function above.
178
+
179
+ ```bash
180
+ cd example
181
+ yarn install
182
+ yarn android
183
+ ```
184
+
185
+ ## Contributing
186
+
187
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
188
+
189
+ ## Code of Conduct
190
+
191
+ This project adheres to the [Code of Conduct](CODE_OF_CONDUCT.md).
192
+
193
+ ## License
194
+
195
+ MIT - See [LICENSE](LICENSE) file for details.
196
+
197
+ ## Support
198
+
199
+ For issues, questions, or suggestions, please open an [issue on GitHub](https://github.com/DeveloperRejaul/react-native-printer-kit/issues).
@@ -0,0 +1,20 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "ReactNativePrinterKit"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/DeveloperRejaul/react-native-printer-kit.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+ end
@@ -0,0 +1,65 @@
1
+ buildscript {
2
+ ext.ReactNativePrinterKit = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36
6
+ ]
7
+
8
+ ext.getExtOrDefault = { prop ->
9
+ if (rootProject.ext.has(prop)) {
10
+ return rootProject.ext.get(prop)
11
+ }
12
+
13
+ return ReactNativePrinterKit[prop]
14
+ }
15
+
16
+ repositories {
17
+ google()
18
+ mavenCentral()
19
+ maven { url = uri("https://jitpack.io") }
20
+ }
21
+
22
+ dependencies {
23
+ classpath "com.android.tools.build:gradle:8.7.2"
24
+ // noinspection DifferentKotlinGradleVersion
25
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
26
+ }
27
+ }
28
+
29
+
30
+ apply plugin: "com.android.library"
31
+
32
+ if (project.extensions.findByName("kotlin") == null) {
33
+ apply plugin: "kotlin-android"
34
+ }
35
+
36
+
37
+ apply plugin: "com.facebook.react"
38
+
39
+ android {
40
+ namespace "com.rejaul.reactnativeprinterkit"
41
+
42
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
43
+
44
+ defaultConfig {
45
+ minSdkVersion getExtOrDefault("minSdkVersion")
46
+ }
47
+
48
+ compileOptions {
49
+ sourceCompatibility JavaVersion.VERSION_17
50
+ targetCompatibility JavaVersion.VERSION_17
51
+ }
52
+ }
53
+
54
+ repositories {
55
+ google()
56
+ mavenCentral()
57
+ // JitPack resolves this multi-module repo by its GitHub repo name
58
+ // (android-printer-kit), not the internal Gradle module name (printerkit).
59
+ maven { url = uri("https://jitpack.io") }
60
+ }
61
+
62
+ dependencies {
63
+ implementation "com.facebook.react:react-android"
64
+ implementation("com.github.DeveloperRejaul:android-printer-kit:v0.0.3")
65
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,283 @@
1
+ package com.rejaul.reactnativeprinterkit
2
+
3
+ import android.content.ComponentName
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import android.content.ServiceConnection
7
+ import android.content.pm.PackageManager
8
+ import android.os.IBinder
9
+ import androidx.core.content.ContextCompat
10
+ import com.facebook.react.bridge.Arguments
11
+ import com.facebook.react.bridge.Promise
12
+ import com.facebook.react.bridge.ReactApplicationContext
13
+ import com.facebook.react.bridge.WritableArray
14
+ import com.facebook.react.bridge.WritableMap
15
+ import com.facebook.react.modules.core.PermissionAwareActivity
16
+ import com.rezaul.printerkit.BluetoothPermissions
17
+ import com.rezaul.printerkit.BluetoothPrinter
18
+ import com.rezaul.printerkit.BluetoothPrinterDevice
19
+ import com.rezaul.printerkit.BluetoothPrinterService
20
+ import com.rezaul.printerkit.PrinterImageType
21
+ import java.util.concurrent.Executors
22
+
23
+ /**
24
+ * Bridges [com.rezaul.printerkit.BluetoothPrinter] to React Native.
25
+ *
26
+ * Connect/print calls run through a bound [BluetoothPrinterService] (started once,
27
+ * on module init) instead of a bare [BluetoothPrinter], so the connection survives
28
+ * the app being swiped away from Recents - see [BluetoothPrinterService]. Calls made
29
+ * before the service finishes binding (essentially instant, but not synchronous) are
30
+ * queued and run once it connects.
31
+ *
32
+ * All blocking Bluetooth/PDF/image I/O runs on a single background executor, off the
33
+ * calling (JS) thread - also serializing printer writes, since concurrent writes to
34
+ * the same socket from two overlapping calls would corrupt the output.
35
+ */
36
+ class ReactNativePrinterKitModule(reactContext: ReactApplicationContext) :
37
+ NativeReactNativePrinterKitSpec(reactContext) {
38
+
39
+ private val executor = Executors.newSingleThreadExecutor()
40
+
41
+ // getBondedBluetoothPrinters() is synchronous (no connection involved) and must
42
+ // answer immediately, so it uses its own plain BluetoothPrinter rather than
43
+ // waiting on the service to bind.
44
+ private val standalonePrinter by lazy { BluetoothPrinter(reactApplicationContext) }
45
+
46
+ private var printerService: BluetoothPrinterService? = null
47
+ private val pendingActions = mutableListOf<(BluetoothPrinterService) -> Unit>()
48
+
49
+ private val serviceConnection = object : ServiceConnection {
50
+ override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
51
+ val service = (binder as BluetoothPrinterService.LocalBinder).getService()
52
+ printerService = service
53
+ val queued = synchronized(pendingActions) {
54
+ val copy = pendingActions.toList()
55
+ pendingActions.clear()
56
+ copy
57
+ }
58
+ queued.forEach { it(service) }
59
+ }
60
+
61
+ override fun onServiceDisconnected(name: ComponentName?) {
62
+ printerService = null
63
+ }
64
+ }
65
+
66
+ init {
67
+ val intent = Intent(reactApplicationContext, BluetoothPrinterService::class.java)
68
+ reactApplicationContext.startService(intent)
69
+ reactApplicationContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
70
+ }
71
+
72
+ /** Runs [action] with the bound service, once available (queued if not yet bound). */
73
+ private fun withService(action: (BluetoothPrinterService) -> Unit) {
74
+ val service = printerService
75
+ if (service != null) {
76
+ action(service)
77
+ } else {
78
+ synchronized(pendingActions) { pendingActions.add(action) }
79
+ }
80
+ }
81
+
82
+ private fun deviceToMap(device: BluetoothPrinterDevice): WritableMap {
83
+ val map = Arguments.createMap()
84
+ map.putString("name", device.name)
85
+ map.putString("address", device.address)
86
+ return map
87
+ }
88
+
89
+ override fun hasBluetoothPermission(): Boolean {
90
+ return BluetoothPermissions.isGranted(reactApplicationContext)
91
+ }
92
+
93
+ override fun requestBluetoothPermission(promise: Promise) {
94
+ // getRequiredPermissions() can list more than one permission (BLUETOOTH_CONNECT
95
+ // and, on Android 13+, POST_NOTIFICATIONS for the foreground service's ongoing
96
+ // notification) - request every one of them, not just check isGranted(), which
97
+ // only reflects BLUETOOTH_CONNECT and would otherwise skip requesting the rest.
98
+ val required = BluetoothPermissions.getRequiredPermissions()
99
+ val alreadyGranted = required.all {
100
+ ContextCompat.checkSelfPermission(reactApplicationContext, it) == PackageManager.PERMISSION_GRANTED
101
+ }
102
+ if (required.isEmpty() || alreadyGranted) {
103
+ promise.resolve(true)
104
+ return
105
+ }
106
+ val activity = currentActivity as? PermissionAwareActivity
107
+ if (activity == null) {
108
+ promise.reject("NO_ACTIVITY", "No current activity to request permission from")
109
+ return
110
+ }
111
+ activity.requestPermissions(required, PERMISSION_REQUEST_CODE) { requestCode, permissions, grantResults ->
112
+ if (requestCode == PERMISSION_REQUEST_CODE) {
113
+ promise.resolve(BluetoothPermissions.isGrantResult(requestCode, permissions, grantResults, PERMISSION_REQUEST_CODE))
114
+ true
115
+ } else {
116
+ false
117
+ }
118
+ }
119
+ }
120
+
121
+ override fun getBondedBluetoothPrinters(): WritableArray {
122
+ val result: WritableArray = Arguments.createArray()
123
+ standalonePrinter.getBondedBluetoothPrinters().forEach { device ->
124
+ result.pushMap(deviceToMap(device))
125
+ }
126
+ return result
127
+ }
128
+
129
+ override fun connectPrinter(address: String, promise: Promise) {
130
+ withService { service ->
131
+ executor.execute {
132
+ try {
133
+ promise.resolve(service.connectAndKeepAlive(address))
134
+ } catch (e: Exception) {
135
+ promise.reject("ERROR", e.message)
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ override fun disconnectPrinter(promise: Promise) {
142
+ withService { service ->
143
+ executor.execute {
144
+ try {
145
+ service.disconnect()
146
+ promise.resolve(null)
147
+ } catch (e: Exception) {
148
+ promise.reject("ERROR", e.message)
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ override fun isConnectedPrinter(promise: Promise) {
155
+ withService { service ->
156
+ executor.execute {
157
+ try {
158
+ promise.resolve(service.printer.isConnectedPrinter())
159
+ } catch (e: Exception) {
160
+ promise.reject("ERROR", e.message)
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ override fun getConnectedPrinter(promise: Promise) {
167
+ withService { service ->
168
+ executor.execute {
169
+ try {
170
+ val device = service.printer.getConnectedPrinter()
171
+ promise.resolve(device?.let { deviceToMap(it) })
172
+ } catch (e: Exception) {
173
+ promise.reject("ERROR", e.message)
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ override fun printText(text: String, feedLines: Double?, promise: Promise) {
180
+ withService { service ->
181
+ executor.execute {
182
+ try {
183
+ service.printer.printText(text, (feedLines ?: 3.0).toInt())
184
+ promise.resolve(null)
185
+ } catch (e: Exception) {
186
+ promise.reject("ERROR", e.message)
187
+ }
188
+ }
189
+ }
190
+ }
191
+
192
+ override fun printImage(imagePath: String, printerWidthDots: Double?, feedLines: Double?, promise: Promise) {
193
+ withService { service ->
194
+ executor.execute {
195
+ try {
196
+ service.printer.printImageFile(imagePath, (printerWidthDots ?: 384.0).toInt(), (feedLines ?: 3.0).toInt())
197
+ promise.resolve(null)
198
+ } catch (e: Exception) {
199
+ promise.reject("ERROR", e.message)
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ override fun printImageBase64(base64: String, printerWidthDots: Double?, feedLines: Double?, promise: Promise) {
206
+ withService { service ->
207
+ executor.execute {
208
+ try {
209
+ service.printer.printImageBase64(base64, (printerWidthDots ?: 384.0).toInt(), (feedLines ?: 3.0).toInt())
210
+ promise.resolve(null)
211
+ } catch (e: Exception) {
212
+ promise.reject("ERROR", e.message)
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ override fun pdfToImage(pdfPath: String, imageType: String?, page: Double?, targetWidthPx: Double?, promise: Promise) {
219
+ withService { service ->
220
+ executor.execute {
221
+ try {
222
+ val type = if (imageType == "JPEG") PrinterImageType.JPEG else PrinterImageType.PNG
223
+ val path = service.printer.pdfToImage(pdfPath, type, (page ?: 0.0).toInt(), targetWidthPx?.toInt())
224
+ promise.resolve(path)
225
+ } catch (e: Exception) {
226
+ promise.reject("ERROR", e.message)
227
+ }
228
+ }
229
+ }
230
+ }
231
+
232
+ override fun printPdf(pdfPath: String, printerWidthDots: Double?, page: Double?, feedLines: Double?, promise: Promise) {
233
+ withService { service ->
234
+ executor.execute {
235
+ try {
236
+ service.printer.printPdf(pdfPath, (printerWidthDots ?: 384.0).toInt(), (page ?: 0.0).toInt(), (feedLines ?: 3.0).toInt())
237
+ promise.resolve(null)
238
+ } catch (e: Exception) {
239
+ promise.reject("ERROR", e.message)
240
+ }
241
+ }
242
+ }
243
+ }
244
+
245
+ override fun htmlToPdf(html: String, pageWidthDp: Double?, heightDp: Double?, minPageHeightDp: Double?, promise: Promise) {
246
+ withService { service ->
247
+ service.printer.htmlToPdf(
248
+ html = html,
249
+ pageWidthDp = (pageWidthDp ?: 412.0).toInt(),
250
+ heightDp = heightDp?.toInt(),
251
+ minPageHeightDp = (minPageHeightDp ?: 1000.0).toInt()
252
+ ) { path ->
253
+ promise.resolve(path)
254
+ }
255
+ }
256
+ }
257
+
258
+ override fun printHtml(
259
+ html: String,
260
+ printerWidthDots: Double?,
261
+ pageWidthDp: Double?,
262
+ heightDp: Double?,
263
+ minPageHeightDp: Double?,
264
+ promise: Promise
265
+ ) {
266
+ withService { service ->
267
+ service.printer.printHtml(
268
+ html = html,
269
+ printerWidthDots = (printerWidthDots ?: 384.0).toInt(),
270
+ pageWidthDp = (pageWidthDp ?: 412.0).toInt(),
271
+ heightDp = heightDp?.toInt(),
272
+ minPageHeightDp = (minPageHeightDp ?: 1000.0).toInt()
273
+ ) { ok ->
274
+ promise.resolve(ok)
275
+ }
276
+ }
277
+ }
278
+
279
+ companion object {
280
+ const val NAME = NativeReactNativePrinterKitSpec.NAME
281
+ private const val PERMISSION_REQUEST_CODE = 4201
282
+ }
283
+ }
@@ -0,0 +1,31 @@
1
+ package com.rejaul.reactnativeprinterkit
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import java.util.HashMap
9
+
10
+ class ReactNativePrinterKitPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return if (name == ReactNativePrinterKitModule.NAME) {
13
+ ReactNativePrinterKitModule(reactContext)
14
+ } else {
15
+ null
16
+ }
17
+ }
18
+
19
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
20
+ mapOf(
21
+ ReactNativePrinterKitModule.NAME to ReactModuleInfo(
22
+ name = ReactNativePrinterKitModule.NAME,
23
+ className = ReactNativePrinterKitModule.NAME,
24
+ canOverrideExistingModule = false,
25
+ needsEagerInit = false,
26
+ isCxxModule = false,
27
+ isTurboModule = true
28
+ )
29
+ )
30
+ }
31
+ }
@@ -0,0 +1,5 @@
1
+ #import <ReactNativePrinterKitSpec/ReactNativePrinterKitSpec.h>
2
+
3
+ @interface ReactNativePrinterKit : NSObject <NativeReactNativePrinterKitSpec>
4
+
5
+ @end
@@ -0,0 +1,21 @@
1
+ #import "ReactNativePrinterKit.h"
2
+
3
+ @implementation ReactNativePrinterKit
4
+ - (NSNumber *)multiply:(double)a b:(double)b {
5
+ NSNumber *result = @(a * b);
6
+
7
+ return result;
8
+ }
9
+
10
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
11
+ (const facebook::react::ObjCTurboModule::InitParams &)params
12
+ {
13
+ return std::make_shared<facebook::react::NativeReactNativePrinterKitSpecJSI>(params);
14
+ }
15
+
16
+ + (NSString *)moduleName
17
+ {
18
+ return @"ReactNativePrinterKit";
19
+ }
20
+
21
+ @end
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry, Platform } from 'react-native';
4
+ function getModule() {
5
+ return Platform.OS === 'android' ? TurboModuleRegistry.getEnforcing('ReactNativePrinterKit') : {};
6
+ }
7
+ export default getModule();
8
+ //# sourceMappingURL=NativeReactNativePrinterKit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","Platform","getModule","OS","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactNativePrinterKit.ts"],"mappings":";;AAAA,SAASA,mBAAmB,EAAoBC,QAAQ,QAAQ,cAAc;AAgI9E,SAASC,SAASA,CAAA,EAAS;EACzB,OAAOD,QAAQ,CAACE,EAAE,KAAK,SAAS,GAC5BH,mBAAmB,CAACI,YAAY,CAAO,uBAAuB,CAAC,GAC9D,CAAC,CAAU;AAClB;AAEA,eAAeF,SAAS,CAAC,CAAC","ignoreList":[]}