@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 CHANGED
@@ -1,76 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { PDFDocument } from 'pdf-lib';
3
-
4
- declare function generateId(): string;
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
- /** US Letter in PDF points (72pt = 1 in). */
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 { PDFDocument } from 'pdf-lib';
3
-
4
- declare function generateId(): string;
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
- /** US Letter in PDF points (72pt = 1 in). */
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({ pageSize: opts.pageSize });
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: getCssTextStyle(field), children: field.value || "" });
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: getCssTextStyle(field), children: field.value || field.placeholder });
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: getCssTextStyle(field), children: field.value || (/* @__PURE__ */ new Date()).toLocaleDateString() });
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`, ...fontStyle },
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: fontStyle
3090
+ style: textStyle
3063
3091
  }
3064
3092
  );
3065
3093
  }, [signer, handleFieldUpdate, setSelectedFieldId]);