mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-24 04:26:14 +00:00
Delete signature
This commit is contained in:
parent
fc2f34ee15
commit
bac61c7e9e
@ -461,6 +461,7 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{/* Signature Creation based on type */}
|
{/* Signature Creation based on type */}
|
||||||
{parameters.signatureType === 'canvas' && (
|
{parameters.signatureType === 'canvas' && (
|
||||||
<Paper withBorder p="md">
|
<Paper withBorder p="md">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState, useRef } from 'react';
|
||||||
import { createPluginRegistration } from '@embedpdf/core';
|
import { createPluginRegistration } from '@embedpdf/core';
|
||||||
import { EmbedPDF } from '@embedpdf/core/react';
|
import { EmbedPDF } from '@embedpdf/core/react';
|
||||||
import { usePdfiumEngine } from '@embedpdf/engines/react';
|
import { usePdfiumEngine } from '@embedpdf/engines/react';
|
||||||
@ -46,6 +46,7 @@ interface LocalEmbedPDFProps {
|
|||||||
|
|
||||||
export function LocalEmbedPDF({ file, url, enableSignature = false, onSignatureAdded, signatureApiRef }: LocalEmbedPDFProps) {
|
export function LocalEmbedPDF({ file, url, enableSignature = false, onSignatureAdded, signatureApiRef }: LocalEmbedPDFProps) {
|
||||||
const [pdfUrl, setPdfUrl] = useState<string | null>(null);
|
const [pdfUrl, setPdfUrl] = useState<string | null>(null);
|
||||||
|
const [annotations, setAnnotations] = useState<Array<{id: string, pageIndex: number, rect: any}>>([]);
|
||||||
|
|
||||||
// Convert File to URL if needed
|
// Convert File to URL if needed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -217,14 +218,34 @@ export function LocalEmbedPDF({ file, url, enableSignature = false, onSignatureA
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for annotation events to notify parent component
|
// Listen for annotation events to track annotations and notify parent
|
||||||
if (onSignatureAdded) {
|
annotationApi.onAnnotationEvent((event: any) => {
|
||||||
annotationApi.onAnnotationEvent((event: any) => {
|
if (event.type === 'create' && event.committed) {
|
||||||
if (event.type === 'create' && event.committed) {
|
// Add to annotations list
|
||||||
|
setAnnotations(prev => [...prev, {
|
||||||
|
id: event.annotation.id,
|
||||||
|
pageIndex: event.pageIndex,
|
||||||
|
rect: event.annotation.rect
|
||||||
|
}]);
|
||||||
|
|
||||||
|
|
||||||
|
// Notify parent if callback provided
|
||||||
|
if (onSignatureAdded) {
|
||||||
onSignatureAdded(event.annotation);
|
onSignatureAdded(event.annotation);
|
||||||
}
|
}
|
||||||
});
|
} else if (event.type === 'delete' && event.committed) {
|
||||||
}
|
// Remove from annotations list
|
||||||
|
setAnnotations(prev => prev.filter(ann => ann.id !== event.annotation.id));
|
||||||
|
} else if (event.type === 'loaded') {
|
||||||
|
// Handle initial load of annotations
|
||||||
|
const loadedAnnotations = event.annotations || [];
|
||||||
|
setAnnotations(loadedAnnotations.map((ann: any) => ({
|
||||||
|
id: ann.id,
|
||||||
|
pageIndex: ann.pageIndex || 0,
|
||||||
|
rect: ann.rect
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
});
|
||||||
} : undefined}
|
} : undefined}
|
||||||
>
|
>
|
||||||
<ZoomAPIBridge />
|
<ZoomAPIBridge />
|
||||||
@ -297,6 +318,7 @@ export function LocalEmbedPDF({ file, url, enableSignature = false, onSignatureA
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Viewport>
|
</Viewport>
|
||||||
|
|
||||||
</GlobalPointerProvider>
|
</GlobalPointerProvider>
|
||||||
</EmbedPDF>
|
</EmbedPDF>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,6 +9,8 @@ export interface SignatureAPI {
|
|||||||
addTextSignature: (text: string, x: number, y: number, pageIndex: number) => void;
|
addTextSignature: (text: string, x: number, y: number, pageIndex: number) => void;
|
||||||
activateDrawMode: () => void;
|
activateDrawMode: () => void;
|
||||||
activateSignaturePlacementMode: () => void;
|
activateSignaturePlacementMode: () => void;
|
||||||
|
activateDeleteMode: () => void;
|
||||||
|
deleteAnnotation: (annotationId: string, pageIndex: number) => void;
|
||||||
updateDrawSettings: (color: string, size: number) => void;
|
updateDrawSettings: (color: string, size: number) => void;
|
||||||
deactivateTools: () => void;
|
deactivateTools: () => void;
|
||||||
applySignatureFromParameters: (params: SignParameters) => void;
|
applySignatureFromParameters: (params: SignParameters) => void;
|
||||||
@ -20,6 +22,30 @@ export const SignatureAPIBridge = forwardRef<SignatureAPI, SignatureAPIBridgePro
|
|||||||
const { provides: annotationApi } = useAnnotationCapability();
|
const { provides: annotationApi } = useAnnotationCapability();
|
||||||
const { signatureConfig } = useSignature();
|
const { signatureConfig } = useSignature();
|
||||||
|
|
||||||
|
// Enable keyboard deletion of selected annotations
|
||||||
|
useEffect(() => {
|
||||||
|
if (!annotationApi) return;
|
||||||
|
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if (event.key === 'Delete' || event.key === 'Backspace') {
|
||||||
|
const selectedAnnotation = annotationApi.getSelectedAnnotation?.();
|
||||||
|
|
||||||
|
if (selectedAnnotation) {
|
||||||
|
const annotation = selectedAnnotation as any;
|
||||||
|
const pageIndex = annotation.object?.pageIndex || 0;
|
||||||
|
const id = annotation.object?.id;
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
annotationApi.deleteAnnotation(pageIndex, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => document.removeEventListener('keydown', handleKeyDown);
|
||||||
|
}, [annotationApi]);
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
addImageSignature: (signatureData: string, x: number, y: number, width: number, height: number, pageIndex: number) => {
|
addImageSignature: (signatureData: string, x: number, y: number, width: number, height: number, pageIndex: number) => {
|
||||||
if (!annotationApi) return;
|
if (!annotationApi) return;
|
||||||
@ -183,6 +209,19 @@ export const SignatureAPIBridge = forwardRef<SignatureAPI, SignatureAPIBridgePro
|
|||||||
}, 50);
|
}, 50);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
activateDeleteMode: () => {
|
||||||
|
if (!annotationApi) return;
|
||||||
|
// Activate selection tool to allow selecting and deleting annotations
|
||||||
|
// Users can click annotations to select them, then press Delete key or right-click to delete
|
||||||
|
annotationApi.setActiveTool('select');
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteAnnotation: (annotationId: string, pageIndex: number) => {
|
||||||
|
if (!annotationApi) return;
|
||||||
|
// Delete specific annotation by ID
|
||||||
|
annotationApi.deleteAnnotation(pageIndex, annotationId);
|
||||||
|
},
|
||||||
|
|
||||||
deactivateTools: () => {
|
deactivateTools: () => {
|
||||||
if (!annotationApi) return;
|
if (!annotationApi) return;
|
||||||
annotationApi.setActiveTool(null);
|
annotationApi.setActiveTool(null);
|
||||||
@ -208,6 +247,11 @@ export const SignatureAPIBridge = forwardRef<SignatureAPI, SignatureAPIBridgePro
|
|||||||
id: uuidV4(),
|
id: uuidV4(),
|
||||||
created: new Date(),
|
created: new Date(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Switch to select mode after placing signature so it can be easily deleted
|
||||||
|
setTimeout(() => {
|
||||||
|
annotationApi.setActiveTool('select');
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -231,6 +275,11 @@ export const SignatureAPIBridge = forwardRef<SignatureAPI, SignatureAPIBridgePro
|
|||||||
id: uuidV4(),
|
id: uuidV4(),
|
||||||
created: new Date(),
|
created: new Date(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Switch to select mode after placing signature so it can be easily deleted
|
||||||
|
setTimeout(() => {
|
||||||
|
annotationApi.setActiveTool('select');
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ interface SignatureActions {
|
|||||||
activateDrawMode: () => void;
|
activateDrawMode: () => void;
|
||||||
deactivateDrawMode: () => void;
|
deactivateDrawMode: () => void;
|
||||||
activateSignaturePlacementMode: () => void;
|
activateSignaturePlacementMode: () => void;
|
||||||
|
activateDeleteMode: () => void;
|
||||||
updateDrawSettings: (color: string, size: number) => void;
|
updateDrawSettings: (color: string, size: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +87,13 @@ export const SignatureProvider: React.FC<{ children: ReactNode }> = ({ children
|
|||||||
}
|
}
|
||||||
}, [state.signatureConfig, setPlacementMode]);
|
}, [state.signatureConfig, setPlacementMode]);
|
||||||
|
|
||||||
|
const activateDeleteMode = useCallback(() => {
|
||||||
|
if (signatureApiRef.current) {
|
||||||
|
signatureApiRef.current.activateDeleteMode();
|
||||||
|
setPlacementMode(true);
|
||||||
|
}
|
||||||
|
}, [setPlacementMode]);
|
||||||
|
|
||||||
const updateDrawSettings = useCallback((color: string, size: number) => {
|
const updateDrawSettings = useCallback((color: string, size: number) => {
|
||||||
if (signatureApiRef.current) {
|
if (signatureApiRef.current) {
|
||||||
signatureApiRef.current.updateDrawSettings(color, size);
|
signatureApiRef.current.updateDrawSettings(color, size);
|
||||||
@ -103,6 +111,7 @@ export const SignatureProvider: React.FC<{ children: ReactNode }> = ({ children
|
|||||||
activateDrawMode,
|
activateDrawMode,
|
||||||
deactivateDrawMode,
|
deactivateDrawMode,
|
||||||
activateSignaturePlacementMode,
|
activateSignaturePlacementMode,
|
||||||
|
activateDeleteMode,
|
||||||
updateDrawSettings,
|
updateDrawSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user