# rn-record-pdf-export URL: /docs/native/docyrus/record-pdf-export Three-step wizard (Select a Template → Preview → PDF) that renders a Docyrus record to PDF with a saved HTML template, previews the server-compiled document in a WebView, and shares or prints the result. Includes the headless useDocyrusRecordPdfExport hook. ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/rn-record-pdf-export ``` **Dependencies:** - [@tanstack/react-query](https://www.npmjs.com/package/@tanstack/react-query) - [@docyrus/api-client](https://www.npmjs.com/package/@docyrus/api-client) - [react-native-webview 13.x (optional)](https://www.npmjs.com/package/react-native-webview) - [expo-file-system (optional)](https://www.npmjs.com/package/expo-file-system) - [expo-sharing (optional)](https://www.npmjs.com/package/expo-sharing) - [expo-print (optional)](https://www.npmjs.com/package/expo-print) This is a **Docyrus-connected** component. It needs an authenticated `RestApiClient` and a `QueryClientProvider` above it. All native modules are **optional peers**, loaded lazily: | Module | Used for | Without it | |--------|----------|------------| | `react-native-webview` | The Preview step, and the inline PDF on iOS. | The preview shows an install notice; the PDF step shows the file card. | | `expo-file-system` | Downloading the signed PDF into the cache directory. | **Share** has nothing to share. | | `expo-sharing` | The **Share** button (share sheet). | Sharing is a no-op. | | `expo-print` | The **Print** button, and rendering the compiled HTML to a PDF on the device when the server returns no public URL. | The Print button is hidden. | ## Usage ### Wizard in a sheet ```tsx import { useState } from 'react'; import { useDocyrusClient } from '@docyrus/signin/react-native'; import { AwesomeDialog, AwesomeDialogContent, AwesomeDialogHeader, AwesomeDialogBody } from '@/components/docyrus-native/awesome-dialog'; import { DocyrusRecordPdfExportWizard } from '@/components/docyrus-native/record-pdf-export'; export function ExportOrderPdf({ dataSourceId, recordId }: { dataSourceId: string; recordId: string }) { const client = useDocyrusClient(); const [open, setOpen] = useState(false); return ( ); } ``` ### Headless: build your own UI ```tsx import { useDocyrusRecordPdfExport } from '@/components/docyrus-native/record-pdf-export'; const pdf = useDocyrusRecordPdfExport({ client, dataSourceId, recordId }); // pdf.templates / pdf.setSelectedTemplateId → pick a template // pdf.previewHtml → render in your own WebView // await pdf.generatePdf() → server render; pdf.pdfUrl when signed // await pdf.sharePdf() / pdf.printPdf() ``` ## How it works 1. **Resolve.** Without `appSlug` / `dataSourceSlug`, the hook resolves them from `GET /v1/dev/data-sources/{id}`. 2. **Select a Template.** Lists `GET /v1/dev/html-templates?tenantDataSourceId=…`. The default template (or the first one) is picked automatically unless `autoSelectDefaultTemplate` is `false` or `initialTemplateId` is set. Each row shows the name, a **Default** badge and page format / orientation. 3. **Preview.** Loads the **server-compiled** document from `GET /v1/apps/{app}/data-sources/{ds}/items/{recordId}/templates/{templateId}/html`. `previewHtml` combines it with the template CSS and an A4 preview stylesheet, and the wizard renders it in a WebView. 4. **PDF.** Pressing **Next** on the Preview step calls `generatePdf()`, which runs `GET …/templates/{templateId}/pdf`. The result (`{ id, path, fullPath, url?, … }`) is surfaced as is. On iOS, a signed `url` renders inline in the WebView. On Android, whose WebView cannot render PDFs, and when there is no `url`, a file card appears instead. 5. **Share / Print.** `sharePdf()` downloads the signed `url` into the cache directory (or, without a `url`, renders the compiled HTML on the device with `expo-print`) and opens the share sheet. `printPdf()` opens the system print dialog. ## API Reference ### DocyrusRecordPdfExportWizardProps Accepts every [`useDocyrusRecordPdfExport`](#options-usedocyrusrecordpdfexportoptions) option plus: | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | — | Root `View` classes. | | `bodyHeight` | `number` | 70% of the window height | Height of the wizard (px). | | `onClose` | `() => void` | — | Fired by the footer **Done** button on the last step. | | `hideClose` | `boolean` | `false` | Hide the **Done** button. | | `onShare` | `(result: DocyrusRecordPdfResult, uri: string) => void` | — | Native: called after the PDF was handed to the share sheet (`uri` = local file). | | `enablePrint` | `boolean` | `true` | Native: show **Print** on the PDF step (needs `expo-print`). | ### Options (`UseDocyrusRecordPdfExportOptions`) | Option | Type | Default | Description | |--------|------|---------|-------------| | `client` | `RestApiClient` | — | Authenticated REST client (required). | | `dataSourceId` | `string` | — | `tenant_data_source.id` of the record's data source (required). | | `recordId` | `string` | — | `tenant_data_source_item.id` of the record (required). | | `appSlug` | `string` | — | App slug. Resolved from `dataSourceId` when omitted. | | `dataSourceSlug` | `string` | — | Data source slug. Resolved from `dataSourceId` when omitted. | | `enabled` | `boolean` | `true` | Toggle all network activity. | | `initialTemplateId` | `string` | — | Pre-select a template by id. | | `autoSelectDefaultTemplate` | `boolean` | `true` | Select the default (or first) template once the list loads. | | `resolveDataSourceEndpoint` | `string` | `'/v1/dev/data-sources/{id}'` | Slug resolution endpoint (`{id}` is replaced). | | `listTemplatesEndpoint` | `string` | `'/v1/dev/html-templates'` | Templates list endpoint. | ### Result (`UseDocyrusRecordPdfExportResult`) | Field | Type | Description | |-------|------|-------------| | `steps` | `RecordPdfExportStep[]` | `['select', 'preview', 'pdf']`. | | `step` / `setStep` / `stepIndex` | `RecordPdfExportStep` / setter / `number` | Current step. | | `goNext` / `goBack` | `() => void` | Step navigation. | | `canGoNext` / `canGoBack` / `isLastStep` | `boolean` | Navigation state. `canGoNext` needs a selected template (select) or a loaded preview (preview). | | `appSlug` / `dataSourceSlug` | `string \| null` | Resolved slugs. | | `isResolving` / `resolveError` | `boolean` / `Error \| null` | Slug resolution state. | | `templates` | `DocyrusHtmlTemplateSummary[]` | Templates for the data source. | | `isLoadingTemplates` / `templatesError` | `boolean` / `Error \| null` | Templates state. | | `refetchTemplates` | `() => Promise` | Invalidate and reload the templates. | | `selectedTemplateId` / `setSelectedTemplateId` / `selectedTemplate` | — | Selection. Changing it resets the PDF result. | | `templateDetail` | `DocyrusHtmlTemplateDetail \| null` | Server-compiled template (body, header / footer, styles). | | `isLoadingTemplateDetail` / `templateDetailError` | `boolean` / `Error \| null` | Preview state. | | `previewHtml` | `string` | Native: full document HTML (compiled body + template CSS + A4 preview CSS) for a WebView. | | `generatePdf` | `() => Promise` | Server-side render. | | `isGeneratingPdf` / `pdfResult` / `pdfUrl` / `pdfError` | — | PDF state. `pdfUrl` is the signed `url` when present. | | `pdfFileName` | `string` | Suggested file name (always ends in `.pdf`). | | `localPdfUri` | `string \| null` | Native: local `file://` URI once prepared. | | `isPreparingFile` / `fileError` | `boolean` / `Error \| null` | Native: download / on-device render state. | | `prepareFile` | `() => Promise` | Native: download the signed url (or render with `expo-print`) into the cache. | | `sharePdf` | `() => Promise` | Native: prepare the file if needed and open the share sheet. Resolves the shared URI. | | `printPdf` | `() => Promise` | Native: open the print dialog. Resolves `false` without `expo-print`. | | `canPrint` | `boolean` | Native: whether `expo-print` is installed. | | `reset` | `() => void` | Back to the first step and clear the result. | ### DocyrusRecordPdfResult | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Storage record id. | | `path` | `string` | Generated file name. | | `fullPath` | `string` | Storage object path (not directly fetchable). | | `url` | `string` | Signed, fetchable URL (when the server returns one). | | `filename` | `string` | File name alias used by some endpoints. | | `bucket` | `string` | Storage bucket. | | `size` | `number` | File size in bytes. | ## Native differences - **No template editing.** The web `templateEditable` mode (Plate `HtmlTemplateEditor`) is web-only, so `templateEditable`, `templateDetailEndpoint` and the record / edit state (`record`, `editedHtml`, `previewEditorProps`, …) are not available. - **No Email step.** There is no native `EmailComposer` yet, so `sendEmail` is not supported. `RecordPdfExportStep` keeps `'email'` for type parity, but native never produces it. - The preview is a WebView (`previewHtml`) instead of the HTML Template Editor preview tab. - Native adds `onShare`, `enablePrint`, `bodyHeight: number` and the local-file API (`prepareFile`, `sharePdf`, `printPdf`, `localPdfUri`, `canPrint`). File writing and sharing use the internal `lib/native-export` helpers. ## Translation keys `ui.recordPdfExport.*`: `stepSelect`, `stepPreview`, `stepPdf`, `stepEmail`, `chooseTemplate`, `reload`, `loadingTemplates`, `noTemplates`, `default`, `loadingPreview`, `webviewMissing`, `retry`, `generatingPdf`, `pdfGenerated`, `pdfOpenHint`, `pdfNoUrl`, `pdfEmpty`, `back`, `next`, `print`, `share`, `done`. ## Components | Component | Description | |-----------|-------------| | `DocyrusRecordPdfExportWizard` | The three-step wizard. | ## Type Exports | Type | Description | |------|-------------| | `DocyrusRecordPdfExportWizardProps` | Wizard props. | | `UseDocyrusRecordPdfExportOptions` | Hook options. | | `UseDocyrusRecordPdfExportResult` | Hook result. | | `RecordPdfExportStep` | `'select' \| 'preview' \| 'pdf' \| 'email'`. | | `DocyrusHtmlTemplateSummary` | Template list row. | | `DocyrusHtmlTemplateDetail` | Template with compiled body, header / footer and styles. | | `DocyrusRecordPdfResult` | PDF render result. | `RECORD_PDF_EXPORT_STEPS` (`['select', 'preview', 'pdf']`) is exported as a value.