@drvillo/react-browser-e-signing 0.2.0 → 0.3.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/INTEGRATION_GUIDELINES.md +471 -0
- package/dist/index.d.ts +41 -3
- package/dist/index.js +188 -11
- package/dist/index.js.map +1 -1
- package/dist/styles.css +48 -0
- package/package.json +3 -2
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
# INTEGRATION_GUIDELINES
|
|
2
|
+
|
|
3
|
+
## 1) Metadata
|
|
4
|
+
|
|
5
|
+
- packageName: `@drvillo/react-browser-e-signing`
|
|
6
|
+
- runtime: browser-only (React)
|
|
7
|
+
- peerDependencies: `react`, `react-dom`
|
|
8
|
+
- requiredCssImport: `@drvillo/react-browser-e-signing/styles.css`
|
|
9
|
+
- recommendedWorkerSetup:
|
|
10
|
+
- import `configure` from package
|
|
11
|
+
- import `getPdfWorkerSrc` from `@drvillo/react-browser-e-signing/worker`
|
|
12
|
+
- call `configure({ pdfWorkerSrc: getPdfWorkerSrc() })`
|
|
13
|
+
|
|
14
|
+
## 2) Full Public API (post-change)
|
|
15
|
+
|
|
16
|
+
### 2.1 Components
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
interface PdfViewerProps {
|
|
20
|
+
pdfData: ArrayBuffer | null
|
|
21
|
+
numPages: number
|
|
22
|
+
scale: number
|
|
23
|
+
onScaleChange: (nextScale: number) => void
|
|
24
|
+
onDocumentLoadSuccess: (numPages: number) => void
|
|
25
|
+
onPageDimensions: (input: { pageIndex: number; widthPt: number; heightPt: number }) => void
|
|
26
|
+
renderOverlay?: (pageIndex: number) => React.ReactNode
|
|
27
|
+
renderToolbarContent?: () => React.ReactNode
|
|
28
|
+
className?: string
|
|
29
|
+
workerSrc?: string
|
|
30
|
+
pageMode?: 'scroll' | 'single'
|
|
31
|
+
currentPageIndex?: number
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
interface PdfPageNavigatorProps {
|
|
37
|
+
currentPageIndex: number
|
|
38
|
+
numPages: number
|
|
39
|
+
onPageChange: (pageIndex: number) => void
|
|
40
|
+
className?: string
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
interface FieldOverlayProps {
|
|
46
|
+
pageIndex: number
|
|
47
|
+
fields: FieldPlacement[]
|
|
48
|
+
selectedFieldType: FieldType | null
|
|
49
|
+
onAddField: (input: { pageIndex: number; type: FieldType; xPercent: number; yPercent: number }) => void
|
|
50
|
+
onUpdateField: (fieldId: string, partial: Partial<FieldPlacement>) => void
|
|
51
|
+
onRemoveField: (fieldId: string) => void
|
|
52
|
+
preview: SignatureFieldPreview
|
|
53
|
+
className?: string
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
interface SignatureFieldProps {
|
|
59
|
+
field: FieldPlacement
|
|
60
|
+
onUpdateField: (fieldId: string, partial: Partial<FieldPlacement>) => void
|
|
61
|
+
onRemoveField: (fieldId: string) => void
|
|
62
|
+
preview: SignatureFieldPreview
|
|
63
|
+
className?: string
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
interface FieldPaletteProps {
|
|
69
|
+
selectedFieldType: FieldType | null
|
|
70
|
+
onSelectFieldType: (fieldType: FieldType | null) => void
|
|
71
|
+
className?: string
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
interface SignerDetailsPanelProps {
|
|
77
|
+
signerInfo: SignerInfo
|
|
78
|
+
onSignerInfoChange: (nextSignerInfo: SignerInfo) => void
|
|
79
|
+
className?: string
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
interface SignaturePreviewProps {
|
|
85
|
+
signerName: string
|
|
86
|
+
style: SignatureStyle
|
|
87
|
+
signatureDataUrl: string | null
|
|
88
|
+
isRendering: boolean
|
|
89
|
+
onStyleChange: (nextStyle: SignatureStyle) => void
|
|
90
|
+
className?: string
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
interface SignaturePadProps {
|
|
96
|
+
onDrawn: (signatureDataUrl: string) => void
|
|
97
|
+
className?: string
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
interface SigningCompleteProps {
|
|
103
|
+
signerName: string
|
|
104
|
+
fieldCount: number
|
|
105
|
+
signedAt: string
|
|
106
|
+
documentHash: string
|
|
107
|
+
downloadUrl: string
|
|
108
|
+
fileName?: string
|
|
109
|
+
onReset: () => void
|
|
110
|
+
className?: string
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 2.2 Hooks
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
type PdfInput = File | Blob | ArrayBuffer | Uint8Array | null
|
|
118
|
+
|
|
119
|
+
function usePdfDocument(pdfInput: PdfInput): {
|
|
120
|
+
pdfData: ArrayBuffer | null
|
|
121
|
+
numPages: number
|
|
122
|
+
scale: number
|
|
123
|
+
setScale: React.Dispatch<React.SetStateAction<number>>
|
|
124
|
+
pageDimensions: PdfPageDimensions[]
|
|
125
|
+
setPageDimension: (pageIndex: number, widthPt: number, heightPt: number) => void
|
|
126
|
+
handleDocumentLoadSuccess: (loadedPages: number) => void
|
|
127
|
+
hasPdf: boolean
|
|
128
|
+
isLoading: boolean
|
|
129
|
+
errorMessage: string | null
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
function useFieldPlacement(options?: {
|
|
135
|
+
defaultWidthPercent?: number
|
|
136
|
+
defaultHeightPercent?: number
|
|
137
|
+
}): {
|
|
138
|
+
fields: FieldPlacement[]
|
|
139
|
+
addField: (input: { pageIndex: number; type: FieldType; xPercent: number; yPercent: number }) => FieldPlacement
|
|
140
|
+
updateField: (id: string, partial: Partial<FieldPlacement>) => void
|
|
141
|
+
removeField: (id: string) => void
|
|
142
|
+
clearFields: () => void
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
function useSignatureRenderer(input: {
|
|
148
|
+
signerName: string
|
|
149
|
+
style: SignatureStyle
|
|
150
|
+
}): {
|
|
151
|
+
signatureDataUrl: string | null
|
|
152
|
+
isRendering: boolean
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
interface UsePdfPageVisibilityOptions {
|
|
158
|
+
containerRef: React.RefObject<HTMLElement | null>
|
|
159
|
+
numPages: number
|
|
160
|
+
threshold?: number
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface UsePdfPageVisibilityReturn {
|
|
164
|
+
currentPageIndex: number
|
|
165
|
+
visiblePageIndices: number[]
|
|
166
|
+
scrollToPage: (pageIndex: number) => void
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function usePdfPageVisibility(options: UsePdfPageVisibilityOptions): UsePdfPageVisibilityReturn
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 2.3 Types
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
type FieldType = 'signature' | 'fullName' | 'title' | 'date'
|
|
176
|
+
|
|
177
|
+
interface FieldPlacement {
|
|
178
|
+
id: string
|
|
179
|
+
type: FieldType
|
|
180
|
+
pageIndex: number
|
|
181
|
+
xPercent: number
|
|
182
|
+
yPercent: number
|
|
183
|
+
widthPercent: number
|
|
184
|
+
heightPercent: number
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
interface SignerInfo {
|
|
188
|
+
firstName: string
|
|
189
|
+
lastName: string
|
|
190
|
+
title: string
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
type SignatureStyle =
|
|
194
|
+
| { mode: 'typed'; fontFamily: string }
|
|
195
|
+
| { mode: 'drawn'; dataUrl: string }
|
|
196
|
+
|
|
197
|
+
interface SigningResult {
|
|
198
|
+
pdfBytes: Uint8Array
|
|
199
|
+
sha256: string
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
interface PdfPageDimensions {
|
|
203
|
+
pageIndex: number
|
|
204
|
+
widthPt: number
|
|
205
|
+
heightPt: number
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
interface SignatureFieldPreview {
|
|
209
|
+
signatureDataUrl: string | null
|
|
210
|
+
fullName: string
|
|
211
|
+
title: string
|
|
212
|
+
dateText: string
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 2.4 Utilities and config
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
function configure(options: {
|
|
220
|
+
pdfWorkerSrc?: string
|
|
221
|
+
fontMode?: 'network' | 'local-only'
|
|
222
|
+
fontUrlResolver?: (fontFamily: string) => string | null
|
|
223
|
+
onWarning?: (warning: { code: string; message: string }) => void
|
|
224
|
+
}): void
|
|
225
|
+
|
|
226
|
+
function modifyPdf(input: {
|
|
227
|
+
pdfBytes: Uint8Array
|
|
228
|
+
fields: FieldPlacement[]
|
|
229
|
+
signer: SignerInfo
|
|
230
|
+
signatureDataUrl: string
|
|
231
|
+
pageDimensions: PdfPageDimensions[]
|
|
232
|
+
dateText?: string
|
|
233
|
+
}): Promise<Uint8Array>
|
|
234
|
+
|
|
235
|
+
function mapToPoints(field: FieldPlacement, page: PdfPageDimensions): {
|
|
236
|
+
x: number
|
|
237
|
+
y: number
|
|
238
|
+
width: number
|
|
239
|
+
height: number
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function mapFromPoints(
|
|
243
|
+
rect: { x: number; y: number; width: number; height: number },
|
|
244
|
+
page: PdfPageDimensions
|
|
245
|
+
): Pick<FieldPlacement, 'xPercent' | 'yPercent' | 'widthPercent' | 'heightPercent'>
|
|
246
|
+
|
|
247
|
+
function loadSignatureFont(fontFamily: string): Promise<void>
|
|
248
|
+
function sha256(data: Uint8Array): Promise<string>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 2.5 Constants
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
const defaults: {
|
|
255
|
+
SIGNATURE_FONTS: readonly string[]
|
|
256
|
+
DEFAULT_FIELD_WIDTH_PERCENT: 25
|
|
257
|
+
DEFAULT_FIELD_HEIGHT_PERCENT: 5
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
const SLOTS = {
|
|
263
|
+
pdfViewer: 'pdf-viewer',
|
|
264
|
+
pdfViewerEmpty: 'pdf-viewer-empty',
|
|
265
|
+
pdfViewerToolbar: 'pdf-viewer-toolbar',
|
|
266
|
+
pdfViewerToolbarContent: 'pdf-viewer-toolbar-content',
|
|
267
|
+
pdfViewerPageCount: 'pdf-viewer-page-count',
|
|
268
|
+
pdfViewerZoom: 'pdf-viewer-zoom',
|
|
269
|
+
pdfViewerZoomButton: 'pdf-viewer-zoom-button',
|
|
270
|
+
pdfViewerZoomValue: 'pdf-viewer-zoom-value',
|
|
271
|
+
pdfViewerPages: 'pdf-viewer-pages',
|
|
272
|
+
pdfViewerPage: 'pdf-viewer-page',
|
|
273
|
+
pdfViewerLoading: 'pdf-viewer-loading',
|
|
274
|
+
pdfViewerError: 'pdf-viewer-error',
|
|
275
|
+
pdfPageNavigator: 'pdf-page-navigator',
|
|
276
|
+
pdfPageNavigatorButton: 'pdf-page-navigator-button',
|
|
277
|
+
pdfPageNavigatorLabel: 'pdf-page-navigator-label',
|
|
278
|
+
fieldOverlay: 'field-overlay',
|
|
279
|
+
signatureField: 'signature-field',
|
|
280
|
+
signatureFieldContent: 'signature-field-content',
|
|
281
|
+
signatureFieldLabel: 'signature-field-label',
|
|
282
|
+
signatureFieldPreview: 'signature-field-preview',
|
|
283
|
+
signatureFieldPreviewImage: 'signature-field-preview-image',
|
|
284
|
+
signatureFieldPreviewText: 'signature-field-preview-text',
|
|
285
|
+
signatureFieldRemove: 'signature-field-remove',
|
|
286
|
+
signatureFieldResize: 'signature-field-resize',
|
|
287
|
+
fieldPalette: 'field-palette',
|
|
288
|
+
fieldPaletteButton: 'field-palette-button',
|
|
289
|
+
signerPanel: 'signer-panel',
|
|
290
|
+
signerPanelHeading: 'signer-panel-heading',
|
|
291
|
+
signerPanelLabel: 'signer-panel-label',
|
|
292
|
+
signerPanelInput: 'signer-panel-input',
|
|
293
|
+
signaturePreview: 'signature-preview',
|
|
294
|
+
signaturePreviewHeading: 'signature-preview-heading',
|
|
295
|
+
signaturePreviewModeToggle: 'signature-preview-mode-toggle',
|
|
296
|
+
signaturePreviewModeButton: 'signature-preview-mode-button',
|
|
297
|
+
signaturePreviewFontLabel: 'signature-preview-font-label',
|
|
298
|
+
signaturePreviewFontSelect: 'signature-preview-font-select',
|
|
299
|
+
signaturePreviewDisplay: 'signature-preview-display',
|
|
300
|
+
signaturePreviewImage: 'signature-preview-image',
|
|
301
|
+
signaturePreviewPlaceholder: 'signature-preview-placeholder',
|
|
302
|
+
signaturePad: 'signature-pad',
|
|
303
|
+
signaturePadCanvas: 'signature-pad-canvas',
|
|
304
|
+
signaturePadActions: 'signature-pad-actions',
|
|
305
|
+
signaturePadClear: 'signature-pad-clear',
|
|
306
|
+
signingComplete: 'signing-complete',
|
|
307
|
+
signingCompleteHeading: 'signing-complete-heading',
|
|
308
|
+
signingCompleteDetails: 'signing-complete-details',
|
|
309
|
+
signingCompleteHash: 'signing-complete-hash',
|
|
310
|
+
signingCompleteHashLabel: 'signing-complete-hash-label',
|
|
311
|
+
signingCompleteHashValue: 'signing-complete-hash-value',
|
|
312
|
+
signingCompleteActions: 'signing-complete-actions',
|
|
313
|
+
signingCompleteDownload: 'signing-complete-download',
|
|
314
|
+
signingCompleteReset: 'signing-complete-reset',
|
|
315
|
+
} as const
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## 3) Multi-Page behavior (post-change)
|
|
319
|
+
|
|
320
|
+
- `pageMode='scroll'`:
|
|
321
|
+
- all pages rendered in vertical stack
|
|
322
|
+
- best for desktop reading/review
|
|
323
|
+
- use `usePdfPageVisibility` + `PdfPageNavigator` for quick jumps
|
|
324
|
+
- `pageMode='single'`:
|
|
325
|
+
- only one page rendered at a time
|
|
326
|
+
- controlled by `currentPageIndex`
|
|
327
|
+
- best for mobile/focused workflows
|
|
328
|
+
- `renderToolbarContent`:
|
|
329
|
+
- add `FieldPalette`, `PdfPageNavigator`, or custom controls directly in viewer toolbar
|
|
330
|
+
- avoids losing field placement controls while moving across pages
|
|
331
|
+
|
|
332
|
+
## 4) Required wiring for page-aware UI
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
const viewerContainerRef = useRef<HTMLDivElement | null>(null)
|
|
336
|
+
const { currentPageIndex, scrollToPage } = usePdfPageVisibility({
|
|
337
|
+
containerRef: viewerContainerRef,
|
|
338
|
+
numPages,
|
|
339
|
+
})
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
<div ref={viewerContainerRef}>
|
|
344
|
+
<PdfViewer
|
|
345
|
+
pdfData={pdfData}
|
|
346
|
+
numPages={numPages}
|
|
347
|
+
scale={scale}
|
|
348
|
+
onScaleChange={setScale}
|
|
349
|
+
onDocumentLoadSuccess={handleDocumentLoadSuccess}
|
|
350
|
+
onPageDimensions={({ pageIndex, widthPt, heightPt }) => setPageDimension(pageIndex, widthPt, heightPt)}
|
|
351
|
+
pageMode="scroll"
|
|
352
|
+
currentPageIndex={currentPageIndex}
|
|
353
|
+
renderToolbarContent={() => (
|
|
354
|
+
<>
|
|
355
|
+
<PdfPageNavigator
|
|
356
|
+
currentPageIndex={currentPageIndex}
|
|
357
|
+
numPages={numPages}
|
|
358
|
+
onPageChange={scrollToPage}
|
|
359
|
+
/>
|
|
360
|
+
<FieldPalette selectedFieldType={selectedFieldType} onSelectFieldType={setSelectedFieldType} />
|
|
361
|
+
</>
|
|
362
|
+
)}
|
|
363
|
+
renderOverlay={(pageIndex) => (
|
|
364
|
+
<FieldOverlay
|
|
365
|
+
pageIndex={pageIndex}
|
|
366
|
+
fields={fields}
|
|
367
|
+
selectedFieldType={selectedFieldType}
|
|
368
|
+
onAddField={handleAddField}
|
|
369
|
+
onUpdateField={updateField}
|
|
370
|
+
onRemoveField={removeField}
|
|
371
|
+
preview={fieldPreview}
|
|
372
|
+
/>
|
|
373
|
+
)}
|
|
374
|
+
/>
|
|
375
|
+
</div>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## 5) Composition patterns
|
|
379
|
+
|
|
380
|
+
### PatternA_desktopStickySidebar
|
|
381
|
+
|
|
382
|
+
- use `pageMode='scroll'`
|
|
383
|
+
- put `PdfPageNavigator + FieldPalette` in `renderToolbarContent`
|
|
384
|
+
- keep signer controls sticky:
|
|
385
|
+
|
|
386
|
+
```tsx
|
|
387
|
+
<aside className="space-y-4 lg:sticky lg:top-6 lg:self-start">
|
|
388
|
+
<SignerDetailsPanel signerInfo={signerInfo} onSignerInfoChange={setSignerInfo} />
|
|
389
|
+
<SignaturePreview
|
|
390
|
+
signerName={displayName}
|
|
391
|
+
style={signatureStyle}
|
|
392
|
+
signatureDataUrl={signatureDataUrl}
|
|
393
|
+
isRendering={isRendering}
|
|
394
|
+
onStyleChange={setSignatureStyle}
|
|
395
|
+
/>
|
|
396
|
+
</aside>
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### PatternB_mobileSinglePage
|
|
400
|
+
|
|
401
|
+
- use `pageMode='single'`
|
|
402
|
+
- keep local `singlePageIndex` state
|
|
403
|
+
- use `PdfPageNavigator.onPageChange -> setSinglePageIndex`
|
|
404
|
+
|
|
405
|
+
### PatternC_responsiveSwitching
|
|
406
|
+
|
|
407
|
+
- desktop: `scroll`
|
|
408
|
+
- narrow viewport: `single`
|
|
409
|
+
- keep one toolbar composition in both modes
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
const [isMobile, setIsMobile] = useState(false)
|
|
413
|
+
const [singlePageIndex, setSinglePageIndex] = useState(0)
|
|
414
|
+
const isSinglePageMode = isMobile
|
|
415
|
+
|
|
416
|
+
const activePageIndex = isSinglePageMode ? singlePageIndex : currentPageIndex
|
|
417
|
+
const handlePageChange = (pageIndex: number) =>
|
|
418
|
+
isSinglePageMode ? setSinglePageIndex(pageIndex) : scrollToPage(pageIndex)
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### PatternD_mobileWizard
|
|
422
|
+
|
|
423
|
+
- step1: upload + signer details
|
|
424
|
+
- step2: `PdfViewer(pageMode='single')` + `FieldPalette` + `PdfPageNavigator`
|
|
425
|
+
- step3: review + sign
|
|
426
|
+
|
|
427
|
+
### PatternE_embeddedMinimal
|
|
428
|
+
|
|
429
|
+
- only `PdfViewer` + overlays + toolbar controls
|
|
430
|
+
- no sidebar
|
|
431
|
+
- recommended for constrained panes/modals
|
|
432
|
+
|
|
433
|
+
## 6) Field placement data flow
|
|
434
|
+
|
|
435
|
+
1. user toggles a field in `FieldPalette`
|
|
436
|
+
2. `FieldOverlay` enters placing mode (`data-state='placing'`, crosshair cursor)
|
|
437
|
+
3. user clicks overlay on target page
|
|
438
|
+
4. overlay computes `xPercent/yPercent` from click position
|
|
439
|
+
5. `useFieldPlacement.addField` adds a `FieldPlacement` with `pageIndex`
|
|
440
|
+
6. `SignatureField` supports drag move + corner resize
|
|
441
|
+
7. `modifyPdf` maps percentages to PDF points using `mapToPoints` for each page
|
|
442
|
+
|
|
443
|
+
## 7) Decision tree (agent-optimized)
|
|
444
|
+
|
|
445
|
+
```txt
|
|
446
|
+
IF desktop-first:
|
|
447
|
+
use PatternA_desktopStickySidebar
|
|
448
|
+
|
|
449
|
+
IF mobile-first:
|
|
450
|
+
use PatternB_mobileSinglePage
|
|
451
|
+
|
|
452
|
+
IF responsive:
|
|
453
|
+
use PatternC_responsiveSwitching
|
|
454
|
+
|
|
455
|
+
IF multi-step signing flow:
|
|
456
|
+
use PatternD_mobileWizard
|
|
457
|
+
|
|
458
|
+
IF embedded in modal or constrained panel:
|
|
459
|
+
use PatternE_embeddedMinimal
|
|
460
|
+
|
|
461
|
+
IF documents are usually 1-2 pages:
|
|
462
|
+
default scroll mode is enough
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## 8) Consumer responsibilities
|
|
466
|
+
|
|
467
|
+
- manage layout (sticky/fixed/sidebar/wizard)
|
|
468
|
+
- manage app-level validation and confirmation UX
|
|
469
|
+
- manage final download flow and success state
|
|
470
|
+
- choose mobile/desktop strategy (`scroll` vs `single`)
|
|
471
|
+
- style components via default `styles.css` or custom `[data-slot]` selectors
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as react from 'react';
|
|
3
|
-
import { ReactNode } from 'react';
|
|
3
|
+
import { ReactNode, RefObject } from 'react';
|
|
4
4
|
|
|
5
5
|
declare const SIGNATURE_FONTS: readonly ["Caveat", "Homemade Apple", "Reenie Beanie", "Mr Dafoe", "Pacifico", "Qwitcher Grypen"];
|
|
6
6
|
declare function loadSignatureFont(fontFamily: string): Promise<void>;
|
|
@@ -33,11 +33,25 @@ interface PdfViewerProps {
|
|
|
33
33
|
heightPt: number;
|
|
34
34
|
}) => void;
|
|
35
35
|
renderOverlay?: (pageIndex: number) => ReactNode;
|
|
36
|
+
/** Render extra controls in the toolbar between page count and zoom controls. */
|
|
37
|
+
renderToolbarContent?: () => ReactNode;
|
|
36
38
|
className?: string;
|
|
37
39
|
/** PDF.js worker script URL. Overrides `configure({ pdfWorkerSrc })`. When neither is set, worker URL is left unset (no CDN injection). */
|
|
38
40
|
workerSrc?: string;
|
|
41
|
+
/** 'scroll' renders all pages. 'single' renders only currentPageIndex. */
|
|
42
|
+
pageMode?: 'scroll' | 'single';
|
|
43
|
+
/** Visible page index in single mode (0-based). */
|
|
44
|
+
currentPageIndex?: number;
|
|
39
45
|
}
|
|
40
|
-
declare function PdfViewer({ pdfData, numPages, scale, onScaleChange, onDocumentLoadSuccess, onPageDimensions, renderOverlay, className, workerSrc, }: PdfViewerProps): react_jsx_runtime.JSX.Element;
|
|
46
|
+
declare function PdfViewer({ pdfData, numPages, scale, onScaleChange, onDocumentLoadSuccess, onPageDimensions, renderOverlay, renderToolbarContent, className, workerSrc, pageMode, currentPageIndex, }: PdfViewerProps): react_jsx_runtime.JSX.Element;
|
|
47
|
+
|
|
48
|
+
interface PdfPageNavigatorProps {
|
|
49
|
+
currentPageIndex: number;
|
|
50
|
+
numPages: number;
|
|
51
|
+
onPageChange: (pageIndex: number) => void;
|
|
52
|
+
className?: string;
|
|
53
|
+
}
|
|
54
|
+
declare function PdfPageNavigator({ currentPageIndex, numPages, onPageChange, className }: PdfPageNavigatorProps): react_jsx_runtime.JSX.Element;
|
|
41
55
|
|
|
42
56
|
type FieldType = 'signature' | 'fullName' | 'title' | 'date';
|
|
43
57
|
interface FieldPlacement {
|
|
@@ -48,6 +62,7 @@ interface FieldPlacement {
|
|
|
48
62
|
yPercent: number;
|
|
49
63
|
widthPercent: number;
|
|
50
64
|
heightPercent: number;
|
|
65
|
+
locked?: boolean;
|
|
51
66
|
}
|
|
52
67
|
interface SignerInfo {
|
|
53
68
|
firstName: string;
|
|
@@ -167,9 +182,27 @@ declare function usePdfDocument(pdfInput: PdfInput): {
|
|
|
167
182
|
errorMessage: string | null;
|
|
168
183
|
};
|
|
169
184
|
|
|
185
|
+
interface UsePdfPageVisibilityOptions {
|
|
186
|
+
/** Ref to the element containing the pdf-viewer pages stack or its parent container. */
|
|
187
|
+
containerRef: RefObject<HTMLElement | null>;
|
|
188
|
+
numPages: number;
|
|
189
|
+
/** IntersectionObserver threshold (0-1). Defaults to 0.5. */
|
|
190
|
+
threshold?: number;
|
|
191
|
+
}
|
|
192
|
+
interface UsePdfPageVisibilityReturn {
|
|
193
|
+
/** 0-based index of the most visible page. */
|
|
194
|
+
currentPageIndex: number;
|
|
195
|
+
/** All currently visible page indices, sorted ascending. */
|
|
196
|
+
visiblePageIndices: number[];
|
|
197
|
+
/** Scroll a page element into view. */
|
|
198
|
+
scrollToPage: (pageIndex: number) => void;
|
|
199
|
+
}
|
|
200
|
+
declare function usePdfPageVisibility({ containerRef, numPages, threshold, }: UsePdfPageVisibilityOptions): UsePdfPageVisibilityReturn;
|
|
201
|
+
|
|
170
202
|
interface UseFieldPlacementOptions {
|
|
171
203
|
defaultWidthPercent?: number;
|
|
172
204
|
defaultHeightPercent?: number;
|
|
205
|
+
initialFields?: FieldPlacement[];
|
|
173
206
|
}
|
|
174
207
|
interface AddFieldInput {
|
|
175
208
|
pageIndex: number;
|
|
@@ -213,6 +246,7 @@ declare const SLOTS: {
|
|
|
213
246
|
readonly pdfViewer: "pdf-viewer";
|
|
214
247
|
readonly pdfViewerEmpty: "pdf-viewer-empty";
|
|
215
248
|
readonly pdfViewerToolbar: "pdf-viewer-toolbar";
|
|
249
|
+
readonly pdfViewerToolbarContent: "pdf-viewer-toolbar-content";
|
|
216
250
|
readonly pdfViewerPageCount: "pdf-viewer-page-count";
|
|
217
251
|
readonly pdfViewerZoom: "pdf-viewer-zoom";
|
|
218
252
|
readonly pdfViewerZoomButton: "pdf-viewer-zoom-button";
|
|
@@ -221,6 +255,9 @@ declare const SLOTS: {
|
|
|
221
255
|
readonly pdfViewerPage: "pdf-viewer-page";
|
|
222
256
|
readonly pdfViewerLoading: "pdf-viewer-loading";
|
|
223
257
|
readonly pdfViewerError: "pdf-viewer-error";
|
|
258
|
+
readonly pdfPageNavigator: "pdf-page-navigator";
|
|
259
|
+
readonly pdfPageNavigatorButton: "pdf-page-navigator-button";
|
|
260
|
+
readonly pdfPageNavigatorLabel: "pdf-page-navigator-label";
|
|
224
261
|
readonly fieldOverlay: "field-overlay";
|
|
225
262
|
readonly signatureField: "signature-field";
|
|
226
263
|
readonly signatureFieldContent: "signature-field-content";
|
|
@@ -230,6 +267,7 @@ declare const SLOTS: {
|
|
|
230
267
|
readonly signatureFieldPreviewText: "signature-field-preview-text";
|
|
231
268
|
readonly signatureFieldRemove: "signature-field-remove";
|
|
232
269
|
readonly signatureFieldResize: "signature-field-resize";
|
|
270
|
+
readonly signatureFieldLock: "signature-field-lock";
|
|
233
271
|
readonly fieldPalette: "field-palette";
|
|
234
272
|
readonly fieldPaletteButton: "field-palette-button";
|
|
235
273
|
readonly signerPanel: "signer-panel";
|
|
@@ -266,4 +304,4 @@ declare const defaults: {
|
|
|
266
304
|
readonly DEFAULT_FIELD_HEIGHT_PERCENT: 5;
|
|
267
305
|
};
|
|
268
306
|
|
|
269
|
-
export { type ESigningConfig, FieldOverlay, FieldPalette, type FieldPlacement, type FieldType, type PdfPageDimensions, PdfViewer, SIGNATURE_FONTS, SLOTS, SignatureField, type SignatureFieldPreview, type SignatureFontWarning, SignaturePad, SignaturePreview, type SignatureStyle, SignerDetailsPanel, type SignerInfo, SigningComplete, type SigningResult, configure, defaults, loadSignatureFont, mapFromPoints, mapToPoints, modifyPdf, sha256, useFieldPlacement, usePdfDocument, useSignatureRenderer };
|
|
307
|
+
export { type ESigningConfig, FieldOverlay, FieldPalette, type FieldPlacement, type FieldType, type PdfPageDimensions, PdfPageNavigator, PdfViewer, SIGNATURE_FONTS, SLOTS, SignatureField, type SignatureFieldPreview, type SignatureFontWarning, SignaturePad, SignaturePreview, type SignatureStyle, SignerDetailsPanel, type SignerInfo, SigningComplete, type SigningResult, type UsePdfPageVisibilityOptions, type UsePdfPageVisibilityReturn, configure, defaults, loadSignatureFont, mapFromPoints, mapToPoints, modifyPdf, sha256, useFieldPlacement, usePdfDocument, usePdfPageVisibility, useSignatureRenderer };
|