Feature/v2/exportpdf (#4487)

# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Reece Browne
2025-09-26 10:28:09 +01:00
committed by GitHub
parent 03f484e0c0
commit d613a4659e
6 changed files with 247 additions and 127 deletions

View File

@@ -66,6 +66,9 @@ export default function RightRail() {
const { totalItems, selectedCount } = getSelectionState();
// Get export state for viewer mode
const exportState = viewerContext?.getExportState?.();
const handleSelectAll = useCallback(() => {
if (currentView === 'fileEditor' || currentView === 'viewer') {
// Select all file IDs
@@ -96,7 +99,10 @@ export default function RightRail() {
}, [currentView, setSelectedFiles, pageEditorFunctions]);
const handleExportAll = useCallback(() => {
if (currentView === 'fileEditor' || currentView === 'viewer') {
if (currentView === 'viewer') {
// Use EmbedPDF export functionality for viewer mode
viewerContext?.exportActions?.download();
} else if (currentView === 'fileEditor') {
// Download selected files (or all if none selected)
const filesToDownload = selectedFiles.length > 0 ? selectedFiles : activeFiles;
@@ -113,7 +119,7 @@ export default function RightRail() {
// Export all pages (not just selected)
pageEditorFunctions?.onExportAll?.();
}
}, [currentView, activeFiles, selectedFiles, pageEditorFunctions]);
}, [currentView, activeFiles, selectedFiles, pageEditorFunctions, viewerContext]);
const handleCloseSelected = useCallback(() => {
if (currentView !== 'fileEditor') return;
@@ -445,7 +451,9 @@ export default function RightRail() {
radius="md"
className="right-rail-icon"
onClick={handleExportAll}
disabled={currentView === 'viewer' || totalItems === 0}
disabled={
currentView === 'viewer' ? !exportState?.canExport : totalItems === 0
}
>
<LocalIcon icon="download" width="1.5rem" height="1.5rem" />
</ActionIcon>

View File

@@ -0,0 +1,25 @@
import { useEffect } from 'react';
import { useExportCapability } from '@embedpdf/plugin-export/react';
import { useViewer } from '../../contexts/ViewerContext';
/**
* Component that runs inside EmbedPDF context and provides export functionality
*/
export function ExportAPIBridge() {
const { provides: exportApi } = useExportCapability();
const { registerBridge } = useViewer();
useEffect(() => {
if (exportApi) {
// Register this bridge with ViewerContext
registerBridge('export', {
state: {
canExport: true,
},
api: exportApi
});
}
}, [exportApi, registerBridge]);
return null;
}

View File

@@ -17,6 +17,7 @@ import { SpreadPluginPackage, SpreadMode } from '@embedpdf/plugin-spread/react';
import { SearchPluginPackage } from '@embedpdf/plugin-search/react';
import { ThumbnailPluginPackage } from '@embedpdf/plugin-thumbnail/react';
import { RotatePluginPackage, Rotate } from '@embedpdf/plugin-rotate/react';
import { ExportPluginPackage } from '@embedpdf/plugin-export/react';
import { Rotation } from '@embedpdf/models';
import { CustomSearchLayer } from './CustomSearchLayer';
import { ZoomAPIBridge } from './ZoomAPIBridge';
@@ -29,6 +30,7 @@ import { SpreadAPIBridge } from './SpreadAPIBridge';
import { SearchAPIBridge } from './SearchAPIBridge';
import { ThumbnailAPIBridge } from './ThumbnailAPIBridge';
import { RotateAPIBridge } from './RotateAPIBridge';
import { ExportAPIBridge } from './ExportAPIBridge';
interface LocalEmbedPDFProps {
file?: File | Blob;
@@ -112,6 +114,11 @@ export function LocalEmbedPDF({ file, url }: LocalEmbedPDFProps) {
createPluginRegistration(RotatePluginPackage, {
defaultRotation: Rotation.Degree0, // Start with no rotation
}),
// Register export plugin for downloading PDFs
createPluginRegistration(ExportPluginPackage, {
defaultFileName: 'document.pdf',
}),
];
}, [pdfUrl]);
@@ -170,6 +177,7 @@ export function LocalEmbedPDF({ file, url }: LocalEmbedPDFProps) {
<SearchAPIBridge />
<ThumbnailAPIBridge />
<RotateAPIBridge />
<ExportAPIBridge />
<GlobalPointerProvider>
<Viewport
style={{