@unlev/exeq 0.5.4 → 0.5.6
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.css +5 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +73 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -60,11 +60,17 @@ function getCssTextStyle(field) {
|
|
|
60
60
|
const decorations = [];
|
|
61
61
|
if (field.underline) decorations.push("underline");
|
|
62
62
|
if (field.strikethrough) decorations.push("line-through");
|
|
63
|
+
const align = field.align ?? "left";
|
|
63
64
|
return {
|
|
64
65
|
fontFamily: getCssFontFamily(field.fontFamily),
|
|
65
66
|
fontWeight: field.bold ? "bold" : void 0,
|
|
66
67
|
fontStyle: field.italic ? "italic" : void 0,
|
|
67
|
-
textDecorationLine: decorations.length ? decorations.join(" ") : void 0
|
|
68
|
+
textDecorationLine: decorations.length ? decorations.join(" ") : void 0,
|
|
69
|
+
textAlign: field.align,
|
|
70
|
+
// Hug the alignment edge — no padding on the trailing side — so text reaches
|
|
71
|
+
// the container edge (matches the PDF's 2pt offsets).
|
|
72
|
+
paddingLeft: align === "right" ? "0px" : "2px",
|
|
73
|
+
paddingRight: align === "left" ? "0px" : "2px"
|
|
68
74
|
};
|
|
69
75
|
}
|
|
70
76
|
function sortFieldsByPosition(fields) {
|
|
@@ -735,6 +741,27 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
735
741
|
/* @__PURE__ */ jsx2("button", { type: "button", className: `text-format-btn ${field.strikethrough ? "active" : ""}`, style: { textDecorationLine: "line-through" }, title: "Strikethrough", onClick: () => onUpdate(field.id, { strikethrough: !field.strikethrough }), children: "S" })
|
|
736
742
|
] })
|
|
737
743
|
] }),
|
|
744
|
+
isText && /* @__PURE__ */ jsxs2("div", { className: "panel-field", children: [
|
|
745
|
+
/* @__PURE__ */ jsx2("label", { children: "Alignment" }),
|
|
746
|
+
/* @__PURE__ */ jsx2("div", { className: "text-format-buttons", children: [
|
|
747
|
+
["left", "Left", "\u2AF7"],
|
|
748
|
+
["center", "Center", "\u2261"],
|
|
749
|
+
["right", "Right", "\u2AF8"]
|
|
750
|
+
].map(([value, label, glyph]) => {
|
|
751
|
+
const active = (field.align || "left") === value;
|
|
752
|
+
return /* @__PURE__ */ jsx2(
|
|
753
|
+
"button",
|
|
754
|
+
{
|
|
755
|
+
type: "button",
|
|
756
|
+
className: `text-format-btn ${active ? "active" : ""}`,
|
|
757
|
+
title: `Align ${label}`,
|
|
758
|
+
onClick: () => onUpdate(field.id, { align: value === "left" ? void 0 : value }),
|
|
759
|
+
children: glyph
|
|
760
|
+
},
|
|
761
|
+
value
|
|
762
|
+
);
|
|
763
|
+
}) })
|
|
764
|
+
] }),
|
|
738
765
|
isText && /* @__PURE__ */ jsxs2("div", { className: "panel-field-row", children: [
|
|
739
766
|
/* @__PURE__ */ jsxs2("div", { className: "panel-field panel-field-half", children: [
|
|
740
767
|
/* @__PURE__ */ jsx2("label", { children: "Letter Spacing" }),
|
|
@@ -2187,11 +2214,17 @@ function resolveFormula(formula, fields, customTransforms, values) {
|
|
|
2187
2214
|
const transformName = pipeMatch ? pipeMatch[2].trim() : null;
|
|
2188
2215
|
const lowerLabel = sourceLabel.toLowerCase();
|
|
2189
2216
|
const sourceField = fields.find((f) => f.label.toLowerCase() === lowerLabel) || fields.find((f) => f.id === sourceLabel);
|
|
2190
|
-
let rawValue
|
|
2217
|
+
let rawValue;
|
|
2218
|
+
if (sourceField && sourceField.value) {
|
|
2219
|
+
rawValue = sourceField.value;
|
|
2220
|
+
}
|
|
2191
2221
|
if (rawValue === void 0 && values) {
|
|
2192
2222
|
const key = Object.keys(values).find((k) => k.toLowerCase() === lowerLabel);
|
|
2193
2223
|
if (key !== void 0) rawValue = values[key] || "";
|
|
2194
2224
|
}
|
|
2225
|
+
if (rawValue === void 0 && sourceField) {
|
|
2226
|
+
rawValue = sourceField.value || "";
|
|
2227
|
+
}
|
|
2195
2228
|
if (rawValue === void 0 && (lowerLabel === "today" || lowerLabel === "now")) {
|
|
2196
2229
|
rawValue = todayIso();
|
|
2197
2230
|
}
|
|
@@ -2326,7 +2359,9 @@ async function renderFieldsOnPages(pages, fields, getFont, getSignature) {
|
|
|
2326
2359
|
fieldHeightPt: h,
|
|
2327
2360
|
measure: textWidthAtSize
|
|
2328
2361
|
});
|
|
2329
|
-
const
|
|
2362
|
+
const fullTextWidth = textWidthAtSize(field.value, fontSize);
|
|
2363
|
+
const pad = 2;
|
|
2364
|
+
const textX = field.align === "center" ? x + Math.max(pad, (w - fullTextWidth) / 2) : field.align === "right" ? x + Math.max(pad, w - fullTextWidth - pad) : x + pad;
|
|
2330
2365
|
const baselineY = y + h * 0.3;
|
|
2331
2366
|
if (spacing > 0) {
|
|
2332
2367
|
let cx = textX;
|
|
@@ -2580,37 +2615,54 @@ function FieldNavigator({
|
|
|
2580
2615
|
// src/components/pdf-builder/SignerView.tsx
|
|
2581
2616
|
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2582
2617
|
var useIsoLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect3;
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2618
|
+
var measureCtx = null;
|
|
2619
|
+
function fitFont(el, box, maxPt, text, shrink) {
|
|
2620
|
+
if (!shrink || typeof document === "undefined") {
|
|
2621
|
+
el.style.fontSize = `${maxPt}pt`;
|
|
2622
|
+
return;
|
|
2623
|
+
}
|
|
2624
|
+
if (!measureCtx) measureCtx = document.createElement("canvas").getContext("2d");
|
|
2625
|
+
const boxStyle = getComputedStyle(box);
|
|
2626
|
+
const padX = (parseFloat(boxStyle.paddingLeft) || 0) + (parseFloat(boxStyle.paddingRight) || 0);
|
|
2627
|
+
const avail = box.clientWidth - padX - 1;
|
|
2628
|
+
if (!text || !measureCtx || avail <= 0) {
|
|
2629
|
+
el.style.fontSize = `${maxPt}pt`;
|
|
2630
|
+
return;
|
|
2631
|
+
}
|
|
2632
|
+
const cs = getComputedStyle(el);
|
|
2633
|
+
const PX_PER_PT = 96 / 72;
|
|
2587
2634
|
let pt = Math.max(1, maxPt);
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2635
|
+
while (pt > 2) {
|
|
2636
|
+
measureCtx.font = `${cs.fontStyle} ${cs.fontWeight} ${pt * PX_PER_PT}px ${cs.fontFamily}`;
|
|
2637
|
+
if (measureCtx.measureText(text).width <= avail) break;
|
|
2591
2638
|
pt -= 0.5;
|
|
2592
|
-
el.style.fontSize = `${pt}pt`;
|
|
2593
2639
|
}
|
|
2640
|
+
el.style.fontSize = `${pt}pt`;
|
|
2594
2641
|
}
|
|
2595
2642
|
function FitInput({
|
|
2596
2643
|
maxPt,
|
|
2644
|
+
shrink,
|
|
2597
2645
|
...rest
|
|
2598
2646
|
}) {
|
|
2599
2647
|
const ref = useRef5(null);
|
|
2600
2648
|
useIsoLayoutEffect(() => {
|
|
2601
|
-
|
|
2649
|
+
const el = ref.current;
|
|
2650
|
+
if (el) fitFont(el, el, maxPt, String(el.value ?? ""), shrink);
|
|
2602
2651
|
});
|
|
2603
2652
|
return /* @__PURE__ */ jsx6("input", { ref, ...rest });
|
|
2604
2653
|
}
|
|
2605
2654
|
function FitText({
|
|
2606
2655
|
maxPt,
|
|
2656
|
+
shrink,
|
|
2607
2657
|
className,
|
|
2608
2658
|
style,
|
|
2609
2659
|
children
|
|
2610
2660
|
}) {
|
|
2611
2661
|
const ref = useRef5(null);
|
|
2612
2662
|
useIsoLayoutEffect(() => {
|
|
2613
|
-
|
|
2663
|
+
const el = ref.current;
|
|
2664
|
+
const box = el?.parentElement;
|
|
2665
|
+
if (el && box) fitFont(el, box, maxPt, el.textContent ?? "", shrink);
|
|
2614
2666
|
});
|
|
2615
2667
|
return /* @__PURE__ */ jsx6("div", { ref, className, style, children });
|
|
2616
2668
|
}
|
|
@@ -2814,7 +2866,7 @@ function SignerView({
|
|
|
2814
2866
|
if (!pdfSource) return;
|
|
2815
2867
|
setSubmitting(true);
|
|
2816
2868
|
try {
|
|
2817
|
-
const finalFields = resolveAllFormulas(fields, transforms);
|
|
2869
|
+
const finalFields = resolveAllFormulas(fields, transforms, initialValues);
|
|
2818
2870
|
let pdfBytes;
|
|
2819
2871
|
if (includeAuditTrail) {
|
|
2820
2872
|
const { PDFDocument: PDFDocument2, StandardFonts: StandardFonts2, rgb: rgb2 } = await import("pdf-lib");
|
|
@@ -2864,13 +2916,13 @@ ${row.join(",")}`, "csv");
|
|
|
2864
2916
|
} finally {
|
|
2865
2917
|
setSubmitting(false);
|
|
2866
2918
|
}
|
|
2867
|
-
}, [pdfSource, fields, callbackUrl, allRequiredFilled, onComplete, isLastSigner, signer, onSignerComplete, includeAuditTrail, exportFormat, onExport, getValues, transforms]);
|
|
2919
|
+
}, [pdfSource, fields, callbackUrl, allRequiredFilled, onComplete, isLastSigner, signer, onSignerComplete, includeAuditTrail, exportFormat, onExport, getValues, transforms, initialValues]);
|
|
2868
2920
|
const renderFieldContent = useCallback5((field) => {
|
|
2869
2921
|
if (isRedactField(field)) {
|
|
2870
2922
|
return null;
|
|
2871
2923
|
}
|
|
2872
2924
|
if (field.formula) {
|
|
2873
|
-
return /* @__PURE__ */ jsx6(FitText, { maxPt: field.fontSize, className: "field-overlay-value formula", style: getCssTextStyle(field), children: field.value || "
|
|
2925
|
+
return /* @__PURE__ */ jsx6(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-value formula", style: getCssTextStyle(field), children: field.value || "" });
|
|
2874
2926
|
}
|
|
2875
2927
|
const editable = field.assignee === signer;
|
|
2876
2928
|
if (!editable) {
|
|
@@ -2880,7 +2932,7 @@ ${row.join(",")}`, "csv");
|
|
|
2880
2932
|
if (field.type === "checkbox") {
|
|
2881
2933
|
return /* @__PURE__ */ jsx6("div", { className: "field-checkbox-display readonly", children: field.value === "true" ? "\u2713" : "" });
|
|
2882
2934
|
}
|
|
2883
|
-
return /* @__PURE__ */ jsx6(FitText, { maxPt: field.fontSize, className: "field-overlay-placeholder readonly", style: getCssTextStyle(field), children: field.value || field.placeholder });
|
|
2935
|
+
return /* @__PURE__ */ jsx6(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-placeholder readonly", style: getCssTextStyle(field), children: field.value || field.placeholder });
|
|
2884
2936
|
}
|
|
2885
2937
|
if (isSignatureField(field)) {
|
|
2886
2938
|
if (field.value) {
|
|
@@ -2902,7 +2954,7 @@ ${row.join(",")}`, "csv");
|
|
|
2902
2954
|
);
|
|
2903
2955
|
}
|
|
2904
2956
|
if (field.type === "signed-date") {
|
|
2905
|
-
return /* @__PURE__ */ jsx6(FitText, { maxPt: field.fontSize, className: "field-overlay-value", style: getCssTextStyle(field), children: field.value || (/* @__PURE__ */ new Date()).toLocaleDateString() });
|
|
2957
|
+
return /* @__PURE__ */ jsx6(FitText, { maxPt: field.fontSize, shrink: !!field.autoShrink, className: "field-overlay-value", style: getCssTextStyle(field), children: field.value || (/* @__PURE__ */ new Date()).toLocaleDateString() });
|
|
2906
2958
|
}
|
|
2907
2959
|
const fontStyle = {
|
|
2908
2960
|
letterSpacing: field.letterSpacing ? `${field.letterSpacing}pt` : void 0,
|
|
@@ -2930,6 +2982,7 @@ ${row.join(",")}`, "csv");
|
|
|
2930
2982
|
FitInput,
|
|
2931
2983
|
{
|
|
2932
2984
|
maxPt: field.fontSize,
|
|
2985
|
+
shrink: !!field.autoShrink,
|
|
2933
2986
|
type: field.textSubtype === "email" ? "email" : field.textSubtype === "number" ? "number" : field.textSubtype === "phone" ? "tel" : field.textSubtype === "date" ? "date" : "text",
|
|
2934
2987
|
className: "field-inline-input",
|
|
2935
2988
|
value: field.value,
|
|
@@ -2957,10 +3010,10 @@ ${row.join(",")}`, "csv");
|
|
|
2957
3010
|
useEffect3(() => {
|
|
2958
3011
|
const hasFormulas = fields.some((f) => f.formula);
|
|
2959
3012
|
if (!hasFormulas) return;
|
|
2960
|
-
const resolved = resolveAllFormulas(fields, transforms);
|
|
3013
|
+
const resolved = resolveAllFormulas(fields, transforms, initialValues);
|
|
2961
3014
|
const changed = resolved.some((f, i) => f.value !== fields[i].value);
|
|
2962
3015
|
if (changed) setFields(resolved);
|
|
2963
|
-
}, [fields, transforms]);
|
|
3016
|
+
}, [fields, transforms, initialValues]);
|
|
2964
3017
|
return /* @__PURE__ */ jsxs6("div", { className: "signer-layout", ref: containerRef, children: [
|
|
2965
3018
|
loading && /* @__PURE__ */ jsx6("div", { className: "loading-indicator", children: "Loading document..." }),
|
|
2966
3019
|
/* @__PURE__ */ jsxs6("div", { className: "signer-content", children: [
|