feat(12-02): FieldPlacer onFieldsChanged callback prop after every persistFields call

- Add onFieldsChanged?: () => void to FieldPlacerProps interface
- Destructure onFieldsChanged in function signature
- Call onFieldsChanged?.() after persistFields in handleDragEnd (new field drop)
- Call onFieldsChanged?.() after persistFields in handleZonePointerUp move case
- Call onFieldsChanged?.() after persistFields in handleZonePointerUp resize case
- Call onFieldsChanged?.() after persistFields in delete button onClick
- Add onFieldsChanged to useCallback dependency arrays (handleDragEnd, handleZonePointerUp)
This commit is contained in:
Chandler Copeland
2026-03-21 15:36:56 -06:00
parent de195a3e80
commit 720d07fd54

View File

@@ -155,9 +155,10 @@ interface FieldPlacerProps {
currentPage: number; currentPage: number;
children: React.ReactNode; children: React.ReactNode;
readOnly?: boolean; readOnly?: boolean;
onFieldsChanged?: () => void;
} }
export function FieldPlacer({ docId, pageInfo, currentPage, children, readOnly = false }: FieldPlacerProps) { export function FieldPlacer({ docId, pageInfo, currentPage, children, readOnly = false, onFieldsChanged }: FieldPlacerProps) {
const [fields, setFields] = useState<SignatureFieldData[]>([]); const [fields, setFields] = useState<SignatureFieldData[]>([]);
const [isDraggingToken, setIsDraggingToken] = useState<string | null>(null); const [isDraggingToken, setIsDraggingToken] = useState<string | null>(null);
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
@@ -294,8 +295,9 @@ export function FieldPlacer({ docId, pageInfo, currentPage, children, readOnly =
const next = [...fields, newField]; const next = [...fields, newField];
setFields(next); setFields(next);
persistFields(docId, next); persistFields(docId, next);
onFieldsChanged?.();
}, },
[fields, pageInfo, currentPage, docId, readOnly], [fields, pageInfo, currentPage, docId, readOnly, onFieldsChanged],
); );
// --- Move / Resize pointer handlers (event delegation on DroppableZone) --- // --- Move / Resize pointer handlers (event delegation on DroppableZone) ---
@@ -477,6 +479,7 @@ export function FieldPlacer({ docId, pageInfo, currentPage, children, readOnly =
}); });
setFields(next); setFields(next);
persistFields(docId, next); persistFields(docId, next);
onFieldsChanged?.();
} else if (drag.type === 'resize') { } else if (drag.type === 'resize') {
const corner = drag.corner ?? 'se'; const corner = drag.corner ?? 'se';
const startW = drag.startFieldW ?? 144; const startW = drag.startFieldW ?? 144;
@@ -543,8 +546,9 @@ export function FieldPlacer({ docId, pageInfo, currentPage, children, readOnly =
}); });
setFields(next); setFields(next);
persistFields(docId, next); persistFields(docId, next);
onFieldsChanged?.();
} }
}, [docId]); }, [docId, onFieldsChanged]);
// Render placed fields for the current page // Render placed fields for the current page
// Uses pageInfo.width/height (not getBoundingClientRect) for consistent coordinate math // Uses pageInfo.width/height (not getBoundingClientRect) for consistent coordinate math
@@ -653,6 +657,7 @@ export function FieldPlacer({ docId, pageInfo, currentPage, children, readOnly =
const next = fields.filter((f) => f.id !== field.id); const next = fields.filter((f) => f.id !== field.id);
setFields(next); setFields(next);
persistFields(docId, next); persistFields(docId, next);
onFieldsChanged?.();
}} }}
onPointerDown={(e) => { onPointerDown={(e) => {
// Prevent dnd-kit sensors and move handler from capturing this pointer event // Prevent dnd-kit sensors and move handler from capturing this pointer event