# PDFViewer

Canonical page: https://docs.ovok.com/native-sdk/guide/components/pdf/pdf-viewer

PDF document viewer component built on [react-native-pdf](https://github.com/wonday/react-native-pdf) with enhanced loading states, theme integration, and automatic error handling. Provides a seamless document viewing experience with smooth loading animations and consistent styling.

## Props [#props]

Every prop, with its type and description, is listed in the [`@ovok/native/pdf` API reference](/native-sdk/reference/pdf).

## Component Behavior [#component-behavior]

### Loading States [#loading-states]

1. **Initial Loading**: Shows animated loading indicator with theme-aware backdrop
2. **Document Ready**: Displays PDF content with fade-in animation
3. **Error State**: Handles loading failures through error callbacks

### Animation System [#animation-system]

- Uses `react-native-reanimated` for smooth fade in/out transitions
- Loading indicator appears immediately when `sourceURI` is provided
- Content fades in seamlessly when document is ready

### Theme Integration [#theme-integration]

- Automatically applies theme colors for loading backdrop
- Respects app theme for consistent visual experience
- Uses `useAppTheme` hook for dynamic theming

## Styling [#styling]

### Container Customization [#container-customization]

```typescript
const containerStyle = {
  backgroundColor: '#f5f5f5',
  borderRadius: 8,
  margin: 16,
};

<PDFViewer
  sourceURI="https://example.com/document.pdf"
  containerStyle={containerStyle}
/>
```

### PDF Content Styling [#pdf-content-styling]

```typescript
const pdfStyle = {
  flex: 1,
  backgroundColor: 'white',
};

<PDFViewer
  sourceURI="https://example.com/document.pdf"
  style={pdfStyle}
/>
```

### Full Screen PDF [#full-screen-pdf]

```typescript
<PDFViewer
  sourceURI="https://example.com/document.pdf"
  containerStyle={{ flex: 1 }}
  style={{ flex: 1 }}
/>
```

## Usage Patterns [#usage-patterns]

### Privacy Policy Display [#privacy-policy-display]

```typescript
import * as React from "react";
import { PDFViewer } from "@ovok/native/pdf";

export const PrivacyPolicyScreen = () => {
  return (
    <PDFViewer
      sourceURI="https://storage.example.com/privacy-policy.pdf"
      testID="privacy-policy-viewer"
    />
  );
};
```

### Terms and Conditions [#terms-and-conditions]

```typescript
import * as React from "react";
import { PDFViewer } from "@ovok/native/pdf";

export const TermsScreen = () => {
  const handleLoadComplete = (pages: number) => {
    console.log(`Terms document has ${pages} pages`);
  };

  return (
    <PDFViewer
      sourceURI="https://storage.example.com/terms.pdf"
      onLoadComplete={handleLoadComplete}
      containerStyle={{ margin: 16 }}
    />
  );
};
```

### Device Instruction Manual [#device-instruction-manual]

```typescript
import * as React from "react";
import { Alert } from "react-native";
import { PDFViewer } from "@ovok/native/pdf";

interface DeviceManualProps {
  deviceType: string;
  manualUrl: string;
}

export const DeviceManual = ({ deviceType, manualUrl }: DeviceManualProps) => {
  const handleError = (error: Error) => {
    Alert.alert(
      "Manual Not Available",
      `Unable to load ${deviceType} instruction manual. Please try again later.`
    );
  };

  return (
    <PDFViewer
      sourceURI={manualUrl}
      onError={handleError}
      testID={`manual-${deviceType.toLowerCase()}`}
      enablePaging
      horizontal={false}
    />
  );
};
```

### Healthcare Document Viewer [#healthcare-document-viewer]

```typescript
import * as React from "react";
import { View, StyleSheet } from "react-native";
import { ActivityIndicator, Text } from "react-native-paper";
import { PDFViewer } from "@ovok/native/pdf";

interface HealthcareDocProps {
  documentId: string;
  documentUrl: string;
  title: string;
}

export const HealthcareDocumentViewer = ({
  documentId,
  documentUrl,
  title
}: HealthcareDocProps) => {
  const [isLoading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);

  const handleLoadComplete = () => {
    setLoading(false);
    setError(null);
  };

  const handleError = (err: Error) => {
    setLoading(false);
    setError(err.message);
  };

  if (error) {
    return (
      <View style={styles.errorContainer}>
        <Text variant="bodyLarge">Unable to load document</Text>
        <Text variant="bodyMedium">{error}</Text>
      </View>
    );
  }

  return (
    <PDFViewer
      sourceURI={documentUrl}
      onLoadComplete={handleLoadComplete}
      onError={handleError}
      testID={`healthcare-doc-${documentId}`}
      containerStyle={styles.container}
    />
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    margin: 16,
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 24,
  },
});
```

### Password Protected PDF [#password-protected-pdf]

```typescript
import * as React from "react";
import { PDFViewer } from "@ovok/native/pdf";

interface SecureDocumentProps {
  documentUrl: string;
  password: string;
}

export const SecureDocument = ({ documentUrl, password }: SecureDocumentProps) => {
  return (
    <PDFViewer
      sourceURI={documentUrl}
      password={password}
      onError={(error) => {
        console.error('PDF Error:', error);
      }}
      testID="secure-document"
    />
  );
};
```

## Error Handling [#error-handling]

### Network Errors [#network-errors]

```typescript
const handleNetworkError = (error: Error) => {
  if (error.message.includes('network')) {
    // Handle network connectivity issues
    showNetworkErrorDialog();
  } else {
    // Handle other PDF errors
    showGenericErrorDialog();
  }
};

<PDFViewer
  sourceURI={documentUrl}
  onError={handleNetworkError}
/>
```

### Validation and Fallbacks [#validation-and-fallbacks]

```typescript
const ValidatedPDFViewer = ({ url }: { url: string }) => {
  if (!url) {
    return <DocumentNotAvailable />;
  }

  return (
    <PDFViewer
      sourceURI={url}
      onError={() => showDocumentErrorAlert()}
    />
  );
};
```

## Performance Considerations [#performance-considerations]

### Large Documents [#large-documents]

- Use appropriate `fitPolicy` settings for optimal rendering
- Consider implementing pagination for very large documents
- Monitor memory usage with large PDF files

### Network Optimization [#network-optimization]

- Implement proper loading states for slow connections
- Consider caching strategies for frequently accessed documents
- Handle offline scenarios gracefully

### Animation Performance [#animation-performance]

- Loading animations are optimized with `react-native-reanimated`
- Smooth 60fps transitions without JavaScript bridge overhead
- Minimal performance impact on document rendering
