@june24/expo-pdf-reader 0.1.3 → 0.1.4

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 +1 @@
1
- {"version":3,"file":"ExpoPdfReader.types.js","sourceRoot":"","sources":["../src/ExpoPdfReader.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ViewProps, StyleProp, ViewStyle } from 'react-native';\n\nexport type AnnotationTool = 'none' | 'pen' | 'highlighter' | 'text' | 'note' | 'eraser';\n\nexport type DisplayMode = 'single' | 'continuous' | 'twoUp' | 'twoUpContinuous';\n\nexport type Point = { x: number; y: number };\n\nexport type Annotation = {\n type: 'pen' | 'highlighter' | 'text';\n color: string;\n page?: number;\n points?: Point[][]; // For pen/highlighter\n width?: number; // Stroke width or font size for text? Let's use fontSize for text explicitly\n text?: string; // For text\n fontSize?: number; // For text\n x?: number; // For text\n y?: number; // For text\n};\n\nexport type AnnotationChangeEvent = {\n nativeEvent: {\n annotations: Annotation[];\n };\n};\n\nexport type PageChangeEvent = {\n nativeEvent: {\n page: number;\n total: number;\n };\n};\n\nexport type ScrollEvent = {\n nativeEvent: {\n x: number;\n y: number;\n contentWidth: number;\n contentHeight: number;\n layoutWidth: number;\n layoutHeight: number;\n };\n};\n\nexport type SearchResult = {\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n textSnippet?: string;\n};\n\n// Public API: group drawing configuration into a single object\nexport type AnnotationOptions = {\n tool?: AnnotationTool;\n color?: string; // Hex color\n fontSize?: number;\n text?: string;\n strokeWidth?: number; // line thickness for pen/highlighter\n};\n\n// Props exposed to JS users of the component\nexport type ExpoPdfReaderViewProps = ViewProps & {\n url: string;\n style?: StyleProp<ViewStyle>;\n displayMode?: DisplayMode; // 'single' | 'continuous' | 'twoUp' | 'twoUpContinuous'\n initialPage?: number; // starting page index (0-based)\n minZoom?: number;\n maxZoom?: number;\n annotationOptions?: AnnotationOptions;\n initialAnnotations?: Annotation[];\n onAnnotationChange?: (event: AnnotationChangeEvent) => void;\n onPageChange?: (event: PageChangeEvent) => void;\n onScroll?: (event: ScrollEvent) => void;\n};\n\n// Internal props that the native view actually receives.\n// This keeps backwards-compat with the native module while giving\n// JS a cleaner grouped API via `annotationOptions`.\nexport type NativeExpoPdfReaderViewProps = ViewProps & {\n url: string;\n style?: StyleProp<ViewStyle>;\n displayMode?: DisplayMode;\n initialPage?: number;\n minZoom?: number;\n maxZoom?: number;\n annotationTool?: AnnotationTool;\n annotationColor?: string; // Hex color\n annotationFontSize?: number;\n annotationText?: string; // Default text to place\n // Native-only props derived from AnnotationOptions\n annotationStrokeWidth?: number;\n initialAnnotations?: Annotation[];\n onAnnotationChange?: (event: AnnotationChangeEvent) => void;\n onPageChange?: (event: PageChangeEvent) => void;\n onScroll?: (event: ScrollEvent) => void;\n};\n\n"]}
1
+ {"version":3,"file":"ExpoPdfReader.types.js","sourceRoot":"","sources":["../src/ExpoPdfReader.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ViewProps, StyleProp, ViewStyle } from 'react-native';\n\nexport type AnnotationTool = 'none' | 'pen' | 'highlighter' | 'text' | 'note' | 'eraser';\n\nexport type DisplayMode = 'single' | 'continuous' | 'twoUp' | 'twoUpContinuous';\n\nexport type Point = { x: number; y: number };\n\nexport type Annotation = {\n type: 'pen' | 'highlighter' | 'text';\n color: string;\n page?: number;\n points?: Point[][]; // For pen/highlighter\n width?: number; // Stroke width or font size for text? Let's use fontSize for text explicitly\n text?: string; // For text\n fontSize?: number; // For text\n x?: number; // For text\n y?: number; // For text\n};\n\nexport type AnnotationChangeEvent = {\n nativeEvent: {\n annotations: Annotation[];\n };\n};\n\nexport type PageChangeEvent = {\n nativeEvent: {\n page: number;\n total: number;\n };\n};\n\nexport type ScrollEvent = {\n nativeEvent: {\n x: number;\n y: number;\n contentWidth: number;\n contentHeight: number;\n layoutWidth: number;\n layoutHeight: number;\n };\n};\n\nexport type SearchResult = {\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n textSnippet?: string;\n};\n\n// Public API: group drawing configuration into a single object\nexport type AnnotationOptions = {\n tool?: AnnotationTool;\n color?: string; // Hex color\n fontSize?: number;\n text?: string;\n strokeWidth?: number; // line thickness for pen/highlighter\n};\n\n// Props exposed to JS users of the component\nexport type ExpoPdfReaderViewProps = ViewProps & {\n url: string;\n style?: StyleProp<ViewStyle>;\n displayMode?: DisplayMode; // 'single' | 'continuous' | 'twoUp' | 'twoUpContinuous'\n initialPage?: number; // starting page index (0-based)\n minZoom?: number;\n maxZoom?: number;\n annotationOptions?: AnnotationOptions;\n initialAnnotations?: Annotation[];\n onAnnotationChange?: (event: AnnotationChangeEvent) => void;\n onPageChange?: (event: PageChangeEvent) => void;\n onScroll?: (event: ScrollEvent) => void;\n};\n\n// Internal props that the native view actually receives.\n// This keeps backwards-compat with the native module while giving\n// JS a cleaner grouped API via `annotationOptions`.\nexport type NativeExpoPdfReaderViewProps = ViewProps & {\n url: string;\n style?: StyleProp<ViewStyle>;\n displayMode?: DisplayMode;\n initialPage?: number;\n minZoom?: number;\n maxZoom?: number;\n annotationTool?: AnnotationTool;\n annotationColor?: string; // Hex color\n annotationFontSize?: number;\n annotationText?: string; // Default text to place\n // Native-only props derived from AnnotationOptions\n annotationStrokeWidth?: number;\n initialAnnotations?: Annotation[];\n onAnnotationChange?: (event: AnnotationChangeEvent) => void;\n onPageChange?: (event: PageChangeEvent) => void;\n onScroll?: (event: ScrollEvent) => void;\n};\n\n"]}
@@ -23,6 +23,9 @@ class ExpoPdfReaderView: ExpoView, UIGestureRecognizerDelegate {
23
23
  private var currentAnnotation: PDFAnnotation?
24
24
  private var currentPath: UIBezierPath?
25
25
 
26
+ // Drawing overlay layer for live preview
27
+ private var drawingLayer: CAShapeLayer?
28
+
26
29
  // Undo/Redo stacks
27
30
  private var undoStack: [PDFAnnotation] = []
28
31
  private var redoStack: [PDFAnnotation] = []
@@ -501,6 +504,7 @@ class ExpoPdfReaderView: ExpoView, UIGestureRecognizerDelegate {
501
504
  guard let page = pdfView.currentPage else { return }
502
505
  let location = gesture.location(in: pdfView)
503
506
  let convertedPoint = pdfView.convert(location, to: page)
507
+ let viewLocation = location // Keep view coordinates for drawing layer
504
508
 
505
509
  // Handle eraser
506
510
  if currentTool == "eraser" {
@@ -552,38 +556,99 @@ class ExpoPdfReaderView: ExpoView, UIGestureRecognizerDelegate {
552
556
  switch gesture.state {
553
557
  case .began:
554
558
  currentPath = UIBezierPath()
555
- currentPath?.move(to: convertedPoint)
559
+ currentPath?.move(to: viewLocation) // Use view coordinates for drawing layer
560
+
561
+ // Create drawing layer for live preview in view coordinates
562
+ if drawingLayer == nil {
563
+ drawingLayer = CAShapeLayer()
564
+ drawingLayer?.fillColor = UIColor.clear.cgColor
565
+ drawingLayer?.lineCap = .round
566
+ drawingLayer?.lineJoin = .round
567
+ pdfView.layer.addSublayer(drawingLayer!)
568
+ }
569
+
570
+ case .changed:
571
+ guard let path = currentPath else { return }
572
+ path.addLine(to: viewLocation) // Use view coordinates for drawing layer
573
+
574
+ // Update drawing layer to show live preview
575
+ drawingLayer?.path = path.cgPath
576
+ if currentTool == "pen" {
577
+ drawingLayer?.strokeColor = currentColor.cgColor
578
+ drawingLayer?.lineWidth = currentStrokeWidth
579
+ drawingLayer?.opacity = 1.0
580
+ } else if currentTool == "highlighter" {
581
+ drawingLayer?.strokeColor = currentColor.cgColor
582
+ drawingLayer?.lineWidth = currentStrokeWidth * 3.0
583
+ drawingLayer?.opacity = 0.3
584
+ }
585
+
586
+ case .ended:
587
+ guard let viewPath = currentPath else { return }
588
+ viewPath.addLine(to: viewLocation) // Complete view path
589
+
590
+ // Remove drawing layer
591
+ drawingLayer?.removeFromSuperlayer()
592
+ drawingLayer = nil
556
593
 
557
- // Create annotation
558
- let bounds = page.bounds(for: pdfView.displayBox)
594
+ // Convert view path to page coordinates
595
+ let pagePathForAnnotation = UIBezierPath()
596
+ viewPath.cgPath.applyWithBlock { element in
597
+ let points = element.pointee.points
598
+ switch element.pointee.type {
599
+ case .moveToPoint:
600
+ let pagePoint = self.pdfView.convert(points[0], to: page)
601
+ pagePathForAnnotation.move(to: pagePoint)
602
+ case .addLineToPoint:
603
+ let pagePoint = self.pdfView.convert(points[0], to: page)
604
+ pagePathForAnnotation.addLine(to: pagePoint)
605
+ case .addQuadCurveToPoint:
606
+ let cp = self.pdfView.convert(points[0], to: page)
607
+ let pt = self.pdfView.convert(points[1], to: page)
608
+ pagePathForAnnotation.addQuadCurve(to: pt, controlPoint: cp)
609
+ case .addCurveToPoint:
610
+ let cp1 = self.pdfView.convert(points[0], to: page)
611
+ let cp2 = self.pdfView.convert(points[1], to: page)
612
+ let pt = self.pdfView.convert(points[2], to: page)
613
+ pagePathForAnnotation.addCurve(to: pt, controlPoint1: cp1, controlPoint2: cp2)
614
+ case .closeSubpath:
615
+ pagePathForAnnotation.close()
616
+ @unknown default:
617
+ break
618
+ }
619
+ }
620
+
621
+ // Calculate proper bounds from path
622
+ var pathBounds = pagePathForAnnotation.bounds
623
+ // Expand bounds slightly to accommodate stroke width
624
+ let expansion = max(currentStrokeWidth * 2, 20)
625
+ pathBounds = pathBounds.insetBy(dx: -expansion, dy: -expansion)
559
626
 
560
627
  if currentTool == "pen" {
561
- let annotation = PDFAnnotation(bounds: bounds, forType: .ink, withProperties: nil)
628
+ let annotation = PDFAnnotation(bounds: pathBounds, forType: .ink, withProperties: nil)
562
629
  annotation.color = currentColor
563
630
  let border = PDFBorder()
564
631
  border.lineWidth = currentStrokeWidth
565
632
  annotation.border = border
566
- annotation.add(currentPath!)
633
+ annotation.add(pagePathForAnnotation)
567
634
  page.addAnnotation(annotation)
568
- currentAnnotation = annotation
635
+
636
+ // Force PDF view to update
637
+ pdfView.setNeedsDisplay()
569
638
  }
570
639
  else if currentTool == "highlighter" {
571
- let annotation = PDFAnnotation(bounds: bounds, forType: .ink, withProperties: nil)
640
+ let annotation = PDFAnnotation(bounds: pathBounds, forType: .ink, withProperties: nil)
572
641
  annotation.color = currentColor.withAlphaComponent(0.3)
573
642
  let border = PDFBorder()
574
643
  border.lineWidth = currentStrokeWidth * 3.0
575
644
  annotation.border = border
576
- annotation.add(currentPath!)
645
+ annotation.add(pagePathForAnnotation)
577
646
  page.addAnnotation(annotation)
578
- currentAnnotation = annotation
647
+
648
+ // Force PDF view to update
649
+ pdfView.setNeedsDisplay()
579
650
  }
580
651
 
581
- case .changed:
582
- guard let path = currentPath, let annotation = currentAnnotation else { return }
583
- path.addLine(to: convertedPoint)
584
- annotation.add(path) // Update path
585
-
586
- case .ended, .cancelled:
587
652
  // Clear redo stack when new annotation is added
588
653
  redoStack.removeAll()
589
654
 
@@ -595,6 +660,13 @@ class ExpoPdfReaderView: ExpoView, UIGestureRecognizerDelegate {
595
660
  "annotations": getAnnotations()
596
661
  ])
597
662
 
663
+ case .cancelled:
664
+ // Remove drawing layer and clear without adding annotation
665
+ drawingLayer?.removeFromSuperlayer()
666
+ drawingLayer = nil
667
+ currentPath = nil
668
+ currentAnnotation = nil
669
+
598
670
  default:
599
671
  break
600
672
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@june24/expo-pdf-reader",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "A PDF reader for Expo apps with annotation and zoom controls",
5
5
  "homepage": "git@gitlab.com:june_241/expo-pdf-reader.git",
6
6
  "main": "build/index.js",