@unlev/exeq 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -2
- package/dist/index.d.mts +116 -2
- package/dist/index.d.ts +116 -2
- package/dist/index.js +258 -143
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +257 -144
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,7 +30,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/lib/index.ts
|
|
31
31
|
var lib_exports = {};
|
|
32
32
|
__export(lib_exports, {
|
|
33
|
+
A4: () => A4,
|
|
33
34
|
BUILTIN_TRANSFORMS: () => BUILTIN_TRANSFORMS,
|
|
35
|
+
DEFAULT_CALIBRATION: () => DEFAULT_CALIBRATION,
|
|
34
36
|
DEFAULT_SIGNER_ROLES: () => DEFAULT_SIGNER_ROLES,
|
|
35
37
|
DesignerView: () => DesignerView,
|
|
36
38
|
FIELD_DEFAULTS: () => FIELD_DEFAULTS,
|
|
@@ -42,7 +44,11 @@ __export(lib_exports, {
|
|
|
42
44
|
SignatureCanvas: () => SignatureCanvas,
|
|
43
45
|
SignerRoleSelector: () => SignerRoleSelector,
|
|
44
46
|
SignerView: () => SignerView,
|
|
47
|
+
US_LEGAL: () => US_LEGAL,
|
|
48
|
+
US_LETTER: () => US_LETTER,
|
|
49
|
+
applyCalibration: () => applyCalibration,
|
|
45
50
|
createField: () => createField,
|
|
51
|
+
createPdfBuilder: () => createPdfBuilder,
|
|
46
52
|
downloadPdf: () => downloadPdf,
|
|
47
53
|
generateFilledPdf: () => generateFilledPdf,
|
|
48
54
|
generateId: () => generateId,
|
|
@@ -671,6 +677,13 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
671
677
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: "0", max: "9999", value: field.maxLength || 0, onChange: (e) => onUpdate(field.id, { maxLength: Number(e.target.value) }) })
|
|
672
678
|
] })
|
|
673
679
|
] }),
|
|
680
|
+
isTextField && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
681
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "panel-checkbox-label", children: [
|
|
682
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: field.autoShrink || false, onChange: (e) => onUpdate(field.id, { autoShrink: e.target.checked }) }),
|
|
683
|
+
"Auto-shrink to fit"
|
|
684
|
+
] }),
|
|
685
|
+
field.autoShrink && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "panel-hint", children: "Font size reduces to fit text within the field width" })
|
|
686
|
+
] }),
|
|
674
687
|
(field.type === "text" || field.type === "dropdown") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
675
688
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: field.type === "dropdown" ? "Options" : "Predefined Options" }),
|
|
676
689
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-options-list", children: [
|
|
@@ -2040,33 +2053,132 @@ var import_react7 = require("react");
|
|
|
2040
2053
|
|
|
2041
2054
|
// src/utils/pdfFiller.ts
|
|
2042
2055
|
var import_pdf_lib = require("pdf-lib");
|
|
2056
|
+
|
|
2057
|
+
// src/utils/formulaResolver.ts
|
|
2058
|
+
var BUILTIN_TRANSFORMS = {
|
|
2059
|
+
// Date transforms (expects a parseable date string)
|
|
2060
|
+
month: (v) => {
|
|
2061
|
+
const d = new Date(v);
|
|
2062
|
+
return isNaN(d.getTime()) ? "" : String(d.getMonth() + 1);
|
|
2063
|
+
},
|
|
2064
|
+
month2: (v) => {
|
|
2065
|
+
const d = new Date(v);
|
|
2066
|
+
return isNaN(d.getTime()) ? "" : String(d.getMonth() + 1).padStart(2, "0");
|
|
2067
|
+
},
|
|
2068
|
+
monthname: (v) => {
|
|
2069
|
+
const d = new Date(v);
|
|
2070
|
+
return isNaN(d.getTime()) ? "" : d.toLocaleString("en", { month: "long" });
|
|
2071
|
+
},
|
|
2072
|
+
monthshort: (v) => {
|
|
2073
|
+
const d = new Date(v);
|
|
2074
|
+
return isNaN(d.getTime()) ? "" : d.toLocaleString("en", { month: "short" });
|
|
2075
|
+
},
|
|
2076
|
+
day: (v) => {
|
|
2077
|
+
const d = new Date(v);
|
|
2078
|
+
return isNaN(d.getTime()) ? "" : String(d.getDate());
|
|
2079
|
+
},
|
|
2080
|
+
day2: (v) => {
|
|
2081
|
+
const d = new Date(v);
|
|
2082
|
+
return isNaN(d.getTime()) ? "" : String(d.getDate()).padStart(2, "0");
|
|
2083
|
+
},
|
|
2084
|
+
year: (v) => {
|
|
2085
|
+
const d = new Date(v);
|
|
2086
|
+
return isNaN(d.getTime()) ? "" : String(d.getFullYear());
|
|
2087
|
+
},
|
|
2088
|
+
year2: (v) => {
|
|
2089
|
+
const d = new Date(v);
|
|
2090
|
+
return isNaN(d.getTime()) ? "" : String(d.getFullYear()).slice(-2);
|
|
2091
|
+
},
|
|
2092
|
+
// String transforms
|
|
2093
|
+
upper: (v) => v.toUpperCase(),
|
|
2094
|
+
lower: (v) => v.toLowerCase(),
|
|
2095
|
+
trim: (v) => v.trim(),
|
|
2096
|
+
first: (v) => v.split(/\s+/)[0] || "",
|
|
2097
|
+
last: (v) => {
|
|
2098
|
+
const parts = v.split(/\s+/);
|
|
2099
|
+
return parts[parts.length - 1] || "";
|
|
2100
|
+
},
|
|
2101
|
+
initials: (v) => v.split(/\s+/).map((w) => w[0] || "").join("").toUpperCase(),
|
|
2102
|
+
// Numeric / substring
|
|
2103
|
+
last4: (v) => v.slice(-4),
|
|
2104
|
+
last2: (v) => v.slice(-2),
|
|
2105
|
+
first4: (v) => v.slice(0, 4),
|
|
2106
|
+
first2: (v) => v.slice(0, 2),
|
|
2107
|
+
digits: (v) => v.replace(/\D/g, ""),
|
|
2108
|
+
number: (v) => {
|
|
2109
|
+
const n = parseFloat(v);
|
|
2110
|
+
return isNaN(n) ? "" : String(n);
|
|
2111
|
+
},
|
|
2112
|
+
currency: (v) => {
|
|
2113
|
+
const n = parseFloat(v.replace(/[^0-9.-]/g, ""));
|
|
2114
|
+
return isNaN(n) ? "" : `$${n.toFixed(2)}`;
|
|
2115
|
+
}
|
|
2116
|
+
};
|
|
2117
|
+
var FORMULA_RE = /\{\{(.+?)\}\}/g;
|
|
2118
|
+
var PIPE_RE = /^(.+?)\s*\|\s*(.+)$/;
|
|
2119
|
+
function resolveFormula(formula, fields, customTransforms) {
|
|
2120
|
+
const transforms = { ...BUILTIN_TRANSFORMS, ...customTransforms };
|
|
2121
|
+
return formula.replace(FORMULA_RE, (_match, expr) => {
|
|
2122
|
+
const pipeMatch = expr.match(PIPE_RE);
|
|
2123
|
+
const sourceLabel = (pipeMatch ? pipeMatch[1] : expr).trim();
|
|
2124
|
+
const transformName = pipeMatch ? pipeMatch[2].trim() : null;
|
|
2125
|
+
const sourceField = fields.find((f) => f.label.toLowerCase() === sourceLabel.toLowerCase()) || fields.find((f) => f.id === sourceLabel);
|
|
2126
|
+
if (!sourceField) return "";
|
|
2127
|
+
const rawValue = sourceField.value || "";
|
|
2128
|
+
if (!transformName) return rawValue;
|
|
2129
|
+
const fn = transforms[transformName];
|
|
2130
|
+
if (!fn) return rawValue;
|
|
2131
|
+
try {
|
|
2132
|
+
return fn(rawValue);
|
|
2133
|
+
} catch {
|
|
2134
|
+
return rawValue;
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
function resolveAllFormulas(fields, customTransforms) {
|
|
2139
|
+
return fields.map((f) => {
|
|
2140
|
+
if (!f.formula) return f;
|
|
2141
|
+
const computed = resolveFormula(f.formula, fields, customTransforms);
|
|
2142
|
+
return computed !== f.value ? { ...f, value: computed } : f;
|
|
2143
|
+
});
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// src/utils/pdfFiller.ts
|
|
2043
2147
|
var FONT_MAP = {
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2148
|
+
Helvetica: import_pdf_lib.StandardFonts.Helvetica,
|
|
2149
|
+
Courier: import_pdf_lib.StandardFonts.Courier,
|
|
2150
|
+
TimesRoman: import_pdf_lib.StandardFonts.TimesRoman
|
|
2047
2151
|
};
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
const stdFont = FONT_MAP[key] || import_pdf_lib.StandardFonts.Helvetica;
|
|
2061
|
-
fontCache.set(key, await pdfDoc.embedFont(stdFont));
|
|
2062
|
-
}
|
|
2063
|
-
const pages = pdfDoc.getPages();
|
|
2064
|
-
function hexToRgb(hex) {
|
|
2065
|
-
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
2066
|
-
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
2067
|
-
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
2068
|
-
return (0, import_pdf_lib.rgb)(r, g, b);
|
|
2152
|
+
var US_LETTER = [612, 792];
|
|
2153
|
+
var US_LEGAL = [612, 1008];
|
|
2154
|
+
var A4 = [595.28, 841.89];
|
|
2155
|
+
var DEFAULT_CALIBRATION = {
|
|
2156
|
+
xOffset: 0,
|
|
2157
|
+
yOffset: 0,
|
|
2158
|
+
xScale: 1,
|
|
2159
|
+
yScale: 1
|
|
2160
|
+
};
|
|
2161
|
+
function applyCalibration(fields, calibration, pageSize = US_LETTER) {
|
|
2162
|
+
if (calibration.xOffset === 0 && calibration.yOffset === 0 && calibration.xScale === 1 && calibration.yScale === 1) {
|
|
2163
|
+
return fields;
|
|
2069
2164
|
}
|
|
2165
|
+
const xPctOff = calibration.xOffset / pageSize[0] * 100;
|
|
2166
|
+
const yPctOff = calibration.yOffset / pageSize[1] * 100;
|
|
2167
|
+
return fields.map((f) => ({
|
|
2168
|
+
...f,
|
|
2169
|
+
x: f.x * calibration.xScale + xPctOff,
|
|
2170
|
+
y: f.y * calibration.yScale + yPctOff,
|
|
2171
|
+
width: f.width * calibration.xScale,
|
|
2172
|
+
height: f.height * calibration.yScale
|
|
2173
|
+
}));
|
|
2174
|
+
}
|
|
2175
|
+
function hexToRgb(hex) {
|
|
2176
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
2177
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
2178
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
2179
|
+
return (0, import_pdf_lib.rgb)(r, g, b);
|
|
2180
|
+
}
|
|
2181
|
+
async function renderFieldsOnPages(pages, fields, getFont, getSignature) {
|
|
2070
2182
|
for (const field of fields) {
|
|
2071
2183
|
const page = pages[field.page];
|
|
2072
2184
|
if (!page) continue;
|
|
@@ -2107,37 +2219,32 @@ async function generateFilledPdf(pdfSource, fields) {
|
|
|
2107
2219
|
}
|
|
2108
2220
|
} else if (field.type === "signature" || field.type === "initials") {
|
|
2109
2221
|
if (field.value.startsWith("data:image/png")) {
|
|
2110
|
-
const
|
|
2111
|
-
|
|
2112
|
-
(c) => c.charCodeAt(0)
|
|
2113
|
-
);
|
|
2114
|
-
const pngImage = await pdfDoc.embedPng(pngBytes);
|
|
2115
|
-
page.drawImage(pngImage, {
|
|
2116
|
-
x,
|
|
2117
|
-
y,
|
|
2118
|
-
width: w,
|
|
2119
|
-
height: h
|
|
2120
|
-
});
|
|
2222
|
+
const img = await getSignature(field.value);
|
|
2223
|
+
page.drawImage(img, { x, y, width: w, height: h });
|
|
2121
2224
|
}
|
|
2122
2225
|
} else {
|
|
2123
|
-
const font =
|
|
2226
|
+
const font = await getFont(field.fontFamily || "Helvetica");
|
|
2124
2227
|
const spacing = field.letterSpacing || 0;
|
|
2125
|
-
const textWidthAtSize = (text, size) =>
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
if (textWidthAtSize(field.value, fontSize) <= w - padding) break;
|
|
2134
|
-
fontSize -= 0.5;
|
|
2228
|
+
const textWidthAtSize = (text, size) => font.widthOfTextAtSize(text, size) + spacing * (text.length - 1);
|
|
2229
|
+
let fontSize = field.autoShrink ? Math.min(field.fontSize, h * 0.7) : field.fontSize;
|
|
2230
|
+
if (field.autoShrink) {
|
|
2231
|
+
const padding = 4;
|
|
2232
|
+
while (fontSize > 4) {
|
|
2233
|
+
if (textWidthAtSize(field.value, fontSize) <= w - padding) break;
|
|
2234
|
+
fontSize -= 0.5;
|
|
2235
|
+
}
|
|
2135
2236
|
}
|
|
2136
2237
|
if (spacing > 0) {
|
|
2137
2238
|
let cx = x + 2;
|
|
2138
2239
|
const cy = y + h * 0.3;
|
|
2139
2240
|
for (const char of field.value) {
|
|
2140
|
-
page.drawText(char, {
|
|
2241
|
+
page.drawText(char, {
|
|
2242
|
+
x: cx,
|
|
2243
|
+
y: cy,
|
|
2244
|
+
size: fontSize,
|
|
2245
|
+
font,
|
|
2246
|
+
color: inkColor
|
|
2247
|
+
});
|
|
2141
2248
|
cx += font.widthOfTextAtSize(char, fontSize) + spacing;
|
|
2142
2249
|
}
|
|
2143
2250
|
} else {
|
|
@@ -2151,7 +2258,98 @@ async function generateFilledPdf(pdfSource, fields) {
|
|
|
2151
2258
|
}
|
|
2152
2259
|
}
|
|
2153
2260
|
}
|
|
2154
|
-
|
|
2261
|
+
}
|
|
2262
|
+
async function generateFilledPdf(opts) {
|
|
2263
|
+
const builder = await createPdfBuilder({ pageSize: opts.pageSize });
|
|
2264
|
+
await builder.addRecord(opts);
|
|
2265
|
+
return builder.save();
|
|
2266
|
+
}
|
|
2267
|
+
async function createPdfBuilder(defaults = {}) {
|
|
2268
|
+
const doc = await import_pdf_lib.PDFDocument.create();
|
|
2269
|
+
const fontCache = /* @__PURE__ */ new Map();
|
|
2270
|
+
const embeddedPagesByUrl = /* @__PURE__ */ new Map();
|
|
2271
|
+
const signatureCache = /* @__PURE__ */ new Map();
|
|
2272
|
+
async function getFont(family) {
|
|
2273
|
+
let f = fontCache.get(family);
|
|
2274
|
+
if (!f) {
|
|
2275
|
+
const stdName = FONT_MAP[family] || import_pdf_lib.StandardFonts.Helvetica;
|
|
2276
|
+
f = await doc.embedFont(stdName);
|
|
2277
|
+
fontCache.set(family, f);
|
|
2278
|
+
}
|
|
2279
|
+
return f;
|
|
2280
|
+
}
|
|
2281
|
+
async function ensureFonts(fields) {
|
|
2282
|
+
const keys = new Set(fields.map((f) => f.fontFamily || "Helvetica"));
|
|
2283
|
+
for (const k of keys) await getFont(k);
|
|
2284
|
+
}
|
|
2285
|
+
async function embedSource(source) {
|
|
2286
|
+
if (typeof source === "string") {
|
|
2287
|
+
let pages = embeddedPagesByUrl.get(source);
|
|
2288
|
+
if (!pages) {
|
|
2289
|
+
const res = await fetch(source);
|
|
2290
|
+
const bytes = await res.arrayBuffer();
|
|
2291
|
+
const srcDoc2 = await import_pdf_lib.PDFDocument.load(bytes);
|
|
2292
|
+
pages = await Promise.all(
|
|
2293
|
+
srcDoc2.getPages().map((p) => doc.embedPage(p))
|
|
2294
|
+
);
|
|
2295
|
+
embeddedPagesByUrl.set(source, pages);
|
|
2296
|
+
}
|
|
2297
|
+
return pages;
|
|
2298
|
+
}
|
|
2299
|
+
const srcDoc = await import_pdf_lib.PDFDocument.load(source);
|
|
2300
|
+
return Promise.all(srcDoc.getPages().map((p) => doc.embedPage(p)));
|
|
2301
|
+
}
|
|
2302
|
+
async function getSignature(dataUrl) {
|
|
2303
|
+
let img = signatureCache.get(dataUrl);
|
|
2304
|
+
if (!img) {
|
|
2305
|
+
const b64 = dataUrl.split(",")[1] ?? "";
|
|
2306
|
+
const pngBytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
2307
|
+
img = await doc.embedPng(pngBytes);
|
|
2308
|
+
signatureCache.set(dataUrl, img);
|
|
2309
|
+
}
|
|
2310
|
+
return img;
|
|
2311
|
+
}
|
|
2312
|
+
return {
|
|
2313
|
+
doc,
|
|
2314
|
+
async addRecord(opts) {
|
|
2315
|
+
const pageSize = opts.pageSize ?? defaults.pageSize;
|
|
2316
|
+
let fields = opts.resolveFormulas ? resolveAllFormulas(opts.fields, opts.customTransforms) : opts.fields;
|
|
2317
|
+
if (opts.calibration) {
|
|
2318
|
+
fields = applyCalibration(
|
|
2319
|
+
fields,
|
|
2320
|
+
opts.calibration,
|
|
2321
|
+
pageSize ?? US_LETTER
|
|
2322
|
+
);
|
|
2323
|
+
}
|
|
2324
|
+
await ensureFonts(fields);
|
|
2325
|
+
let sourcePages = [];
|
|
2326
|
+
let pageCount;
|
|
2327
|
+
if (opts.pdfSource !== null) {
|
|
2328
|
+
sourcePages = await embedSource(opts.pdfSource);
|
|
2329
|
+
pageCount = sourcePages.length;
|
|
2330
|
+
} else {
|
|
2331
|
+
pageCount = opts.pageCount ?? 1;
|
|
2332
|
+
}
|
|
2333
|
+
const newPages = [];
|
|
2334
|
+
for (let i = 0; i < pageCount; i++) {
|
|
2335
|
+
const size = pageSize ? pageSize : sourcePages[i] ? [sourcePages[i].width, sourcePages[i].height] : US_LETTER;
|
|
2336
|
+
const page = doc.addPage(size);
|
|
2337
|
+
newPages.push(page);
|
|
2338
|
+
if (sourcePages[i]) {
|
|
2339
|
+
page.drawPage(sourcePages[i], {
|
|
2340
|
+
x: 0,
|
|
2341
|
+
y: 0,
|
|
2342
|
+
width: size[0],
|
|
2343
|
+
height: size[1]
|
|
2344
|
+
});
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
await renderFieldsOnPages(newPages, fields, getFont, getSignature);
|
|
2348
|
+
},
|
|
2349
|
+
async save() {
|
|
2350
|
+
return doc.save();
|
|
2351
|
+
}
|
|
2352
|
+
};
|
|
2155
2353
|
}
|
|
2156
2354
|
function downloadPdf(bytes, filename) {
|
|
2157
2355
|
const blob = new Blob([bytes.slice().buffer], { type: "application/pdf" });
|
|
@@ -2263,95 +2461,6 @@ function FieldNavigator({
|
|
|
2263
2461
|
] });
|
|
2264
2462
|
}
|
|
2265
2463
|
|
|
2266
|
-
// src/utils/formulaResolver.ts
|
|
2267
|
-
var BUILTIN_TRANSFORMS = {
|
|
2268
|
-
// Date transforms (expects a parseable date string)
|
|
2269
|
-
month: (v) => {
|
|
2270
|
-
const d = new Date(v);
|
|
2271
|
-
return isNaN(d.getTime()) ? "" : String(d.getMonth() + 1);
|
|
2272
|
-
},
|
|
2273
|
-
month2: (v) => {
|
|
2274
|
-
const d = new Date(v);
|
|
2275
|
-
return isNaN(d.getTime()) ? "" : String(d.getMonth() + 1).padStart(2, "0");
|
|
2276
|
-
},
|
|
2277
|
-
monthname: (v) => {
|
|
2278
|
-
const d = new Date(v);
|
|
2279
|
-
return isNaN(d.getTime()) ? "" : d.toLocaleString("en", { month: "long" });
|
|
2280
|
-
},
|
|
2281
|
-
monthshort: (v) => {
|
|
2282
|
-
const d = new Date(v);
|
|
2283
|
-
return isNaN(d.getTime()) ? "" : d.toLocaleString("en", { month: "short" });
|
|
2284
|
-
},
|
|
2285
|
-
day: (v) => {
|
|
2286
|
-
const d = new Date(v);
|
|
2287
|
-
return isNaN(d.getTime()) ? "" : String(d.getDate());
|
|
2288
|
-
},
|
|
2289
|
-
day2: (v) => {
|
|
2290
|
-
const d = new Date(v);
|
|
2291
|
-
return isNaN(d.getTime()) ? "" : String(d.getDate()).padStart(2, "0");
|
|
2292
|
-
},
|
|
2293
|
-
year: (v) => {
|
|
2294
|
-
const d = new Date(v);
|
|
2295
|
-
return isNaN(d.getTime()) ? "" : String(d.getFullYear());
|
|
2296
|
-
},
|
|
2297
|
-
year2: (v) => {
|
|
2298
|
-
const d = new Date(v);
|
|
2299
|
-
return isNaN(d.getTime()) ? "" : String(d.getFullYear()).slice(-2);
|
|
2300
|
-
},
|
|
2301
|
-
// String transforms
|
|
2302
|
-
upper: (v) => v.toUpperCase(),
|
|
2303
|
-
lower: (v) => v.toLowerCase(),
|
|
2304
|
-
trim: (v) => v.trim(),
|
|
2305
|
-
first: (v) => v.split(/\s+/)[0] || "",
|
|
2306
|
-
last: (v) => {
|
|
2307
|
-
const parts = v.split(/\s+/);
|
|
2308
|
-
return parts[parts.length - 1] || "";
|
|
2309
|
-
},
|
|
2310
|
-
initials: (v) => v.split(/\s+/).map((w) => w[0] || "").join("").toUpperCase(),
|
|
2311
|
-
// Numeric / substring
|
|
2312
|
-
last4: (v) => v.slice(-4),
|
|
2313
|
-
last2: (v) => v.slice(-2),
|
|
2314
|
-
first4: (v) => v.slice(0, 4),
|
|
2315
|
-
first2: (v) => v.slice(0, 2),
|
|
2316
|
-
digits: (v) => v.replace(/\D/g, ""),
|
|
2317
|
-
number: (v) => {
|
|
2318
|
-
const n = parseFloat(v);
|
|
2319
|
-
return isNaN(n) ? "" : String(n);
|
|
2320
|
-
},
|
|
2321
|
-
currency: (v) => {
|
|
2322
|
-
const n = parseFloat(v.replace(/[^0-9.-]/g, ""));
|
|
2323
|
-
return isNaN(n) ? "" : `$${n.toFixed(2)}`;
|
|
2324
|
-
}
|
|
2325
|
-
};
|
|
2326
|
-
var FORMULA_RE = /\{\{(.+?)\}\}/g;
|
|
2327
|
-
var PIPE_RE = /^(.+?)\s*\|\s*(.+)$/;
|
|
2328
|
-
function resolveFormula(formula, fields, customTransforms) {
|
|
2329
|
-
const transforms = { ...BUILTIN_TRANSFORMS, ...customTransforms };
|
|
2330
|
-
return formula.replace(FORMULA_RE, (_match, expr) => {
|
|
2331
|
-
const pipeMatch = expr.match(PIPE_RE);
|
|
2332
|
-
const sourceLabel = (pipeMatch ? pipeMatch[1] : expr).trim();
|
|
2333
|
-
const transformName = pipeMatch ? pipeMatch[2].trim() : null;
|
|
2334
|
-
const sourceField = fields.find((f) => f.label.toLowerCase() === sourceLabel.toLowerCase()) || fields.find((f) => f.id === sourceLabel);
|
|
2335
|
-
if (!sourceField) return "";
|
|
2336
|
-
const rawValue = sourceField.value || "";
|
|
2337
|
-
if (!transformName) return rawValue;
|
|
2338
|
-
const fn = transforms[transformName];
|
|
2339
|
-
if (!fn) return rawValue;
|
|
2340
|
-
try {
|
|
2341
|
-
return fn(rawValue);
|
|
2342
|
-
} catch {
|
|
2343
|
-
return rawValue;
|
|
2344
|
-
}
|
|
2345
|
-
});
|
|
2346
|
-
}
|
|
2347
|
-
function resolveAllFormulas(fields, customTransforms) {
|
|
2348
|
-
return fields.map((f) => {
|
|
2349
|
-
if (!f.formula) return f;
|
|
2350
|
-
const computed = resolveFormula(f.formula, fields, customTransforms);
|
|
2351
|
-
return computed !== f.value ? { ...f, value: computed } : f;
|
|
2352
|
-
});
|
|
2353
|
-
}
|
|
2354
|
-
|
|
2355
2464
|
// src/components/pdf-builder/SignerView.tsx
|
|
2356
2465
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2357
2466
|
function SignerView({
|
|
@@ -2569,7 +2678,7 @@ function SignerView({
|
|
|
2569
2678
|
let pdfBytes;
|
|
2570
2679
|
if (includeAuditTrail) {
|
|
2571
2680
|
const { PDFDocument: PDFDocument2, StandardFonts: StandardFonts2, rgb: rgb2 } = await import("pdf-lib");
|
|
2572
|
-
const basePdf = await generateFilledPdf(pdfSource, finalFields);
|
|
2681
|
+
const basePdf = await generateFilledPdf({ pdfSource, fields: finalFields });
|
|
2573
2682
|
const pdfDoc = await PDFDocument2.load(basePdf);
|
|
2574
2683
|
const font = await pdfDoc.embedFont(StandardFonts2.Helvetica);
|
|
2575
2684
|
const boldFont = await pdfDoc.embedFont(StandardFonts2.HelveticaBold);
|
|
@@ -2586,7 +2695,7 @@ function SignerView({
|
|
|
2586
2695
|
}
|
|
2587
2696
|
pdfBytes = await pdfDoc.save();
|
|
2588
2697
|
} else {
|
|
2589
|
-
pdfBytes = await generateFilledPdf(pdfSource, finalFields);
|
|
2698
|
+
pdfBytes = await generateFilledPdf({ pdfSource, fields: finalFields });
|
|
2590
2699
|
}
|
|
2591
2700
|
const blob = new Blob([pdfBytes.slice().buffer], { type: "application/pdf" });
|
|
2592
2701
|
if (onExport && exportFormat) {
|
|
@@ -2694,9 +2803,9 @@ ${row.join(",")}`, "csv");
|
|
|
2694
2803
|
);
|
|
2695
2804
|
}, [signer, handleFieldUpdate, setSelectedFieldId]);
|
|
2696
2805
|
(0, import_react7.useEffect)(() => {
|
|
2697
|
-
const
|
|
2698
|
-
|
|
2699
|
-
|
|
2806
|
+
const dateStr = (/* @__PURE__ */ new Date()).toLocaleDateString();
|
|
2807
|
+
const needsFill = fields.some((f) => f.assignee === signer && f.type === "signed-date" && !f.value);
|
|
2808
|
+
if (needsFill) {
|
|
2700
2809
|
setFields((prev) => prev.map((f) => {
|
|
2701
2810
|
if (f.assignee === signer && f.type === "signed-date" && !f.value) {
|
|
2702
2811
|
return { ...f, value: dateStr };
|
|
@@ -2704,7 +2813,7 @@ ${row.join(",")}`, "csv");
|
|
|
2704
2813
|
return f;
|
|
2705
2814
|
}));
|
|
2706
2815
|
}
|
|
2707
|
-
}, [fields.filter((f) => f.type === "signature" && f.value).length]);
|
|
2816
|
+
}, [signer, fields.filter((f) => f.type === "signature" && f.value).length]);
|
|
2708
2817
|
(0, import_react7.useEffect)(() => {
|
|
2709
2818
|
const hasFormulas = fields.some((f) => f.formula);
|
|
2710
2819
|
if (!hasFormulas) return;
|
|
@@ -2909,7 +3018,9 @@ function SignerRoleSelector({
|
|
|
2909
3018
|
}
|
|
2910
3019
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2911
3020
|
0 && (module.exports = {
|
|
3021
|
+
A4,
|
|
2912
3022
|
BUILTIN_TRANSFORMS,
|
|
3023
|
+
DEFAULT_CALIBRATION,
|
|
2913
3024
|
DEFAULT_SIGNER_ROLES,
|
|
2914
3025
|
DesignerView,
|
|
2915
3026
|
FIELD_DEFAULTS,
|
|
@@ -2921,7 +3032,11 @@ function SignerRoleSelector({
|
|
|
2921
3032
|
SignatureCanvas,
|
|
2922
3033
|
SignerRoleSelector,
|
|
2923
3034
|
SignerView,
|
|
3035
|
+
US_LEGAL,
|
|
3036
|
+
US_LETTER,
|
|
3037
|
+
applyCalibration,
|
|
2924
3038
|
createField,
|
|
3039
|
+
createPdfBuilder,
|
|
2925
3040
|
downloadPdf,
|
|
2926
3041
|
generateFilledPdf,
|
|
2927
3042
|
generateId,
|