CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-pdf

A react native PDF view component for displaying PDF documents from various sources with caching support.

Pending
Overview
Eval results
Files

event-handling.mddocs/

Event Handling

Comprehensive event system for PDF loading, page navigation, user interactions, and error handling with detailed callback information. This covers all events and callbacks available in the PDF component.

Capabilities

Loading Events

Handle PDF loading progress and completion events.

/**
 * PDF loading event handlers
 * Monitor PDF download and loading progress
 */
interface LoadingEvents {
  /** 
   * Called during PDF download/loading progress
   * @param percent - Loading progress from 0 to 1
   */
  onLoadProgress?: (percent: number) => void;
  
  /** 
   * Called when PDF loading is complete
   * @param numberOfPages - Total number of pages in the PDF
   * @param path - Local file path where PDF is stored
   * @param size - PDF dimensions in points
   * @param tableContents - PDF table of contents (optional)
   */
  onLoadComplete?: (
    numberOfPages: number,
    path: string,
    size: { height: number; width: number },
    tableContents?: TableContent[]
  ) => void;
}

type TableContent = {
  /** Nested table of contents items */
  children: TableContent[];
  /** Native pointer reference */
  mNativePtr: number;
  /** Page index for this item */
  pageIdx: number;
  /** Display title for this item */
  title: string;
};

Usage Examples:

<Pdf
  source={{ uri: "https://example.com/large-document.pdf" }}
  onLoadProgress={(progress) => {
    console.log(`Loading: ${Math.round(progress * 100)}%`);
    // Update progress bar, loading indicator, etc.
  }}
  onLoadComplete={(numberOfPages, filePath, { width, height }, tableContents) => {
    console.log(`Loaded ${numberOfPages} pages`);
    console.log(`PDF size: ${width}x${height} points`);
    console.log(`Cached at: ${filePath}`);
    
    if (tableContents) {
      console.log("Table of contents available:");
      tableContents.forEach(item => {
        console.log(`- ${item.title} (page ${item.pageIdx + 1})`);
      });
    }
  }}
  style={{ flex: 1 }}
/>

Navigation Events

Handle page navigation and current page changes.

/**
 * Page navigation event handlers
 * Monitor user navigation through PDF pages
 */
interface NavigationEvents {
  /** 
   * Called when the current page changes
   * @param page - Current page number (1-based)
   * @param numberOfPages - Total number of pages
   */
  onPageChanged?: (page: number, numberOfPages: number) => void;
}

Usage Example:

const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);

<Pdf
  source={{ uri: "document.pdf" }}
  onPageChanged={(page, total) => {
    setCurrentPage(page);
    setTotalPages(total);
    console.log(`Page ${page} of ${total}`);
  }}
  style={{ flex: 1 }}
/>

// Display page indicator
<Text>{`${currentPage} / ${totalPages}`}</Text>

User Interaction Events

Handle user touch interactions and gestures.

/**
 * User interaction event handlers
 * Respond to touch gestures and user interactions
 */
interface InteractionEvents {
  /** 
   * Called when user single-taps on a page
   * @param page - Page number that was tapped (1-based)
   * @param x - X coordinate of tap relative to page
   * @param y - Y coordinate of tap relative to page
   */
  onPageSingleTap?: (page: number, x: number, y: number) => void;
  
  /** 
   * Called when zoom scale changes
   * @param scale - New scale factor
   */
  onScaleChanged?: (scale: number) => void;
  
  /** 
   * Called when user taps on a link within the PDF
   * @param url - URL or link destination
   */
  onPressLink?: (url: string) => void;
}

Usage Examples:

<Pdf
  source={{ uri: "interactive-document.pdf" }}
  onPageSingleTap={(page, x, y) => {
    console.log(`Tapped page ${page} at coordinates (${x}, ${y})`);
    // Show context menu, add annotation, etc.
  }}
  onScaleChanged={(scale) => {
    console.log(`Zoom level: ${Math.round(scale * 100)}%`);
    // Update zoom controls, save preference, etc.
  }}
  onPressLink={(url) => {
    console.log(`Link pressed: ${url}`);
    // Handle external links
    if (url.startsWith('http')) {
      Linking.openURL(url);
    }
  }}
  style={{ flex: 1 }}
/>

Error Handling

Handle errors during PDF loading and rendering.

/**
 * Error handling
 * Handle various error conditions during PDF operations
 */
interface ErrorEvents {
  /** 
   * Called when an error occurs during PDF loading or rendering
   * @param error - Error object with details about the failure
   */
  onError?: (error: Error) => void;
}

Usage Examples:

<Pdf
  source={{ uri: "https://example.com/document.pdf" }}
  onError={(error) => {
    console.error("PDF Error:", error);
    
    // Handle different error types
    if (error.message?.includes("404")) {
      Alert.alert("Error", "PDF document not found");
    } else if (error.message?.includes("password")) {
      Alert.alert("Error", "PDF requires a password");
    } else if (error.message?.includes("network")) {
      Alert.alert("Error", "Network error loading PDF");
    } else {
      Alert.alert("Error", "Failed to load PDF");
    }
  }}
  style={{ flex: 1 }}
/>

Complete Event Handler Example

Comprehensive example showing all event handlers working together.

/**
 * Complete event handling setup
 * Example showing all available event handlers
 */
interface CompleteEvents extends LoadingEvents, NavigationEvents, InteractionEvents, ErrorEvents {}

Complete Usage Example:

import React, { useState } from "react";
import { View, Text, Alert, ActivityIndicator } from "react-native";
import Pdf from "react-native-pdf";

export default function CompletePdfViewer() {
  const [loading, setLoading] = useState(true);
  const [progress, setProgress] = useState(0);
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(0);
  const [scale, setScale] = useState(1);

  return (
    <View style={{ flex: 1 }}>
      {/* Status bar */}
      <View style={{ flexDirection: "row", justifyContent: "space-between", padding: 10 }}>
        <Text>Page: {currentPage}/{totalPages}</Text>
        <Text>Zoom: {Math.round(scale * 100)}%</Text>
      </View>

      <Pdf
        source={{ 
          uri: "https://example.com/document.pdf",
          cache: true 
        }}
        // Loading events
        onLoadProgress={(percent) => {
          setProgress(percent);
          console.log(`Loading progress: ${Math.round(percent * 100)}%`);
        }}
        onLoadComplete={(numberOfPages, filePath, { width, height }, tableContents) => {
          setLoading(false);
          setTotalPages(numberOfPages);
          console.log(`PDF loaded: ${numberOfPages} pages, ${width}x${height}px`);
          
          if (tableContents?.length) {
            console.log("Table of contents:", tableContents);
          }
        }}
        // Navigation events
        onPageChanged={(page, total) => {
          setCurrentPage(page);
          console.log(`Navigated to page ${page} of ${total}`);
        }}
        // Interaction events
        onPageSingleTap={(page, x, y) => {
          console.log(`Single tap on page ${page} at (${x}, ${y})`);
          // Could show/hide controls, add annotations, etc.
        }}
        onScaleChanged={(newScale) => {
          setScale(newScale);
          console.log(`Scale changed to ${newScale}`);
        }}
        onPressLink={(url) => {
          console.log(`Link pressed: ${url}`);
          Alert.alert("Link", `Open ${url}?`);
        }}
        // Error handling
        onError={(error) => {
          setLoading(false);
          console.error("PDF Error:", error);
          Alert.alert("Error", "Failed to load PDF document");
        }}
        style={{ flex: 1 }}
      />

      {/* Loading overlay */}
      {loading && (
        <View style={{
          position: "absolute",
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          justifyContent: "center",
          alignItems: "center",
          backgroundColor: "rgba(255,255,255,0.8)"
        }}>
          <ActivityIndicator size="large" />
          <Text>{Math.round(progress * 100)}% loaded</Text>
        </View>
      )}
    </View>
  );
}

Event Timing and Lifecycle

Understanding when events are triggered during PDF lifecycle.

/**
 * Event lifecycle and timing
 * Order and timing of events during PDF operations
 */
interface EventLifecycle {
  // 1. Loading starts - component mounts
  // 2. onLoadProgress - called repeatedly during download
  // 3. onLoadComplete - called when PDF is ready
  // 4. onPageChanged - called for initial page and navigation
  // 5. onPageSingleTap - called on user interaction
  // 6. onScaleChanged - called on zoom changes
  // 7. onPressLink - called when links are tapped
  // 8. onError - called if any errors occur
}

Install with Tessl CLI

npx tessl i tessl/npm-react-native-pdf

docs

component-control.md

event-handling.md

index.md

pdf-display.md

user-interface.md

tile.json