import { PdfViewer } from "@samplehc/ui/components";
import { useTaskState } from "@samplehc/ui/data";
import { Button } from "@/components/ui/button";
import { useRef } from "react";

function DocumentReviewScreen({ documentUrl }) {
  const [highlights, setHighlights] = useTaskState("highlights", []);
  const [selectedPage, setSelectedPage] = useTaskState("currentPage", 1);
  const viewerRef = useRef();

  const addHighlight = (pageNumber, region) => {
    const newHighlight = {
      pageNumber,
      left: region.left,
      top: region.top,
      width: region.width,
      height: region.height,
      color: "yellow"
    };
    setHighlights([...highlights, newHighlight]);
  };

  const goToNextPage = () => {
    viewerRef.current?.scrollToPage(selectedPage + 1);
  };

  return (
    <div className="flex h-full">
      <div className="flex-1">
        <PdfViewer
          url={documentUrl}
          pdfViewerRef={viewerRef}
          highlights={highlights}
          selectedPage={selectedPage}
          onPageClick={setSelectedPage}
          renderTextLayer={true}
          renderAnnotationLayer={false}
        />
      </div>
      <div className="w-64 p-4 border-l">
        <h3 className="font-semibold mb-4">Review Tools</h3>
        <Button onClick={goToNextPage} className="mb-2">
          Next Page
        </Button>
        <div className="text-sm">
          Current Page: {selectedPage}
        </div>
        <div className="text-sm">
          Highlights: {highlights.length}
        </div>
      </div>
    </div>
  );
}

Overview

The PdfViewer component provides a full-featured PDF viewing experience with support for annotations, highlighting, and navigation. It’s designed specifically for healthcare document review workflows.

Basic Usage

import { PdfViewer } from "@samplehc/ui/components";
import { useRef } from "react";

function DocumentViewer({ documentUrl }) {
  const viewerRef = useRef();

  return (
    <PdfViewer
      pdfViewerRef={viewerRef}
      url={documentUrl}
      onPageClick={(pageNumber) => {
        console.log("Page clicked:", pageNumber);
      }}
      renderTextLayer={true}
      renderAnnotationLayer={true}
    />
  );
}

API Reference

PdfViewerProps

url
string
required
URL of the PDF document to display.
id
string
Optional identifier for the PDF viewer instance, used for local storage of preferences.
highlights
PdfHighlight[]
Array of highlight objects to display on the PDF pages.
pdfViewerRef
Ref<PdfViewerHandle>
Ref to access the PDF viewer handle methods.
onPageClick
function
Callback fired when a PDF page is clicked.
onPageClick?: (pageNumber: number) => void
selectedPage
number
The currently selected page number (1-indexed).
renderAnnotationLayer
boolean
Whether to render PDF annotation layer. Defaults to true.
renderTextLayer
boolean
Whether to render PDF text layer for text selection. Defaults to true.
splitterOptions
SplitterOptions
Options to configure page splitters for document processing workflows.

PdfViewerHandle

scrollToPage
function
Navigate to a specific page number by scrolling to it.
scrollToPage: (pageNumber: number) => void

PdfHighlight

pageNumber
number
required
The page number (1-indexed) where the highlight appears.
left
number
required
Left position as a percentage of page width (0-1).
top
number
required
Top position as a percentage of page height (0-1).
width
number
required
Width as a percentage of page width (0-1).
height
number
required
Height as a percentage of page height (0-1).
color
'yellow' | 'blue'
Highlight color. Defaults to yellow.

SplitterOptions

hidePageNumber
boolean
Hide the page number text below the splitter.
onSelect
function
Callback function when a splitter is clicked.
onSelect?: (pageNumber: number) => void
selectedSplits
number[]
Array of page numbers after which the splitter is selected.

Features

  • Page Navigation: Navigate through PDF pages with controls and virtualized scrolling
  • Zoom Controls: Zoom in/out with automatic fit-to-width calculation
  • Highlights: Overlay custom highlights on PDF pages with configurable colors
  • Page Rotation: Rotate individual pages clockwise or counterclockwise
  • Grid View: Switch between standard scroll view and grid thumbnail view
  • Page Splitters: Add interactive splitters between pages for document processing
  • Responsive: Adapts to container width with automatic scaling
  • Performance: Virtualized rendering for smooth scrolling of large documents

Integration with Workflow

import { PdfViewer } from "@samplehc/ui/components";
import { useTaskState } from "@samplehc/ui/data";
import { useRef } from "react";

function ReviewDocument({ documentUrl }) {
  const [highlights, setHighlights] = useTaskState("pdfHighlights", []);
  const [selectedPage, setSelectedPage] = useTaskState("selectedPage", 1);
  const viewerRef = useRef();

  return (
    <PdfViewer
      url={documentUrl}
      pdfViewerRef={viewerRef}
      highlights={highlights}
      selectedPage={selectedPage}
      onPageClick={setSelectedPage}
      renderTextLayer={true}
      renderAnnotationLayer={true}
    />
  );
}

Advanced Examples

Document Review with Highlights

import { PdfViewer } from "@samplehc/ui/components";
import { useTaskState } from "@samplehc/ui/data";
import { Button } from "@/components/ui/button";
import { useRef } from "react";

function DocumentReviewScreen({ documentUrl }) {
  const [highlights, setHighlights] = useTaskState("highlights", []);
  const [selectedPage, setSelectedPage] = useTaskState("currentPage", 1);
  const viewerRef = useRef();

  const addHighlight = (pageNumber, region) => {
    const newHighlight = {
      pageNumber,
      left: region.left,
      top: region.top,
      width: region.width,
      height: region.height,
      color: "yellow"
    };
    setHighlights([...highlights, newHighlight]);
  };

  const goToNextPage = () => {
    viewerRef.current?.scrollToPage(selectedPage + 1);
  };

  return (
    <div className="flex h-full">
      <div className="flex-1">
        <PdfViewer
          url={documentUrl}
          pdfViewerRef={viewerRef}
          highlights={highlights}
          selectedPage={selectedPage}
          onPageClick={setSelectedPage}
          renderTextLayer={true}
          renderAnnotationLayer={false}
        />
      </div>
      <div className="w-64 p-4 border-l">
        <h3 className="font-semibold mb-4">Review Tools</h3>
        <Button onClick={goToNextPage} className="mb-2">
          Next Page
        </Button>
        <div className="text-sm">
          Current Page: {selectedPage}
        </div>
        <div className="text-sm">
          Highlights: {highlights.length}
        </div>
      </div>
    </div>
  );
}

Document Splitting with Page Splitters

import { PdfViewer } from "@samplehc/ui/components";
import { useTaskState } from "@samplehc/ui/data";
import { Button } from "@/components/ui/button";

function DocumentSplittingScreen({ documentUrl }) {
  const [selectedSplits, setSelectedSplits] = useTaskState("splits", []);
  const [selectedPage, setSelectedPage] = useTaskState("currentPage", 1);

  const splitterOptions = {
    hidePageNumber: false,
    selectedSplits,
    onSelect: (pageNumber) => {
      setSelectedSplits(prev => 
        prev.includes(pageNumber)
          ? prev.filter(p => p !== pageNumber)
          : [...prev, pageNumber]
      );
    }
  };

  const processSplits = () => {
    console.log("Processing document splits:", selectedSplits);
    // Handle document splitting logic
  };

  return (
    <div className="h-full flex flex-col">
      <div className="p-4 border-b">
        <div className="flex justify-between items-center">
          <h2 className="text-lg font-semibold">Split Document</h2>
          <Button onClick={processSplits} disabled={selectedSplits.length === 0}>
            Create {selectedSplits.length} Documents
          </Button>
        </div>
      </div>
      <div className="flex-1">
        <PdfViewer
          url={documentUrl}
          selectedPage={selectedPage}
          onPageClick={setSelectedPage}
          splitterOptions={splitterOptions}
          renderTextLayer={false}
          renderAnnotationLayer={false}
        />
      </div>
    </div>
  );
}