react-native-optimized-pdf 1.1.0 → 1.2.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.
@@ -1,5 +1,6 @@
1
1
  import UIKit
2
2
  import React
3
+ import PDFKit
3
4
 
4
5
  /// Protocol for receiving PDF view events.
5
6
  @objc protocol OptimizedPDFViewDelegate: AnyObject {
@@ -44,7 +45,7 @@ final class OptimizedPDFView: UIScrollView {
44
45
  @objc var enableAntialiasing: Bool = true {
45
46
  didSet {
46
47
  configuration.enableAntialiasing = enableAntialiasing
47
- tiledPageView.enableAntialiasing = enableAntialiasing
48
+ tiledPageView?.enableAntialiasing = enableAntialiasing
48
49
  }
49
50
  }
50
51
 
@@ -73,7 +74,8 @@ final class OptimizedPDFView: UIScrollView {
73
74
  // MARK: - Private Properties
74
75
 
75
76
  private var pdfDocument: CGPDFDocument?
76
- private let tiledPageView: TiledPDFPageView
77
+ private var tiledPageView: TiledPDFPageView!
78
+ private var pdfURL: URL?
77
79
  private var configuration = PDFConfiguration.default
78
80
  private let documentLoader: PDFDocumentLoading
79
81
 
@@ -145,6 +147,8 @@ private extension OptimizedPDFView {
145
147
 
146
148
  func handleSourceChange() {
147
149
  resetDocument()
150
+ pdfURL = nil
151
+ FlattenedPageCache.shared.removeAll()
148
152
  pendingPageIndex = page.intValue
149
153
  needsLoad = true
150
154
  setNeedsLayout()
@@ -173,6 +177,9 @@ private extension OptimizedPDFView {
173
177
  func loadDocument() {
174
178
  guard !source.isEmpty else { return }
175
179
 
180
+ let path = source.hasPrefix("file://") ? String(source.dropFirst(7)) : source
181
+ pdfURL = URL(fileURLWithPath: path)
182
+
176
183
  let result = documentLoader.loadDocument(from: source, password: configuration.password)
177
184
 
178
185
  switch result {
@@ -234,7 +241,22 @@ private extension OptimizedPDFView {
234
241
  currentPageRect = pageRect
235
242
 
236
243
  prepareForPageDisplay()
237
- configureTiledView(for: page, rect: pageRect)
244
+
245
+ tiledPageView?.cancel()
246
+ tiledPageView?.removeFromSuperview()
247
+
248
+ let newView = TiledPDFPageView(frame: CGRect(origin: .zero, size: pageRect.size))
249
+ newView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
250
+ newView.configuration = configuration
251
+ newView.pdfURL = pdfURL
252
+ newView.pageIndex = index
253
+ newView.pdfPage = page
254
+ addSubview(newView)
255
+ tiledPageView = newView
256
+
257
+ contentSize = pageRect.size
258
+ tiledPageView.preparePage()
259
+
238
260
  applyFitScale(for: pageRect)
239
261
  centerContent()
240
262
  notifyPageDisplayed(index: index, size: pageRect.size)
@@ -245,11 +267,6 @@ private extension OptimizedPDFView {
245
267
  contentOffset = .zero
246
268
  }
247
269
 
248
- func configureTiledView(for page: CGPDFPage, rect: CGRect) {
249
- tiledPageView.updateFrame(for: page)
250
- contentSize = rect.size
251
- }
252
-
253
270
  func applyFitScale(for pageRect: CGRect) {
254
271
  let fitScale = calculateFitScale(for: pageRect)
255
272
  minimumZoomScale = fitScale
@@ -1,3 +1,8 @@
1
+ import UIKit
2
+ import CoreGraphics
3
+ import PDFKit
4
+
5
+
1
6
  import UIKit
2
7
  import CoreGraphics
3
8
 
@@ -5,40 +10,93 @@ import CoreGraphics
5
10
  ///
6
11
  /// CATiledLayer divides the content into tiles, allowing smooth zooming and scrolling
7
12
  /// without rendering the entire PDF at once. This is essential for large PDF documents.
13
+
14
+ // MARK: - Global cache of flattened pages
15
+ final class FlattenedPageCache {
16
+ static let shared = FlattenedPageCache()
17
+
18
+ private let cache = NSCache<NSString, FlattenedPageEntry>()
19
+
20
+ private init() {
21
+ cache.countLimit = 10
22
+ }
23
+
24
+ func entry(forKey key: String) -> FlattenedPageEntry? {
25
+ cache.object(forKey: key as NSString)
26
+ }
27
+
28
+ func setEntry(_ entry: FlattenedPageEntry, forKey key: String) {
29
+ cache.setObject(entry, forKey: key as NSString)
30
+ }
31
+
32
+ func removeEntry(forKey key: String) {
33
+ cache.removeObject(forKey: key as NSString)
34
+ }
35
+
36
+ func removeAll() {
37
+ cache.removeAllObjects()
38
+ }
39
+ }
40
+
41
+ final class FlattenedPageEntry: NSObject {
42
+ let document: CGPDFDocument
43
+ let page: CGPDFPage
44
+
45
+ init(document: CGPDFDocument, page: CGPDFPage) {
46
+ self.document = document
47
+ self.page = page
48
+ }
49
+ }
50
+
51
+ // MARK: - Atomic flag for thread-safe cancellation
52
+
53
+ final class OSAtomicFlag {
54
+ private var _value: Bool = false
55
+ private var _lock = os_unfair_lock()
56
+
57
+ func set() {
58
+ os_unfair_lock_lock(&_lock)
59
+ _value = true
60
+ os_unfair_lock_unlock(&_lock)
61
+ }
62
+
63
+ func isSet() -> Bool {
64
+ os_unfair_lock_lock(&_lock)
65
+ let v = _value
66
+ os_unfair_lock_unlock(&_lock)
67
+ return v
68
+ }
69
+ }
70
+
71
+ // MARK: - TiledPDFPageView
72
+
8
73
  final class TiledPDFPageView: UIView {
9
74
 
10
75
  // MARK: - Properties
11
76
 
12
- /// The PDF page to render.
13
77
  var pdfPage: CGPDFPage? {
14
- didSet {
15
- setNeedsDisplay()
16
- }
78
+ didSet { setNeedsDisplay() }
17
79
  }
18
80
 
19
- /// Whether antialiasing is enabled for rendering.
81
+ var pdfURL: URL?
82
+ var pageIndex: Int = 0
83
+
20
84
  var enableAntialiasing: Bool = true {
21
- didSet {
22
- setNeedsDisplay()
23
- }
85
+ didSet { setNeedsDisplay() }
24
86
  }
25
87
 
26
- /// The configuration for tiled rendering.
27
88
  var configuration: PDFConfiguration = .default {
28
- didSet {
29
- applyConfiguration()
30
- }
89
+ didSet { applyConfiguration() }
31
90
  }
32
91
 
33
- /// Returns CATiledLayer as the backing layer.
34
- override class var layerClass: AnyClass {
35
- CATiledLayer.self
36
- }
92
+ override class var layerClass: AnyClass { CATiledLayer.self }
37
93
 
38
- /// Typed accessor for the tiled layer.
39
- private var tiledLayer: CATiledLayer {
40
- layer as! CATiledLayer
41
- }
94
+ private var tiledLayer: CATiledLayer { layer as! CATiledLayer }
95
+
96
+ private var _activePage: CGPDFPage?
97
+ private var _pdfKitDocument: PDFDocument?
98
+ private var _generation: UInt = 0
99
+ private let _cancelled = OSAtomicFlag()
42
100
 
43
101
  // MARK: - Initialization
44
102
 
@@ -52,7 +110,6 @@ final class TiledPDFPageView: UIView {
52
110
  commonInit()
53
111
  }
54
112
 
55
- /// Initializes with a specific configuration.
56
113
  convenience init(frame: CGRect, configuration: PDFConfiguration) {
57
114
  self.init(frame: frame)
58
115
  self.configuration = configuration
@@ -74,35 +131,138 @@ final class TiledPDFPageView: UIView {
74
131
  enableAntialiasing = configuration.enableAntialiasing
75
132
  }
76
133
 
134
+ // MARK: - Cancellation
135
+
136
+ func cancel() {
137
+ _cancelled.set()
138
+ }
139
+
140
+ private var currentCacheKey: String {
141
+ guard let url = pdfURL else { return "" }
142
+ return "\(url.absoluteString)_page\(pageIndex)"
143
+ }
144
+
145
+ // MARK: - Prepare Page (Flatten Pipeline)
146
+
147
+ func preparePage() {
148
+ _generation &+= 1
149
+ let currentGen = _generation
150
+
151
+ let cacheKey = currentCacheKey
152
+ if let cached = FlattenedPageCache.shared.entry(forKey: cacheKey) {
153
+ _activePage = cached.page
154
+ setNeedsDisplay()
155
+ return
156
+ }
157
+
158
+ _activePage = pdfPage
159
+
160
+ guard let url = pdfURL,
161
+ let originalPage = pdfPage else { return }
162
+
163
+ let idx = pageIndex
164
+ let originalCropBox = originalPage.getBoxRect(.cropBox)
165
+ let rotation = originalPage.rotationAngle
166
+
167
+ let pdfKitDoc: PDFDocument
168
+ if let existing = _pdfKitDocument {
169
+ pdfKitDoc = existing
170
+ } else if let newDoc = PDFDocument(url: url) {
171
+ _pdfKitDocument = newDoc
172
+ pdfKitDoc = newDoc
173
+ } else {
174
+ return
175
+ }
176
+
177
+ guard let pdfKitPage = pdfKitDoc.page(at: idx) else { return }
178
+ let annotations = pdfKitPage.annotations
179
+ if annotations.isEmpty { return }
180
+
181
+ DispatchQueue.global(qos: .userInitiated).async { [weak self] in
182
+ guard let self = self else { return }
183
+
184
+ let entry = Self.createFlattenedEntry(
185
+ pdfKitPage: pdfKitPage,
186
+ originalCropBox: originalCropBox,
187
+ rotation: Int(rotation)
188
+ )
189
+
190
+ guard let entry = entry else { return }
191
+ FlattenedPageCache.shared.setEntry(entry, forKey: cacheKey)
192
+
193
+ DispatchQueue.main.async { [weak self] in
194
+ guard let self = self, self._generation == currentGen else { return }
195
+ self._activePage = entry.page
196
+ self.setNeedsDisplay()
197
+ }
198
+ }
199
+ }
200
+
201
+ // MARK: - Flattening Logic
202
+ private static func createFlattenedEntry(
203
+ pdfKitPage: PDFPage,
204
+ originalCropBox: CGRect,
205
+ rotation: Int
206
+ ) -> FlattenedPageEntry? {
207
+ let finalSize: CGSize
208
+ if rotation == 90 || rotation == 270 {
209
+ finalSize = CGSize(width: originalCropBox.height, height: originalCropBox.width)
210
+ } else {
211
+ finalSize = originalCropBox.size
212
+ }
213
+
214
+ var mediaBox = CGRect(origin: .zero, size: finalSize)
215
+
216
+ let pdfData = NSMutableData()
217
+ guard let consumer = CGDataConsumer(data: pdfData as CFMutableData),
218
+ let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, nil) else {
219
+ return nil
220
+ }
221
+
222
+ pdfContext.beginPage(mediaBox: &mediaBox)
223
+
224
+ if originalCropBox.origin.x != 0 || originalCropBox.origin.y != 0 {
225
+ pdfContext.translateBy(x: -originalCropBox.origin.x, y: -originalCropBox.origin.y)
226
+ }
227
+
228
+ pdfKitPage.draw(with: .cropBox, to: pdfContext)
229
+
230
+ pdfContext.endPage()
231
+ pdfContext.closePDF()
232
+
233
+ guard let provider = CGDataProvider(data: pdfData as CFData),
234
+ let flattenedDoc = CGPDFDocument(provider),
235
+ let flattenedCGPage = flattenedDoc.page(at: 1) else {
236
+ return nil
237
+ }
238
+
239
+ return FlattenedPageEntry(document: flattenedDoc, page: flattenedCGPage)
240
+ }
241
+
77
242
  // MARK: - Rendering
78
243
 
79
244
  override func draw(_ rect: CGRect) {
245
+ guard !_cancelled.isSet() else { return }
246
+
80
247
  guard let context = UIGraphicsGetCurrentContext(),
81
- let page = pdfPage else {
82
- return
83
- }
248
+ let page = _activePage else { return }
84
249
 
85
250
  renderPage(page, in: context, rect: rect)
86
251
  }
87
252
 
88
- /// Renders the PDF page in the given graphics context.
89
253
  private func renderPage(_ page: CGPDFPage, in context: CGContext, rect: CGRect) {
90
254
  context.saveGState()
91
255
  defer { context.restoreGState() }
92
256
 
93
- // Configure rendering quality
94
257
  context.setShouldAntialias(enableAntialiasing)
95
258
  context.interpolationQuality = determineInterpolationQuality()
96
259
 
97
- // Fill background
98
260
  context.setFillColor(UIColor.white.cgColor)
99
261
  context.fill(rect)
100
262
 
101
- // Transform coordinate system (UIKit uses top-left origin, PDF uses bottom-left)
102
263
  context.translateBy(x: 0, y: bounds.height)
103
264
  context.scaleBy(x: 1.0, y: -1.0)
104
265
 
105
- // Apply PDF transform to fit the page
106
266
  let pdfTransform = page.getDrawingTransform(
107
267
  .cropBox,
108
268
  rect: bounds,
@@ -110,12 +270,10 @@ final class TiledPDFPageView: UIView {
110
270
  preserveAspectRatio: true
111
271
  )
112
272
  context.concatenate(pdfTransform)
113
-
114
273
  // Draw the page
115
274
  context.drawPDFPage(page)
116
275
  }
117
276
 
118
- /// Determines the interpolation quality based on zoom level.
119
277
  private func determineInterpolationQuality() -> CGInterpolationQuality {
120
278
  tiledLayer.levelsOfDetail == 1 ? .low : .high
121
279
  }
@@ -125,9 +283,9 @@ final class TiledPDFPageView: UIView {
125
283
 
126
284
  extension TiledPDFPageView {
127
285
 
128
- /// Prepares the view for displaying a new page.
129
286
  func prepareForReuse() {
130
287
  pdfPage = nil
288
+ _activePage = nil
131
289
  layer.contents = nil
132
290
  }
133
291
 
@@ -137,4 +295,18 @@ extension TiledPDFPageView {
137
295
  frame = CGRect(origin: .zero, size: pageRect.size)
138
296
  pdfPage = page
139
297
  }
298
+
299
+ func invalidateCache() {
300
+ FlattenedPageCache.shared.removeEntry(forKey: currentCacheKey)
301
+ _activePage = pdfPage
302
+ _pdfKitDocument = nil
303
+ setNeedsDisplay()
304
+ }
305
+
306
+ func invalidateAllCache() {
307
+ FlattenedPageCache.shared.removeAll()
308
+ _pdfKitDocument = nil
309
+ _activePage = pdfPage
310
+ setNeedsDisplay()
311
+ }
140
312
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-native-optimized-pdf",
3
- "version": "1.1.0",
4
- "description": "Ultra high-performance PDF viewer for React Native. Renders massive PDFs (1000+ pages) with extreme zoom levels while using minimal memory. 10x faster than native PDFKit on iOS, prevents crashes on large documents. Uses CATiledLayer (iOS) and PdfRenderer (Android) for tile-based rendering.",
3
+ "version": "1.2.0",
4
+ "description": "React Native PDF viewer with high performance, zoom, and support for large PDF files. Fast, memory-efficient, and supports annotations (annots) on iOS and Android.",
5
5
  "main": "index.ts",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
@@ -14,21 +14,27 @@
14
14
  },
15
15
  "keywords": [
16
16
  "react-native",
17
+ "react-native-pdf",
17
18
  "pdf",
18
19
  "pdf-viewer",
19
- "viewer",
20
+ "react-native-pdf-viewer",
21
+ "pdf-reader",
22
+ "pdf-renderer",
23
+ "pdf-display",
20
24
  "ios",
21
25
  "android",
22
- "performance",
23
- "high-performance",
24
26
  "large-pdf",
27
+ "big-pdf",
28
+ "pdf-performance",
29
+ "fast-pdf",
25
30
  "memory-efficient",
26
31
  "tiled-rendering",
27
32
  "zoom",
28
- "catiled-layer",
29
- "pdfrenderer",
30
- "no-crash",
31
- "optimized"
33
+ "annotations",
34
+ "annots",
35
+ "pdfkit",
36
+ "pdfium",
37
+ "catiledlayer"
32
38
  ],
33
39
  "author": "Your Name",
34
40
  "license": "MIT",
@@ -39,8 +45,8 @@
39
45
  "devDependencies": {
40
46
  "@react-native-community/eslint-config": "^3.2.0",
41
47
  "@types/crypto-js": "^4.2.2",
42
- "@types/react": "^18.0.0",
43
- "@types/react-native": "^0.72.0",
48
+ "@types/react": "^18.2.6",
49
+ "@types/react-native": "^0.64.19",
44
50
  "@typescript-eslint/eslint-plugin": "^6.0.0",
45
51
  "@typescript-eslint/parser": "^6.0.0",
46
52
  "eslint": "^8.0.0",
@@ -48,6 +54,8 @@
48
54
  "eslint-plugin-jest": "^29.11.0",
49
55
  "eslint-plugin-prettier": "^5.5.4",
50
56
  "prettier": "2.8.8",
57
+ "react": "18.2.0",
58
+ "react-native": "0.73.11",
51
59
  "typescript": "^5.0.0"
52
60
  },
53
61
  "repository": {
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- const { View, Platform, requireNativeComponent } = require('react-native');
2
+ import { View, Platform, requireNativeComponent } from 'react-native';
3
3
  import { PdfCacheService } from './services/pdfCache';
4
4
  import { PdfNavigationControls } from './components/PdfNavigationControls';
5
5
  import { PdfLoadingOverlay, PdfErrorOverlay } from './components/PdfOverlays';
@@ -9,11 +9,16 @@ import {
9
9
  DEFAULT_SHOW_NAVIGATION_CONTROLS,
10
10
  ERROR_MESSAGES,
11
11
  } from './constants';
12
- import type { OptimizedPdfViewProps, NativeLoadCompleteEvent, NativePageCountEvent } from './types';
12
+ import type {
13
+ OptimizedPdfViewProps,
14
+ NativeLoadCompleteEvent,
15
+ NativePageCountEvent,
16
+ NativeOptimizedPdfViewProps,
17
+ } from './types';
13
18
 
14
19
  const NativeOptimizedPdfView =
15
20
  Platform.OS === 'ios' || Platform.OS === 'android'
16
- ? requireNativeComponent('OptimizedPdfView')
21
+ ? requireNativeComponent<NativeOptimizedPdfViewProps>('OptimizedPdfView')
17
22
  : () => null;
18
23
 
19
24
  /**
@@ -37,6 +42,7 @@ const NativeOptimizedPdfView =
37
42
  */
38
43
  export default function OptimizedPdfView({
39
44
  source,
45
+ page,
40
46
  password,
41
47
  maximumZoom = DEFAULT_MAXIMUM_ZOOM,
42
48
  enableAntialiasing = DEFAULT_ENABLE_ANTIALIASING,
@@ -52,7 +58,7 @@ export default function OptimizedPdfView({
52
58
  const [loading, setLoading] = useState(true);
53
59
  const [progress, setProgress] = useState(0);
54
60
  const [error, setError] = useState<string | null>(null);
55
- const [page, setPage] = useState(0);
61
+ const [internalPage, setInternalPage] = useState(0);
56
62
  const [totalPages, setTotalPages] = useState(1);
57
63
  const lastSource = useRef<string | null>(null);
58
64
 
@@ -64,7 +70,7 @@ export default function OptimizedPdfView({
64
70
  setProgress(0);
65
71
  setError(null);
66
72
  setLocalPath(null);
67
- setPage(0);
73
+ setInternalPage(0);
68
74
  setTotalPages(1);
69
75
  lastSource.current = source.uri;
70
76
 
@@ -96,23 +102,23 @@ export default function OptimizedPdfView({
96
102
  }, [source.uri, source.cache, source.cacheFileName, source.expiration, onError, source]);
97
103
 
98
104
  const handleNextPage = () => {
99
- if (page < totalPages - 1) {
100
- const newPage = page + 1;
101
- setPage(newPage);
105
+ if (internalPage < totalPages - 1) {
106
+ const newPage = internalPage + 1;
107
+ setInternalPage(newPage);
102
108
  onPageChange?.(newPage);
103
109
  }
104
110
  };
105
111
 
106
112
  const handlePrevPage = () => {
107
- if (page > 0) {
108
- const newPage = page - 1;
109
- setPage(newPage);
113
+ if (internalPage > 0) {
114
+ const newPage = internalPage - 1;
115
+ setInternalPage(newPage);
110
116
  onPageChange?.(newPage);
111
117
  }
112
118
  };
113
119
 
114
120
  const handlePageChange = (newPage: number) => {
115
- setPage(newPage);
121
+ setInternalPage(newPage);
116
122
  onPageChange?.(newPage);
117
123
  };
118
124
 
@@ -143,7 +149,7 @@ export default function OptimizedPdfView({
143
149
  <View style={[{ flex: 1 }, style]}>
144
150
  <NativeOptimizedPdfView
145
151
  source={localPath}
146
- page={page}
152
+ page={showNavigationControls ? internalPage : page || 0}
147
153
  enableAntialiasing={enableAntialiasing}
148
154
  maximumZoom={maximumZoom}
149
155
  password={password || ''}
@@ -155,7 +161,7 @@ export default function OptimizedPdfView({
155
161
  />
156
162
  {showNavigationControls && (
157
163
  <PdfNavigationControls
158
- currentPage={page}
164
+ currentPage={internalPage}
159
165
  totalPages={totalPages}
160
166
  onNextPage={handleNextPage}
161
167
  onPrevPage={handlePrevPage}
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- const { View, Text, TouchableOpacity, TextInput, StyleSheet } = require('react-native');
2
+ import { View, Text, TouchableOpacity, TextInput, StyleSheet } from 'react-native';
3
3
  import type { PdfNavigationControlsProps } from '../types';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- const { View, Text, ActivityIndicator, StyleSheet } = require('react-native');
2
+ import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
3
3
  import type { PdfLoadingOverlayProps, PdfErrorOverlayProps } from '../types';
4
4
 
5
5
  /**
@@ -8,7 +8,7 @@ import type { PdfLoadingOverlayProps, PdfErrorOverlayProps } from '../types';
8
8
  export const PdfLoadingOverlay: React.FC<PdfLoadingOverlayProps> = ({ progress, style }) => {
9
9
  return (
10
10
  <View style={[styles.container, style]}>
11
- <ActivityIndicator size="large" color="#fff" />
11
+ <ActivityIndicator size="large" color="#000000" />
12
12
  <Text style={styles.progressText}>{progress}%</Text>
13
13
  </View>
14
14
  );
@@ -33,7 +33,7 @@ const styles = StyleSheet.create({
33
33
  padding: 20,
34
34
  },
35
35
  progressText: {
36
- color: '#fff',
36
+ color: '#000000',
37
37
  marginTop: 10,
38
38
  fontSize: 16,
39
39
  fontWeight: '600',
@@ -41,6 +41,8 @@ export interface PdfErrorEvent {
41
41
  export interface OptimizedPdfViewProps {
42
42
  /** PDF source configuration */
43
43
  source: PdfSource;
44
+ /** Current page index (0-based) */
45
+ page?: number;
44
46
  /** Password for encrypted PDF files */
45
47
  password?: string;
46
48
  /** Maximum zoom level. Default: 3 */
@@ -110,3 +112,26 @@ export interface PdfErrorOverlayProps {
110
112
  error: string;
111
113
  style?: ViewStyle;
112
114
  }
115
+
116
+ export interface NativeOptimizedPdfViewProps {
117
+ /** PDF source configuration */
118
+ source: string;
119
+ /** Current page index (0-based) */
120
+ page: number;
121
+ /** Password for encrypted PDF files */
122
+ password?: string;
123
+ /** Maximum zoom level. Default: 3 */
124
+ maximumZoom?: number;
125
+ /** Enable antialiasing for better rendering quality. Default: true */
126
+ enableAntialiasing?: boolean;
127
+ /** Callback when PDF is loaded successfully */
128
+ onLoadComplete?: (event: NativeLoadCompleteEvent) => void;
129
+ /** Callback when an error occurs */
130
+ onError?: (error: PdfErrorEvent) => void;
131
+ /** Callback when page count is available */
132
+ onPageCount?: (event: NativePageCountEvent) => void;
133
+ /** Callback when page changes */
134
+ onPasswordRequired?: () => void;
135
+ /** Custom style for the container */
136
+ style?: ViewStyle;
137
+ }
package/tsconfig.json CHANGED
@@ -1,17 +1,24 @@
1
1
  {
2
+ // "extends": "@react-native/typescript-config/tsconfig.json",
2
3
  "compilerOptions": {
3
- "target": "es2017",
4
- "module": "commonjs",
5
- "lib": ["es6"],
6
- "allowJs": true,
7
- "jsx": "react-native",
8
- "noEmit": true,
9
- "isolatedModules": true,
10
- "strict": true,
11
- "moduleResolution": "node",
4
+ "target": "ESNext",
5
+ "module": "ESNext",
12
6
  "esModuleInterop": true,
7
+ "moduleResolution": "bundler",
8
+ "jsx": "react-native",
13
9
  "skipLibCheck": true,
14
- "forceConsistentCasingInFileNames": true
10
+ "strict": true,
11
+ "noUnusedLocals": true,
12
+ "noUnusedParameters": true,
13
+ "noEmit": false,
14
+ "checkJs": false,
15
+ "allowJs": false,
16
+ "noImplicitAny": false,
17
+ "declaration": true,
18
+ "paths": {
19
+ "react-native-calendars": ["./src/index.ts"]
20
+ },
15
21
  },
22
+ "include": ["src/**/*", "example/App.tsx"],
16
23
  "exclude": ["node_modules", "**/__tests__/**"]
17
24
  }