@unlev/exeq 0.4.0 → 0.4.1
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 +1 -0
- package/dist/index.d.mts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +121 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -51
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,6 +74,7 @@ function MultiPartySigner() {
|
|
|
74
74
|
| `initialPdfUrl` | `string` | No | URL to a PDF to pre-load |
|
|
75
75
|
| `initialTemplate` | `Template` | No | Existing template to resume editing |
|
|
76
76
|
| `onSave` | `(template: Template) => void` | No | Called on "Export Template". If omitted, downloads JSON. |
|
|
77
|
+
| `onChange` | `(template: Template) => void` | No | Fires on every change to fields / signer roles / loaded PDF. Use for draft persistence (e.g. `localStorage`) so accidental refresh or tab close doesn't lose work. |
|
|
77
78
|
|
|
78
79
|
### `SignerView` Props
|
|
79
80
|
|
package/dist/index.d.mts
CHANGED
|
@@ -38,6 +38,20 @@ interface Template {
|
|
|
38
38
|
declare const DEFAULT_SIGNER_ROLES: string[];
|
|
39
39
|
declare const SIGNER_ROLE_COLORS: Record<string, string>;
|
|
40
40
|
declare function getSignerColor(role: string): string;
|
|
41
|
+
declare function isRedactField(f: FormField | {
|
|
42
|
+
type: FieldType;
|
|
43
|
+
}): boolean;
|
|
44
|
+
declare function isSignatureField(f: FormField | {
|
|
45
|
+
type: FieldType;
|
|
46
|
+
}): boolean;
|
|
47
|
+
declare function isTextLikeField(f: FormField | {
|
|
48
|
+
type: FieldType;
|
|
49
|
+
}): boolean;
|
|
50
|
+
declare function getInputType(subtype?: TextSubtype): string;
|
|
51
|
+
declare function getCssFontFamily(fontFamily?: string): string | undefined;
|
|
52
|
+
declare function sortFieldsByPosition(fields: FormField[]): FormField[];
|
|
53
|
+
declare function preserveFieldValues(oldFields: FormField[], newFields: FormField[]): FormField[];
|
|
54
|
+
declare function getFieldValues(fields: FormField[]): Record<string, string>;
|
|
41
55
|
declare const FONT_FAMILIES: readonly [{
|
|
42
56
|
readonly value: "Helvetica";
|
|
43
57
|
readonly label: "Helvetica";
|
|
@@ -62,12 +76,18 @@ interface DesignerViewProps {
|
|
|
62
76
|
initialTemplate?: Template;
|
|
63
77
|
/** Called when the user clicks "Export Template" */
|
|
64
78
|
onSave?: (template: Template) => void;
|
|
79
|
+
/** Called whenever the template changes (field added/moved/edited, signer
|
|
80
|
+
* role changed, PDF loaded). Use for draft persistence — e.g. save to
|
|
81
|
+
* localStorage so a refresh or accidental tab close doesn't lose work.
|
|
82
|
+
* Fires on every change, including programmatic ones from `initialTemplate`.
|
|
83
|
+
* Debounce on the caller side if you want fewer writes. */
|
|
84
|
+
onChange?: (template: Template) => void;
|
|
65
85
|
/** When true, the built-in header bar is hidden (use headerPortalRef to place buttons externally) */
|
|
66
86
|
hideHeader?: boolean;
|
|
67
87
|
/** Ref to an element where the header action buttons should be portalled into */
|
|
68
88
|
headerPortalRef?: React.RefObject<HTMLElement | null>;
|
|
69
89
|
}
|
|
70
|
-
declare function DesignerView({ apiKey, initialPdfUrl, initialTemplate, onSave, hideHeader, headerPortalRef, }?: DesignerViewProps): react_jsx_runtime.JSX.Element;
|
|
90
|
+
declare function DesignerView({ apiKey, initialPdfUrl, initialTemplate, onSave, onChange, hideHeader, headerPortalRef, }?: DesignerViewProps): react_jsx_runtime.JSX.Element;
|
|
71
91
|
|
|
72
92
|
type TransformFn = (value: string) => string;
|
|
73
93
|
type TransformMap = Record<string, TransformFn>;
|
|
@@ -311,4 +331,4 @@ declare function createPdfBuilder(defaults?: CreatePdfBuilderOptions): Promise<P
|
|
|
311
331
|
declare function downloadPdf(bytes: Uint8Array, filename: string): void;
|
|
312
332
|
declare function postPdfToCallback(bytes: Uint8Array, callbackUrl: string, filename: string): Promise<void>;
|
|
313
333
|
|
|
314
|
-
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, getSignerColor, postPdfToCallback, renderPdfPages, resolveAllFormulas, resolveFormula, uniqueLabel };
|
|
334
|
+
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, postPdfToCallback, preserveFieldValues, renderPdfPages, resolveAllFormulas, resolveFormula, sortFieldsByPosition, uniqueLabel };
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,20 @@ interface Template {
|
|
|
38
38
|
declare const DEFAULT_SIGNER_ROLES: string[];
|
|
39
39
|
declare const SIGNER_ROLE_COLORS: Record<string, string>;
|
|
40
40
|
declare function getSignerColor(role: string): string;
|
|
41
|
+
declare function isRedactField(f: FormField | {
|
|
42
|
+
type: FieldType;
|
|
43
|
+
}): boolean;
|
|
44
|
+
declare function isSignatureField(f: FormField | {
|
|
45
|
+
type: FieldType;
|
|
46
|
+
}): boolean;
|
|
47
|
+
declare function isTextLikeField(f: FormField | {
|
|
48
|
+
type: FieldType;
|
|
49
|
+
}): boolean;
|
|
50
|
+
declare function getInputType(subtype?: TextSubtype): string;
|
|
51
|
+
declare function getCssFontFamily(fontFamily?: string): string | undefined;
|
|
52
|
+
declare function sortFieldsByPosition(fields: FormField[]): FormField[];
|
|
53
|
+
declare function preserveFieldValues(oldFields: FormField[], newFields: FormField[]): FormField[];
|
|
54
|
+
declare function getFieldValues(fields: FormField[]): Record<string, string>;
|
|
41
55
|
declare const FONT_FAMILIES: readonly [{
|
|
42
56
|
readonly value: "Helvetica";
|
|
43
57
|
readonly label: "Helvetica";
|
|
@@ -62,12 +76,18 @@ interface DesignerViewProps {
|
|
|
62
76
|
initialTemplate?: Template;
|
|
63
77
|
/** Called when the user clicks "Export Template" */
|
|
64
78
|
onSave?: (template: Template) => void;
|
|
79
|
+
/** Called whenever the template changes (field added/moved/edited, signer
|
|
80
|
+
* role changed, PDF loaded). Use for draft persistence — e.g. save to
|
|
81
|
+
* localStorage so a refresh or accidental tab close doesn't lose work.
|
|
82
|
+
* Fires on every change, including programmatic ones from `initialTemplate`.
|
|
83
|
+
* Debounce on the caller side if you want fewer writes. */
|
|
84
|
+
onChange?: (template: Template) => void;
|
|
65
85
|
/** When true, the built-in header bar is hidden (use headerPortalRef to place buttons externally) */
|
|
66
86
|
hideHeader?: boolean;
|
|
67
87
|
/** Ref to an element where the header action buttons should be portalled into */
|
|
68
88
|
headerPortalRef?: React.RefObject<HTMLElement | null>;
|
|
69
89
|
}
|
|
70
|
-
declare function DesignerView({ apiKey, initialPdfUrl, initialTemplate, onSave, hideHeader, headerPortalRef, }?: DesignerViewProps): react_jsx_runtime.JSX.Element;
|
|
90
|
+
declare function DesignerView({ apiKey, initialPdfUrl, initialTemplate, onSave, onChange, hideHeader, headerPortalRef, }?: DesignerViewProps): react_jsx_runtime.JSX.Element;
|
|
71
91
|
|
|
72
92
|
type TransformFn = (value: string) => string;
|
|
73
93
|
type TransformMap = Record<string, TransformFn>;
|
|
@@ -311,4 +331,4 @@ declare function createPdfBuilder(defaults?: CreatePdfBuilderOptions): Promise<P
|
|
|
311
331
|
declare function downloadPdf(bytes: Uint8Array, filename: string): void;
|
|
312
332
|
declare function postPdfToCallback(bytes: Uint8Array, callbackUrl: string, filename: string): Promise<void>;
|
|
313
333
|
|
|
314
|
-
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, getSignerColor, postPdfToCallback, renderPdfPages, resolveAllFormulas, resolveFormula, uniqueLabel };
|
|
334
|
+
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, postPdfToCallback, preserveFieldValues, renderPdfPages, resolveAllFormulas, resolveFormula, sortFieldsByPosition, uniqueLabel };
|
package/dist/index.js
CHANGED
|
@@ -52,11 +52,19 @@ __export(lib_exports, {
|
|
|
52
52
|
downloadPdf: () => downloadPdf,
|
|
53
53
|
generateFilledPdf: () => generateFilledPdf,
|
|
54
54
|
generateId: () => generateId,
|
|
55
|
+
getCssFontFamily: () => getCssFontFamily,
|
|
56
|
+
getFieldValues: () => getFieldValues,
|
|
57
|
+
getInputType: () => getInputType,
|
|
55
58
|
getSignerColor: () => getSignerColor,
|
|
59
|
+
isRedactField: () => isRedactField,
|
|
60
|
+
isSignatureField: () => isSignatureField,
|
|
61
|
+
isTextLikeField: () => isTextLikeField,
|
|
56
62
|
postPdfToCallback: () => postPdfToCallback,
|
|
63
|
+
preserveFieldValues: () => preserveFieldValues,
|
|
57
64
|
renderPdfPages: () => renderPdfPages,
|
|
58
65
|
resolveAllFormulas: () => resolveAllFormulas,
|
|
59
66
|
resolveFormula: () => resolveFormula,
|
|
67
|
+
sortFieldsByPosition: () => sortFieldsByPosition,
|
|
60
68
|
uniqueLabel: () => uniqueLabel
|
|
61
69
|
});
|
|
62
70
|
module.exports = __toCommonJS(lib_exports);
|
|
@@ -88,6 +96,56 @@ var SIGNER_ROLE_COLORS = {
|
|
|
88
96
|
function getSignerColor(role) {
|
|
89
97
|
return SIGNER_ROLE_COLORS[role] || "#888888";
|
|
90
98
|
}
|
|
99
|
+
function isRedactField(f) {
|
|
100
|
+
return f.type === "blackout" || f.type === "whiteout";
|
|
101
|
+
}
|
|
102
|
+
function isSignatureField(f) {
|
|
103
|
+
return f.type === "signature" || f.type === "initials";
|
|
104
|
+
}
|
|
105
|
+
function isTextLikeField(f) {
|
|
106
|
+
return f.type === "text" || f.type === "dropdown" || f.type === "signed-date";
|
|
107
|
+
}
|
|
108
|
+
function getInputType(subtype) {
|
|
109
|
+
switch (subtype) {
|
|
110
|
+
case "email":
|
|
111
|
+
return "email";
|
|
112
|
+
case "number":
|
|
113
|
+
return "number";
|
|
114
|
+
case "phone":
|
|
115
|
+
return "tel";
|
|
116
|
+
case "date":
|
|
117
|
+
return "date";
|
|
118
|
+
default:
|
|
119
|
+
return "text";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
var CSS_FONT_MAP = {
|
|
123
|
+
Courier: '"Courier New", Courier, monospace',
|
|
124
|
+
TimesRoman: '"Times New Roman", Times, serif',
|
|
125
|
+
Helvetica: "Helvetica, Arial, sans-serif"
|
|
126
|
+
};
|
|
127
|
+
function getCssFontFamily(fontFamily) {
|
|
128
|
+
return fontFamily ? CSS_FONT_MAP[fontFamily] : void 0;
|
|
129
|
+
}
|
|
130
|
+
function sortFieldsByPosition(fields) {
|
|
131
|
+
return [...fields].sort((a, b) => {
|
|
132
|
+
if (a.page !== b.page) return a.page - b.page;
|
|
133
|
+
const bandThreshold = 2;
|
|
134
|
+
if (Math.abs(a.y - b.y) > bandThreshold) return a.y - b.y;
|
|
135
|
+
return a.x - b.x;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function preserveFieldValues(oldFields, newFields) {
|
|
139
|
+
const valueMap = new Map(oldFields.filter((f) => f.value).map((f) => [f.id, f.value]));
|
|
140
|
+
return newFields.map((f) => valueMap.has(f.id) ? { ...f, value: valueMap.get(f.id) } : f);
|
|
141
|
+
}
|
|
142
|
+
function getFieldValues(fields) {
|
|
143
|
+
const values = {};
|
|
144
|
+
fields.forEach((f) => {
|
|
145
|
+
if (!isRedactField(f)) values[f.label] = f.value || "";
|
|
146
|
+
});
|
|
147
|
+
return values;
|
|
148
|
+
}
|
|
91
149
|
var FONT_FAMILIES = [
|
|
92
150
|
{ value: "Helvetica", label: "Helvetica" },
|
|
93
151
|
{ value: "Courier", label: "Courier New" },
|
|
@@ -443,7 +501,7 @@ function FieldOverlayItem({
|
|
|
443
501
|
const dragPosRef = (0, import_react.useRef)({ x: field.x, y: field.y });
|
|
444
502
|
const didDragRef = (0, import_react.useRef)(false);
|
|
445
503
|
const resizeStartRef = (0, import_react.useRef)(null);
|
|
446
|
-
const isRedact = field
|
|
504
|
+
const isRedact = isRedactField(field);
|
|
447
505
|
const isEditable = mode === "designer" || mode === "signer" && field.assignee === currentSigner;
|
|
448
506
|
const isInactiveSigner = mode === "signer" && !isRedact && field.assignee !== currentSigner;
|
|
449
507
|
const isFilled = mode === "signer" && isEditable && !isRedact && (field.type === "checkbox" ? true : field.formula ? true : !!field.value);
|
|
@@ -584,9 +642,9 @@ var INK_COLORS = [
|
|
|
584
642
|
];
|
|
585
643
|
function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillContent, pageSize }) {
|
|
586
644
|
const color = getSignerColor(field.assignee);
|
|
587
|
-
const
|
|
588
|
-
const
|
|
589
|
-
const showInkColor =
|
|
645
|
+
const isRedact = isRedactField(field);
|
|
646
|
+
const isText = isTextLikeField(field);
|
|
647
|
+
const showInkColor = isText || isSignatureField(field);
|
|
590
648
|
const [newOption, setNewOption] = (0, import_react2.useState)("");
|
|
591
649
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "field-property-panel", children: [
|
|
592
650
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-header", children: [
|
|
@@ -618,7 +676,7 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
618
676
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => onDelete(field.id), className: "panel-icon-btn panel-icon-btn-danger", title: "Delete", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 1h4v1H5V1zM2 3v1h1v8.5A1.5 1.5 0 004.5 14h5a1.5 1.5 0 001.5-1.5V4h1V3H2zm2 1h6v8.5a.5.5 0 01-.5.5h-5a.5.5 0 01-.5-.5V4z" }) }) })
|
|
619
677
|
] })
|
|
620
678
|
] }),
|
|
621
|
-
!
|
|
679
|
+
!isRedact && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-section", children: [
|
|
622
680
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "panel-section-heading", children: "Assigned To" }),
|
|
623
681
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
624
682
|
"select",
|
|
@@ -633,7 +691,7 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
633
691
|
] }),
|
|
634
692
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-section", children: [
|
|
635
693
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "panel-section-heading", children: "Content" }),
|
|
636
|
-
!
|
|
694
|
+
!isRedact && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
637
695
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Field Type" }),
|
|
638
696
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("select", { value: field.type, onChange: (e) => onUpdate(field.id, { type: e.target.value }), children: [
|
|
639
697
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "text", children: "Text" }),
|
|
@@ -654,15 +712,15 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
654
712
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "phone", children: "Phone" })
|
|
655
713
|
] })
|
|
656
714
|
] }),
|
|
657
|
-
!
|
|
715
|
+
!isRedact && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
658
716
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Placeholder" }),
|
|
659
717
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "text", value: field.placeholder, onChange: (e) => onUpdate(field.id, { placeholder: e.target.value }) })
|
|
660
718
|
] }),
|
|
661
|
-
!
|
|
719
|
+
!isRedact && field.type !== "checkbox" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "panel-field", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "panel-checkbox-label", children: [
|
|
662
720
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: field.required, onChange: (e) => onUpdate(field.id, { required: e.target.checked }) }),
|
|
663
721
|
"Required"
|
|
664
722
|
] }) }),
|
|
665
|
-
|
|
723
|
+
isText && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
666
724
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Formula" }),
|
|
667
725
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "text", value: field.formula || "", onChange: (e) => onUpdate(field.id, { formula: e.target.value || void 0 }), placeholder: "e.g. {{Date Field | month}}" }),
|
|
668
726
|
field.formula && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "panel-hint", children: "Auto-computed. Signer cannot edit." })
|
|
@@ -677,7 +735,7 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
677
735
|
/* @__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) }) })
|
|
678
736
|
] })
|
|
679
737
|
] }),
|
|
680
|
-
|
|
738
|
+
isText && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
681
739
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "panel-checkbox-label", children: [
|
|
682
740
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: field.autoShrink || false, onChange: (e) => onUpdate(field.id, { autoShrink: e.target.checked }) }),
|
|
683
741
|
"Auto-shrink to fit"
|
|
@@ -714,17 +772,17 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete, prefillCon
|
|
|
714
772
|
] }),
|
|
715
773
|
prefillContent
|
|
716
774
|
] }),
|
|
717
|
-
(
|
|
775
|
+
(isText || showInkColor) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-section", children: [
|
|
718
776
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "panel-section-heading", children: "Style" }),
|
|
719
|
-
|
|
777
|
+
isText && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
720
778
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Font" }),
|
|
721
779
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("select", { value: field.fontFamily || "Helvetica", onChange: (e) => onUpdate(field.id, { fontFamily: e.target.value }), children: FONT_FAMILIES.map((f) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: f.value, children: f.label }, f.value)) })
|
|
722
780
|
] }),
|
|
723
|
-
|
|
781
|
+
isText && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field", children: [
|
|
724
782
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Font Size (pt)" }),
|
|
725
783
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: "6", max: "72", value: field.fontSize, onChange: (e) => onUpdate(field.id, { fontSize: Number(e.target.value) }) })
|
|
726
784
|
] }),
|
|
727
|
-
|
|
785
|
+
isText && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field-row", children: [
|
|
728
786
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-field panel-field-half", children: [
|
|
729
787
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Letter Spacing" }),
|
|
730
788
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: "0", max: "20", step: "0.5", value: field.letterSpacing || 0, onChange: (e) => onUpdate(field.id, { letterSpacing: Number(e.target.value) }) })
|
|
@@ -1201,6 +1259,7 @@ function DesignerView({
|
|
|
1201
1259
|
initialPdfUrl,
|
|
1202
1260
|
initialTemplate,
|
|
1203
1261
|
onSave,
|
|
1262
|
+
onChange,
|
|
1204
1263
|
hideHeader,
|
|
1205
1264
|
headerPortalRef
|
|
1206
1265
|
} = {}) {
|
|
@@ -1235,6 +1294,20 @@ function DesignerView({
|
|
|
1235
1294
|
const dragGhostRef = (0, import_react5.useRef)(null);
|
|
1236
1295
|
const resizingRef = (0, import_react5.useRef)(false);
|
|
1237
1296
|
const lastStylesRef = (0, import_react5.useRef)({});
|
|
1297
|
+
const onChangeMountedRef = (0, import_react5.useRef)(false);
|
|
1298
|
+
(0, import_react5.useEffect)(() => {
|
|
1299
|
+
if (!onChange) return;
|
|
1300
|
+
if (!onChangeMountedRef.current) {
|
|
1301
|
+
onChangeMountedRef.current = true;
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
const template = {
|
|
1305
|
+
fields,
|
|
1306
|
+
signerRoles,
|
|
1307
|
+
pdfUrl: typeof pdfSource === "string" ? pdfSource : ""
|
|
1308
|
+
};
|
|
1309
|
+
onChange(template);
|
|
1310
|
+
}, [fields, signerRoles, pdfSource, onChange]);
|
|
1238
1311
|
(0, import_react5.useEffect)(() => {
|
|
1239
1312
|
const pdfUrl = initialPdfUrl || initialTemplate?.pdfUrl;
|
|
1240
1313
|
if (pdfUrl) {
|
|
@@ -1281,11 +1354,16 @@ function DesignerView({
|
|
|
1281
1354
|
reader.readAsArrayBuffer(file);
|
|
1282
1355
|
}, [loadPdf]);
|
|
1283
1356
|
const handlePageClick = (0, import_react5.useCallback)((page, x, y) => {
|
|
1357
|
+
const scrollEl = pdfAreaRef.current;
|
|
1358
|
+
const scrollTop = scrollEl?.scrollTop ?? 0;
|
|
1284
1359
|
const field = createField(activeFieldType, activeRole, page, x, y, fields);
|
|
1285
1360
|
const sticky = lastStylesRef.current[activeFieldType];
|
|
1286
1361
|
const styledField = sticky ? { ...field, ...sticky } : field;
|
|
1287
1362
|
setFields((prev) => [...prev, styledField]);
|
|
1288
1363
|
setSelectedFieldIds(/* @__PURE__ */ new Set([styledField.id]));
|
|
1364
|
+
requestAnimationFrame(() => {
|
|
1365
|
+
if (scrollEl) scrollEl.scrollTop = scrollTop;
|
|
1366
|
+
});
|
|
1289
1367
|
setRightTab("properties");
|
|
1290
1368
|
}, [activeFieldType, activeRole, fields]);
|
|
1291
1369
|
const handleFieldMove = (0, import_react5.useCallback)((id, page, x, y) => {
|
|
@@ -1660,24 +1738,19 @@ function DesignerView({
|
|
|
1660
1738
|
window.addEventListener("mousemove", handleMouseMove);
|
|
1661
1739
|
window.addEventListener("mouseup", handleMouseUp);
|
|
1662
1740
|
}, [panelWidth]);
|
|
1663
|
-
const sortedFields =
|
|
1664
|
-
if (a.page !== b.page) return a.page - b.page;
|
|
1665
|
-
const bandThreshold = 2;
|
|
1666
|
-
if (Math.abs(a.y - b.y) > bandThreshold) return a.y - b.y;
|
|
1667
|
-
return a.x - b.x;
|
|
1668
|
-
});
|
|
1741
|
+
const sortedFields = sortFieldsByPosition(fields);
|
|
1669
1742
|
const selectedField = selectedFieldIds.size === 1 ? fields.find((f) => f.id === Array.from(selectedFieldIds)[0]) || null : null;
|
|
1670
1743
|
const renderFieldContent = (0, import_react5.useCallback)((field) => {
|
|
1671
|
-
if (field
|
|
1744
|
+
if (isRedactField(field)) {
|
|
1672
1745
|
return null;
|
|
1673
1746
|
}
|
|
1674
|
-
if (field
|
|
1747
|
+
if (isSignatureField(field)) {
|
|
1675
1748
|
if (field.value) {
|
|
1676
1749
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: field.value, alt: field.label, className: "field-signature-preview" });
|
|
1677
1750
|
}
|
|
1678
1751
|
}
|
|
1679
1752
|
const inkColor = field.inkColor || "#000000";
|
|
1680
|
-
const cssFontFamily = field.fontFamily
|
|
1753
|
+
const cssFontFamily = getCssFontFamily(field.fontFamily);
|
|
1681
1754
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1682
1755
|
"div",
|
|
1683
1756
|
{
|
|
@@ -1906,9 +1979,9 @@ function DesignerView({
|
|
|
1906
1979
|
onUpdate: handleFieldUpdate,
|
|
1907
1980
|
onDelete: handleFieldDelete,
|
|
1908
1981
|
pageSize: pages[selectedField.page] ? { width: pages[selectedField.page].pdfWidth, height: pages[selectedField.page].pdfHeight } : void 0,
|
|
1909
|
-
prefillContent: selectedField
|
|
1982
|
+
prefillContent: !isRedactField(selectedField) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "prefill-section", children: [
|
|
1910
1983
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Pre-fill Value" }),
|
|
1911
|
-
selectedField
|
|
1984
|
+
isSignatureField(selectedField) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1912
1985
|
SignatureCanvas,
|
|
1913
1986
|
{
|
|
1914
1987
|
width: panelWidth - 40,
|
|
@@ -2188,7 +2261,7 @@ async function renderFieldsOnPages(pages, fields, getFont, getSignature) {
|
|
|
2188
2261
|
const y = pageHeight - field.y / 100 * pageHeight - field.height / 100 * pageHeight;
|
|
2189
2262
|
const w = field.width / 100 * pageWidth;
|
|
2190
2263
|
const h = field.height / 100 * pageHeight;
|
|
2191
|
-
if (field
|
|
2264
|
+
if (isRedactField(field)) {
|
|
2192
2265
|
page.drawRectangle({
|
|
2193
2266
|
x,
|
|
2194
2267
|
y,
|
|
@@ -2217,7 +2290,7 @@ async function renderFieldsOnPages(pages, fields, getFont, getSignature) {
|
|
|
2217
2290
|
color: inkColor
|
|
2218
2291
|
});
|
|
2219
2292
|
}
|
|
2220
|
-
} else if (field
|
|
2293
|
+
} else if (isSignatureField(field)) {
|
|
2221
2294
|
if (field.value.startsWith("data:image/png")) {
|
|
2222
2295
|
const img = await getSignature(field.value);
|
|
2223
2296
|
page.drawImage(img, { x, y, width: w, height: h });
|
|
@@ -2515,7 +2588,7 @@ function SignerView({
|
|
|
2515
2588
|
(0, import_react7.useEffect)(() => {
|
|
2516
2589
|
if (fields.length === 0 || !isMultiSigner) return;
|
|
2517
2590
|
const signerFields = fields.filter(
|
|
2518
|
-
(f) => f.assignee === signer && f
|
|
2591
|
+
(f) => f.assignee === signer && !isRedactField(f)
|
|
2519
2592
|
);
|
|
2520
2593
|
const allFilled = signerFields.length > 0 && signerFields.every((f) => {
|
|
2521
2594
|
if (!f.required) return true;
|
|
@@ -2609,14 +2682,9 @@ function SignerView({
|
|
|
2609
2682
|
setLoading(false);
|
|
2610
2683
|
}
|
|
2611
2684
|
}, []);
|
|
2612
|
-
const editableFields = fields.filter((f) => f.assignee === signer && f
|
|
2613
|
-
if (a.page !== b.page) return a.page - b.page;
|
|
2614
|
-
const bandThreshold = 2;
|
|
2615
|
-
if (Math.abs(a.y - b.y) > bandThreshold) return a.y - b.y;
|
|
2616
|
-
return a.x - b.x;
|
|
2617
|
-
});
|
|
2685
|
+
const editableFields = sortFieldsByPosition(fields.filter((f) => f.assignee === signer && !isRedactField(f) && !f.formula));
|
|
2618
2686
|
const selectedField = fields.find((f) => f.id === selectedFieldId) || null;
|
|
2619
|
-
const isFieldEditable = selectedField ? selectedField.assignee === signer && selectedField
|
|
2687
|
+
const isFieldEditable = selectedField ? selectedField.assignee === signer && !isRedactField(selectedField) && !selectedField.formula : false;
|
|
2620
2688
|
const handleFieldUpdate = (0, import_react7.useCallback)((id, value) => {
|
|
2621
2689
|
setFields((prev) => prev.map((f) => f.id === id ? { ...f, value } : f));
|
|
2622
2690
|
}, []);
|
|
@@ -2628,7 +2696,7 @@ function SignerView({
|
|
|
2628
2696
|
if (!onChange) return;
|
|
2629
2697
|
const values = {};
|
|
2630
2698
|
fields.forEach((f) => {
|
|
2631
|
-
if (f
|
|
2699
|
+
if (!isRedactField(f)) values[f.label] = f.value || "";
|
|
2632
2700
|
});
|
|
2633
2701
|
onChange(values);
|
|
2634
2702
|
}, [fieldValuesKey]);
|
|
@@ -2649,18 +2717,12 @@ function SignerView({
|
|
|
2649
2717
|
if (f.minLength && f.value.length < f.minLength) return false;
|
|
2650
2718
|
return true;
|
|
2651
2719
|
});
|
|
2652
|
-
const
|
|
2653
|
-
const values = {};
|
|
2654
|
-
fields.forEach((f) => {
|
|
2655
|
-
if (f.type !== "blackout" && f.type !== "whiteout") values[f.label] = f.value || "";
|
|
2656
|
-
});
|
|
2657
|
-
return values;
|
|
2658
|
-
}, [fields]);
|
|
2720
|
+
const getValues = (0, import_react7.useCallback)(() => getFieldValues(fields), [fields]);
|
|
2659
2721
|
const handleAdvanceOrSubmit = (0, import_react7.useCallback)(async () => {
|
|
2660
2722
|
if (!allRequiredFilled) return;
|
|
2661
2723
|
auditLogRef.current.push({ signer, completedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
2662
2724
|
if (onSignerComplete) {
|
|
2663
|
-
onSignerComplete(signer,
|
|
2725
|
+
onSignerComplete(signer, getValues());
|
|
2664
2726
|
}
|
|
2665
2727
|
if (!isLastSigner) {
|
|
2666
2728
|
setCurrentSignerIndex((prev) => prev + 1);
|
|
@@ -2699,7 +2761,7 @@ function SignerView({
|
|
|
2699
2761
|
}
|
|
2700
2762
|
const blob = new Blob([pdfBytes.slice().buffer], { type: "application/pdf" });
|
|
2701
2763
|
if (onExport && exportFormat) {
|
|
2702
|
-
const values =
|
|
2764
|
+
const values = getValues();
|
|
2703
2765
|
if (exportFormat === "json") {
|
|
2704
2766
|
onExport(JSON.stringify(values, null, 2), "json");
|
|
2705
2767
|
} else {
|
|
@@ -2724,9 +2786,9 @@ ${row.join(",")}`, "csv");
|
|
|
2724
2786
|
} finally {
|
|
2725
2787
|
setSubmitting(false);
|
|
2726
2788
|
}
|
|
2727
|
-
}, [pdfSource, fields, callbackUrl, allRequiredFilled, onComplete, isLastSigner, signer, onSignerComplete, includeAuditTrail, exportFormat, onExport,
|
|
2789
|
+
}, [pdfSource, fields, callbackUrl, allRequiredFilled, onComplete, isLastSigner, signer, onSignerComplete, includeAuditTrail, exportFormat, onExport, getValues, transforms]);
|
|
2728
2790
|
const renderFieldContent = (0, import_react7.useCallback)((field) => {
|
|
2729
|
-
if (field
|
|
2791
|
+
if (isRedactField(field)) {
|
|
2730
2792
|
return null;
|
|
2731
2793
|
}
|
|
2732
2794
|
if (field.formula) {
|
|
@@ -2734,7 +2796,7 @@ ${row.join(",")}`, "csv");
|
|
|
2734
2796
|
}
|
|
2735
2797
|
const editable = field.assignee === signer;
|
|
2736
2798
|
if (!editable) {
|
|
2737
|
-
if (field
|
|
2799
|
+
if (isSignatureField(field)) {
|
|
2738
2800
|
return field.value ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: field.value, alt: field.label, className: "field-signature-preview" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "field-overlay-placeholder readonly", children: field.placeholder });
|
|
2739
2801
|
}
|
|
2740
2802
|
if (field.type === "checkbox") {
|
|
@@ -2742,7 +2804,7 @@ ${row.join(",")}`, "csv");
|
|
|
2742
2804
|
}
|
|
2743
2805
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "field-overlay-placeholder readonly", children: field.value || field.placeholder });
|
|
2744
2806
|
}
|
|
2745
|
-
if (field
|
|
2807
|
+
if (isSignatureField(field)) {
|
|
2746
2808
|
if (field.value) {
|
|
2747
2809
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "field-signature-filled", onClick: () => handleFieldUpdate(field.id, ""), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: field.value, alt: field.label, className: "field-signature-preview" }) });
|
|
2748
2810
|
}
|
|
@@ -2768,7 +2830,7 @@ ${row.join(",")}`, "csv");
|
|
|
2768
2830
|
fontSize: `${field.fontSize}pt`,
|
|
2769
2831
|
letterSpacing: field.letterSpacing ? `${field.letterSpacing}pt` : void 0,
|
|
2770
2832
|
lineHeight: field.lineHeight ? `${field.lineHeight}` : void 0,
|
|
2771
|
-
fontFamily: field.fontFamily
|
|
2833
|
+
fontFamily: getCssFontFamily(field.fontFamily)
|
|
2772
2834
|
};
|
|
2773
2835
|
if (field.type === "dropdown" || field.options && field.options.length > 0) {
|
|
2774
2836
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
@@ -2853,7 +2915,7 @@ ${row.join(",")}`, "csv");
|
|
|
2853
2915
|
selectedField && isFieldEditable && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "signer-field-input", children: [
|
|
2854
2916
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: selectedField.label }),
|
|
2855
2917
|
selectedField.required && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "required-badge", children: "Required" }),
|
|
2856
|
-
(selectedField
|
|
2918
|
+
isSignatureField(selectedField) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2857
2919
|
SignatureCanvas,
|
|
2858
2920
|
{
|
|
2859
2921
|
width: 280,
|
|
@@ -3040,11 +3102,19 @@ function SignerRoleSelector({
|
|
|
3040
3102
|
downloadPdf,
|
|
3041
3103
|
generateFilledPdf,
|
|
3042
3104
|
generateId,
|
|
3105
|
+
getCssFontFamily,
|
|
3106
|
+
getFieldValues,
|
|
3107
|
+
getInputType,
|
|
3043
3108
|
getSignerColor,
|
|
3109
|
+
isRedactField,
|
|
3110
|
+
isSignatureField,
|
|
3111
|
+
isTextLikeField,
|
|
3044
3112
|
postPdfToCallback,
|
|
3113
|
+
preserveFieldValues,
|
|
3045
3114
|
renderPdfPages,
|
|
3046
3115
|
resolveAllFormulas,
|
|
3047
3116
|
resolveFormula,
|
|
3117
|
+
sortFieldsByPosition,
|
|
3048
3118
|
uniqueLabel
|
|
3049
3119
|
});
|
|
3050
3120
|
//# sourceMappingURL=index.js.map
|