Rasterex APINPM Package/docs/components/pdf/page-manipulation

Page Manipulation

Execute page-level operations including rotate, delete, insert, copy, paste, and blank page creation.

Overview

Use viewer.documents.manipulatePages(...) to run page-level PDF operations in Canvas.

Page manipulation is available after the viewer is mounted, ready, and a PDF is open.

  • displayName must include the file extension.
typescript
await viewer.mount();
await viewer.ready();

await viewer.documents.open({
  url: "https://files.example.com/Sample PDF.pdf",
  displayName: "Sample PDF.pdf"
});
Overview

Method

Invoke the manipulatePages method to perform operations.

  • The SDK sends pageManipulation and waits for the matching pageManipulationResult.
typescript
const result = await viewer.documents.manipulatePages({
  action: "rotate-r",
  pageRange: [[0]]
});
Method

Actions

Supported workflows and actions:

  • Move pages: move-top, move-bottom, move-up, move-down (targets pageRange)
  • Rotate pages: rotate-r, rotate-l (targets pageRange)
  • Copy/paste pages: page-copy (targets pageRange for copy), page-paste (targets targetPageIndex for paste)
  • Extract/delete pages: page-extract, page-extract-delete, page-delete (targets pageRange)
  • Insert/replace from file: page-insert, page-replace (targets pageRange, file, selectedPages)
  • Insert blank pages: page-insert-blank (targets pageRange, count, width, height)
  • pageRange uses Canvas page indexes, not human-facing page numbers (e.g. pageRange: [[0], [3, 5]] targets page index 0 and inclusive range 3 through 5).

Rotate Pages

Rotate specific pages in the PDF document.

  • Use rotate-l for left rotation.
typescript
await viewer.documents.manipulatePages({
  action: "rotate-r",
  pageRange: [[0, 2]]
});
Rotate Pages

Move Pages

Reorder existing pages in the active PDF.

  • Move actions reorder existing pages in the active PDF. The SDK does not send page bytes, file URLs, or source files for move operations.
typescript
await viewer.documents.manipulatePages({
  action: "move-top",
  pageRange: [[3, 4]]
});
Move Pages

Copy and Paste Pages

Copy pages to the Canvas clipboard and paste them at a target index.

  • Copy and paste use Canvas session state. page-paste can fail if nothing was copied in the same viewer session.
typescript
await viewer.documents.manipulatePages({
  action: "page-copy",
  pageRange: [[1, 3]]
});

await viewer.documents.manipulatePages({
  action: "page-paste",
  targetPageIndex: 5
});
Copy and Paste Pages

Extract or Delete Pages

Extract range of pages or delete pages from the current PDF.

  • Use page-extract-delete when Canvas should extract pages and remove them from the active PDF.
typescript
await viewer.documents.manipulatePages({
  action: "page-extract",
  pageRange: [[2, 4]]
});

await viewer.documents.manipulatePages({
  action: "page-delete",
  pageRange: [[5]]
});
Extract or Delete Pages

Insert Pages From Another PDF

Use a browser File for source PDF pages. Canvas expects the file directly; do not pass a URL for this workflow.

  • pageRange is the insertion location in the active PDF. selectedPages identifies pages from the source file.
typescript
const sourceFile = fileInput.files?.[0];

if (sourceFile) {
  await viewer.documents.manipulatePages({
    action: "page-insert",
    pageRange: [[2]],
    file: sourceFile,
    selectedPages: [[0, 1]]
  });
}
Insert Pages From Another PDF

Replace Pages From Another PDF

Replace pages in the current document with pages from another PDF file.

typescript
const sourceFile = fileInput.files?.[0];

if (sourceFile) {
  await viewer.documents.manipulatePages({
    action: "page-replace",
    pageRange: [[4]],
    file: sourceFile,
    selectedPages: [[0]]
  });
}
Replace Pages From Another PDF

Insert Blank Pages

Insert blank pages specifying width and height.

  • Canvas interprets width and height as document units for the blank page.
typescript
await viewer.documents.manipulatePages({
  action: "page-insert-blank",
  pageRange: [[3]],
  count: 2,
  width: 816,
  height: 1056
});
Insert Blank Pages

Result and Errors

Handle result resolution and promise rejections.

  • The promise rejects when: viewer.ready() has not completed, Canvas reports success: false, Canvas returns an empty result, Canvas result does not include the matching requestId, or no matching result arrives before timeoutMs.
  • Use timeoutMs for larger operations, such as:

Operation Timeout Example

await viewer.documents.manipulatePages({
  action: "page-insert",
  pageRange: [[2]],
  file: sourceFile,
  selectedPages: [[0, 10]],
  timeoutMs: 60000
});
typescript
try {
  const result = await viewer.documents.manipulatePages({
    action: "rotate-r",
    pageRange: [[0]]
  });

  console.log(result.requestId, result.success);
} catch (error) {
  console.error(error);
}
Result and Errors

Vanilla Integration

Complete implementation details for Vanilla HTML/TypeScript setups:

import { createViewer } from "@rasterex/viewer";

const viewer = createViewer({
  container: "#viewer"
});

const status = document.querySelector<HTMLElement>("#status");
let currentPageIndex = 0;

function setStatus(message: string): void {
  if (status) status.textContent = message;
}

await viewer.mount();
await viewer.ready();

viewer.documents.on("pageList", (event) => {
  currentPageIndex = event.currentPage;
});

await viewer.documents.open({
  url: "https://pdfobject.com/pdf/sample.pdf",
  displayName: "sample.pdf"
});

document.querySelector("#rotate-page")?.addEventListener("click", () => {
  void viewer.documents
    .manipulatePages({
      action: "rotate-r",
      pageRange: [[currentPageIndex]]
    })
    .then(() => setStatus("Page rotated"))
    .catch((error) => {
      console.error(error);
      setStatus("Could not rotate page");
    });
});

document.querySelector("#delete-page")?.addEventListener("click", () => {
  void viewer.documents
    .manipulatePages({
      action: "page-delete",
      pageRange: [[currentPageIndex]]
    })
    .then(() => setStatus("Page deleted"))
    .catch((error) => {
      console.error(error);
      setStatus("Could not delete page");
    });
});
Vanilla Integration

React Integration

Implement page manipulation inside a React functional component:

tsx
import { useEffect, useRef, useState } from "react";
import { createViewer, type RasterexViewer } from "@rasterex/viewer";

export function PageManipulationExample() {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const viewerRef = useRef<RasterexViewer | null>(null);
  const [currentPageIndex, setCurrentPageIndex] = useState(0);
  const [status, setStatus] = useState("Starting viewer...");

  useEffect(() => {
    if (!containerRef.current) return undefined;

    let stopPageList: (() => void) | undefined;
    const viewer = createViewer({ container: containerRef.current });
    viewerRef.current = viewer;

    async function start(): Promise<void> {
      await viewer.mount();
      await viewer.ready();

      stopPageList = viewer.documents.on("pageList", (event) => {
        setCurrentPageIndex(event.currentPage);
      });

      await viewer.documents.open({
        url: "https://pdfobject.com/pdf/sample.pdf",
        displayName: "sample.pdf"
      });

      setStatus("Viewer ready");
    }

    void start().catch((error) => {
      console.error(error);
      setStatus("Viewer failed to start");
    });

    return () => {
      stopPageList?.();
      viewer.destroy();
      viewerRef.current = null;
    };
  }, []);

  async function rotateCurrentPage(): Promise<void> {
    await viewerRef.current?.documents.manipulatePages({
      action: "rotate-r",
      pageRange: [[currentPageIndex]]
    });
    setStatus("Page rotated");
  }

  async function deleteCurrentPage(): Promise<void> {
    await viewerRef.current?.documents.manipulatePages({
      action: "page-delete",
      pageRange: [[currentPageIndex]]
    });
    setStatus("Page deleted");
  }

  return (
    <div>
      <div ref={containerRef} style={{ height: 600 }} />
      <button type="button" onClick={() => void rotateCurrentPage()}>Rotate</button>
      <button type="button" onClick={() => void deleteCurrentPage()}>Delete</button>
      <pre>{status}</pre>
    </div>
  );
}
React Integration

Next.js Integration

Use the SDK within a client component in Next.js:

tsx
"use client";

import { useEffect, useRef, useState } from "react";
import { createViewer, type RasterexViewer } from "@rasterex/viewer";

export default function PageManipulationPage() {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const viewerRef = useRef<RasterexViewer | null>(null);
  const [currentPageIndex, setCurrentPageIndex] = useState(0);
  const [status, setStatus] = useState("Starting viewer...");

  useEffect(() => {
    if (!containerRef.current) return undefined;

    let stopPageList: (() => void) | undefined;
    const viewer = createViewer({ container: containerRef.current });
    viewerRef.current = viewer;

    void viewer
      .mount()
      .then(() => viewer.ready())
      .then(async () => {
        stopPageList = viewer.documents.on("pageList", (event) => {
          setCurrentPageIndex(event.currentPage);
        });

        await viewer.documents.open({
          url: "https://pdfobject.com/pdf/sample.pdf",
          displayName: "sample.pdf"
        });

        setStatus("Viewer ready");
      })
      .catch((error) => {
        console.error(error);
        setStatus("Viewer failed to start");
      });

    return () => {
      stopPageList?.();
      viewer.destroy();
      viewerRef.current = null;
    };
  }, []);

  async function rotateCurrentPage(): Promise<void> {
    await viewerRef.current?.documents.manipulatePages({
      action: "rotate-r",
      pageRange: [[currentPageIndex]]
    });
    setStatus("Page rotated");
  }

  return (
    <main>
      <div ref={containerRef} style={{ height: "70vh" }} />
      <button type="button" onClick={() => void rotateCurrentPage()}>Rotate</button>
      <pre>{status}</pre>
    </main>
  );
}
Next.js Integration

Angular Integration

Leverage the SDK inside Angular component logic:

typescript
import {
  AfterViewInit,
  Component,
  ElementRef,
  OnDestroy,
  ViewChild
} from "@angular/core";
import { createViewer, type RasterexViewer } from "@rasterex/viewer";

@Component({
  selector: "app-page-manipulation",
  template: `
    <div #viewerContainer class="viewer"></div>
    <button type="button" (click)="rotateCurrentPage()">Rotate</button>
    <button type="button" (click)="deleteCurrentPage()">Delete</button>
    <pre>{{ status }}</pre>
  `,
  styles: [".viewer { height: 600px; }"]
})
export class PageManipulationComponent implements AfterViewInit, OnDestroy {
  @ViewChild("viewerContainer", { static: true })
  viewerContainer!: ElementRef<HTMLElement>;

  status = "Starting viewer...";
  currentPageIndex = 0;

  private viewer: RasterexViewer | null = null;
  private stopPageList?: () => void;

  async ngAfterViewInit(): Promise<void> {
    const viewer = createViewer({
      container: this.viewerContainer.nativeElement
    });

    this.viewer = viewer;
    await viewer.mount();
    await viewer.ready();

    this.stopPageList = viewer.documents.on("pageList", (event) => {
      this.currentPageIndex = event.currentPage;
    });

    await viewer.documents.open({
      url: "https://pdfobject.com/pdf/sample.pdf",
      displayName: "sample.pdf"
    });

    this.status = "Viewer ready";
  }

  async rotateCurrentPage(): Promise<void> {
    await this.viewer?.documents.manipulatePages({
      action: "rotate-r",
      pageRange: [[this.currentPageIndex]]
    });
    this.status = "Page rotated";
  }

  async deleteCurrentPage(): Promise<void> {
    await this.viewer?.documents.manipulatePages({
      action: "page-delete",
      pageRange: [[this.currentPageIndex]]
    });
    this.status = "Page deleted";
  }

  ngOnDestroy(): void {
    this.stopPageList?.();
    this.viewer?.destroy();
  }
}
Angular Integration

TypeScript Types

The package exports the page manipulation types for compile-time safety:

typescript
import type {
  PageManipulationOptions,
  PageManipulationResult,
  PageRange
} from "@rasterex/viewer";

const pageRange: PageRange[] = [[0], [3, 5]];

const options: PageManipulationOptions = {
  action: "rotate-r",
  pageRange
};

const result: PageManipulationResult =
  await viewer.documents.manipulatePages(options);
TypeScript Types

Canvas Broker Mapping

Maps the SDK API to Canvas internal command/event triggers:

  • viewer.documents.manipulatePages(...) maps to pageManipulation / pageManipulationResult.