@unlev/exeq 0.5.6 → 0.6.0
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/dist/index.d.mts +4 -229
- package/dist/index.d.ts +4 -229
- package/dist/index.js +40 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -608
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +34 -0
- package/dist/server.d.ts +34 -0
- package/dist/server.js +663 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +61 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +13 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,76 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type FieldType = 'text' | 'dropdown' | 'signature' | 'signed-date' | 'checkbox' | 'initials' | 'blackout' | 'whiteout';
|
|
6
|
-
type TextSubtype = 'freeform' | 'number' | 'date' | 'email' | 'phone';
|
|
7
|
-
interface FormField {
|
|
8
|
-
id: string;
|
|
9
|
-
type: FieldType;
|
|
10
|
-
textSubtype?: TextSubtype;
|
|
11
|
-
label: string;
|
|
12
|
-
placeholder: string;
|
|
13
|
-
required: boolean;
|
|
14
|
-
assignee: string;
|
|
15
|
-
page: number;
|
|
16
|
-
x: number;
|
|
17
|
-
y: number;
|
|
18
|
-
width: number;
|
|
19
|
-
height: number;
|
|
20
|
-
fontSize: number;
|
|
21
|
-
value: string;
|
|
22
|
-
inkColor?: string;
|
|
23
|
-
letterSpacing?: number;
|
|
24
|
-
lineHeight?: number;
|
|
25
|
-
align?: 'left' | 'center' | 'right';
|
|
26
|
-
bold?: boolean;
|
|
27
|
-
italic?: boolean;
|
|
28
|
-
underline?: boolean;
|
|
29
|
-
strikethrough?: boolean;
|
|
30
|
-
minLength?: number;
|
|
31
|
-
maxLength?: number;
|
|
32
|
-
fontFamily?: string;
|
|
33
|
-
options?: string[];
|
|
34
|
-
formula?: string;
|
|
35
|
-
locked?: boolean;
|
|
36
|
-
autoShrink?: boolean;
|
|
37
|
-
}
|
|
38
|
-
interface Template {
|
|
39
|
-
fields: FormField[];
|
|
40
|
-
signerRoles: string[];
|
|
41
|
-
pdfUrl: string;
|
|
42
|
-
}
|
|
43
|
-
declare const DEFAULT_SIGNER_ROLES: string[];
|
|
44
|
-
declare const SIGNER_ROLE_COLORS: Record<string, string>;
|
|
45
|
-
declare function getSignerColor(role: string): string;
|
|
46
|
-
declare function isRedactField(f: FormField | {
|
|
47
|
-
type: FieldType;
|
|
48
|
-
}): boolean;
|
|
49
|
-
declare function isSignatureField(f: FormField | {
|
|
50
|
-
type: FieldType;
|
|
51
|
-
}): boolean;
|
|
52
|
-
declare function isTextLikeField(f: FormField | {
|
|
53
|
-
type: FieldType;
|
|
54
|
-
}): boolean;
|
|
55
|
-
declare function getInputType(subtype?: TextSubtype): string;
|
|
56
|
-
declare function getCssFontFamily(fontFamily?: string): string | undefined;
|
|
57
|
-
declare function sortFieldsByPosition(fields: FormField[]): FormField[];
|
|
58
|
-
declare function preserveFieldValues(oldFields: FormField[], newFields: FormField[]): FormField[];
|
|
59
|
-
declare function getFieldValues(fields: FormField[]): Record<string, string>;
|
|
60
|
-
declare const FONT_FAMILIES: readonly [{
|
|
61
|
-
readonly value: "Helvetica";
|
|
62
|
-
readonly label: "Helvetica";
|
|
63
|
-
}, {
|
|
64
|
-
readonly value: "Courier";
|
|
65
|
-
readonly label: "Courier New";
|
|
66
|
-
}, {
|
|
67
|
-
readonly value: "TimesRoman";
|
|
68
|
-
readonly label: "Times New Roman";
|
|
69
|
-
}];
|
|
70
|
-
declare const FIELD_DEFAULTS: Record<FieldType, Partial<FormField>>;
|
|
71
|
-
/** Given a desired label and a list of existing labels, return a unique label by appending a number if needed. */
|
|
72
|
-
declare function uniqueLabel(desired: string, existingLabels: string[]): string;
|
|
73
|
-
declare function createField(type: FieldType, assignee: string, page: number, x: number, y: number, existingFields?: FormField[]): FormField;
|
|
2
|
+
import { T as Template, a as TransformMap, F as FormField, b as FieldType } from './pdfFiller-Btf-SnEB.mjs';
|
|
3
|
+
export { A as A4, B as BUILTIN_TRANSFORMS, C as Calibration, c as CreatePdfBuilderOptions, D as DEFAULT_CALIBRATION, d as DEFAULT_SIGNER_ROLES, e as FIELD_DEFAULTS, f as FONT_FAMILIES, g as FillPdfOptions, P as PdfBuilder, h as PdfMetadata, S as SIGNER_ROLE_COLORS, i as TextSubtype, j as TransformFn, U as US_LEGAL, k as US_LETTER, l as applyCalibration, m as createField, n as createPdfBuilder, o as downloadPdf, p as generateFilledPdf, q as generateId, r as getCssFontFamily, s as getFieldValues, t as getInputType, u as getSignerColor, v as isRedactField, w as isSignatureField, x as isTextLikeField, y as parseDate, z as postPdfToCallback, E as preserveFieldValues, G as resolveAllFormulas, H as resolveFormula, I as sortFieldsByPosition, J as uniqueLabel } from './pdfFiller-Btf-SnEB.mjs';
|
|
4
|
+
import 'pdf-lib';
|
|
74
5
|
|
|
75
6
|
interface DesignerViewProps {
|
|
76
7
|
/** API key for authentication */
|
|
@@ -94,42 +25,6 @@ interface DesignerViewProps {
|
|
|
94
25
|
}
|
|
95
26
|
declare function DesignerView({ apiKey, initialPdfUrl, initialTemplate, onSave, onChange, hideHeader, headerPortalRef, }?: DesignerViewProps): react_jsx_runtime.JSX.Element;
|
|
96
27
|
|
|
97
|
-
type TransformFn = (value: string) => string;
|
|
98
|
-
type TransformMap = Record<string, TransformFn>;
|
|
99
|
-
/**
|
|
100
|
-
* Parse a date string robustly into a local Date (midnight, local TZ) so that
|
|
101
|
-
* getMonth/getDate/getFullYear are calendar-correct. Handles:
|
|
102
|
-
* - ISO date-only "YYYY-MM-DD" → parsed as LOCAL (avoids the classic UTC
|
|
103
|
-
* off-by-one where "2024-03-15" becomes the 14th in western timezones).
|
|
104
|
-
* - Excel serial numbers (a bare integer, e.g. "45000") → converted.
|
|
105
|
-
* - Anything else → native `new Date` (handles "M/D/YYYY", ISO datetimes, …).
|
|
106
|
-
* Returns null when unparseable.
|
|
107
|
-
*/
|
|
108
|
-
declare function parseDate(value: string): Date | null;
|
|
109
|
-
/** Built-in transforms that ship with exeq. */
|
|
110
|
-
declare const BUILTIN_TRANSFORMS: TransformMap;
|
|
111
|
-
/**
|
|
112
|
-
* Resolve a single formula string against a set of fields and transforms.
|
|
113
|
-
* Formula format: "{{Source Field Label | transform}}" or "{{Source Field Label}}" (no transform = raw value).
|
|
114
|
-
* Multiple expressions can appear in one formula: "{{First}} {{Last}}" → "Jane Smith"
|
|
115
|
-
*
|
|
116
|
-
* Source resolution order for "{{Name}}":
|
|
117
|
-
* 1. a placed field whose label (case-insensitive) or id matches Name
|
|
118
|
-
* 2. `values[Name]` — imported/contextual data not tied to a placed field
|
|
119
|
-
* 3. the built-in `today` / `now` source (current date)
|
|
120
|
-
*
|
|
121
|
-
* @param values Extra named values (e.g. imported CSV/form data) made available
|
|
122
|
-
* to formula sources even when there is no placed field for them.
|
|
123
|
-
*/
|
|
124
|
-
declare function resolveFormula(formula: string, fields: FormField[], customTransforms?: TransformMap, values?: Record<string, string>): string;
|
|
125
|
-
/**
|
|
126
|
-
* Resolve all formula fields in a fields array.
|
|
127
|
-
* Returns a new array with computed values filled in.
|
|
128
|
-
*
|
|
129
|
-
* @param values Extra named values available to formula sources (see resolveFormula).
|
|
130
|
-
*/
|
|
131
|
-
declare function resolveAllFormulas(fields: FormField[], customTransforms?: TransformMap, values?: Record<string, string>): FormField[];
|
|
132
|
-
|
|
133
28
|
interface SignerViewProps {
|
|
134
29
|
/** API key for authentication */
|
|
135
30
|
apiKey?: string;
|
|
@@ -240,124 +135,4 @@ interface SignerRoleSelectorProps {
|
|
|
240
135
|
}
|
|
241
136
|
declare function SignerRoleSelector({ roles, activeRole, onSetActiveRole, onAddRole, onRemoveRole, }: SignerRoleSelectorProps): react_jsx_runtime.JSX.Element;
|
|
242
137
|
|
|
243
|
-
|
|
244
|
-
declare const US_LETTER: [number, number];
|
|
245
|
-
/** US Legal in PDF points. */
|
|
246
|
-
declare const US_LEGAL: [number, number];
|
|
247
|
-
/** A4 in PDF points. */
|
|
248
|
-
declare const A4: [number, number];
|
|
249
|
-
/**
|
|
250
|
-
* Linear calibration applied to every field's percentage position and size.
|
|
251
|
-
* Use to align rendered output with a physical pre-printed form when the
|
|
252
|
-
* template's source PDF and the real paper don't exactly agree on crop or
|
|
253
|
-
* scale.
|
|
254
|
-
*
|
|
255
|
-
* Math (for an output page of size [pW, pH] pt):
|
|
256
|
-
* xPctOff = (xOffset / pW) * 100
|
|
257
|
-
* yPctOff = (yOffset / pH) * 100
|
|
258
|
-
* x' = x_pct * xScale + xPctOff
|
|
259
|
-
* y' = y_pct * yScale + yPctOff
|
|
260
|
-
* width' = width_pct * xScale
|
|
261
|
-
* height' = height_pct * yScale
|
|
262
|
-
*
|
|
263
|
-
* Defaults (scale=1, offsets=0) are a no-op.
|
|
264
|
-
*/
|
|
265
|
-
interface Calibration {
|
|
266
|
-
/** Horizontal offset in PDF points; positive = right. */
|
|
267
|
-
xOffset: number;
|
|
268
|
-
/** Vertical offset in PDF points; positive = down (screen coords). */
|
|
269
|
-
yOffset: number;
|
|
270
|
-
/** Horizontal multiplier applied to x and width. */
|
|
271
|
-
xScale: number;
|
|
272
|
-
/** Vertical multiplier applied to y and height. */
|
|
273
|
-
yScale: number;
|
|
274
|
-
}
|
|
275
|
-
declare const DEFAULT_CALIBRATION: Calibration;
|
|
276
|
-
/**
|
|
277
|
-
* Returns a copy of `fields` with calibration applied to x / y / width /
|
|
278
|
-
* height. The math is page-size-aware so an `xOffset` of 5pt actually
|
|
279
|
-
* shifts the rendered output 5pt to the right.
|
|
280
|
-
*
|
|
281
|
-
* @param pageSize Output page size in pt used to convert pt offsets to
|
|
282
|
-
* percent offsets. Defaults to US Letter.
|
|
283
|
-
*/
|
|
284
|
-
declare function applyCalibration(fields: FormField[], calibration: Calibration, pageSize?: [number, number]): FormField[];
|
|
285
|
-
interface FillPdfOptions {
|
|
286
|
-
/** Source PDF used as the background.
|
|
287
|
-
* - `string` (URL): fetched, embedded once per URL across the document.
|
|
288
|
-
* - `ArrayBuffer`: embedded uniquely each call.
|
|
289
|
-
* - `null`: render onto blank pages (overlay-only output). */
|
|
290
|
-
pdfSource: string | ArrayBuffer | null;
|
|
291
|
-
/** Fields to render on top of the background. */
|
|
292
|
-
fields: FormField[];
|
|
293
|
-
/** Override the output page size in PDF points.
|
|
294
|
-
* - With a `pdfSource`, source pages are drawn stretched to fit.
|
|
295
|
-
* - With `pdfSource: null`, blank pages of this size are created.
|
|
296
|
-
* - When omitted with a source, output uses the source's page sizes.
|
|
297
|
-
* - When omitted with `pdfSource: null`, defaults to US Letter. */
|
|
298
|
-
pageSize?: [number, number];
|
|
299
|
-
/** When `pdfSource` is null, how many blank pages to render. Default `1`.
|
|
300
|
-
* Fields with out-of-range `page` indices are skipped. */
|
|
301
|
-
pageCount?: number;
|
|
302
|
-
/** Run `resolveAllFormulas` on fields before rendering. */
|
|
303
|
-
resolveFormulas?: boolean;
|
|
304
|
-
/** Custom transforms merged with `BUILTIN_TRANSFORMS` during formula
|
|
305
|
-
* resolution. Only meaningful when `resolveFormulas` is true. */
|
|
306
|
-
customTransforms?: TransformMap;
|
|
307
|
-
/** Extra named values made available to formula sources (e.g. imported CSV/
|
|
308
|
-
* form data) even when there is no placed field for them. Only meaningful
|
|
309
|
-
* when `resolveFormulas` is true. */
|
|
310
|
-
formulaValues?: Record<string, string>;
|
|
311
|
-
/** Linear calibration applied to field positions before rendering. */
|
|
312
|
-
calibration?: Calibration;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Generates one filled PDF.
|
|
316
|
-
*
|
|
317
|
-
* const bytes = await generateFilledPdf({
|
|
318
|
-
* pdfSource: '/forms/template.pdf',
|
|
319
|
-
* fields: template.fields,
|
|
320
|
-
* pageSize: US_LETTER,
|
|
321
|
-
* resolveFormulas: true,
|
|
322
|
-
* });
|
|
323
|
-
*
|
|
324
|
-
* For multi-record output that shares a background, use `createPdfBuilder`
|
|
325
|
-
* — it dedupes the embedded source across all pages.
|
|
326
|
-
*/
|
|
327
|
-
declare function generateFilledPdf(opts: FillPdfOptions): Promise<Uint8Array>;
|
|
328
|
-
interface PdfBuilder {
|
|
329
|
-
/** Underlying pdf-lib document — exposed for advanced post-processing
|
|
330
|
-
* (audit-trail pages, custom metadata, etc.). */
|
|
331
|
-
readonly doc: PDFDocument;
|
|
332
|
-
/** Append one record's pages to the output. */
|
|
333
|
-
addRecord(opts: FillPdfOptions): Promise<void>;
|
|
334
|
-
/** Finalize and return the merged PDF bytes. */
|
|
335
|
-
save(): Promise<Uint8Array>;
|
|
336
|
-
}
|
|
337
|
-
interface CreatePdfBuilderOptions {
|
|
338
|
-
/** Default `pageSize` for any `addRecord` call that doesn't set its own. */
|
|
339
|
-
pageSize?: [number, number];
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Creates a builder that merges multiple filled records into one PDF.
|
|
343
|
-
*
|
|
344
|
-
* Resources (source PDFs indexed by URL, embedded fonts, signature PNGs) are
|
|
345
|
-
* embedded once across the whole document and reused — critical for
|
|
346
|
-
* mail-merge style batches where dozens of records share the same background.
|
|
347
|
-
*
|
|
348
|
-
* const builder = await createPdfBuilder({ pageSize: US_LETTER });
|
|
349
|
-
* for (const record of records) {
|
|
350
|
-
* await builder.addRecord({
|
|
351
|
-
* pdfSource: '/forms/template.pdf',
|
|
352
|
-
* fields: record.fields,
|
|
353
|
-
* resolveFormulas: true,
|
|
354
|
-
* });
|
|
355
|
-
* }
|
|
356
|
-
* const bytes = await builder.save();
|
|
357
|
-
* downloadPdf(bytes, 'merged.pdf');
|
|
358
|
-
*/
|
|
359
|
-
declare function createPdfBuilder(defaults?: CreatePdfBuilderOptions): Promise<PdfBuilder>;
|
|
360
|
-
declare function downloadPdf(bytes: Uint8Array, filename: string): void;
|
|
361
|
-
declare function postPdfToCallback(bytes: Uint8Array, callbackUrl: string, filename: string): Promise<void>;
|
|
362
|
-
|
|
363
|
-
export { A4, BUILTIN_TRANSFORMS, type Calibration, type CreatePdfBuilderOptions, DEFAULT_CALIBRATION, DEFAULT_SIGNER_ROLES, DesignerView, type DesignerViewProps, FIELD_DEFAULTS, FONT_FAMILIES, FieldNavigator, FieldPropertyPanel, type FieldType, type FillPdfOptions, type FormField, type PdfBuilder, PdfViewer, type RenderedPage, SIGNER_ROLE_COLORS, SignatureCanvas, SignerRoleSelector, SignerView, type SignerViewProps, type Template, type TextSubtype, type TransformFn, type TransformMap, US_LEGAL, US_LETTER, applyCalibration, createField, createPdfBuilder, downloadPdf, generateFilledPdf, generateId, getCssFontFamily, getFieldValues, getInputType, getSignerColor, isRedactField, isSignatureField, isTextLikeField, parseDate, postPdfToCallback, preserveFieldValues, renderPdfPages, resolveAllFormulas, resolveFormula, sortFieldsByPosition, uniqueLabel };
|
|
138
|
+
export { DesignerView, type DesignerViewProps, FieldNavigator, FieldPropertyPanel, FieldType, FormField, PdfViewer, type RenderedPage, SignatureCanvas, SignerRoleSelector, SignerView, type SignerViewProps, Template, TransformMap, renderPdfPages };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,76 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type FieldType = 'text' | 'dropdown' | 'signature' | 'signed-date' | 'checkbox' | 'initials' | 'blackout' | 'whiteout';
|
|
6
|
-
type TextSubtype = 'freeform' | 'number' | 'date' | 'email' | 'phone';
|
|
7
|
-
interface FormField {
|
|
8
|
-
id: string;
|
|
9
|
-
type: FieldType;
|
|
10
|
-
textSubtype?: TextSubtype;
|
|
11
|
-
label: string;
|
|
12
|
-
placeholder: string;
|
|
13
|
-
required: boolean;
|
|
14
|
-
assignee: string;
|
|
15
|
-
page: number;
|
|
16
|
-
x: number;
|
|
17
|
-
y: number;
|
|
18
|
-
width: number;
|
|
19
|
-
height: number;
|
|
20
|
-
fontSize: number;
|
|
21
|
-
value: string;
|
|
22
|
-
inkColor?: string;
|
|
23
|
-
letterSpacing?: number;
|
|
24
|
-
lineHeight?: number;
|
|
25
|
-
align?: 'left' | 'center' | 'right';
|
|
26
|
-
bold?: boolean;
|
|
27
|
-
italic?: boolean;
|
|
28
|
-
underline?: boolean;
|
|
29
|
-
strikethrough?: boolean;
|
|
30
|
-
minLength?: number;
|
|
31
|
-
maxLength?: number;
|
|
32
|
-
fontFamily?: string;
|
|
33
|
-
options?: string[];
|
|
34
|
-
formula?: string;
|
|
35
|
-
locked?: boolean;
|
|
36
|
-
autoShrink?: boolean;
|
|
37
|
-
}
|
|
38
|
-
interface Template {
|
|
39
|
-
fields: FormField[];
|
|
40
|
-
signerRoles: string[];
|
|
41
|
-
pdfUrl: string;
|
|
42
|
-
}
|
|
43
|
-
declare const DEFAULT_SIGNER_ROLES: string[];
|
|
44
|
-
declare const SIGNER_ROLE_COLORS: Record<string, string>;
|
|
45
|
-
declare function getSignerColor(role: string): string;
|
|
46
|
-
declare function isRedactField(f: FormField | {
|
|
47
|
-
type: FieldType;
|
|
48
|
-
}): boolean;
|
|
49
|
-
declare function isSignatureField(f: FormField | {
|
|
50
|
-
type: FieldType;
|
|
51
|
-
}): boolean;
|
|
52
|
-
declare function isTextLikeField(f: FormField | {
|
|
53
|
-
type: FieldType;
|
|
54
|
-
}): boolean;
|
|
55
|
-
declare function getInputType(subtype?: TextSubtype): string;
|
|
56
|
-
declare function getCssFontFamily(fontFamily?: string): string | undefined;
|
|
57
|
-
declare function sortFieldsByPosition(fields: FormField[]): FormField[];
|
|
58
|
-
declare function preserveFieldValues(oldFields: FormField[], newFields: FormField[]): FormField[];
|
|
59
|
-
declare function getFieldValues(fields: FormField[]): Record<string, string>;
|
|
60
|
-
declare const FONT_FAMILIES: readonly [{
|
|
61
|
-
readonly value: "Helvetica";
|
|
62
|
-
readonly label: "Helvetica";
|
|
63
|
-
}, {
|
|
64
|
-
readonly value: "Courier";
|
|
65
|
-
readonly label: "Courier New";
|
|
66
|
-
}, {
|
|
67
|
-
readonly value: "TimesRoman";
|
|
68
|
-
readonly label: "Times New Roman";
|
|
69
|
-
}];
|
|
70
|
-
declare const FIELD_DEFAULTS: Record<FieldType, Partial<FormField>>;
|
|
71
|
-
/** Given a desired label and a list of existing labels, return a unique label by appending a number if needed. */
|
|
72
|
-
declare function uniqueLabel(desired: string, existingLabels: string[]): string;
|
|
73
|
-
declare function createField(type: FieldType, assignee: string, page: number, x: number, y: number, existingFields?: FormField[]): FormField;
|
|
2
|
+
import { T as Template, a as TransformMap, F as FormField, b as FieldType } from './pdfFiller-Btf-SnEB.js';
|
|
3
|
+
export { A as A4, B as BUILTIN_TRANSFORMS, C as Calibration, c as CreatePdfBuilderOptions, D as DEFAULT_CALIBRATION, d as DEFAULT_SIGNER_ROLES, e as FIELD_DEFAULTS, f as FONT_FAMILIES, g as FillPdfOptions, P as PdfBuilder, h as PdfMetadata, S as SIGNER_ROLE_COLORS, i as TextSubtype, j as TransformFn, U as US_LEGAL, k as US_LETTER, l as applyCalibration, m as createField, n as createPdfBuilder, o as downloadPdf, p as generateFilledPdf, q as generateId, r as getCssFontFamily, s as getFieldValues, t as getInputType, u as getSignerColor, v as isRedactField, w as isSignatureField, x as isTextLikeField, y as parseDate, z as postPdfToCallback, E as preserveFieldValues, G as resolveAllFormulas, H as resolveFormula, I as sortFieldsByPosition, J as uniqueLabel } from './pdfFiller-Btf-SnEB.js';
|
|
4
|
+
import 'pdf-lib';
|
|
74
5
|
|
|
75
6
|
interface DesignerViewProps {
|
|
76
7
|
/** API key for authentication */
|
|
@@ -94,42 +25,6 @@ interface DesignerViewProps {
|
|
|
94
25
|
}
|
|
95
26
|
declare function DesignerView({ apiKey, initialPdfUrl, initialTemplate, onSave, onChange, hideHeader, headerPortalRef, }?: DesignerViewProps): react_jsx_runtime.JSX.Element;
|
|
96
27
|
|
|
97
|
-
type TransformFn = (value: string) => string;
|
|
98
|
-
type TransformMap = Record<string, TransformFn>;
|
|
99
|
-
/**
|
|
100
|
-
* Parse a date string robustly into a local Date (midnight, local TZ) so that
|
|
101
|
-
* getMonth/getDate/getFullYear are calendar-correct. Handles:
|
|
102
|
-
* - ISO date-only "YYYY-MM-DD" → parsed as LOCAL (avoids the classic UTC
|
|
103
|
-
* off-by-one where "2024-03-15" becomes the 14th in western timezones).
|
|
104
|
-
* - Excel serial numbers (a bare integer, e.g. "45000") → converted.
|
|
105
|
-
* - Anything else → native `new Date` (handles "M/D/YYYY", ISO datetimes, …).
|
|
106
|
-
* Returns null when unparseable.
|
|
107
|
-
*/
|
|
108
|
-
declare function parseDate(value: string): Date | null;
|
|
109
|
-
/** Built-in transforms that ship with exeq. */
|
|
110
|
-
declare const BUILTIN_TRANSFORMS: TransformMap;
|
|
111
|
-
/**
|
|
112
|
-
* Resolve a single formula string against a set of fields and transforms.
|
|
113
|
-
* Formula format: "{{Source Field Label | transform}}" or "{{Source Field Label}}" (no transform = raw value).
|
|
114
|
-
* Multiple expressions can appear in one formula: "{{First}} {{Last}}" → "Jane Smith"
|
|
115
|
-
*
|
|
116
|
-
* Source resolution order for "{{Name}}":
|
|
117
|
-
* 1. a placed field whose label (case-insensitive) or id matches Name
|
|
118
|
-
* 2. `values[Name]` — imported/contextual data not tied to a placed field
|
|
119
|
-
* 3. the built-in `today` / `now` source (current date)
|
|
120
|
-
*
|
|
121
|
-
* @param values Extra named values (e.g. imported CSV/form data) made available
|
|
122
|
-
* to formula sources even when there is no placed field for them.
|
|
123
|
-
*/
|
|
124
|
-
declare function resolveFormula(formula: string, fields: FormField[], customTransforms?: TransformMap, values?: Record<string, string>): string;
|
|
125
|
-
/**
|
|
126
|
-
* Resolve all formula fields in a fields array.
|
|
127
|
-
* Returns a new array with computed values filled in.
|
|
128
|
-
*
|
|
129
|
-
* @param values Extra named values available to formula sources (see resolveFormula).
|
|
130
|
-
*/
|
|
131
|
-
declare function resolveAllFormulas(fields: FormField[], customTransforms?: TransformMap, values?: Record<string, string>): FormField[];
|
|
132
|
-
|
|
133
28
|
interface SignerViewProps {
|
|
134
29
|
/** API key for authentication */
|
|
135
30
|
apiKey?: string;
|
|
@@ -240,124 +135,4 @@ interface SignerRoleSelectorProps {
|
|
|
240
135
|
}
|
|
241
136
|
declare function SignerRoleSelector({ roles, activeRole, onSetActiveRole, onAddRole, onRemoveRole, }: SignerRoleSelectorProps): react_jsx_runtime.JSX.Element;
|
|
242
137
|
|
|
243
|
-
|
|
244
|
-
declare const US_LETTER: [number, number];
|
|
245
|
-
/** US Legal in PDF points. */
|
|
246
|
-
declare const US_LEGAL: [number, number];
|
|
247
|
-
/** A4 in PDF points. */
|
|
248
|
-
declare const A4: [number, number];
|
|
249
|
-
/**
|
|
250
|
-
* Linear calibration applied to every field's percentage position and size.
|
|
251
|
-
* Use to align rendered output with a physical pre-printed form when the
|
|
252
|
-
* template's source PDF and the real paper don't exactly agree on crop or
|
|
253
|
-
* scale.
|
|
254
|
-
*
|
|
255
|
-
* Math (for an output page of size [pW, pH] pt):
|
|
256
|
-
* xPctOff = (xOffset / pW) * 100
|
|
257
|
-
* yPctOff = (yOffset / pH) * 100
|
|
258
|
-
* x' = x_pct * xScale + xPctOff
|
|
259
|
-
* y' = y_pct * yScale + yPctOff
|
|
260
|
-
* width' = width_pct * xScale
|
|
261
|
-
* height' = height_pct * yScale
|
|
262
|
-
*
|
|
263
|
-
* Defaults (scale=1, offsets=0) are a no-op.
|
|
264
|
-
*/
|
|
265
|
-
interface Calibration {
|
|
266
|
-
/** Horizontal offset in PDF points; positive = right. */
|
|
267
|
-
xOffset: number;
|
|
268
|
-
/** Vertical offset in PDF points; positive = down (screen coords). */
|
|
269
|
-
yOffset: number;
|
|
270
|
-
/** Horizontal multiplier applied to x and width. */
|
|
271
|
-
xScale: number;
|
|
272
|
-
/** Vertical multiplier applied to y and height. */
|
|
273
|
-
yScale: number;
|
|
274
|
-
}
|
|
275
|
-
declare const DEFAULT_CALIBRATION: Calibration;
|
|
276
|
-
/**
|
|
277
|
-
* Returns a copy of `fields` with calibration applied to x / y / width /
|
|
278
|
-
* height. The math is page-size-aware so an `xOffset` of 5pt actually
|
|
279
|
-
* shifts the rendered output 5pt to the right.
|
|
280
|
-
*
|
|
281
|
-
* @param pageSize Output page size in pt used to convert pt offsets to
|
|
282
|
-
* percent offsets. Defaults to US Letter.
|
|
283
|
-
*/
|
|
284
|
-
declare function applyCalibration(fields: FormField[], calibration: Calibration, pageSize?: [number, number]): FormField[];
|
|
285
|
-
interface FillPdfOptions {
|
|
286
|
-
/** Source PDF used as the background.
|
|
287
|
-
* - `string` (URL): fetched, embedded once per URL across the document.
|
|
288
|
-
* - `ArrayBuffer`: embedded uniquely each call.
|
|
289
|
-
* - `null`: render onto blank pages (overlay-only output). */
|
|
290
|
-
pdfSource: string | ArrayBuffer | null;
|
|
291
|
-
/** Fields to render on top of the background. */
|
|
292
|
-
fields: FormField[];
|
|
293
|
-
/** Override the output page size in PDF points.
|
|
294
|
-
* - With a `pdfSource`, source pages are drawn stretched to fit.
|
|
295
|
-
* - With `pdfSource: null`, blank pages of this size are created.
|
|
296
|
-
* - When omitted with a source, output uses the source's page sizes.
|
|
297
|
-
* - When omitted with `pdfSource: null`, defaults to US Letter. */
|
|
298
|
-
pageSize?: [number, number];
|
|
299
|
-
/** When `pdfSource` is null, how many blank pages to render. Default `1`.
|
|
300
|
-
* Fields with out-of-range `page` indices are skipped. */
|
|
301
|
-
pageCount?: number;
|
|
302
|
-
/** Run `resolveAllFormulas` on fields before rendering. */
|
|
303
|
-
resolveFormulas?: boolean;
|
|
304
|
-
/** Custom transforms merged with `BUILTIN_TRANSFORMS` during formula
|
|
305
|
-
* resolution. Only meaningful when `resolveFormulas` is true. */
|
|
306
|
-
customTransforms?: TransformMap;
|
|
307
|
-
/** Extra named values made available to formula sources (e.g. imported CSV/
|
|
308
|
-
* form data) even when there is no placed field for them. Only meaningful
|
|
309
|
-
* when `resolveFormulas` is true. */
|
|
310
|
-
formulaValues?: Record<string, string>;
|
|
311
|
-
/** Linear calibration applied to field positions before rendering. */
|
|
312
|
-
calibration?: Calibration;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Generates one filled PDF.
|
|
316
|
-
*
|
|
317
|
-
* const bytes = await generateFilledPdf({
|
|
318
|
-
* pdfSource: '/forms/template.pdf',
|
|
319
|
-
* fields: template.fields,
|
|
320
|
-
* pageSize: US_LETTER,
|
|
321
|
-
* resolveFormulas: true,
|
|
322
|
-
* });
|
|
323
|
-
*
|
|
324
|
-
* For multi-record output that shares a background, use `createPdfBuilder`
|
|
325
|
-
* — it dedupes the embedded source across all pages.
|
|
326
|
-
*/
|
|
327
|
-
declare function generateFilledPdf(opts: FillPdfOptions): Promise<Uint8Array>;
|
|
328
|
-
interface PdfBuilder {
|
|
329
|
-
/** Underlying pdf-lib document — exposed for advanced post-processing
|
|
330
|
-
* (audit-trail pages, custom metadata, etc.). */
|
|
331
|
-
readonly doc: PDFDocument;
|
|
332
|
-
/** Append one record's pages to the output. */
|
|
333
|
-
addRecord(opts: FillPdfOptions): Promise<void>;
|
|
334
|
-
/** Finalize and return the merged PDF bytes. */
|
|
335
|
-
save(): Promise<Uint8Array>;
|
|
336
|
-
}
|
|
337
|
-
interface CreatePdfBuilderOptions {
|
|
338
|
-
/** Default `pageSize` for any `addRecord` call that doesn't set its own. */
|
|
339
|
-
pageSize?: [number, number];
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Creates a builder that merges multiple filled records into one PDF.
|
|
343
|
-
*
|
|
344
|
-
* Resources (source PDFs indexed by URL, embedded fonts, signature PNGs) are
|
|
345
|
-
* embedded once across the whole document and reused — critical for
|
|
346
|
-
* mail-merge style batches where dozens of records share the same background.
|
|
347
|
-
*
|
|
348
|
-
* const builder = await createPdfBuilder({ pageSize: US_LETTER });
|
|
349
|
-
* for (const record of records) {
|
|
350
|
-
* await builder.addRecord({
|
|
351
|
-
* pdfSource: '/forms/template.pdf',
|
|
352
|
-
* fields: record.fields,
|
|
353
|
-
* resolveFormulas: true,
|
|
354
|
-
* });
|
|
355
|
-
* }
|
|
356
|
-
* const bytes = await builder.save();
|
|
357
|
-
* downloadPdf(bytes, 'merged.pdf');
|
|
358
|
-
*/
|
|
359
|
-
declare function createPdfBuilder(defaults?: CreatePdfBuilderOptions): Promise<PdfBuilder>;
|
|
360
|
-
declare function downloadPdf(bytes: Uint8Array, filename: string): void;
|
|
361
|
-
declare function postPdfToCallback(bytes: Uint8Array, callbackUrl: string, filename: string): Promise<void>;
|
|
362
|
-
|
|
363
|
-
export { A4, BUILTIN_TRANSFORMS, type Calibration, type CreatePdfBuilderOptions, DEFAULT_CALIBRATION, DEFAULT_SIGNER_ROLES, DesignerView, type DesignerViewProps, FIELD_DEFAULTS, FONT_FAMILIES, FieldNavigator, FieldPropertyPanel, type FieldType, type FillPdfOptions, type FormField, type PdfBuilder, PdfViewer, type RenderedPage, SIGNER_ROLE_COLORS, SignatureCanvas, SignerRoleSelector, SignerView, type SignerViewProps, type Template, type TextSubtype, type TransformFn, type TransformMap, US_LEGAL, US_LETTER, applyCalibration, createField, createPdfBuilder, downloadPdf, generateFilledPdf, generateId, getCssFontFamily, getFieldValues, getInputType, getSignerColor, isRedactField, isSignatureField, isTextLikeField, parseDate, postPdfToCallback, preserveFieldValues, renderPdfPages, resolveAllFormulas, resolveFormula, sortFieldsByPosition, uniqueLabel };
|
|
138
|
+
export { DesignerView, type DesignerViewProps, FieldNavigator, FieldPropertyPanel, FieldType, FormField, PdfViewer, type RenderedPage, SignatureCanvas, SignerRoleSelector, SignerView, type SignerViewProps, Template, TransformMap, renderPdfPages };
|
package/dist/index.js
CHANGED
|
@@ -2253,6 +2253,20 @@ var BUILTIN_TRANSFORMS = {
|
|
|
2253
2253
|
return parts[parts.length - 1] || "";
|
|
2254
2254
|
},
|
|
2255
2255
|
initials: (v) => v.split(/\s+/).map((w) => w[0] || "").join("").toUpperCase(),
|
|
2256
|
+
// Name parts. Handles "Last, First [Middle]" (comma form) and "First [Middle]
|
|
2257
|
+
// Last" (no comma). firstName → the given name(s); lastName → the surname.
|
|
2258
|
+
firstName: (v) => {
|
|
2259
|
+
const c = v.indexOf(",");
|
|
2260
|
+
if (c >= 0) return v.slice(c + 1).trim();
|
|
2261
|
+
const parts = v.trim().split(/\s+/).filter(Boolean);
|
|
2262
|
+
return parts.length > 1 ? parts.slice(0, -1).join(" ") : parts[0] || "";
|
|
2263
|
+
},
|
|
2264
|
+
lastName: (v) => {
|
|
2265
|
+
const c = v.indexOf(",");
|
|
2266
|
+
if (c >= 0) return v.slice(0, c).trim();
|
|
2267
|
+
const parts = v.trim().split(/\s+/).filter(Boolean);
|
|
2268
|
+
return parts.length > 1 ? parts[parts.length - 1] : parts[0] || "";
|
|
2269
|
+
},
|
|
2256
2270
|
// Numeric / substring
|
|
2257
2271
|
last4: (v) => v.slice(-4),
|
|
2258
2272
|
last2: (v) => v.slice(-2),
|
|
@@ -2477,11 +2491,24 @@ async function renderFieldsOnPages(pages, fields, getFont, getSignature) {
|
|
|
2477
2491
|
}
|
|
2478
2492
|
}
|
|
2479
2493
|
}
|
|
2480
|
-
async function generateFilledPdf(opts) {
|
|
2481
|
-
const builder = await createPdfBuilder({
|
|
2494
|
+
async function generateFilledPdf(opts, builderOptions) {
|
|
2495
|
+
const builder = await createPdfBuilder({
|
|
2496
|
+
pageSize: opts.pageSize,
|
|
2497
|
+
metadata: builderOptions?.metadata
|
|
2498
|
+
});
|
|
2482
2499
|
await builder.addRecord(opts);
|
|
2483
2500
|
return builder.save();
|
|
2484
2501
|
}
|
|
2502
|
+
function applyMetadata(doc, m) {
|
|
2503
|
+
if (!m) return;
|
|
2504
|
+
if (m.title !== void 0) doc.setTitle(m.title);
|
|
2505
|
+
if (m.author !== void 0) doc.setAuthor(m.author);
|
|
2506
|
+
if (m.subject !== void 0) doc.setSubject(m.subject);
|
|
2507
|
+
if (m.creator !== void 0) doc.setCreator(m.creator);
|
|
2508
|
+
if (m.producer !== void 0) doc.setProducer(m.producer);
|
|
2509
|
+
if (m.creationDate !== void 0) doc.setCreationDate(m.creationDate);
|
|
2510
|
+
if (m.modificationDate !== void 0) doc.setModificationDate(m.modificationDate);
|
|
2511
|
+
}
|
|
2485
2512
|
async function createPdfBuilder(defaults = {}) {
|
|
2486
2513
|
const doc = await import_pdf_lib.PDFDocument.create();
|
|
2487
2514
|
const fontCache = /* @__PURE__ */ new Map();
|
|
@@ -2566,6 +2593,7 @@ async function createPdfBuilder(defaults = {}) {
|
|
|
2566
2593
|
await renderFieldsOnPages(newPages, fields, getFont, getSignature);
|
|
2567
2594
|
},
|
|
2568
2595
|
async save() {
|
|
2596
|
+
applyMetadata(doc, defaults.metadata);
|
|
2569
2597
|
return doc.save();
|
|
2570
2598
|
}
|
|
2571
2599
|
};
|
|
@@ -2989,8 +3017,13 @@ ${row.join(",")}`, "csv");
|
|
|
2989
3017
|
if (isRedactField(field)) {
|
|
2990
3018
|
return null;
|
|
2991
3019
|
}
|
|
3020
|
+
const textStyle = {
|
|
3021
|
+
letterSpacing: field.letterSpacing ? `${field.letterSpacing}pt` : void 0,
|
|
3022
|
+
lineHeight: field.lineHeight ? `${field.lineHeight}` : void 0,
|
|
3023
|
+
...getCssTextStyle(field)
|
|
3024
|
+
};
|
|
2992
3025
|
if (field.formula) {
|
|
2993
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-value formula", style:
|
|
3026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-value formula", style: textStyle, children: field.value || "" });
|
|
2994
3027
|
}
|
|
2995
3028
|
const editable = field.assignee === signer;
|
|
2996
3029
|
if (!editable) {
|
|
@@ -3000,7 +3033,7 @@ ${row.join(",")}`, "csv");
|
|
|
3000
3033
|
if (field.type === "checkbox") {
|
|
3001
3034
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "field-checkbox-display readonly", children: field.value === "true" ? "\u2713" : "" });
|
|
3002
3035
|
}
|
|
3003
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-placeholder readonly", style:
|
|
3036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-placeholder readonly", style: textStyle, children: field.value || field.placeholder });
|
|
3004
3037
|
}
|
|
3005
3038
|
if (isSignatureField(field)) {
|
|
3006
3039
|
if (field.value) {
|
|
@@ -3022,13 +3055,8 @@ ${row.join(",")}`, "csv");
|
|
|
3022
3055
|
);
|
|
3023
3056
|
}
|
|
3024
3057
|
if (field.type === "signed-date") {
|
|
3025
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-value", style:
|
|
3058
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-value", style: textStyle, children: field.value || (/* @__PURE__ */ new Date()).toLocaleDateString() });
|
|
3026
3059
|
}
|
|
3027
|
-
const fontStyle = {
|
|
3028
|
-
letterSpacing: field.letterSpacing ? `${field.letterSpacing}pt` : void 0,
|
|
3029
|
-
lineHeight: field.lineHeight ? `${field.lineHeight}` : void 0,
|
|
3030
|
-
...getCssTextStyle(field)
|
|
3031
|
-
};
|
|
3032
3060
|
if (field.type === "dropdown" || field.options && field.options.length > 0) {
|
|
3033
3061
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3034
3062
|
"select",
|
|
@@ -3038,7 +3066,7 @@ ${row.join(",")}`, "csv");
|
|
|
3038
3066
|
onChange: (e) => handleFieldUpdate(field.id, e.target.value),
|
|
3039
3067
|
onFocus: () => setSelectedFieldId(field.id),
|
|
3040
3068
|
onClick: (e) => e.stopPropagation(),
|
|
3041
|
-
style: { fontSize: `${field.fontSize}pt`, ...
|
|
3069
|
+
style: { fontSize: `${field.fontSize}pt`, ...textStyle },
|
|
3042
3070
|
children: [
|
|
3043
3071
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: field.placeholder || "Select..." }),
|
|
3044
3072
|
(field.options || []).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: opt, children: opt }, opt))
|
|
@@ -3059,7 +3087,7 @@ ${row.join(",")}`, "csv");
|
|
|
3059
3087
|
onChange: (e) => handleFieldUpdate(field.id, e.target.value),
|
|
3060
3088
|
onFocus: () => setSelectedFieldId(field.id),
|
|
3061
3089
|
onClick: (e) => e.stopPropagation(),
|
|
3062
|
-
style:
|
|
3090
|
+
style: textStyle
|
|
3063
3091
|
}
|
|
3064
3092
|
);
|
|
3065
3093
|
}, [signer, handleFieldUpdate, setSelectedFieldId]);
|