@signiphi/page-assembly 0.2.0-beta.1 → 0.2.0-beta.3
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 +283 -92
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -5
- package/dist/index.mjs.map +1 -1
- package/dist/styles/index.css +42 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
# @signiphi/page-assembly
|
|
2
2
|
|
|
3
|
-
React component for PDF and image page manipulation - upload, reorder, delete, and combine pages into a single document.
|
|
3
|
+
> A powerful React component for PDF and image page manipulation - upload, reorder, delete, and combine pages into a single document.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@signiphi/page-assembly)
|
|
6
|
+
[](https://github.com/signiphi/signiphi)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
8
|
+
## ✨ Features
|
|
9
|
+
|
|
10
|
+
- 📄 **Multi-File Upload** - Upload multiple PDF files and images simultaneously
|
|
11
|
+
- 🔄 **Drag & Drop Interface** - Intuitive drag-and-drop for reordering pages and files
|
|
12
|
+
- ✂️ **Advanced Selection** - Multi-select pages with Ctrl+Click, Shift+Click, or checkboxes
|
|
13
|
+
- 🗑️ **Bulk Operations** - Move or delete multiple pages at once with ease
|
|
11
14
|
- 🖼️ **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
|
-
- 🎨 **
|
|
15
|
+
- 📦 **PDF Assembly** - Generate a final assembled PDF with all selected pages in order
|
|
16
|
+
- ♻️ **State Management** - Save and restore page assembly state for persistence
|
|
17
|
+
- 🎨 **Scoped Styling** - CSS is scoped and won't conflict with your application styles
|
|
18
|
+
- ⚡ **Performance** - Optimized for handling large documents with many pages
|
|
19
|
+
- 🔒 **Client-Side** - All processing happens in the browser, no server required
|
|
15
20
|
|
|
16
|
-
## Installation
|
|
21
|
+
## 📦 Installation
|
|
17
22
|
|
|
18
23
|
```bash
|
|
19
24
|
npm install @signiphi/page-assembly
|
|
@@ -28,12 +33,22 @@ yarn add @signiphi/page-assembly
|
|
|
28
33
|
This package requires the following peer dependencies:
|
|
29
34
|
|
|
30
35
|
```bash
|
|
31
|
-
npm install react react-dom lucide-react
|
|
36
|
+
npm install react react-dom lucide-react \
|
|
37
|
+
@radix-ui/react-alert-dialog \
|
|
38
|
+
@radix-ui/react-dialog \
|
|
39
|
+
@radix-ui/react-dropdown-menu \
|
|
40
|
+
@radix-ui/react-label \
|
|
41
|
+
@radix-ui/react-select \
|
|
42
|
+
@radix-ui/react-tooltip
|
|
32
43
|
```
|
|
33
44
|
|
|
34
|
-
|
|
45
|
+
Or install them all at once:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @signiphi/page-assembly 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
|
|
49
|
+
```
|
|
35
50
|
|
|
36
|
-
|
|
51
|
+
## 🚀 Quick Start
|
|
37
52
|
|
|
38
53
|
```tsx
|
|
39
54
|
import { useRef } from 'react';
|
|
@@ -78,8 +93,12 @@ function App() {
|
|
|
78
93
|
}
|
|
79
94
|
```
|
|
80
95
|
|
|
96
|
+
## 📖 Usage Examples
|
|
97
|
+
|
|
81
98
|
### With Initial PDF
|
|
82
99
|
|
|
100
|
+
Load an existing PDF as the starting point:
|
|
101
|
+
|
|
83
102
|
```tsx
|
|
84
103
|
import { PageAssembler } from '@signiphi/page-assembly';
|
|
85
104
|
import '@signiphi/page-assembly/styles';
|
|
@@ -110,6 +129,8 @@ function App() {
|
|
|
110
129
|
|
|
111
130
|
### With State Persistence
|
|
112
131
|
|
|
132
|
+
Save and restore the page assembly state:
|
|
133
|
+
|
|
113
134
|
```tsx
|
|
114
135
|
import { PageAssembler, PageAssemblerState } from '@signiphi/page-assembly';
|
|
115
136
|
import '@signiphi/page-assembly/styles';
|
|
@@ -148,57 +169,166 @@ function App() {
|
|
|
148
169
|
}
|
|
149
170
|
```
|
|
150
171
|
|
|
151
|
-
|
|
172
|
+
### Template Mode (Disable File Upload)
|
|
173
|
+
|
|
174
|
+
Use when you want users to only manipulate pages from a pre-loaded document:
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { PageAssembler } from '@signiphi/page-assembly';
|
|
178
|
+
import '@signiphi/page-assembly/styles';
|
|
179
|
+
|
|
180
|
+
function App() {
|
|
181
|
+
const [templatePdf, setTemplatePdf] = useState<Uint8Array | null>(null);
|
|
182
|
+
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
// Load template PDF
|
|
185
|
+
fetch('/template.pdf')
|
|
186
|
+
.then(res => res.arrayBuffer())
|
|
187
|
+
.then(buffer => setTemplatePdf(new Uint8Array(buffer)));
|
|
188
|
+
}, []);
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<div className="signiphi-page-assembly">
|
|
192
|
+
<PageAssembler
|
|
193
|
+
initialPdf={templatePdf || undefined}
|
|
194
|
+
disableFileUpload={true}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Upload to Server
|
|
202
|
+
|
|
203
|
+
Assemble and upload the PDF to your backend:
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
const handleAssembleAndUpload = async () => {
|
|
207
|
+
if (!assemblerRef.current) return;
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
// Assemble the PDF
|
|
211
|
+
const pdfBlob = await assemblerRef.current.assemble();
|
|
212
|
+
|
|
213
|
+
// Create form data
|
|
214
|
+
const formData = new FormData();
|
|
215
|
+
formData.append('pdf', pdfBlob, 'assembled.pdf');
|
|
216
|
+
|
|
217
|
+
// Upload to server
|
|
218
|
+
const response = await fetch('/api/documents/upload', {
|
|
219
|
+
method: 'POST',
|
|
220
|
+
body: formData
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (response.ok) {
|
|
224
|
+
const result = await response.json();
|
|
225
|
+
console.log('Upload successful:', result);
|
|
226
|
+
}
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('Failed to assemble/upload PDF:', error);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Custom Image Sizing
|
|
234
|
+
|
|
235
|
+
Control how images are converted to PDF pages:
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
const handleAssemble = async () => {
|
|
239
|
+
if (!assemblerRef.current) return;
|
|
240
|
+
|
|
241
|
+
// Use original image dimensions
|
|
242
|
+
const pdfBlob = await assemblerRef.current.assemble({
|
|
243
|
+
imageSizing: 'original-size'
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Or use auto letter sizing (default)
|
|
247
|
+
const pdfBlob2 = await assemblerRef.current.assemble({
|
|
248
|
+
imageSizing: 'auto-letter'
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Monitor State Changes
|
|
254
|
+
|
|
255
|
+
Track when users add, remove, or reorder pages:
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
function App() {
|
|
259
|
+
const handleStateChange = (state: PageAssemblerState) => {
|
|
260
|
+
const totalPages = state.files.reduce((acc, file) => acc + file.pages.length, 0);
|
|
261
|
+
console.log(`Total files: ${state.files.length}`);
|
|
262
|
+
console.log(`Total pages: ${totalPages}`);
|
|
263
|
+
console.log(`Selected pages: ${state.selection.length}`);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
return (
|
|
267
|
+
<div className="signiphi-page-assembly">
|
|
268
|
+
<PageAssembler
|
|
269
|
+
onChange={handleStateChange}
|
|
270
|
+
onValidityChange={(isValid) => {
|
|
271
|
+
if (!isValid) {
|
|
272
|
+
console.warn('No pages to assemble');
|
|
273
|
+
}
|
|
274
|
+
}}
|
|
275
|
+
/>
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## 📚 API Reference
|
|
152
282
|
|
|
153
283
|
### PageAssembler Props
|
|
154
284
|
|
|
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
|
|
163
|
-
| `className` | `string` | Optional className passthrough |
|
|
285
|
+
| Prop | Type | Default | Description |
|
|
286
|
+
|------|------|---------|-------------|
|
|
287
|
+
| `initialPdf` | `File \| Blob \| ArrayBuffer \| Uint8Array` | `undefined` | Optional initial PDF to pre-load into the assembler |
|
|
288
|
+
| `initialState` | `PageAssemblerState` | `undefined` | Optional initial state to restore previous session |
|
|
289
|
+
| `onChange` | `(state: PageAssemblerState) => void` | `undefined` | Called when state changes (files/pages added/removed/reordered) |
|
|
290
|
+
| `onValidityChange` | `(isValid: boolean) => void` | `undefined` | Called when validity changes (e.g., when there are 0 pages) |
|
|
291
|
+
| `limits` | `{ maxFileSizeMB?: number; maxTotalPages?: number }` | `undefined` | Optional file size and page count limits |
|
|
292
|
+
| `disableFileUpload` | `boolean` | `false` | Disable file upload UI (useful for template-only workflows) |
|
|
293
|
+
| `className` | `string` | `undefined` | Optional className passthrough for custom styling |
|
|
164
294
|
|
|
165
295
|
### PageAssemblerHandle Methods
|
|
166
296
|
|
|
167
|
-
|
|
297
|
+
Access these methods via the `ref`:
|
|
168
298
|
|
|
169
299
|
| Method | Type | Description |
|
|
170
300
|
|--------|------|-------------|
|
|
171
|
-
| `assemble` | `(opts?: AssembleOptions) => Promise<Blob>` | Assembles current pages into a single PDF |
|
|
172
|
-
| `getSummary` | `() => { totalFiles: number; totalPages: number }` | Returns summary
|
|
173
|
-
| `isBusy` | `() => boolean` | Returns true if loading
|
|
174
|
-
| `getState` | `() => PageAssemblerState` | Returns current state |
|
|
301
|
+
| `assemble` | `(opts?: AssembleOptions) => Promise<Blob>` | Assembles current pages into a single PDF blob |
|
|
302
|
+
| `getSummary` | `() => { totalFiles: number; totalPages: number }` | Returns summary information about current state |
|
|
303
|
+
| `isBusy` | `() => boolean` | Returns true if currently loading or assembling |
|
|
304
|
+
| `getState` | `() => PageAssemblerState` | Returns the current state (files, pages, selection) |
|
|
175
305
|
|
|
176
306
|
### Types
|
|
177
307
|
|
|
178
308
|
```typescript
|
|
179
309
|
interface PageInfo {
|
|
180
|
-
id: string;
|
|
181
|
-
srcIndex: number;
|
|
182
|
-
thumbUrl: string;
|
|
183
|
-
width?: number;
|
|
184
|
-
height?: number;
|
|
185
|
-
mime: string;
|
|
186
|
-
originalFileId?: string;
|
|
310
|
+
id: string; // Unique page identifier
|
|
311
|
+
srcIndex: number; // Original page index in source document
|
|
312
|
+
thumbUrl: string; // Data URL for thumbnail preview
|
|
313
|
+
width?: number; // Page width in points
|
|
314
|
+
height?: number; // Page height in points
|
|
315
|
+
mime: string; // MIME type (application/pdf or image/*)
|
|
316
|
+
originalFileId?: string; // ID of the source file
|
|
187
317
|
}
|
|
188
318
|
|
|
189
319
|
interface FileInfo {
|
|
190
|
-
id: string;
|
|
191
|
-
name: string;
|
|
192
|
-
type: "pdf" | "image";
|
|
193
|
-
originalFile: File;
|
|
194
|
-
originalBytes: Uint8Array;
|
|
195
|
-
pages: PageInfo[];
|
|
320
|
+
id: string; // Unique file identifier
|
|
321
|
+
name: string; // Original filename
|
|
322
|
+
type: "pdf" | "image"; // File type
|
|
323
|
+
originalFile: File; // Original File object
|
|
324
|
+
originalBytes: Uint8Array; // Original file bytes
|
|
325
|
+
pages: PageInfo[]; // Array of pages from this file
|
|
196
326
|
}
|
|
197
327
|
|
|
198
328
|
interface PageAssemblerState {
|
|
199
|
-
files: FileInfo[];
|
|
200
|
-
selection: string[];
|
|
201
|
-
lastSelectedPageId?: string;
|
|
329
|
+
files: FileInfo[]; // All uploaded files
|
|
330
|
+
selection: string[]; // IDs of currently selected pages
|
|
331
|
+
lastSelectedPageId?: string; // ID of last selected page (for shift-click)
|
|
202
332
|
}
|
|
203
333
|
|
|
204
334
|
interface AssembleOptions {
|
|
@@ -206,91 +336,152 @@ interface AssembleOptions {
|
|
|
206
336
|
}
|
|
207
337
|
```
|
|
208
338
|
|
|
209
|
-
## Styling
|
|
339
|
+
## 🎨 Styling
|
|
340
|
+
|
|
341
|
+
The package includes scoped Tailwind CSS styles that won't conflict with your application.
|
|
210
342
|
|
|
211
|
-
|
|
343
|
+
### Import Styles
|
|
212
344
|
|
|
213
345
|
```tsx
|
|
214
346
|
import '@signiphi/page-assembly/styles';
|
|
215
347
|
```
|
|
216
348
|
|
|
217
|
-
All styles are prefixed with `.signiphi-page-assembly` to prevent conflicts
|
|
349
|
+
All styles are prefixed with `.signiphi-page-assembly` to prevent conflicts.
|
|
218
350
|
|
|
219
351
|
### Custom Styling
|
|
220
352
|
|
|
221
|
-
|
|
353
|
+
Override default styles by wrapping the component:
|
|
222
354
|
|
|
223
355
|
```tsx
|
|
224
|
-
<div className="my-custom-
|
|
356
|
+
<div className="my-custom-styles signiphi-page-assembly">
|
|
225
357
|
<PageAssembler />
|
|
226
358
|
</div>
|
|
227
359
|
```
|
|
228
360
|
|
|
229
|
-
|
|
361
|
+
Then add your custom CSS:
|
|
230
362
|
|
|
231
|
-
|
|
363
|
+
```css
|
|
364
|
+
.my-custom-styles {
|
|
365
|
+
/* Your custom styles here */
|
|
366
|
+
}
|
|
367
|
+
```
|
|
232
368
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
369
|
+
## 🏗️ Architecture
|
|
370
|
+
|
|
371
|
+
The PageAssembler component is built with:
|
|
372
|
+
|
|
373
|
+
- **PDF Processing**: Uses `pdf-lib` for PDF manipulation and assembly
|
|
374
|
+
- **PDF Rendering**: Uses `pdfjs-dist` for rendering PDF thumbnails
|
|
375
|
+
- **Drag & Drop**: Uses `react-dnd` for intuitive page reordering
|
|
376
|
+
- **UI Components**: Uses Radix UI for accessible, unstyled component primitives
|
|
377
|
+
- **State Management**: React hooks for efficient state management
|
|
378
|
+
- **Performance**: Optimized with React.memo, useMemo, and useCallback
|
|
379
|
+
|
|
380
|
+
### Component Structure
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
PageAssembler
|
|
384
|
+
├── FileUploadArea (drag & drop, file selection)
|
|
385
|
+
├── FileList (list of uploaded files)
|
|
386
|
+
│ └── FileCard (individual file with pages)
|
|
387
|
+
│ └── PageThumbnail[] (draggable page previews)
|
|
388
|
+
└── BulkActions (multi-select operations)
|
|
248
389
|
```
|
|
249
390
|
|
|
250
|
-
|
|
391
|
+
## 🔧 Troubleshooting
|
|
392
|
+
|
|
393
|
+
### PDF.js Worker Issues
|
|
394
|
+
|
|
395
|
+
If you encounter errors related to PDF.js worker, make sure you're properly configured:
|
|
251
396
|
|
|
252
397
|
```tsx
|
|
253
|
-
|
|
398
|
+
// In your app's entry point (e.g., main.tsx or App.tsx)
|
|
399
|
+
import { GlobalWorkerOptions } from 'pdfjs-dist';
|
|
254
400
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
console.log(`Total pages: ${summary.totalPages}`);
|
|
401
|
+
// Set the worker source
|
|
402
|
+
GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@5.3.93/build/pdf.worker.min.mjs`;
|
|
258
403
|
```
|
|
259
404
|
|
|
260
|
-
###
|
|
405
|
+
### Large File Performance
|
|
406
|
+
|
|
407
|
+
For better performance with large files:
|
|
261
408
|
|
|
409
|
+
1. Set appropriate limits:
|
|
410
|
+
```tsx
|
|
411
|
+
<PageAssembler
|
|
412
|
+
limits={{
|
|
413
|
+
maxFileSizeMB: 10, // Limit individual file size
|
|
414
|
+
maxTotalPages: 50 // Limit total page count
|
|
415
|
+
}}
|
|
416
|
+
/>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
2. Implement loading states:
|
|
262
420
|
```tsx
|
|
263
421
|
const isBusy = assemblerRef.current?.isBusy();
|
|
264
422
|
if (isBusy) {
|
|
265
|
-
|
|
423
|
+
return <LoadingSpinner />;
|
|
266
424
|
}
|
|
267
425
|
```
|
|
268
426
|
|
|
269
|
-
|
|
427
|
+
### Memory Management
|
|
428
|
+
|
|
429
|
+
When working with many large files, consider:
|
|
430
|
+
|
|
431
|
+
- Limiting the number of concurrent file uploads
|
|
432
|
+
- Clearing state when unmounting
|
|
433
|
+
- Using the `onChange` callback to implement auto-save and state cleanup
|
|
434
|
+
|
|
435
|
+
## 🌐 Browser Support
|
|
436
|
+
|
|
437
|
+
| Browser | Minimum Version |
|
|
438
|
+
|---------|-----------------|
|
|
439
|
+
| Chrome | Latest 2 versions |
|
|
440
|
+
| Edge | Latest 2 versions |
|
|
441
|
+
| Firefox | Latest 2 versions |
|
|
442
|
+
| Safari | Latest 2 versions |
|
|
443
|
+
|
|
444
|
+
**Note**: This component requires modern browser APIs including:
|
|
445
|
+
- Web Workers (for PDF.js)
|
|
446
|
+
- FileReader API
|
|
447
|
+
- Blob API
|
|
448
|
+
- Drag and Drop API
|
|
449
|
+
|
|
450
|
+
## 📦 Dependencies
|
|
451
|
+
|
|
452
|
+
### Core Dependencies
|
|
453
|
+
- `pdf-lib` (^1.17.1) - PDF manipulation and assembly
|
|
454
|
+
- `pdfjs-dist` (5.3.93) - PDF rendering and parsing
|
|
455
|
+
- `react-dnd` (^16.0.1) - Drag and drop functionality
|
|
456
|
+
- `react-dnd-html5-backend` (^16.0.1) - HTML5 backend for react-dnd
|
|
457
|
+
|
|
458
|
+
### UI Dependencies (Peer Dependencies)
|
|
459
|
+
- `react` (^18.2.0 || ^19.0.0)
|
|
460
|
+
- `react-dom` (^18.2.0 || ^19.0.0)
|
|
461
|
+
- `lucide-react` (^0.454.0) - Icon components
|
|
462
|
+
- `@radix-ui/react-*` - Accessible UI primitives
|
|
463
|
+
|
|
464
|
+
## 🤝 Contributing
|
|
465
|
+
|
|
466
|
+
Contributions are welcome! Please read the [contributing guidelines](https://github.com/signiphi/signiphi/blob/main/CONTRIBUTING.md) before submitting PRs.
|
|
270
467
|
|
|
271
|
-
|
|
272
|
-
- Firefox: Latest 2 versions
|
|
273
|
-
- Safari: Latest 2 versions
|
|
468
|
+
## 📄 License
|
|
274
469
|
|
|
275
|
-
|
|
470
|
+
See the [LICENSE](https://github.com/signiphi/signiphi/blob/main/LICENSE) file in the root of the repository.
|
|
276
471
|
|
|
277
|
-
|
|
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)
|
|
472
|
+
## 💬 Support
|
|
285
473
|
|
|
286
|
-
|
|
474
|
+
- 📚 [Documentation](https://github.com/signiphi/signiphi)
|
|
475
|
+
- 🐛 [Report Issues](https://github.com/signiphi/signiphi/issues)
|
|
476
|
+
- 💡 [Feature Requests](https://github.com/signiphi/signiphi/issues)
|
|
287
477
|
|
|
288
|
-
|
|
478
|
+
## 🔗 Related Packages
|
|
289
479
|
|
|
290
|
-
|
|
480
|
+
Part of the Signiphi ecosystem:
|
|
291
481
|
|
|
292
|
-
|
|
482
|
+
- [`@signiphi/pdf-signer`](https://www.npmjs.com/package/@signiphi/pdf-signer) - PDF signing and form filling
|
|
483
|
+
- [`@signiphi/document-prepare`](https://www.npmjs.com/package/@signiphi/document-prepare) - Document preparation workflow
|
|
293
484
|
|
|
294
|
-
|
|
485
|
+
---
|
|
295
486
|
|
|
296
|
-
|
|
487
|
+
Made with ❤️ by the Signiphi team
|
package/dist/index.js
CHANGED
|
@@ -1624,7 +1624,7 @@ var PageAssembler = React7.forwardRef(
|
|
|
1624
1624
|
const fileMap = /* @__PURE__ */ new Map();
|
|
1625
1625
|
for (const file of state.files) {
|
|
1626
1626
|
fileMap.set(file.id, file);
|
|
1627
|
-
if (file.type === "pdf" && file.originalBytes) {
|
|
1627
|
+
if (file.type === "pdf" && file.originalBytes && file.originalBytes.length > 0) {
|
|
1628
1628
|
try {
|
|
1629
1629
|
const sourcePdf = await PDFDocument2.load(file.originalBytes);
|
|
1630
1630
|
loadedPdfs.set(file.id, sourcePdf);
|
|
@@ -1672,7 +1672,8 @@ var PageAssembler = React7.forwardRef(
|
|
|
1672
1672
|
}
|
|
1673
1673
|
}
|
|
1674
1674
|
const pdfBytes = await combinedDoc.save();
|
|
1675
|
-
const
|
|
1675
|
+
const arrayBuffer = pdfBytes.buffer.slice(pdfBytes.byteOffset, pdfBytes.byteOffset + pdfBytes.byteLength);
|
|
1676
|
+
const blob = new Blob([arrayBuffer], { type: "application/pdf" });
|
|
1676
1677
|
return blob;
|
|
1677
1678
|
} catch (error) {
|
|
1678
1679
|
console.error("Error assembling PDF:", error);
|
|
@@ -1686,7 +1687,7 @@ var PageAssembler = React7.forwardRef(
|
|
|
1686
1687
|
isBusy: () => isLoading,
|
|
1687
1688
|
getState: () => state
|
|
1688
1689
|
}), [state, summary, isLoading]);
|
|
1689
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(reactDnd.DndProvider, { backend: reactDndHtml5Backend.HTML5Backend, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-
|
|
1690
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(reactDnd.DndProvider, { backend: reactDndHtml5Backend.HTML5Backend, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-3", className), children: [
|
|
1690
1691
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1691
1692
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1692
1693
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium", children: "Page Assembly" }),
|
|
@@ -1777,9 +1778,9 @@ var PageAssembler = React7.forwardRef(
|
|
|
1777
1778
|
]
|
|
1778
1779
|
}
|
|
1779
1780
|
) : !disableFileUpload && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1780
|
-
|
|
1781
|
+
"div",
|
|
1781
1782
|
{
|
|
1782
|
-
className: "p-12
|
|
1783
|
+
className: "p-12 rounded-lg bg-card text-card-foreground cursor-pointer transition-all border-2 border-dashed border-border hover:border-primary/60 hover:bg-primary/10",
|
|
1783
1784
|
onClick: handleFileUpload,
|
|
1784
1785
|
onDrop: handleDrop,
|
|
1785
1786
|
onDragOver: handleDragOver,
|