@unlev/exeq 0.5.0 → 0.5.2
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 +28 -4
- package/dist/index.d.ts +28 -4
- package/dist/index.js +108 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +107 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -344,6 +344,8 @@ function PdfViewer({
|
|
|
344
344
|
selectedIds: selectedFieldIds,
|
|
345
345
|
mode,
|
|
346
346
|
currentSigner,
|
|
347
|
+
pageWidthPt: page.pdfWidth,
|
|
348
|
+
pageHeightPt: page.pdfHeight,
|
|
347
349
|
renderContent: renderFieldContent
|
|
348
350
|
},
|
|
349
351
|
field.id
|
|
@@ -434,6 +436,8 @@ function FieldOverlayItem({
|
|
|
434
436
|
selectedIds,
|
|
435
437
|
mode,
|
|
436
438
|
currentSigner,
|
|
439
|
+
pageWidthPt,
|
|
440
|
+
pageHeightPt,
|
|
437
441
|
renderContent
|
|
438
442
|
}) {
|
|
439
443
|
const overlayRef = useRef(null);
|
|
@@ -560,7 +564,7 @@ function FieldOverlayItem({
|
|
|
560
564
|
onMouseDown: handleMouseDown,
|
|
561
565
|
children: [
|
|
562
566
|
mode === "designer" && !isRedact && /* @__PURE__ */ jsx("div", { className: "field-overlay-label", style: { backgroundColor: color }, children: field.label }),
|
|
563
|
-
renderContent ? renderContent(field) : /* @__PURE__ */ jsx("div", { className: "field-overlay-placeholder", children: field.value || field.placeholder }),
|
|
567
|
+
renderContent ? renderContent(field, pageWidthPt, pageHeightPt) : /* @__PURE__ */ jsx("div", { className: "field-overlay-placeholder", children: field.value || field.placeholder }),
|
|
564
568
|
mode === "designer" && isSelected && !field.locked && /* @__PURE__ */ jsx(
|
|
565
569
|
"div",
|
|
566
570
|
{
|
|
@@ -2093,39 +2097,56 @@ import {
|
|
|
2093
2097
|
} from "pdf-lib";
|
|
2094
2098
|
|
|
2095
2099
|
// src/utils/formulaResolver.ts
|
|
2100
|
+
function parseDate(value) {
|
|
2101
|
+
const s = value.trim();
|
|
2102
|
+
if (!s) return null;
|
|
2103
|
+
if (/^\d+(\.\d+)?$/.test(s)) {
|
|
2104
|
+
const serial = parseFloat(s);
|
|
2105
|
+
if (serial > 59) {
|
|
2106
|
+
const utc = new Date(Math.round((serial - 25569) * 864e5));
|
|
2107
|
+
if (!isNaN(utc.getTime())) {
|
|
2108
|
+
return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
const iso = s.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
2113
|
+
if (iso) return new Date(+iso[1], +iso[2] - 1, +iso[3]);
|
|
2114
|
+
const d = new Date(s);
|
|
2115
|
+
return isNaN(d.getTime()) ? null : d;
|
|
2116
|
+
}
|
|
2096
2117
|
var BUILTIN_TRANSFORMS = {
|
|
2097
2118
|
// Date transforms (expects a parseable date string)
|
|
2098
2119
|
month: (v) => {
|
|
2099
|
-
const d =
|
|
2100
|
-
return
|
|
2120
|
+
const d = parseDate(v);
|
|
2121
|
+
return d ? String(d.getMonth() + 1) : "";
|
|
2101
2122
|
},
|
|
2102
2123
|
month2: (v) => {
|
|
2103
|
-
const d =
|
|
2104
|
-
return
|
|
2124
|
+
const d = parseDate(v);
|
|
2125
|
+
return d ? String(d.getMonth() + 1).padStart(2, "0") : "";
|
|
2105
2126
|
},
|
|
2106
2127
|
monthname: (v) => {
|
|
2107
|
-
const d =
|
|
2108
|
-
return
|
|
2128
|
+
const d = parseDate(v);
|
|
2129
|
+
return d ? d.toLocaleString("en", { month: "long" }) : "";
|
|
2109
2130
|
},
|
|
2110
2131
|
monthshort: (v) => {
|
|
2111
|
-
const d =
|
|
2112
|
-
return
|
|
2132
|
+
const d = parseDate(v);
|
|
2133
|
+
return d ? d.toLocaleString("en", { month: "short" }) : "";
|
|
2113
2134
|
},
|
|
2114
2135
|
day: (v) => {
|
|
2115
|
-
const d =
|
|
2116
|
-
return
|
|
2136
|
+
const d = parseDate(v);
|
|
2137
|
+
return d ? String(d.getDate()) : "";
|
|
2117
2138
|
},
|
|
2118
2139
|
day2: (v) => {
|
|
2119
|
-
const d =
|
|
2120
|
-
return
|
|
2140
|
+
const d = parseDate(v);
|
|
2141
|
+
return d ? String(d.getDate()).padStart(2, "0") : "";
|
|
2121
2142
|
},
|
|
2122
2143
|
year: (v) => {
|
|
2123
|
-
const d =
|
|
2124
|
-
return
|
|
2144
|
+
const d = parseDate(v);
|
|
2145
|
+
return d ? String(d.getFullYear()) : "";
|
|
2125
2146
|
},
|
|
2126
2147
|
year2: (v) => {
|
|
2127
|
-
const d =
|
|
2128
|
-
return
|
|
2148
|
+
const d = parseDate(v);
|
|
2149
|
+
return d ? String(d.getFullYear()).slice(-2) : "";
|
|
2129
2150
|
},
|
|
2130
2151
|
// String transforms
|
|
2131
2152
|
upper: (v) => v.toUpperCase(),
|
|
@@ -2154,15 +2175,27 @@ var BUILTIN_TRANSFORMS = {
|
|
|
2154
2175
|
};
|
|
2155
2176
|
var FORMULA_RE = /\{\{(.+?)\}\}/g;
|
|
2156
2177
|
var PIPE_RE = /^(.+?)\s*\|\s*(.+)$/;
|
|
2157
|
-
function
|
|
2178
|
+
function todayIso() {
|
|
2179
|
+
const d = /* @__PURE__ */ new Date();
|
|
2180
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
2181
|
+
}
|
|
2182
|
+
function resolveFormula(formula, fields, customTransforms, values) {
|
|
2158
2183
|
const transforms = { ...BUILTIN_TRANSFORMS, ...customTransforms };
|
|
2159
2184
|
return formula.replace(FORMULA_RE, (_match, expr) => {
|
|
2160
2185
|
const pipeMatch = expr.match(PIPE_RE);
|
|
2161
2186
|
const sourceLabel = (pipeMatch ? pipeMatch[1] : expr).trim();
|
|
2162
2187
|
const transformName = pipeMatch ? pipeMatch[2].trim() : null;
|
|
2163
|
-
const
|
|
2164
|
-
|
|
2165
|
-
|
|
2188
|
+
const lowerLabel = sourceLabel.toLowerCase();
|
|
2189
|
+
const sourceField = fields.find((f) => f.label.toLowerCase() === lowerLabel) || fields.find((f) => f.id === sourceLabel);
|
|
2190
|
+
let rawValue = sourceField ? sourceField.value || "" : void 0;
|
|
2191
|
+
if (rawValue === void 0 && values) {
|
|
2192
|
+
const key = Object.keys(values).find((k) => k.toLowerCase() === lowerLabel);
|
|
2193
|
+
if (key !== void 0) rawValue = values[key] || "";
|
|
2194
|
+
}
|
|
2195
|
+
if (rawValue === void 0 && (lowerLabel === "today" || lowerLabel === "now")) {
|
|
2196
|
+
rawValue = todayIso();
|
|
2197
|
+
}
|
|
2198
|
+
if (rawValue === void 0) return "";
|
|
2166
2199
|
if (!transformName) return rawValue;
|
|
2167
2200
|
const fn = transforms[transformName];
|
|
2168
2201
|
if (!fn) return rawValue;
|
|
@@ -2173,14 +2206,38 @@ function resolveFormula(formula, fields, customTransforms) {
|
|
|
2173
2206
|
}
|
|
2174
2207
|
});
|
|
2175
2208
|
}
|
|
2176
|
-
function resolveAllFormulas(fields, customTransforms) {
|
|
2209
|
+
function resolveAllFormulas(fields, customTransforms, values) {
|
|
2177
2210
|
return fields.map((f) => {
|
|
2178
2211
|
if (!f.formula) return f;
|
|
2179
|
-
const computed = resolveFormula(f.formula, fields, customTransforms);
|
|
2212
|
+
const computed = resolveFormula(f.formula, fields, customTransforms, values);
|
|
2180
2213
|
return computed !== f.value ? { ...f, value: computed } : f;
|
|
2181
2214
|
});
|
|
2182
2215
|
}
|
|
2183
2216
|
|
|
2217
|
+
// src/utils/fitText.ts
|
|
2218
|
+
function fitFontSize(o) {
|
|
2219
|
+
let size = o.autoShrink ? Math.min(o.fontSize, o.fieldHeightPt * 0.7) : o.fontSize;
|
|
2220
|
+
if (o.autoShrink && o.value) {
|
|
2221
|
+
const padding = 4;
|
|
2222
|
+
while (size > 4) {
|
|
2223
|
+
if (o.measure(o.value, size) <= o.fieldWidthPt - padding) break;
|
|
2224
|
+
size -= 0.5;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
return size;
|
|
2228
|
+
}
|
|
2229
|
+
var measureCtx = null;
|
|
2230
|
+
function measureTextWidth(text, size, opts) {
|
|
2231
|
+
if (typeof document === "undefined") return text.length * size * 0.5;
|
|
2232
|
+
if (!measureCtx) measureCtx = document.createElement("canvas").getContext("2d");
|
|
2233
|
+
if (!measureCtx) return text.length * size * 0.5;
|
|
2234
|
+
const family = getCssFontFamily(opts?.fontFamily) || "Helvetica, Arial, sans-serif";
|
|
2235
|
+
measureCtx.font = `${opts?.italic ? "italic " : ""}${opts?.bold ? "bold " : ""}${size}px ${family}`;
|
|
2236
|
+
const base = measureCtx.measureText(text).width;
|
|
2237
|
+
const spacing = opts?.letterSpacing ? opts.letterSpacing * Math.max(0, text.length - 1) : 0;
|
|
2238
|
+
return base + spacing;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2184
2241
|
// src/utils/pdfFiller.ts
|
|
2185
2242
|
var FONT_VARIANTS = {
|
|
2186
2243
|
Helvetica: [StandardFonts.Helvetica, StandardFonts.HelveticaBold, StandardFonts.HelveticaOblique, StandardFonts.HelveticaBoldOblique],
|
|
@@ -2272,14 +2329,14 @@ async function renderFieldsOnPages(pages, fields, getFont, getSignature) {
|
|
|
2272
2329
|
const font = await getFont(field.fontFamily || "Helvetica", field.bold, field.italic);
|
|
2273
2330
|
const spacing = field.letterSpacing || 0;
|
|
2274
2331
|
const textWidthAtSize = (text, size) => font.widthOfTextAtSize(text, size) + spacing * (text.length - 1);
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
}
|
|
2332
|
+
const fontSize = fitFontSize({
|
|
2333
|
+
value: field.value,
|
|
2334
|
+
fontSize: field.fontSize,
|
|
2335
|
+
autoShrink: field.autoShrink,
|
|
2336
|
+
fieldWidthPt: w,
|
|
2337
|
+
fieldHeightPt: h,
|
|
2338
|
+
measure: textWidthAtSize
|
|
2339
|
+
});
|
|
2283
2340
|
const textX = x + 2;
|
|
2284
2341
|
const baselineY = y + h * 0.3;
|
|
2285
2342
|
if (spacing > 0) {
|
|
@@ -2383,7 +2440,7 @@ async function createPdfBuilder(defaults = {}) {
|
|
|
2383
2440
|
doc,
|
|
2384
2441
|
async addRecord(opts) {
|
|
2385
2442
|
const pageSize = opts.pageSize ?? defaults.pageSize;
|
|
2386
|
-
let fields = opts.resolveFormulas ? resolveAllFormulas(opts.fields, opts.customTransforms) : opts.fields;
|
|
2443
|
+
let fields = opts.resolveFormulas ? resolveAllFormulas(opts.fields, opts.customTransforms, opts.formulaValues) : opts.fields;
|
|
2387
2444
|
if (opts.calibration) {
|
|
2388
2445
|
fields = applyCalibration(
|
|
2389
2446
|
fields,
|
|
@@ -2784,7 +2841,7 @@ ${row.join(",")}`, "csv");
|
|
|
2784
2841
|
setSubmitting(false);
|
|
2785
2842
|
}
|
|
2786
2843
|
}, [pdfSource, fields, callbackUrl, allRequiredFilled, onComplete, isLastSigner, signer, onSignerComplete, includeAuditTrail, exportFormat, onExport, getValues, transforms]);
|
|
2787
|
-
const renderFieldContent = useCallback5((field) => {
|
|
2844
|
+
const renderFieldContent = useCallback5((field, pageWidthPt, pageHeightPt) => {
|
|
2788
2845
|
if (isRedactField(field)) {
|
|
2789
2846
|
return null;
|
|
2790
2847
|
}
|
|
@@ -2823,8 +2880,23 @@ ${row.join(",")}`, "csv");
|
|
|
2823
2880
|
if (field.type === "signed-date") {
|
|
2824
2881
|
return /* @__PURE__ */ jsx6("div", { className: "field-overlay-value", children: field.value || (/* @__PURE__ */ new Date()).toLocaleDateString() });
|
|
2825
2882
|
}
|
|
2883
|
+
const fieldWidthPt = pageWidthPt ? field.width / 100 * pageWidthPt : Infinity;
|
|
2884
|
+
const fieldHeightPt = pageHeightPt ? field.height / 100 * pageHeightPt : 0;
|
|
2885
|
+
const effectiveFontSize = pageWidthPt ? fitFontSize({
|
|
2886
|
+
value: field.value || "",
|
|
2887
|
+
fontSize: field.fontSize,
|
|
2888
|
+
autoShrink: field.autoShrink,
|
|
2889
|
+
fieldWidthPt,
|
|
2890
|
+
fieldHeightPt,
|
|
2891
|
+
measure: (t, s) => measureTextWidth(t, s, {
|
|
2892
|
+
fontFamily: field.fontFamily,
|
|
2893
|
+
bold: field.bold,
|
|
2894
|
+
italic: field.italic,
|
|
2895
|
+
letterSpacing: field.letterSpacing
|
|
2896
|
+
})
|
|
2897
|
+
}) : field.fontSize;
|
|
2826
2898
|
const fontStyle = {
|
|
2827
|
-
fontSize: `${
|
|
2899
|
+
fontSize: `${effectiveFontSize}pt`,
|
|
2828
2900
|
letterSpacing: field.letterSpacing ? `${field.letterSpacing}pt` : void 0,
|
|
2829
2901
|
lineHeight: field.lineHeight ? `${field.lineHeight}` : void 0,
|
|
2830
2902
|
...getCssTextStyle(field)
|
|
@@ -3105,6 +3177,7 @@ export {
|
|
|
3105
3177
|
isRedactField,
|
|
3106
3178
|
isSignatureField,
|
|
3107
3179
|
isTextLikeField,
|
|
3180
|
+
parseDate,
|
|
3108
3181
|
postPdfToCallback,
|
|
3109
3182
|
preserveFieldValues,
|
|
3110
3183
|
renderPdfPages,
|