@unlev/exeq 0.1.5 → 0.1.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/README.md +1 -0
- package/dist/index.css +4 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +91 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +91 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -95,7 +95,7 @@ function createField(type, assignee, page, x, y, existingFields) {
|
|
|
95
95
|
type,
|
|
96
96
|
label: uniqueLabel(baseLabel, existingLabels),
|
|
97
97
|
placeholder: defaults.placeholder || "",
|
|
98
|
-
required: true,
|
|
98
|
+
required: type === "checkbox" || type === "blackout" || type === "whiteout" ? false : true,
|
|
99
99
|
assignee,
|
|
100
100
|
page,
|
|
101
101
|
x,
|
|
@@ -311,7 +311,8 @@ function FieldOverlayItem({
|
|
|
311
311
|
borderColor: isRedact ? field.type === "blackout" ? "#666" : "#bbb" : color,
|
|
312
312
|
borderStyle: isRedact ? "dashed" : "solid",
|
|
313
313
|
backgroundColor: isRedact ? field.type === "blackout" ? "#000000" : "#ffffff" : isSelected ? `${color}22` : `${color}11`,
|
|
314
|
-
cursor: mode === "designer" ? "move" : "default"
|
|
314
|
+
cursor: mode === "designer" ? "move" : "default",
|
|
315
|
+
pointerEvents: mode === "signer" && isRedact ? "none" : void 0
|
|
315
316
|
},
|
|
316
317
|
onClick: (e) => {
|
|
317
318
|
e.stopPropagation();
|
|
@@ -416,7 +417,7 @@ function FieldPropertyPanel({ field, signerRoles, onUpdate, onDelete }) {
|
|
|
416
417
|
}
|
|
417
418
|
)
|
|
418
419
|
] }),
|
|
419
|
-
!isRedactField && /* @__PURE__ */ jsx2("div", { className: "panel-field", children: /* @__PURE__ */ jsxs2("label", { className: "panel-checkbox-label", children: [
|
|
420
|
+
!isRedactField && field.type !== "checkbox" && /* @__PURE__ */ jsx2("div", { className: "panel-field", children: /* @__PURE__ */ jsxs2("label", { className: "panel-checkbox-label", children: [
|
|
420
421
|
/* @__PURE__ */ jsx2(
|
|
421
422
|
"input",
|
|
422
423
|
{
|
|
@@ -516,10 +517,20 @@ function SignatureCanvas({
|
|
|
516
517
|
}
|
|
517
518
|
}, [paths, currentPath, width, height]);
|
|
518
519
|
const getPoint = useCallback2((e) => {
|
|
519
|
-
const
|
|
520
|
+
const canvas = canvasRef.current;
|
|
521
|
+
const rect = canvas.getBoundingClientRect();
|
|
522
|
+
const style = getComputedStyle(canvas);
|
|
523
|
+
const borderL = parseFloat(style.borderLeftWidth) || 0;
|
|
524
|
+
const borderT = parseFloat(style.borderTopWidth) || 0;
|
|
525
|
+
const borderR = parseFloat(style.borderRightWidth) || 0;
|
|
526
|
+
const borderB = parseFloat(style.borderBottomWidth) || 0;
|
|
527
|
+
const contentW = rect.width - borderL - borderR;
|
|
528
|
+
const contentH = rect.height - borderT - borderB;
|
|
529
|
+
const scaleX = canvas.width / contentW;
|
|
530
|
+
const scaleY = canvas.height / contentH;
|
|
520
531
|
return [
|
|
521
|
-
e.clientX - rect.left,
|
|
522
|
-
e.clientY - rect.top,
|
|
532
|
+
(e.clientX - rect.left - borderL) * scaleX,
|
|
533
|
+
(e.clientY - rect.top - borderT) * scaleY,
|
|
523
534
|
e.pressure
|
|
524
535
|
];
|
|
525
536
|
}, []);
|
|
@@ -628,8 +639,10 @@ function DesignerView({
|
|
|
628
639
|
const [newRoleName, setNewRoleName] = useState2("");
|
|
629
640
|
const [draggingFieldType, setDraggingFieldType] = useState2(null);
|
|
630
641
|
const [panelWidth, setPanelWidth] = useState2(380);
|
|
642
|
+
const [clipboardField, setClipboardField] = useState2(null);
|
|
631
643
|
const dragGhostRef = useRef3(null);
|
|
632
644
|
const resizingRef = useRef3(false);
|
|
645
|
+
const lastStylesRef = useRef3({});
|
|
633
646
|
useEffect2(() => {
|
|
634
647
|
const pdfUrl = initialPdfUrl || initialTemplate?.pdfUrl;
|
|
635
648
|
if (pdfUrl) {
|
|
@@ -677,15 +690,24 @@ function DesignerView({
|
|
|
677
690
|
}, [loadPdf]);
|
|
678
691
|
const handlePageClick = useCallback3((page, x, y) => {
|
|
679
692
|
const field = createField(activeFieldType, activeRole, page, x, y, fields);
|
|
680
|
-
|
|
681
|
-
|
|
693
|
+
const sticky = lastStylesRef.current[activeFieldType];
|
|
694
|
+
const styledField = sticky ? { ...field, ...sticky } : field;
|
|
695
|
+
setFields((prev) => [...prev, styledField]);
|
|
696
|
+
setSelectedFieldId(styledField.id);
|
|
682
697
|
setRightTab("properties");
|
|
683
698
|
}, [activeFieldType, activeRole, fields]);
|
|
684
699
|
const handleFieldMove = useCallback3((id, page, x, y) => {
|
|
685
700
|
setFields((prev) => prev.map((f) => f.id === id ? { ...f, page, x, y } : f));
|
|
686
701
|
}, []);
|
|
687
702
|
const handleFieldResize = useCallback3((id, width, height) => {
|
|
688
|
-
setFields((prev) =>
|
|
703
|
+
setFields((prev) => {
|
|
704
|
+
const field = prev.find((f) => f.id === id);
|
|
705
|
+
if (field) {
|
|
706
|
+
const existing = lastStylesRef.current[field.type] || {};
|
|
707
|
+
lastStylesRef.current[field.type] = { ...existing, width, height, fontSize: field.fontSize };
|
|
708
|
+
}
|
|
709
|
+
return prev.map((f) => f.id === id ? { ...f, width, height } : f);
|
|
710
|
+
});
|
|
689
711
|
}, []);
|
|
690
712
|
const handleFieldUpdate = useCallback3((id, updates) => {
|
|
691
713
|
setFields((prev) => {
|
|
@@ -693,7 +715,18 @@ function DesignerView({
|
|
|
693
715
|
const otherLabels = prev.filter((f) => f.id !== id).map((f) => f.label);
|
|
694
716
|
updates.label = uniqueLabel(updates.label, otherLabels);
|
|
695
717
|
}
|
|
696
|
-
|
|
718
|
+
const updated = prev.map((f) => f.id === id ? { ...f, ...updates } : f);
|
|
719
|
+
const field = prev.find((f) => f.id === id);
|
|
720
|
+
if (field && (updates.fontSize !== void 0 || updates.width !== void 0 || updates.height !== void 0 || updates.inkColor !== void 0)) {
|
|
721
|
+
const merged = { ...field, ...updates };
|
|
722
|
+
lastStylesRef.current[field.type] = {
|
|
723
|
+
width: merged.width,
|
|
724
|
+
height: merged.height,
|
|
725
|
+
fontSize: merged.fontSize,
|
|
726
|
+
inkColor: merged.inkColor
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
return updated;
|
|
697
730
|
});
|
|
698
731
|
}, []);
|
|
699
732
|
const handleFieldDelete = useCallback3((id) => {
|
|
@@ -759,8 +792,10 @@ function DesignerView({
|
|
|
759
792
|
}, []);
|
|
760
793
|
const handleDropOnPage = useCallback3((page, x, y, fieldType) => {
|
|
761
794
|
const field = createField(fieldType, activeRole, page, x, y, fields);
|
|
762
|
-
|
|
763
|
-
|
|
795
|
+
const sticky = lastStylesRef.current[fieldType];
|
|
796
|
+
const styledField = sticky ? { ...field, ...sticky } : field;
|
|
797
|
+
setFields((prev) => [...prev, styledField]);
|
|
798
|
+
setSelectedFieldId(styledField.id);
|
|
764
799
|
setRightTab("properties");
|
|
765
800
|
}, [activeRole, fields]);
|
|
766
801
|
useEffect2(() => {
|
|
@@ -778,6 +813,38 @@ function DesignerView({
|
|
|
778
813
|
window.addEventListener("keydown", handleKeyDown);
|
|
779
814
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
780
815
|
}, [selectedFieldId, handleFieldDelete]);
|
|
816
|
+
useEffect2(() => {
|
|
817
|
+
const handleKeyDown = (e) => {
|
|
818
|
+
const tag = (document.activeElement?.tagName || "").toLowerCase();
|
|
819
|
+
if (tag === "input" || tag === "textarea" || tag === "select") return;
|
|
820
|
+
if (document.activeElement?.isContentEditable) return;
|
|
821
|
+
const isMod = e.metaKey || e.ctrlKey;
|
|
822
|
+
if (isMod && e.key === "c" && selectedFieldId) {
|
|
823
|
+
const field = fields.find((f) => f.id === selectedFieldId);
|
|
824
|
+
if (field) {
|
|
825
|
+
e.preventDefault();
|
|
826
|
+
setClipboardField(field);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
if (isMod && e.key === "v" && clipboardField) {
|
|
830
|
+
e.preventDefault();
|
|
831
|
+
const existingLabels = fields.map((f) => f.label);
|
|
832
|
+
const newField = {
|
|
833
|
+
...clipboardField,
|
|
834
|
+
id: generateId(),
|
|
835
|
+
label: uniqueLabel(clipboardField.label, existingLabels),
|
|
836
|
+
x: clipboardField.x + 2,
|
|
837
|
+
y: clipboardField.y + 2,
|
|
838
|
+
value: ""
|
|
839
|
+
};
|
|
840
|
+
setFields((prev) => [...prev, newField]);
|
|
841
|
+
setSelectedFieldId(newField.id);
|
|
842
|
+
setRightTab("properties");
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
846
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
847
|
+
}, [selectedFieldId, fields, clipboardField]);
|
|
781
848
|
const handleResizeStart = useCallback3((e) => {
|
|
782
849
|
e.preventDefault();
|
|
783
850
|
resizingRef.current = true;
|
|
@@ -1149,7 +1216,8 @@ function FieldNavigator({
|
|
|
1149
1216
|
currentFieldId,
|
|
1150
1217
|
onNavigate,
|
|
1151
1218
|
allRequiredFilled,
|
|
1152
|
-
onSubmit
|
|
1219
|
+
onSubmit,
|
|
1220
|
+
submitLabel = "Complete"
|
|
1153
1221
|
}) {
|
|
1154
1222
|
const currentIndex = fields.findIndex((f) => f.id === currentFieldId);
|
|
1155
1223
|
const hasPrev = currentIndex > 0;
|
|
@@ -1203,7 +1271,7 @@ function FieldNavigator({
|
|
|
1203
1271
|
onClick: onSubmit,
|
|
1204
1272
|
disabled: !allRequiredFilled,
|
|
1205
1273
|
className: "submit-btn",
|
|
1206
|
-
children:
|
|
1274
|
+
children: submitLabel
|
|
1207
1275
|
}
|
|
1208
1276
|
)
|
|
1209
1277
|
] });
|
|
@@ -1218,7 +1286,8 @@ function SignerView({
|
|
|
1218
1286
|
initialSigner,
|
|
1219
1287
|
callbackUrl: initialCallbackUrl,
|
|
1220
1288
|
onComplete,
|
|
1221
|
-
initialValues
|
|
1289
|
+
initialValues,
|
|
1290
|
+
submitLabel
|
|
1222
1291
|
} = {}) {
|
|
1223
1292
|
if (!isValidApiKey(apiKey)) {
|
|
1224
1293
|
return /* @__PURE__ */ jsx6("div", { className: "signer-layout", children: /* @__PURE__ */ jsxs6("div", { className: "empty-state", children: [
|
|
@@ -1290,14 +1359,14 @@ function SignerView({
|
|
|
1290
1359
|
setLoading(false);
|
|
1291
1360
|
}
|
|
1292
1361
|
}, []);
|
|
1293
|
-
const editableFields = fields.filter((f) => f.assignee === signer).sort((a, b) => {
|
|
1362
|
+
const editableFields = fields.filter((f) => f.assignee === signer && f.type !== "blackout" && f.type !== "whiteout").sort((a, b) => {
|
|
1294
1363
|
if (a.page !== b.page) return a.page - b.page;
|
|
1295
1364
|
const bandThreshold = 2;
|
|
1296
1365
|
if (Math.abs(a.y - b.y) > bandThreshold) return a.y - b.y;
|
|
1297
1366
|
return a.x - b.x;
|
|
1298
1367
|
});
|
|
1299
1368
|
const selectedField = fields.find((f) => f.id === selectedFieldId) || null;
|
|
1300
|
-
const isFieldEditable = selectedField ? selectedField.assignee === signer : false;
|
|
1369
|
+
const isFieldEditable = selectedField ? selectedField.assignee === signer && selectedField.type !== "blackout" && selectedField.type !== "whiteout" : false;
|
|
1301
1370
|
const handleFieldUpdate = useCallback4((id, value) => {
|
|
1302
1371
|
setFields((prev) => prev.map((f) => f.id === id ? { ...f, value } : f));
|
|
1303
1372
|
}, []);
|
|
@@ -1339,6 +1408,9 @@ function SignerView({
|
|
|
1339
1408
|
}
|
|
1340
1409
|
}, [pdfSource, fields, callbackUrl, allRequiredFilled, onComplete]);
|
|
1341
1410
|
const renderFieldContent = useCallback4((field) => {
|
|
1411
|
+
if (field.type === "blackout" || field.type === "whiteout") {
|
|
1412
|
+
return null;
|
|
1413
|
+
}
|
|
1342
1414
|
const editable = field.assignee === signer;
|
|
1343
1415
|
if (!editable) {
|
|
1344
1416
|
if (field.type === "signature" || field.type === "initials") {
|
|
@@ -1460,7 +1532,8 @@ function SignerView({
|
|
|
1460
1532
|
currentFieldId: selectedFieldId,
|
|
1461
1533
|
onNavigate: handleNavigate,
|
|
1462
1534
|
allRequiredFilled,
|
|
1463
|
-
onSubmit: handleSubmit
|
|
1535
|
+
onSubmit: handleSubmit,
|
|
1536
|
+
submitLabel
|
|
1464
1537
|
}
|
|
1465
1538
|
),
|
|
1466
1539
|
submitting && /* @__PURE__ */ jsx6("div", { className: "loading-indicator", children: "Generating PDF..." })
|