@signiphi/page-assembly 0.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -0
- package/dist/index.d.mts +178 -0
- package/dist/index.d.ts +178 -0
- package/dist/index.js +1872 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1837 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles/index.css +1762 -0
- package/package.json +85 -0
- package/src/styles/index.css +109 -0
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# @signiphi/page-assembly
|
|
2
|
+
|
|
3
|
+
React component for PDF and image page manipulation - upload, reorder, delete, and combine pages into a single document.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📄 **File Upload** - Upload multiple PDF files and images
|
|
8
|
+
- 🔄 **Drag & Drop** - Reorder pages and files with intuitive drag-and-drop
|
|
9
|
+
- ✂️ **Multi-Select** - Select multiple pages with Ctrl+Click, Shift+Click, or checkboxes
|
|
10
|
+
- 🗑️ **Bulk Operations** - Move or delete multiple pages at once
|
|
11
|
+
- 🖼️ **Image Support** - Convert and combine images (PNG, JPEG, WebP) into PDFs
|
|
12
|
+
- 📦 **PDF Assembly** - Generate a final assembled PDF with all selected pages
|
|
13
|
+
- ♻️ **State Management** - Save and restore page assembly state
|
|
14
|
+
- 🎨 **Customizable** - Scoped styles that don't leak to parent application
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @signiphi/page-assembly
|
|
20
|
+
# or
|
|
21
|
+
pnpm add @signiphi/page-assembly
|
|
22
|
+
# or
|
|
23
|
+
yarn add @signiphi/page-assembly
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Peer Dependencies
|
|
27
|
+
|
|
28
|
+
This package requires the following peer dependencies:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install react react-dom lucide-react @radix-ui/react-alert-dialog @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-select @radix-ui/react-tooltip
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Basic Example
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { useRef } from 'react';
|
|
40
|
+
import { PageAssembler, PageAssemblerHandle } from '@signiphi/page-assembly';
|
|
41
|
+
import '@signiphi/page-assembly/styles';
|
|
42
|
+
|
|
43
|
+
function App() {
|
|
44
|
+
const assemblerRef = useRef<PageAssemblerHandle>(null);
|
|
45
|
+
|
|
46
|
+
const handleAssemble = async () => {
|
|
47
|
+
if (!assemblerRef.current) return;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const pdfBlob = await assemblerRef.current.assemble();
|
|
51
|
+
|
|
52
|
+
// Download the assembled PDF
|
|
53
|
+
const url = URL.createObjectURL(pdfBlob);
|
|
54
|
+
const a = document.createElement('a');
|
|
55
|
+
a.href = url;
|
|
56
|
+
a.download = 'assembled-document.pdf';
|
|
57
|
+
a.click();
|
|
58
|
+
URL.revokeObjectURL(url);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Failed to assemble PDF:', error);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div className="signiphi-page-assembly">
|
|
66
|
+
<PageAssembler
|
|
67
|
+
ref={assemblerRef}
|
|
68
|
+
onChange={(state) => {
|
|
69
|
+
console.log('State changed:', state);
|
|
70
|
+
}}
|
|
71
|
+
onValidityChange={(isValid) => {
|
|
72
|
+
console.log('Valid:', isValid);
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
<button onClick={handleAssemble}>Assemble PDF</button>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### With Initial PDF
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { PageAssembler } from '@signiphi/page-assembly';
|
|
85
|
+
import '@signiphi/page-assembly/styles';
|
|
86
|
+
|
|
87
|
+
function App() {
|
|
88
|
+
const [pdfBytes, setPdfBytes] = useState<Uint8Array | null>(null);
|
|
89
|
+
|
|
90
|
+
// Load initial PDF
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
fetch('/document.pdf')
|
|
93
|
+
.then(res => res.arrayBuffer())
|
|
94
|
+
.then(buffer => setPdfBytes(new Uint8Array(buffer)));
|
|
95
|
+
}, []);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div className="signiphi-page-assembly">
|
|
99
|
+
<PageAssembler
|
|
100
|
+
initialPdf={pdfBytes || undefined}
|
|
101
|
+
limits={{
|
|
102
|
+
maxFileSizeMB: 20,
|
|
103
|
+
maxTotalPages: 100
|
|
104
|
+
}}
|
|
105
|
+
/>
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### With State Persistence
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { PageAssembler, PageAssemblerState } from '@signiphi/page-assembly';
|
|
115
|
+
import '@signiphi/page-assembly/styles';
|
|
116
|
+
|
|
117
|
+
function App() {
|
|
118
|
+
const [savedState, setSavedState] = useState<PageAssemblerState | null>(null);
|
|
119
|
+
const assemblerRef = useRef<PageAssemblerHandle>(null);
|
|
120
|
+
|
|
121
|
+
const handleSave = () => {
|
|
122
|
+
if (!assemblerRef.current) return;
|
|
123
|
+
const state = assemblerRef.current.getState();
|
|
124
|
+
localStorage.setItem('pageAssemblerState', JSON.stringify(state));
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const handleRestore = () => {
|
|
128
|
+
const stateJson = localStorage.getItem('pageAssemblerState');
|
|
129
|
+
if (stateJson) {
|
|
130
|
+
setSavedState(JSON.parse(stateJson));
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div className="signiphi-page-assembly">
|
|
136
|
+
<PageAssembler
|
|
137
|
+
ref={assemblerRef}
|
|
138
|
+
initialState={savedState || undefined}
|
|
139
|
+
onChange={(state) => {
|
|
140
|
+
// Auto-save state changes
|
|
141
|
+
localStorage.setItem('pageAssemblerState', JSON.stringify(state));
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
<button onClick={handleSave}>Save State</button>
|
|
145
|
+
<button onClick={handleRestore}>Restore State</button>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## API Reference
|
|
152
|
+
|
|
153
|
+
### PageAssembler Props
|
|
154
|
+
|
|
155
|
+
| Prop | Type | Description |
|
|
156
|
+
|------|------|-------------|
|
|
157
|
+
| `initialPdf` | `File \| Blob \| ArrayBuffer \| Uint8Array` | Optional initial PDF to pre-load |
|
|
158
|
+
| `initialState` | `PageAssemblerState` | Optional initial state to restore previous session |
|
|
159
|
+
| `onChange` | `(state: PageAssemblerState) => void` | Called when state changes (files/pages added/removed/reordered) |
|
|
160
|
+
| `onValidityChange` | `(isValid: boolean) => void` | Called when validity changes (e.g., 0 pages) |
|
|
161
|
+
| `limits` | `{ maxFileSizeMB?: number; maxTotalPages?: number }` | Optional file size and page count limits |
|
|
162
|
+
| `disableFileUpload` | `boolean` | Disable file upload UI (for template-only flows) |
|
|
163
|
+
| `className` | `string` | Optional className passthrough |
|
|
164
|
+
|
|
165
|
+
### PageAssemblerHandle Methods
|
|
166
|
+
|
|
167
|
+
The `ref` provides access to imperative methods:
|
|
168
|
+
|
|
169
|
+
| Method | Type | Description |
|
|
170
|
+
|--------|------|-------------|
|
|
171
|
+
| `assemble` | `(opts?: AssembleOptions) => Promise<Blob>` | Assembles current pages into a single PDF |
|
|
172
|
+
| `getSummary` | `() => { totalFiles: number; totalPages: number }` | Returns summary of current state |
|
|
173
|
+
| `isBusy` | `() => boolean` | Returns true if loading/assembling |
|
|
174
|
+
| `getState` | `() => PageAssemblerState` | Returns current state |
|
|
175
|
+
|
|
176
|
+
### Types
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
interface PageInfo {
|
|
180
|
+
id: string;
|
|
181
|
+
srcIndex: number;
|
|
182
|
+
thumbUrl: string;
|
|
183
|
+
width?: number;
|
|
184
|
+
height?: number;
|
|
185
|
+
mime: string;
|
|
186
|
+
originalFileId?: string;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
interface FileInfo {
|
|
190
|
+
id: string;
|
|
191
|
+
name: string;
|
|
192
|
+
type: "pdf" | "image";
|
|
193
|
+
originalFile: File;
|
|
194
|
+
originalBytes: Uint8Array;
|
|
195
|
+
pages: PageInfo[];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
interface PageAssemblerState {
|
|
199
|
+
files: FileInfo[];
|
|
200
|
+
selection: string[];
|
|
201
|
+
lastSelectedPageId?: string;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
interface AssembleOptions {
|
|
205
|
+
imageSizing?: "auto-letter" | "original-size";
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Styling
|
|
210
|
+
|
|
211
|
+
The package includes scoped Tailwind CSS styles. Import the styles in your application:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import '@signiphi/page-assembly/styles';
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
All styles are prefixed with `.signiphi-page-assembly` to prevent conflicts with your application's styles.
|
|
218
|
+
|
|
219
|
+
### Custom Styling
|
|
220
|
+
|
|
221
|
+
You can override the default styles by wrapping the component in a container with custom CSS:
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
<div className="my-custom-page-assembly signiphi-page-assembly">
|
|
225
|
+
<PageAssembler />
|
|
226
|
+
</div>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Advanced Usage
|
|
230
|
+
|
|
231
|
+
### Working with Assembled PDF
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
const handleAssemble = async () => {
|
|
235
|
+
if (!assemblerRef.current) return;
|
|
236
|
+
|
|
237
|
+
const pdfBlob = await assemblerRef.current.assemble();
|
|
238
|
+
|
|
239
|
+
// Upload to server
|
|
240
|
+
const formData = new FormData();
|
|
241
|
+
formData.append('pdf', pdfBlob, 'assembled.pdf');
|
|
242
|
+
|
|
243
|
+
await fetch('/api/upload', {
|
|
244
|
+
method: 'POST',
|
|
245
|
+
body: formData
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Getting Summary Information
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
const assemblerRef = useRef<PageAssemblerHandle>(null);
|
|
254
|
+
|
|
255
|
+
const summary = assemblerRef.current?.getSummary();
|
|
256
|
+
console.log(`Total files: ${summary.totalFiles}`);
|
|
257
|
+
console.log(`Total pages: ${summary.totalPages}`);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Checking if Busy
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
const isBusy = assemblerRef.current?.isBusy();
|
|
264
|
+
if (isBusy) {
|
|
265
|
+
console.log('Page assembler is currently processing...');
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Browser Support
|
|
270
|
+
|
|
271
|
+
- Chrome/Edge: Latest 2 versions
|
|
272
|
+
- Firefox: Latest 2 versions
|
|
273
|
+
- Safari: Latest 2 versions
|
|
274
|
+
|
|
275
|
+
## Dependencies
|
|
276
|
+
|
|
277
|
+
- `react` - ^18.2.0 || ^19.0.0
|
|
278
|
+
- `react-dom` - ^18.2.0 || ^19.0.0
|
|
279
|
+
- `pdf-lib` - ^1.17.1 (PDF manipulation)
|
|
280
|
+
- `pdfjs-dist` - 5.3.93 (PDF rendering)
|
|
281
|
+
- `react-dnd` - ^16.0.1 (Drag and drop)
|
|
282
|
+
- `react-dnd-html5-backend` - ^16.0.1
|
|
283
|
+
- Radix UI components (see peer dependencies)
|
|
284
|
+
- `lucide-react` - ^0.454.0 (Icons)
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
See the LICENSE file in the root of the repository.
|
|
289
|
+
|
|
290
|
+
## Contributing
|
|
291
|
+
|
|
292
|
+
Contributions are welcome! Please read the contributing guidelines in the repository.
|
|
293
|
+
|
|
294
|
+
## Support
|
|
295
|
+
|
|
296
|
+
For issues and questions, please visit the [GitHub repository](https://github.com/signiphi/signiphi).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a single page in the page assembly system
|
|
8
|
+
*/
|
|
9
|
+
type PageInfo = {
|
|
10
|
+
/** Unique identifier for the page */
|
|
11
|
+
id: string;
|
|
12
|
+
/** Index of this page in the original source file */
|
|
13
|
+
srcIndex: number;
|
|
14
|
+
/** Data URL for the page thumbnail */
|
|
15
|
+
thumbUrl: string;
|
|
16
|
+
/** Page width in points (for PDFs) or pixels (for images) */
|
|
17
|
+
width?: number;
|
|
18
|
+
/** Page height in points (for PDFs) or pixels (for images) */
|
|
19
|
+
height?: number;
|
|
20
|
+
/** MIME type of the page */
|
|
21
|
+
mime: string;
|
|
22
|
+
/** ID of the original file this page came from (for tracking across moves) */
|
|
23
|
+
originalFileId?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Represents a file (PDF or image) in the page assembly system
|
|
27
|
+
*/
|
|
28
|
+
type FileInfo = {
|
|
29
|
+
/** Unique identifier for the file */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Original file name */
|
|
32
|
+
name: string;
|
|
33
|
+
/** File type */
|
|
34
|
+
type: "pdf" | "image";
|
|
35
|
+
/** Original File object */
|
|
36
|
+
originalFile: File;
|
|
37
|
+
/** Raw bytes of the file */
|
|
38
|
+
originalBytes: Uint8Array;
|
|
39
|
+
/** Pages extracted from this file */
|
|
40
|
+
pages: PageInfo[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* State of the page assembler
|
|
44
|
+
*/
|
|
45
|
+
type PageAssemblerState = {
|
|
46
|
+
/** Files currently in the assembler */
|
|
47
|
+
files: FileInfo[];
|
|
48
|
+
/** IDs of currently selected pages */
|
|
49
|
+
selection: string[];
|
|
50
|
+
/** ID of the last selected page (for range selection) */
|
|
51
|
+
lastSelectedPageId?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Options for assembling the final PDF
|
|
55
|
+
*/
|
|
56
|
+
type AssembleOptions = {
|
|
57
|
+
/** How to handle image pages: "auto-letter" (default) or "original-size" */
|
|
58
|
+
imageSizing?: "auto-letter" | "original-size";
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Imperative handle exposed by PageAssembler component
|
|
62
|
+
*/
|
|
63
|
+
type PageAssemblerHandle = {
|
|
64
|
+
/** Assemble the current canvas into a single PDF Blob */
|
|
65
|
+
assemble: (opts?: AssembleOptions) => Promise<Blob>;
|
|
66
|
+
/** Get derived info for the parent (total files and pages) */
|
|
67
|
+
getSummary: () => {
|
|
68
|
+
totalFiles: number;
|
|
69
|
+
totalPages: number;
|
|
70
|
+
};
|
|
71
|
+
/** True while loading/assembling */
|
|
72
|
+
isBusy: () => boolean;
|
|
73
|
+
/** Get current state */
|
|
74
|
+
getState: () => PageAssemblerState;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Props for the PageAssembler component
|
|
78
|
+
*/
|
|
79
|
+
type PageAssemblerProps = {
|
|
80
|
+
/** Optional initial PDF to pre-load */
|
|
81
|
+
initialPdf?: File | Blob | ArrayBuffer | Uint8Array;
|
|
82
|
+
/** Optional initial state to restore previous session */
|
|
83
|
+
initialState?: PageAssemblerState;
|
|
84
|
+
/** Notified on any structural change (files/pages added/removed/reordered) */
|
|
85
|
+
onChange?: (state: PageAssemblerState) => void;
|
|
86
|
+
/** Called when internal validity changes (e.g., 0 pages) */
|
|
87
|
+
onValidityChange?: (isValid: boolean) => void;
|
|
88
|
+
/** Optional limits */
|
|
89
|
+
limits?: {
|
|
90
|
+
maxFileSizeMB?: number;
|
|
91
|
+
maxTotalPages?: number;
|
|
92
|
+
};
|
|
93
|
+
/** Disable file upload (e.g., for template-only flows) */
|
|
94
|
+
disableFileUpload?: boolean;
|
|
95
|
+
/** Optional className passthrough */
|
|
96
|
+
className?: string;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Represents a page image extracted from a PDF
|
|
100
|
+
*/
|
|
101
|
+
type PageImage = {
|
|
102
|
+
/** Data URL for the image */
|
|
103
|
+
imageUrl: string;
|
|
104
|
+
/** Page width in points */
|
|
105
|
+
width: number;
|
|
106
|
+
/** Page height in points */
|
|
107
|
+
height: number;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
declare const PageAssembler: React__default.ForwardRefExoticComponent<PageAssemblerProps & React__default.RefAttributes<PageAssemblerHandle>>;
|
|
111
|
+
|
|
112
|
+
declare const buttonVariants: (props?: ({
|
|
113
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
114
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
115
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
116
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
117
|
+
asChild?: boolean;
|
|
118
|
+
}
|
|
119
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Converts a PDF document to an array of rendered page images
|
|
123
|
+
*
|
|
124
|
+
* @param pdfBytes - The PDF document as a Uint8Array
|
|
125
|
+
* @param options - Optional configuration
|
|
126
|
+
* @param options.hideFormFields - If true, hides existing form fields during rendering
|
|
127
|
+
* @returns Promise resolving to array of PageImage objects with rendered images
|
|
128
|
+
* @throws {Error} If PDF is invalid or rendering fails
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const pages = await pdfToImages(pdfBytes, { hideFormFields: true });
|
|
133
|
+
* console.log(`Rendered ${pages.length} pages`);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
declare function pdfToImages(pdfBytes: Uint8Array, options?: {
|
|
137
|
+
hideFormFields?: boolean;
|
|
138
|
+
}): Promise<PageImage[]>;
|
|
139
|
+
/**
|
|
140
|
+
* Converts an image file to a PDF document with a single page
|
|
141
|
+
*
|
|
142
|
+
* @param imageFile - The image file to convert (supports common image formats)
|
|
143
|
+
* @returns Promise resolving to PDF bytes as Uint8Array
|
|
144
|
+
* @throws {Error} If image fails to load or convert
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* const pdfBytes = await imageToPdf(imageFile);
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function imageToPdf(imageFile: File): Promise<Uint8Array>;
|
|
152
|
+
/**
|
|
153
|
+
* Create a blob URL from PDF bytes for preview
|
|
154
|
+
*
|
|
155
|
+
* @param pdfBytes - The PDF document as Uint8Array
|
|
156
|
+
* @returns Blob URL string
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* const url = createPdfBlobUrl(pdfBytes);
|
|
161
|
+
* // Remember to revoke: URL.revokeObjectURL(url);
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
declare function createPdfBlobUrl(pdfBytes: Uint8Array): string;
|
|
165
|
+
/**
|
|
166
|
+
* Triggers a browser download of a PDF file
|
|
167
|
+
*
|
|
168
|
+
* @param pdfBytes - The PDF document as Uint8Array
|
|
169
|
+
* @param filename - The filename for the downloaded file (e.g., 'document.pdf')
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* downloadPdf(pdfBytes, 'assembled-document.pdf');
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function downloadPdf(pdfBytes: Uint8Array, filename: string): void;
|
|
177
|
+
|
|
178
|
+
export { type AssembleOptions, Button, type FileInfo, PageAssembler, type PageAssemblerHandle, type PageAssemblerProps, type PageAssemblerState, type PageImage, type PageInfo, createPdfBlobUrl, PageAssembler as default, downloadPdf, imageToPdf, pdfToImages };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a single page in the page assembly system
|
|
8
|
+
*/
|
|
9
|
+
type PageInfo = {
|
|
10
|
+
/** Unique identifier for the page */
|
|
11
|
+
id: string;
|
|
12
|
+
/** Index of this page in the original source file */
|
|
13
|
+
srcIndex: number;
|
|
14
|
+
/** Data URL for the page thumbnail */
|
|
15
|
+
thumbUrl: string;
|
|
16
|
+
/** Page width in points (for PDFs) or pixels (for images) */
|
|
17
|
+
width?: number;
|
|
18
|
+
/** Page height in points (for PDFs) or pixels (for images) */
|
|
19
|
+
height?: number;
|
|
20
|
+
/** MIME type of the page */
|
|
21
|
+
mime: string;
|
|
22
|
+
/** ID of the original file this page came from (for tracking across moves) */
|
|
23
|
+
originalFileId?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Represents a file (PDF or image) in the page assembly system
|
|
27
|
+
*/
|
|
28
|
+
type FileInfo = {
|
|
29
|
+
/** Unique identifier for the file */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Original file name */
|
|
32
|
+
name: string;
|
|
33
|
+
/** File type */
|
|
34
|
+
type: "pdf" | "image";
|
|
35
|
+
/** Original File object */
|
|
36
|
+
originalFile: File;
|
|
37
|
+
/** Raw bytes of the file */
|
|
38
|
+
originalBytes: Uint8Array;
|
|
39
|
+
/** Pages extracted from this file */
|
|
40
|
+
pages: PageInfo[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* State of the page assembler
|
|
44
|
+
*/
|
|
45
|
+
type PageAssemblerState = {
|
|
46
|
+
/** Files currently in the assembler */
|
|
47
|
+
files: FileInfo[];
|
|
48
|
+
/** IDs of currently selected pages */
|
|
49
|
+
selection: string[];
|
|
50
|
+
/** ID of the last selected page (for range selection) */
|
|
51
|
+
lastSelectedPageId?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Options for assembling the final PDF
|
|
55
|
+
*/
|
|
56
|
+
type AssembleOptions = {
|
|
57
|
+
/** How to handle image pages: "auto-letter" (default) or "original-size" */
|
|
58
|
+
imageSizing?: "auto-letter" | "original-size";
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Imperative handle exposed by PageAssembler component
|
|
62
|
+
*/
|
|
63
|
+
type PageAssemblerHandle = {
|
|
64
|
+
/** Assemble the current canvas into a single PDF Blob */
|
|
65
|
+
assemble: (opts?: AssembleOptions) => Promise<Blob>;
|
|
66
|
+
/** Get derived info for the parent (total files and pages) */
|
|
67
|
+
getSummary: () => {
|
|
68
|
+
totalFiles: number;
|
|
69
|
+
totalPages: number;
|
|
70
|
+
};
|
|
71
|
+
/** True while loading/assembling */
|
|
72
|
+
isBusy: () => boolean;
|
|
73
|
+
/** Get current state */
|
|
74
|
+
getState: () => PageAssemblerState;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Props for the PageAssembler component
|
|
78
|
+
*/
|
|
79
|
+
type PageAssemblerProps = {
|
|
80
|
+
/** Optional initial PDF to pre-load */
|
|
81
|
+
initialPdf?: File | Blob | ArrayBuffer | Uint8Array;
|
|
82
|
+
/** Optional initial state to restore previous session */
|
|
83
|
+
initialState?: PageAssemblerState;
|
|
84
|
+
/** Notified on any structural change (files/pages added/removed/reordered) */
|
|
85
|
+
onChange?: (state: PageAssemblerState) => void;
|
|
86
|
+
/** Called when internal validity changes (e.g., 0 pages) */
|
|
87
|
+
onValidityChange?: (isValid: boolean) => void;
|
|
88
|
+
/** Optional limits */
|
|
89
|
+
limits?: {
|
|
90
|
+
maxFileSizeMB?: number;
|
|
91
|
+
maxTotalPages?: number;
|
|
92
|
+
};
|
|
93
|
+
/** Disable file upload (e.g., for template-only flows) */
|
|
94
|
+
disableFileUpload?: boolean;
|
|
95
|
+
/** Optional className passthrough */
|
|
96
|
+
className?: string;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Represents a page image extracted from a PDF
|
|
100
|
+
*/
|
|
101
|
+
type PageImage = {
|
|
102
|
+
/** Data URL for the image */
|
|
103
|
+
imageUrl: string;
|
|
104
|
+
/** Page width in points */
|
|
105
|
+
width: number;
|
|
106
|
+
/** Page height in points */
|
|
107
|
+
height: number;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
declare const PageAssembler: React__default.ForwardRefExoticComponent<PageAssemblerProps & React__default.RefAttributes<PageAssemblerHandle>>;
|
|
111
|
+
|
|
112
|
+
declare const buttonVariants: (props?: ({
|
|
113
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
114
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
115
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
116
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
117
|
+
asChild?: boolean;
|
|
118
|
+
}
|
|
119
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Converts a PDF document to an array of rendered page images
|
|
123
|
+
*
|
|
124
|
+
* @param pdfBytes - The PDF document as a Uint8Array
|
|
125
|
+
* @param options - Optional configuration
|
|
126
|
+
* @param options.hideFormFields - If true, hides existing form fields during rendering
|
|
127
|
+
* @returns Promise resolving to array of PageImage objects with rendered images
|
|
128
|
+
* @throws {Error} If PDF is invalid or rendering fails
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const pages = await pdfToImages(pdfBytes, { hideFormFields: true });
|
|
133
|
+
* console.log(`Rendered ${pages.length} pages`);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
declare function pdfToImages(pdfBytes: Uint8Array, options?: {
|
|
137
|
+
hideFormFields?: boolean;
|
|
138
|
+
}): Promise<PageImage[]>;
|
|
139
|
+
/**
|
|
140
|
+
* Converts an image file to a PDF document with a single page
|
|
141
|
+
*
|
|
142
|
+
* @param imageFile - The image file to convert (supports common image formats)
|
|
143
|
+
* @returns Promise resolving to PDF bytes as Uint8Array
|
|
144
|
+
* @throws {Error} If image fails to load or convert
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* const pdfBytes = await imageToPdf(imageFile);
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function imageToPdf(imageFile: File): Promise<Uint8Array>;
|
|
152
|
+
/**
|
|
153
|
+
* Create a blob URL from PDF bytes for preview
|
|
154
|
+
*
|
|
155
|
+
* @param pdfBytes - The PDF document as Uint8Array
|
|
156
|
+
* @returns Blob URL string
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* const url = createPdfBlobUrl(pdfBytes);
|
|
161
|
+
* // Remember to revoke: URL.revokeObjectURL(url);
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
declare function createPdfBlobUrl(pdfBytes: Uint8Array): string;
|
|
165
|
+
/**
|
|
166
|
+
* Triggers a browser download of a PDF file
|
|
167
|
+
*
|
|
168
|
+
* @param pdfBytes - The PDF document as Uint8Array
|
|
169
|
+
* @param filename - The filename for the downloaded file (e.g., 'document.pdf')
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* downloadPdf(pdfBytes, 'assembled-document.pdf');
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function downloadPdf(pdfBytes: Uint8Array, filename: string): void;
|
|
177
|
+
|
|
178
|
+
export { type AssembleOptions, Button, type FileInfo, PageAssembler, type PageAssemblerHandle, type PageAssemblerProps, type PageAssemblerState, type PageImage, type PageInfo, createPdfBlobUrl, PageAssembler as default, downloadPdf, imageToPdf, pdfToImages };
|