Compare commits

...
Author SHA1 Message Date
Frooodle a48da724ee Merge branch 'main' into fix/viewer-pan-mode-text-selection-lock 2026-07-13 09:27:52 +01:00
Frooodle 0530b0d2f5 merge main 2026-07-10 10:39:59 +01:00
Frooodle e2d4ac2431 merge main 2026-07-06 18:45:18 +01:00
Frooodle 24f5d63cfa merge main 2026-07-02 09:36:30 +01:00
Frooodle 2df406eed3 merge main 2026-07-01 08:43:52 +01:00
Frooodle 5efef66a58 merge main 2026-06-30 08:25:42 +01:00
Frooodle 9ebbd08b4b merge main 2026-06-29 11:19:25 +01:00
Frooodle 934ba9d8f9 merge main 2026-06-27 08:18:33 +01:00
Frooodle 144344d1c8 merge main 2026-06-25 13:57:27 +01:00
Frooodle 65ed0a0326 merge main 2026-06-25 09:32:39 +01:00
Frooodle 288a68b831 merge main 2026-06-24 10:19:25 +01:00
Frooodle abfbac75ea Merge remote-tracking branch 'origin/main' into fix/viewer-pan-mode-text-selection-lock 2026-06-23 15:22:47 +01:00
Anthony StirlingandGitHub 2ec34b7968 Merge branch 'main' into fix/viewer-pan-mode-text-selection-lock 2026-06-19 17:02:02 +01:00
Anthony Stirling e104d47dc1 fix(viewer): always restore text selection when pan is toggled off 2026-06-19 15:01:22 +01:00
2 changed files with 30 additions and 17 deletions
@@ -1,5 +1,6 @@
import { useEffect, useRef } from "react";
import { usePan } from "@embedpdf/plugin-pan/react";
import { useInteractionManagerCapability } from "@embedpdf/plugin-interaction-manager/react";
import { useViewer } from "@app/contexts/ViewerContext";
import { useActiveDocumentId } from "@app/components/viewer/useActiveDocumentId";
import { useDocumentReady } from "@app/components/viewer/hooks/useDocumentReady";
@@ -21,13 +22,18 @@ export function PanAPIBridge() {
function PanAPIBridgeInner({ documentId }: { documentId: string }) {
const { provides: pan, isPanning } = usePan(documentId);
const { provides: imCapability } = useInteractionManagerCapability();
const { registerBridge, triggerImmediatePanUpdate } = useViewer();
// Keep pan ref updated to avoid re-running effect when object reference changes
// Keep refs updated to avoid re-running effect when object references change
const panRef = useRef(pan);
useEffect(() => {
panRef.current = pan;
}, [pan]);
const imRef = useRef(imCapability);
useEffect(() => {
imRef.current = imCapability;
}, [imCapability]);
// Track previous isPanning value to detect changes
const prevIsPanningRef = useRef<boolean>(isPanning);
@@ -39,6 +45,17 @@ function PanAPIBridgeInner({ documentId }: { documentId: string }) {
isPanning,
};
// Pan off must always land in selection (pointerMode), not the default mode -
// if pan ever became the default, disablePan/togglePan couldn't escape it (#5175).
const goToPointerMode = () => {
const im = imRef.current;
if (im) {
im.forDocument(documentId).activate("pointerMode");
} else {
currentPan.disablePan();
}
};
// Register this bridge with ViewerContext
registerBridge("pan", {
state: newState,
@@ -47,22 +64,20 @@ function PanAPIBridgeInner({ documentId }: { documentId: string }) {
currentPan.enablePan();
},
disable: () => {
currentPan.disablePan();
goToPointerMode();
},
toggle: () => {
currentPan.togglePan();
},
makePanDefault: () => {
// v2.5.0: makePanDefault may not exist, enable pan as fallback
if (
"makePanDefault" in currentPan &&
typeof (currentPan as any).makePanDefault === "function"
) {
(currentPan as any).makePanDefault();
if (isPanning) {
goToPointerMode();
} else {
currentPan.enablePan();
}
},
makePanDefault: () => {
// Never make pan the default mode (that is what locks the viewer in
// #5175). Just enable pan for the current interaction.
currentPan.enablePan();
},
},
});
@@ -75,7 +90,7 @@ function PanAPIBridgeInner({ documentId }: { documentId: string }) {
return () => {
registerBridge("pan", null);
};
}, [isPanning, registerBridge, triggerImmediatePanUpdate]);
}, [isPanning, registerBridge, triggerImmediatePanUpdate, documentId]);
return null;
}
@@ -209,12 +209,10 @@ export function useViewerWorkbenchBarButtons(
disabled:
!isPanning && pendingCount > 0 && redactionActiveType !== null,
onClick: () => {
// Don't optimistically flip isPanning - it must reflect the real EmbedPDF
// mode so the button can't show "off" while still stuck in pan (#5175).
viewer.panActions.togglePan();
setIsPanning((prev) => {
const next = !prev;
if (next && isRulerActive) setIsRulerActive?.(false);
return next;
});
if (!isPanning && isRulerActive) setIsRulerActive?.(false);
},
},
{