Skip to content

Latest commit

 

History

History
341 lines (274 loc) · 13.1 KB

File metadata and controls

341 lines (274 loc) · 13.1 KB



Add a powerful PDF editor directly into your React App.



Read more about SimplePDF Embed »

Join Our Discord · Follow us on Twitter



Easily add SimplePDF to your React app, by using the EmbedPDF component.

Install

npm install @simplepdf/react-embed-pdf

The package root (<EmbedPDF>, useEmbed) has no zod dependency. Only the agentic tools, the opt-in @simplepdf/react-embed-pdf/ai-sdk subpath, need zod (a peer). Install it alongside if you use them (npm 7+ adds it automatically; pnpm / Yarn PnP users must add it explicitly):

npm install zod

Related documentation

For shared product behavior and account-specific features, see the main embed README:

How to use it

The EmbedPDF component has two modes: "modal" (default) and "inline".

List of all available props

Account-specific features

The features below require a SimplePDF account

While the component does not require any account to be used (without any limits), you can specify the companyIdentifier to:

Example

import { EmbedPDF } from '@simplepdf/react-embed-pdf';

<EmbedPDF companyIdentifier="yourcompany">
  <a href="https://cdn.simplepdf.com/simple-pdf/assets/sample.pdf">Opens sample.pdf</a>
</EmbedPDF>;

Modal mode

Modal is the default, just wrap any HTML element and the editor opens in a modal on the user's click. You don't need the mode prop; pass mode="modal" only if you want to be explicit.

import { EmbedPDF } from "@simplepdf/react-embed-pdf";

// Opens the PDF on click
<EmbedPDF>
  <a href="https://cdn.simplepdf.com/simple-pdf/assets/sample.pdf">
    Opens sample.pdf
  </a>
</EmbedPDF>

// Let the user pick the PDF
<EmbedPDF>
  <button>Opens the simplePDF editor</button>
</EmbedPDF>

Inline mode

Render the PDF editor directly in your app

import { EmbedPDF } from "@simplepdf/react-embed-pdf";

// The PDF is displayed when rendering the component
 <EmbedPDF
  mode="inline"
  style={{ width: 900, height: 800 }}
  document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/sample.pdf' }}
/>

// The PDF picker is displayed when rendering the component
 <EmbedPDF
  mode="inline"
  style={{ width: 900, height: 800 }}
/>

Viewer mode only

Specify react-viewer as companyIdentifier to disable the editing features:

import { EmbedPDF } from '@simplepdf/react-embed-pdf';

// The PDF is displayed using the viewer: all editing features are disabled
<EmbedPDF
  companyIdentifier="react-viewer"
  mode="inline"
  style={{ width: 900, height: 800 }}
  document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/sample.pdf' }}
/>;

See Data Privacy & companyIdentifier for reserved values and mode behavior.

Programmatic Control

Some actions require a SimplePDF account. See Retrieving PDF Data for storage and submission behavior.

const { embedRef, actions } = useEmbed(); drives the editor imperatively (actions); the agentic tools come from the opt-in @simplepdf/react-embed-pdf/ai-sdk subpath (useEmbedTools(embedRef)). Attach embedRef to the component: <EmbedPDF ref={embedRef} mode="inline" … />.

Imperative: actions

Actions are camelCase (the editor's snake_case wire is transformed for you). useEmbed().actions exposes the FULL editor surface; the most common:

Action Description
actions.goTo({ page }) Navigate to a specific page
actions.selectTool({ tool }) Select a tool: 'TEXT', 'COMB_TEXT', 'CHECKBOX', 'PICTURE', 'SIGNATURE', or null to deselect
actions.detectFields() Automatically detect form fields in the document
actions.deleteFields({ fieldIds?, page? }) Delete fields by id or page, or all fields if both are omitted
actions.getDocumentContent({ extractionMode }) Extract document content ('auto' or 'ocr')
actions.setFieldValue({ fieldId, value }) Set a field's value
actions.submit({ downloadCopy }) Submit the document

…plus createField, getFields, focusField, movePage, rotatePage, deletePages, download, and loadDocument. All actions return a Promise with a result object: { success: true, data: ... } or { success: false, error: { code, message } }.

import { EmbedPDF, useEmbed } from '@simplepdf/react-embed-pdf';

const Editor = () => {
  const { embedRef, actions } = useEmbed();

  const handleSubmit = async () => {
    const result = await actions.submit({ downloadCopy: false });
    if (result.success) console.log('Submitted!');
  };

  const handleExtract = async () => {
    const result = await actions.getDocumentContent({ extractionMode: 'auto' });
    if (result.success) console.log('Pages:', result.data.pages);
  };

  return (
    <>
      <button onClick={handleSubmit}>Submit</button>
      <button onClick={handleExtract}>Extract Content</button>
      <button onClick={() => actions.detectFields()}>Detect Fields</button>
      <button onClick={() => actions.selectTool({ tool: 'TEXT' })}>Select Text Tool</button>
      <button onClick={() => actions.goTo({ page: 2 })}>Go to Page 2</button>
      <EmbedPDF
        ref={embedRef}
        mode="inline"
        companyIdentifier="yourcompany"
        style={{ width: 900, height: 800 }}
        document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/sample.pdf' }}
      />
    </>
  );
};

"Fill and read this document for me" is just these actions in sequence, exactly what an AI agent calls on your behalf (read the fields, fill one, then walk the user to a signature: navigate to its page, focus it, open the signature tool):

const { embedRef, actions } = useEmbed();

const fields = await actions.getFields(); // read
await actions.setFieldValue({ fieldId: 'f_full_name', value: 'Jane Doe' }); // fill
await actions.goTo({ page: 3 });
await actions.focusField({ fieldId: 'f_signature' });
await actions.selectTool({ tool: 'SIGNATURE' });

Agentic: useEmbedTools (Vercel AI SDK)

The agentic tools live in the opt-in @simplepdf/react-embed-pdf/ai-sdk subpath, importing it is what pulls zod, so a non-agentic app never loads it (mirroring @simplepdf/embed's /ai-sdk). useEmbedTools(embedRef) binds the SimplePDF tool set to the live editor, drop it straight into the AI SDK and an LLM can drive the editor:

import { useChat } from '@ai-sdk/react';
import { EmbedPDF, useEmbed } from '@simplepdf/react-embed-pdf';
import { useEmbedTools } from '@simplepdf/react-embed-pdf/ai-sdk';

const CopilotEditor = () => {
  const { embedRef } = useEmbed();
  const tools = useEmbedTools(embedRef);
  useChat({ tools }); // the model's tool calls run against the live editor
  return <EmbedPDF ref={embedRef} mode="inline" companyIdentifier="yourcompany" style={{ width: 900, height: 800 }} />;
};

For server-side tool definitions (execute-less, for streamText), import simplePDFToolDefinitions from the React-free core @simplepdf/embed/ai-sdk (it is intentionally not re-exported from this React subpath, which imports React). embedRef.current is the flat editor-actions handle, every camelCase operation, with the deprecated selectTool / submit overloads; subscribe to editor events via the onEmbedEvent prop. (The framework-free @simplepdf/embed core exposes the grouped embed.actions / embed.events / embed.lifecycle handle for non-React use.)

Agentic: useEmbedTools (TanStack AI)

The TanStack mirror lives in the opt-in @simplepdf/react-embed-pdf/tanstack-ai subpath (importing it pulls @tanstack/ai). useEmbedTools(embedRef) returns the editor-bound client tools; pass them to clientTools(...), then useChat:

import { useChat, clientTools } from '@tanstack/ai-react';
import { EmbedPDF, useEmbed } from '@simplepdf/react-embed-pdf';
import { useEmbedTools } from '@simplepdf/react-embed-pdf/tanstack-ai';

const CopilotEditor = () => {
  const { embedRef } = useEmbed();
  const tools = clientTools(...useEmbedTools(embedRef));
  useChat({ connection, tools }); // the model's tool calls run against the live editor
  return <EmbedPDF ref={embedRef} mode="inline" companyIdentifier="yourcompany" style={{ width: 900, height: 800 }} />;
};

On your server chat({ tools }) route, register simplePDFToolDefinitions() imported from the React-free core @simplepdf/embed/tanstack-ai (not from this React subpath, which would pull React into your server) so the model is aware of the tools.

See Retrieving PDF Data for text extraction, downloading, and server-side storage options.

Available props

Name Type Required Description
ref EmbedActions No The live editor-actions handle, for programmatic control (see Programmatic Control). Attach the embedRef from useEmbed().
mode "inline" | "modal" No (defaults to "modal") Inline the editor in your layout, or display it inside a click-to-open modal
locale "en" | "de" | "es" | "fr" | "it" | "nl" | "pt" No (defaults to "en") Language to display the editor in (ISO locale)
children React.ReactElement Yes in "modal" mode Elements triggering the editor
companyIdentifier string No Your SimplePDF portal. See Data Privacy & companyIdentifier for reserved values and data handling details.
baseDomain string No Override the editor's base domain (defaults to simplepdf.com)
context Record<string, unknown> No Sent via webhooks
onEmbedEvent (event: EmbedEvent) => Promise<void> | void No Events sent by the Iframe
document { url: string } | { dataUrl: string } | { file: File | Blob } No The document to open (same typed shape as createEmbed): a URL (CORS / authenticated same-origin / a SimplePDF documents URL), a data URL, or a File/Blob
style React.CSSProperties No Available for inline mode only
className string No Available for inline mode only

How to dev

  1. Link the widget
npm link
npm start
  1. Use it in the target application
npm link @simplepdf/react-embed-pdf