react-native-pdf-jsi 4.2.1 → 4.3.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/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
  ---
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/react-native-pdf-jsi?style=flat-square&logo=npm&color=cb3837)](https://www.npmjs.com/package/react-native-pdf-jsi)
12
+ [![Expo Compatible](https://img.shields.io/badge/Expo-Compatible-4630EB?style=flat-square&logo=expo)](https://expo.dev)
12
13
  [![total downloads](https://img.shields.io/npm/dt/react-native-pdf-jsi?style=flat-square&logo=npm&color=cb3837)](https://www.npmjs.com/package/react-native-pdf-jsi)
13
14
  [![weekly downloads](https://img.shields.io/npm/dw/react-native-pdf-jsi?style=flat-square&logo=npm&color=cb3837)](https://www.npmjs.com/package/react-native-pdf-jsi)
14
15
  [![GitHub stars](https://img.shields.io/github/stars/126punith/react-native-pdf-jsi?style=flat-square&logo=github&color=181717)](https://github.com/126punith/react-native-pdf-jsi)
@@ -111,6 +112,51 @@ react-native link react-native-blob-util
111
112
  react-native link react-native-pdf-jsi
112
113
  ```
113
114
 
115
+ ### Expo Installation
116
+
117
+ This package works with **Expo development builds** (not Expo Go, as it requires native code).
118
+
119
+ **1. Install the package and peer dependencies:**
120
+
121
+ ```bash
122
+ npx expo install react-native-pdf-jsi react-native-blob-util @react-native-async-storage/async-storage
123
+ ```
124
+
125
+ **2. Add the config plugin to your `app.json` or `app.config.js`:**
126
+
127
+ ```json
128
+ {
129
+ "expo": {
130
+ "plugins": ["react-native-pdf-jsi"]
131
+ }
132
+ }
133
+ ```
134
+
135
+ **3. Rebuild your development build:**
136
+
137
+ ```bash
138
+ # Generate native projects
139
+ npx expo prebuild
140
+
141
+ # Run on iOS
142
+ npx expo run:ios
143
+
144
+ # Run on Android
145
+ npx expo run:android
146
+ ```
147
+
148
+ > **Note:** The config plugin automatically configures:
149
+ > - Android: Adds Jitpack repository for PDF rendering dependencies
150
+ > - iOS: Ensures PDFKit framework is properly linked
151
+
152
+ **For EAS Build users:**
153
+
154
+ ```bash
155
+ # Build development client
156
+ eas build --profile development --platform ios
157
+ eas build --profile development --platform android
158
+ ```
159
+
114
160
  ### Windows Installation
115
161
 
116
162
  1. Open your solution in Visual Studio 2019 (e.g., `windows\yourapp.sln`)
@@ -409,6 +455,38 @@ MIT License - see [LICENSE](LICENSE) file for details.
409
455
  - **Author**: Punith M ([@126punith](https://github.com/126punith))
410
456
 
411
457
  ## Recent Fixes
458
+
459
+ ### Expo Support (v4.3.0)
460
+ Added Expo config plugin for seamless integration with Expo development builds. The package now works with `npx expo prebuild` and `npx expo run:ios/android`.
461
+
462
+ **Installation:**
463
+ ```bash
464
+ npx expo install react-native-pdf-jsi react-native-blob-util @react-native-async-storage/async-storage
465
+ ```
466
+
467
+ **Configuration (app.json):**
468
+ ```json
469
+ {
470
+ "expo": {
471
+ "plugins": ["react-native-pdf-jsi"]
472
+ }
473
+ }
474
+ ```
475
+
476
+ **Note:** Expo Go is NOT supported (requires native code). Use Expo development builds.
477
+
478
+ ### PDFCompressor Module Fix (v4.2.2)
479
+ Fixed "Unable to resolve module react-native-pdf-jsi/src/PDFCompressor" error ([#17](https://github.com/126punith/react-native-pdf-jsi/issues/17)). The PDFCompressor module is now properly exported and accessible. Also fixed iOS compilation error for missing `RCTLogInfo` import. The compression feature now works correctly with accurate size estimates (~15-18% compression using native zlib deflate).
480
+
481
+ **Usage:**
482
+ ```jsx
483
+ import { PDFCompressor, CompressionPreset } from 'react-native-pdf-jsi';
484
+
485
+ // Compress a PDF
486
+ const result = await PDFCompressor.compressWithPreset(pdfPath, CompressionPreset.WEB);
487
+ console.log(`Compressed: ${result.originalSizeMB}MB → ${result.compressedSizeMB}MB`);
488
+ ```
489
+
412
490
  ### iOS Performance - Unnecessary Path Handlers (v4.2.1)
413
491
  Use v4.2.1 it contains stable fixes for IOS with unwanted debug logs removed
414
492
 
@@ -734,4 +734,78 @@ public class PDFExporter extends ReactContextBaseJavaModule {
734
734
  promise.reject("PAGE_COUNT_ERROR", e.getMessage());
735
735
  }
736
736
  }
737
+
738
+ /**
739
+ * Compress PDF using streaming processor
740
+ * Uses O(1) constant memory regardless of file size
741
+ * @param inputPath Input PDF file path
742
+ * @param outputPath Output compressed PDF file path
743
+ * @param compressionLevel Compression level (0-9, 9 is maximum compression)
744
+ * @param promise Promise to resolve with compression result
745
+ */
746
+ @ReactMethod
747
+ public void compressPDF(String inputPath, String outputPath, int compressionLevel, Promise promise) {
748
+ try {
749
+ Log.d(TAG, "compressPDF called with inputPath: " + inputPath + ", outputPath: " + outputPath + ", level: " + compressionLevel);
750
+
751
+ if (inputPath == null || inputPath.isEmpty()) {
752
+ promise.reject("INVALID_PATH", "Input file path is required");
753
+ return;
754
+ }
755
+
756
+ File inputFile = new File(inputPath);
757
+ if (!inputFile.exists()) {
758
+ promise.reject("FILE_NOT_FOUND", "Input PDF file not found: " + inputPath);
759
+ return;
760
+ }
761
+
762
+ // Generate output path if not provided
763
+ File outputFile;
764
+ if (outputPath == null || outputPath.isEmpty()) {
765
+ String baseName = inputFile.getName().replaceAll("\\.pdf$", "");
766
+ String outputFileName = generateTimestampedFileName(baseName + "_compressed", -1, "pdf");
767
+ outputFile = new File(inputFile.getParent(), outputFileName);
768
+ } else {
769
+ outputFile = new File(outputPath);
770
+ }
771
+
772
+ // Ensure output directory exists
773
+ File outputDir = outputFile.getParentFile();
774
+ if (outputDir != null && !outputDir.exists()) {
775
+ outputDir.mkdirs();
776
+ }
777
+
778
+ Log.d(TAG, "Starting compression: " + inputFile.getAbsolutePath() + " -> " + outputFile.getAbsolutePath());
779
+
780
+ // Use StreamingPDFProcessor for O(1) memory compression
781
+ StreamingPDFProcessor processor = new StreamingPDFProcessor();
782
+ StreamingPDFProcessor.CompressionResult result = processor.compressPDFStreaming(
783
+ inputFile,
784
+ outputFile,
785
+ compressionLevel
786
+ );
787
+
788
+ // Build response
789
+ WritableMap response = Arguments.createMap();
790
+ response.putDouble("originalSize", result.originalSize);
791
+ response.putDouble("compressedSize", result.compressedSize);
792
+ response.putDouble("durationMs", result.durationMs);
793
+ response.putDouble("compressionRatio", result.compressionRatio);
794
+ response.putDouble("spaceSavedPercent", result.spaceSavedPercent);
795
+ response.putString("outputPath", outputFile.getAbsolutePath());
796
+ response.putBoolean("success", true);
797
+
798
+ Log.d(TAG, String.format("Compression complete: %.2f MB -> %.2f MB (%.1f%% saved) in %dms",
799
+ result.originalSize / (1024.0 * 1024.0),
800
+ result.compressedSize / (1024.0 * 1024.0),
801
+ result.spaceSavedPercent,
802
+ result.durationMs));
803
+
804
+ promise.resolve(response);
805
+
806
+ } catch (Exception e) {
807
+ Log.e(TAG, "Error compressing PDF", e);
808
+ promise.reject("COMPRESSION_ERROR", e.getMessage(), e);
809
+ }
810
+ }
737
811
  }
package/app.plugin.js ADDED
@@ -0,0 +1,2 @@
1
+ // Expo config plugin entry point
2
+ module.exports = require('./plugin/build').default;
package/index.d.ts CHANGED
@@ -219,3 +219,247 @@ export const PDFCache: PDFCacheManager;
219
219
  * CacheManager (alias for PDFCache)
220
220
  */
221
221
  export const CacheManager: PDFCacheManager;
222
+
223
+ // ========================================
224
+ // PDFCompressor (PDF Compression)
225
+ // ========================================
226
+
227
+ /**
228
+ * Compression presets for different use cases
229
+ */
230
+ export enum CompressionPreset {
231
+ /** Optimized for email attachments (high compression, smaller file) */
232
+ EMAIL = 'email',
233
+ /** Optimized for web viewing (balanced compression) */
234
+ WEB = 'web',
235
+ /** Optimized for mobile devices (good compression, fast decompression) */
236
+ MOBILE = 'mobile',
237
+ /** Optimized for printing (low compression, high quality) */
238
+ PRINT = 'print',
239
+ /** Optimized for long-term archival (maximum compression) */
240
+ ARCHIVE = 'archive',
241
+ /** Custom compression settings */
242
+ CUSTOM = 'custom'
243
+ }
244
+
245
+ /**
246
+ * Compression levels (0-9, higher = more compression but slower)
247
+ */
248
+ export enum CompressionLevel {
249
+ NONE = 0,
250
+ FASTEST = 1,
251
+ FAST = 3,
252
+ BALANCED = 5,
253
+ DEFAULT = 6,
254
+ GOOD = 7,
255
+ BETTER = 8,
256
+ BEST = 9
257
+ }
258
+
259
+ /**
260
+ * Compression options
261
+ */
262
+ export interface CompressionOptions {
263
+ /** Compression preset (from CompressionPreset) */
264
+ preset?: CompressionPreset;
265
+ /** Compression level (0-9), overrides preset */
266
+ level?: number;
267
+ /** Output file path (optional, auto-generated if not provided) */
268
+ outputPath?: string;
269
+ /** Progress callback function */
270
+ onProgress?: (progress: { progress: number; bytesProcessed: number; totalBytes: number }) => void;
271
+ }
272
+
273
+ /**
274
+ * Compression result
275
+ */
276
+ export interface CompressionResult {
277
+ /** Whether compression was successful */
278
+ success: boolean;
279
+ /** Input file path */
280
+ inputPath: string;
281
+ /** Output file path */
282
+ outputPath: string;
283
+ /** Original file size in bytes */
284
+ originalSize: number;
285
+ /** Compressed file size in bytes */
286
+ compressedSize: number;
287
+ /** Original file size in MB */
288
+ originalSizeMB: number;
289
+ /** Compressed file size in MB */
290
+ compressedSizeMB: number;
291
+ /** Compression ratio (0-1, lower is better) */
292
+ compressionRatio: number;
293
+ /** Space saved percentage */
294
+ spaceSavedPercent: number;
295
+ /** Duration in milliseconds */
296
+ durationMs: number;
297
+ /** Throughput in MB/s */
298
+ throughputMBps: number;
299
+ /** Preset used */
300
+ preset: CompressionPreset;
301
+ /** Compression level used */
302
+ compressionLevel: number;
303
+ /** Method used (native_streaming or fallback) */
304
+ method: string;
305
+ }
306
+
307
+ /**
308
+ * Compression estimate result
309
+ */
310
+ export interface CompressionEstimate {
311
+ /** Input file path */
312
+ inputPath: string;
313
+ /** Original file size in bytes */
314
+ originalSize: number;
315
+ /** Original file size in MB */
316
+ originalSizeMB: number;
317
+ /** Estimated compressed size in bytes */
318
+ estimatedCompressedSize: number;
319
+ /** Estimated compressed size in MB */
320
+ estimatedCompressedSizeMB: number;
321
+ /** Estimated compression ratio */
322
+ estimatedCompressionRatio: number;
323
+ /** Estimated space savings percentage */
324
+ estimatedSavingsPercent: number;
325
+ /** Estimated duration in milliseconds */
326
+ estimatedDurationMs: number;
327
+ /** Preset used for estimate */
328
+ preset: CompressionPreset;
329
+ /** Description of the preset */
330
+ presetDescription: string;
331
+ /** Confidence level of the estimate */
332
+ confidence: 'low' | 'medium' | 'high';
333
+ /** Additional notes */
334
+ note: string;
335
+ }
336
+
337
+ /**
338
+ * PDFCompressor capabilities
339
+ */
340
+ export interface CompressionCapabilities {
341
+ /** Whether streaming compression is available */
342
+ streamingCompression: boolean;
343
+ /** Available presets */
344
+ presets: CompressionPreset[];
345
+ /** Maximum file size in MB */
346
+ maxFileSizeMB: number;
347
+ /** Supported platforms */
348
+ supportedPlatforms: string[];
349
+ /** Current platform */
350
+ currentPlatform: string;
351
+ /** Whether native module is available */
352
+ nativeModuleAvailable: boolean;
353
+ }
354
+
355
+ /**
356
+ * PDFCompressor Manager for PDF compression
357
+ * Uses native streaming for O(1) memory operations on large files (1GB+)
358
+ */
359
+ export interface PDFCompressorManager {
360
+ /**
361
+ * Check if compression functionality is available
362
+ * @returns True if compression is available
363
+ */
364
+ isAvailable(): boolean;
365
+
366
+ /**
367
+ * Get compression capabilities
368
+ * @returns Capabilities object
369
+ */
370
+ getCapabilities(): CompressionCapabilities;
371
+
372
+ /**
373
+ * Compress a PDF file
374
+ * @param inputPath Path to input PDF file
375
+ * @param options Compression options
376
+ * @returns Promise resolving to compression result
377
+ */
378
+ compress(inputPath: string, options?: CompressionOptions): Promise<CompressionResult>;
379
+
380
+ /**
381
+ * Compress PDF with a specific preset
382
+ * @param inputPath Path to input PDF file
383
+ * @param preset Compression preset
384
+ * @param outputPath Output file path (optional)
385
+ * @returns Promise resolving to compression result
386
+ */
387
+ compressWithPreset(inputPath: string, preset: CompressionPreset, outputPath?: string): Promise<CompressionResult>;
388
+
389
+ /**
390
+ * Compress PDF for email (maximum compression)
391
+ * @param inputPath Path to input PDF file
392
+ * @param outputPath Output file path (optional)
393
+ * @returns Promise resolving to compression result
394
+ */
395
+ compressForEmail(inputPath: string, outputPath?: string): Promise<CompressionResult>;
396
+
397
+ /**
398
+ * Compress PDF for web viewing
399
+ * @param inputPath Path to input PDF file
400
+ * @param outputPath Output file path (optional)
401
+ * @returns Promise resolving to compression result
402
+ */
403
+ compressForWeb(inputPath: string, outputPath?: string): Promise<CompressionResult>;
404
+
405
+ /**
406
+ * Compress PDF for mobile viewing
407
+ * @param inputPath Path to input PDF file
408
+ * @param outputPath Output file path (optional)
409
+ * @returns Promise resolving to compression result
410
+ */
411
+ compressForMobile(inputPath: string, outputPath?: string): Promise<CompressionResult>;
412
+
413
+ /**
414
+ * Compress PDF for archival (maximum compression)
415
+ * @param inputPath Path to input PDF file
416
+ * @param outputPath Output file path (optional)
417
+ * @returns Promise resolving to compression result
418
+ */
419
+ compressForArchive(inputPath: string, outputPath?: string): Promise<CompressionResult>;
420
+
421
+ /**
422
+ * Estimate compression result without actually compressing
423
+ * @param inputPath Path to input PDF file
424
+ * @param preset Compression preset
425
+ * @returns Promise resolving to estimated compression result
426
+ */
427
+ estimateCompression(inputPath: string, preset?: CompressionPreset): Promise<CompressionEstimate>;
428
+
429
+ /**
430
+ * Delete a compressed file
431
+ * @param filePath Path to file to delete
432
+ * @returns Promise resolving to true if deleted successfully
433
+ */
434
+ deleteCompressedFile(filePath: string): Promise<boolean>;
435
+
436
+ /**
437
+ * Get preset configuration
438
+ * @param preset Preset name
439
+ * @returns Preset configuration
440
+ */
441
+ getPresetConfig(preset: CompressionPreset): {
442
+ level: CompressionLevel;
443
+ targetSizeKB: number | null;
444
+ description: string;
445
+ };
446
+
447
+ /**
448
+ * Get module information
449
+ * @returns Module info object
450
+ */
451
+ getModuleInfo(): {
452
+ name: string;
453
+ version: string;
454
+ platform: string;
455
+ nativeAvailable: boolean;
456
+ presets: string[];
457
+ compressionLevels: string[];
458
+ capabilities: CompressionCapabilities;
459
+ };
460
+ }
461
+
462
+ /**
463
+ * PDFCompressor singleton instance
464
+ */
465
+ export const PDFCompressor: PDFCompressorManager;
package/index.js CHANGED
@@ -742,6 +742,7 @@ import BookmarkManager from './src/managers/BookmarkManager';
742
742
  import AnalyticsManager from './src/managers/AnalyticsManager';
743
743
  import FileManager from './src/managers/FileManager';
744
744
  import CacheManager from './src/managers/CacheManager';
745
+ import PDFCompressor, { CompressionPreset, CompressionLevel } from './src/PDFCompressor';
745
746
 
746
747
  // Alias for backward compatibility and intuitive naming
747
748
  export const PDFCache = CacheManager;
@@ -751,7 +752,10 @@ export {
751
752
  BookmarkManager,
752
753
  AnalyticsManager,
753
754
  FileManager,
754
- CacheManager
755
+ CacheManager,
756
+ PDFCompressor,
757
+ CompressionPreset,
758
+ CompressionLevel
755
759
  };
756
760
 
757
761
  // ========================================
@@ -1,5 +1,7 @@
1
1
  #import "PDFExporter.h"
2
2
  #import "ImagePool.h"
3
+ #import "StreamingPDFProcessor.h"
4
+ #import <React/RCTLog.h>
3
5
  #import <PDFKit/PDFKit.h>
4
6
  #import <UIKit/UIKit.h>
5
7
 
@@ -956,4 +958,85 @@ RCT_EXPORT_METHOD(getPageCount:(NSString *)filePath
956
958
  resolve(@(pageCount));
957
959
  }
958
960
 
961
+ /**
962
+ * Compress PDF using streaming processor
963
+ * Uses O(1) constant memory regardless of file size
964
+ * @param inputPath Input PDF file path
965
+ * @param outputPath Output compressed PDF file path
966
+ * @param compressionLevel Compression level (0-9, 9 is maximum compression)
967
+ */
968
+ RCT_EXPORT_METHOD(compressPDF:(NSString *)inputPath
969
+ outputPath:(NSString *)outputPath
970
+ compressionLevel:(int)compressionLevel
971
+ resolver:(RCTPromiseResolveBlock)resolve
972
+ rejecter:(RCTPromiseRejectBlock)reject) {
973
+
974
+ RCTLogInfo(@"compressPDF called with inputPath: %@, outputPath: %@, level: %d", inputPath, outputPath, compressionLevel);
975
+
976
+ if (!inputPath || inputPath.length == 0) {
977
+ reject(@"INVALID_PATH", @"Input file path is required", nil);
978
+ return;
979
+ }
980
+
981
+ NSFileManager *fileManager = [NSFileManager defaultManager];
982
+ if (![fileManager fileExistsAtPath:inputPath]) {
983
+ reject(@"FILE_NOT_FOUND", [NSString stringWithFormat:@"Input PDF file not found: %@", inputPath], nil);
984
+ return;
985
+ }
986
+
987
+ // Generate output path if not provided
988
+ NSString *finalOutputPath = outputPath;
989
+ if (!finalOutputPath || finalOutputPath.length == 0) {
990
+ NSString *directory = [inputPath stringByDeletingLastPathComponent];
991
+ NSString *baseName = [[inputPath lastPathComponent] stringByDeletingPathExtension];
992
+ NSString *outputFileName = [self generateTimestampedFileName:[baseName stringByAppendingString:@"_compressed"] pageNum:-1 extension:@"pdf"];
993
+ finalOutputPath = [directory stringByAppendingPathComponent:outputFileName];
994
+ }
995
+
996
+ // Ensure output directory exists
997
+ NSString *outputDir = [finalOutputPath stringByDeletingLastPathComponent];
998
+ if (![fileManager fileExistsAtPath:outputDir]) {
999
+ NSError *error;
1000
+ [fileManager createDirectoryAtPath:outputDir withIntermediateDirectories:YES attributes:nil error:&error];
1001
+ if (error) {
1002
+ reject(@"DIR_CREATE_ERROR", @"Failed to create output directory", error);
1003
+ return;
1004
+ }
1005
+ }
1006
+
1007
+ RCTLogInfo(@"Starting compression: %@ -> %@", inputPath, finalOutputPath);
1008
+
1009
+ // Use StreamingPDFProcessor for O(1) memory compression
1010
+ StreamingPDFProcessor *processor = [StreamingPDFProcessor sharedInstance];
1011
+ NSError *error;
1012
+ CompressionResult *result = [processor compressPDFStreaming:inputPath
1013
+ outputPath:finalOutputPath
1014
+ compressionLevel:compressionLevel
1015
+ error:&error];
1016
+
1017
+ if (error || !result) {
1018
+ reject(@"COMPRESSION_ERROR", error ? error.localizedDescription : @"Compression failed", error);
1019
+ return;
1020
+ }
1021
+
1022
+ // Build response
1023
+ NSDictionary *response = @{
1024
+ @"originalSize": @(result.originalSize),
1025
+ @"compressedSize": @(result.compressedSize),
1026
+ @"durationMs": @(result.durationMs),
1027
+ @"compressionRatio": @(result.compressionRatio),
1028
+ @"spaceSavedPercent": @(result.spaceSavedPercent),
1029
+ @"outputPath": finalOutputPath,
1030
+ @"success": @YES
1031
+ };
1032
+
1033
+ RCTLogInfo(@"Compression complete: %.2f MB -> %.2f MB (%.1f%% saved) in %.0fms",
1034
+ result.originalSize / (1024.0 * 1024.0),
1035
+ result.compressedSize / (1024.0 * 1024.0),
1036
+ result.spaceSavedPercent,
1037
+ result.durationMs);
1038
+
1039
+ resolve(response);
1040
+ }
1041
+
959
1042
  @end
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "react-native-pdf-jsi",
3
- "version": "4.2.1",
3
+ "version": "4.3.0",
4
4
  "summary": "High-performance React Native PDF viewer with JSI acceleration - up to 80x faster than traditional bridge",
5
5
  "description": "🚀 Ultra-fast React Native PDF viewer with JSI (JavaScript Interface) integration for maximum performance. Features lazy loading, smart caching, progressive loading, and zero-bridge overhead operations. Perfect for large PDF files with 30-day persistent cache and advanced memory optimization. Google Play 16KB page size compliant for Android 15+. Supports iOS, Android, and Windows platforms.",
6
6
  "main": "index.js",
7
7
  "typings": "./index.d.ts",
8
+ "app": {
9
+ "plugin": "./plugin/build"
10
+ },
8
11
  "repository": {
9
12
  "type": "git",
10
13
  "url": "git+https://github.com/126punith/react-native-pdf-jsi.git"
@@ -50,7 +53,9 @@
50
53
  "optimization",
51
54
  "caching",
52
55
  "persistent-cache",
53
- "react-native-pdf-jsi-enhanced"
56
+ "react-native-pdf-jsi-enhanced",
57
+ "expo",
58
+ "expo-plugin"
54
59
  ],
55
60
  "author": {
56
61
  "name": "Punith M",
@@ -69,7 +74,13 @@
69
74
  "devDependencies": {
70
75
  "@babel/core": "^7.20.2",
71
76
  "@babel/runtime": "^7.20.1",
72
- "prop-types": "^15.7.2"
77
+ "@expo/config-plugins": "^9.0.0",
78
+ "prop-types": "^15.7.2",
79
+ "typescript": "^5.0.0"
80
+ },
81
+ "scripts": {
82
+ "build:plugin": "tsc -p plugin/tsconfig.json",
83
+ "prepublishOnly": "npm run build:plugin"
73
84
  },
74
85
  "peerDependencies": {
75
86
  "@react-native-async-storage/async-storage": ">=1.17.0",
@@ -82,6 +93,8 @@
82
93
  "ios/",
83
94
  "windows/",
84
95
  "src/",
96
+ "plugin/",
97
+ "app.plugin.js",
85
98
  "DoubleTapView.js",
86
99
  "index.d.ts",
87
100
  "index.js",
@@ -0,0 +1,3 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ declare const _default: ConfigPlugin<void>;
3
+ export default _default;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_plugins_1 = require("@expo/config-plugins");
4
+ const withPdfJsiAndroid_1 = require("./withPdfJsiAndroid");
5
+ const withPdfJsiIos_1 = require("./withPdfJsiIos");
6
+ const pkg = require('../../package.json');
7
+ /**
8
+ * Expo config plugin for react-native-pdf-jsi
9
+ *
10
+ * This plugin configures the native projects for Expo development builds.
11
+ * It handles:
12
+ * - Android: Jitpack repository for AndroidPdfViewer, NDK configuration
13
+ * - iOS: PDFKit framework linking
14
+ *
15
+ * Note: This package requires development builds and won't work with Expo Go.
16
+ */
17
+ const withPdfJsi = (config) => {
18
+ // Warn about peer dependencies
19
+ console.log('[react-native-pdf-jsi] Remember to install peer dependencies:\n' +
20
+ ' - react-native-blob-util\n' +
21
+ ' - @react-native-async-storage/async-storage');
22
+ config = (0, withPdfJsiAndroid_1.withPdfJsiAndroid)(config);
23
+ config = (0, withPdfJsiIos_1.withPdfJsiIos)(config);
24
+ return config;
25
+ };
26
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withPdfJsi, pkg.name, pkg.version);
@@ -0,0 +1,8 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ /**
3
+ * Android config plugin for react-native-pdf-jsi
4
+ *
5
+ * Configures the Android project to support the PDF library:
6
+ * - Adds Jitpack repository for AndroidPdfViewer dependency
7
+ */
8
+ export declare const withPdfJsiAndroid: ConfigPlugin;