mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-04-22 23:08:53 +02:00
feat(annotation): add moveAnnotation API for efficient repositioning of annotations, and bump embed to 2.7.0 (#5809)
This commit is contained in:
@@ -7,6 +7,7 @@ import type {
|
||||
AnnotationAPI,
|
||||
AnnotationEvent,
|
||||
AnnotationPatch,
|
||||
AnnotationRect,
|
||||
} from '@app/components/viewer/viewerTypes';
|
||||
import { useDocumentReady } from '@app/components/viewer/hooks/useDocumentReady';
|
||||
|
||||
@@ -90,6 +91,8 @@ type AnnotationApiSurface = {
|
||||
updateAnnotation?: (pageIndex: number, annotationId: string, patch: AnnotationPatch) => void;
|
||||
onAnnotationEvent?: (listener: (event: AnnotationEvent) => void) => void | (() => void);
|
||||
purgeAnnotation?: (pageIndex: number, annotationId: string) => void;
|
||||
/** v2.7.0: move annotation without regenerating its appearance stream */
|
||||
moveAnnotation?: (pageIndex: number, annotationId: string, newRect: AnnotationRect) => void;
|
||||
};
|
||||
|
||||
type ToolDefaultsBuilder = (options?: AnnotationToolOptions) => AnnotationDefaults;
|
||||
@@ -301,7 +304,7 @@ export const AnnotationAPIBridge = forwardRef<AnnotationAPI>(function Annotation
|
||||
|
||||
const configureAnnotationTool = useCallback(
|
||||
(toolId: AnnotationToolId, options?: AnnotationToolOptions) => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
if (!api?.setActiveTool) return;
|
||||
|
||||
const defaults = buildAnnotationDefaults(toolId, options);
|
||||
@@ -328,13 +331,13 @@ export const AnnotationAPIBridge = forwardRef<AnnotationAPI>(function Annotation
|
||||
isReady: () => !!annotationApi && documentReady,
|
||||
setAnnotationStyle: (toolId: AnnotationToolId, options?: AnnotationToolOptions) => {
|
||||
const defaults = buildAnnotationDefaults(toolId, options);
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
if (defaults && api?.setToolDefaults) {
|
||||
api.setToolDefaults(toolId, defaults);
|
||||
}
|
||||
},
|
||||
getSelectedAnnotation: () => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
if (!api?.getSelectedAnnotation) {
|
||||
return null;
|
||||
}
|
||||
@@ -354,33 +357,38 @@ export const AnnotationAPIBridge = forwardRef<AnnotationAPI>(function Annotation
|
||||
}
|
||||
},
|
||||
deselectAnnotation: () => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
api?.deselectAnnotation?.();
|
||||
},
|
||||
updateAnnotation: (pageIndex: number, annotationId: string, patch: AnnotationPatch) => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
api?.updateAnnotation?.(pageIndex, annotationId, patch);
|
||||
},
|
||||
deactivateTools: () => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
api?.setActiveTool?.(null);
|
||||
},
|
||||
onAnnotationEvent: (listener: (event: AnnotationEvent) => void) => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
if (api?.onAnnotationEvent) {
|
||||
return api.onAnnotationEvent(listener);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
getActiveTool: () => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
return api?.getActiveTool?.() ?? null;
|
||||
},
|
||||
|
||||
purgeAnnotation: (pageIndex: number, annotationId: string) => {
|
||||
const api = annotationApi as AnnotationApiSurface | undefined;
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
api?.purgeAnnotation?.(pageIndex, annotationId);
|
||||
},
|
||||
|
||||
moveAnnotation: (pageIndex: number, annotationId: string, newRect: AnnotationRect) => {
|
||||
const api = annotationApi as unknown as AnnotationApiSurface | undefined;
|
||||
api?.moveAnnotation?.(pageIndex, annotationId, newRect);
|
||||
},
|
||||
}),
|
||||
[annotationApi, configureAnnotationTool, buildAnnotationDefaults]
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useImperativeHandle, forwardRef, useEffect, useCallback, useRef, useSta
|
||||
import { useAnnotationCapability } from '@embedpdf/plugin-annotation/react';
|
||||
import { PdfAnnotationSubtype, uuidV4 } from '@embedpdf/models';
|
||||
import { useSignature } from '@app/contexts/SignatureContext';
|
||||
import type { SignatureAPI } from '@app/components/viewer/viewerTypes';
|
||||
import type { SignatureAPI, AnnotationRect } from '@app/components/viewer/viewerTypes';
|
||||
import type { SignParameters } from '@app/hooks/tools/sign/useSignParameters';
|
||||
import { useViewer } from '@app/contexts/ViewerContext';
|
||||
import { useDocumentReady } from '@app/components/viewer/hooks/useDocumentReady';
|
||||
@@ -394,6 +394,13 @@ export const SignatureAPIBridge = forwardRef<SignatureAPI>(function SignatureAPI
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
moveAnnotation: (pageIndex: number, annotationId: string, newRect: AnnotationRect) => {
|
||||
if (!annotationApi) return;
|
||||
// v2.7.0: move signature stamp to newRect without regenerating the AP stream,
|
||||
// preserving the original appearance (image data stays intact).
|
||||
(annotationApi as any).moveAnnotation?.(pageIndex, annotationId, newRect);
|
||||
},
|
||||
}), [annotationApi, signatureConfig, placementPreviewSize, applyStampDefaults]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export interface AnnotationRect {
|
||||
origin: { x: number; y: number };
|
||||
size: { width: number; height: number };
|
||||
}
|
||||
|
||||
export interface SignatureAPI {
|
||||
addImageSignature: (
|
||||
signatureData: string,
|
||||
@@ -14,6 +19,7 @@ export interface SignatureAPI {
|
||||
updateDrawSettings: (color: string, size: number) => void;
|
||||
deactivateTools: () => void;
|
||||
getPageAnnotations: (pageIndex: number) => Promise<any[]>;
|
||||
moveAnnotation?: (pageIndex: number, annotationId: string, newRect: AnnotationRect) => void;
|
||||
}
|
||||
|
||||
export interface AnnotationAPI {
|
||||
@@ -26,6 +32,12 @@ export interface AnnotationAPI {
|
||||
onAnnotationEvent?: (listener: (event: AnnotationEvent) => void) => void | (() => void);
|
||||
getActiveTool?: () => { id: AnnotationToolId } | null;
|
||||
purgeAnnotation?: (pageIndex: number, annotationId: string) => void;
|
||||
/**
|
||||
* Move an annotation to a new position without regenerating its appearance stream.
|
||||
* Uses the embedPDF v2.7.0 moveAnnotation API for efficient repositioning of annotations
|
||||
* that have existing AP streams (e.g. stamps, signatures).
|
||||
*/
|
||||
moveAnnotation?: (pageIndex: number, annotationId: string, newRect: AnnotationRect) => void;
|
||||
}
|
||||
|
||||
export interface HistoryAPI {
|
||||
|
||||
Reference in New Issue
Block a user