From 312fc2d615393bb0ff26b0e01fb65a4141431229 Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Thu, 18 Sep 2025 02:14:31 +0100 Subject: [PATCH] Clean up --- frontend/src/components/shared/RightRail.tsx | 1 - .../src/components/viewer/EmbedPdfViewer.tsx | 3 +- .../components/viewer/PdfViewerToolbar.tsx | 1 - .../src/components/viewer/ScrollAPIBridge.tsx | 18 +-- .../src/components/viewer/SearchInterface.tsx | 5 +- .../components/viewer/SelectionAPIBridge.tsx | 8 -- .../src/components/viewer/SpreadAPIBridge.tsx | 10 +- .../components/viewer/ThumbnailSidebar.tsx | 19 +-- .../src/components/viewer/ZoomAPIBridge.tsx | 18 +-- frontend/src/contexts/ViewerContext.tsx | 118 ++++++++++-------- frontend/src/types/embedPdf.ts | 57 --------- 11 files changed, 78 insertions(+), 180 deletions(-) delete mode 100644 frontend/src/types/embedPdf.ts diff --git a/frontend/src/components/shared/RightRail.tsx b/frontend/src/components/shared/RightRail.tsx index 67bf1d41e..caffbee07 100644 --- a/frontend/src/components/shared/RightRail.tsx +++ b/frontend/src/components/shared/RightRail.tsx @@ -7,7 +7,6 @@ import { useRightRail } from '../../contexts/RightRailContext'; import { useFileState, useFileSelection, useFileManagement } from '../../contexts/FileContext'; import { useNavigationState } from '../../contexts/NavigationContext'; import { useTranslation } from 'react-i18next'; -import '../../types/embedPdf'; import LanguageSelector from '../shared/LanguageSelector'; import { useRainbowThemeContext } from '../shared/RainbowThemeProvider'; diff --git a/frontend/src/components/viewer/EmbedPdfViewer.tsx b/frontend/src/components/viewer/EmbedPdfViewer.tsx index b4590db00..74a3e40c8 100644 --- a/frontend/src/components/viewer/EmbedPdfViewer.tsx +++ b/frontend/src/components/viewer/EmbedPdfViewer.tsx @@ -9,7 +9,6 @@ import { useViewer } from "../../contexts/ViewerContext"; import { LocalEmbedPDF } from './LocalEmbedPDF'; import { PdfViewerToolbar } from './PdfViewerToolbar'; import { ThumbnailSidebar } from './ThumbnailSidebar'; -import '../../types/embedPdf'; export interface EmbedPdfViewerProps { sidebarsVisible: boolean; @@ -200,7 +199,7 @@ const EmbedPdfViewerContent = ({ currentPage={scrollState.currentPage} totalPages={scrollState.totalPages} onPageChange={(page) => { - // Placeholder - will implement page navigation later + // Page navigation handled by scrollActions console.log('Navigate to page:', page); }} dualPage={spreadState.isDualPage} diff --git a/frontend/src/components/viewer/PdfViewerToolbar.tsx b/frontend/src/components/viewer/PdfViewerToolbar.tsx index cb1f126eb..2064182db 100644 --- a/frontend/src/components/viewer/PdfViewerToolbar.tsx +++ b/frontend/src/components/viewer/PdfViewerToolbar.tsx @@ -8,7 +8,6 @@ import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; import LastPageIcon from '@mui/icons-material/LastPage'; import DescriptionIcon from '@mui/icons-material/Description'; import ViewWeekIcon from '@mui/icons-material/ViewWeek'; -import '../../types/embedPdf'; interface PdfViewerToolbarProps { // Page navigation props (placeholders for now) diff --git a/frontend/src/components/viewer/ScrollAPIBridge.tsx b/frontend/src/components/viewer/ScrollAPIBridge.tsx index d34548a18..45522f7f8 100644 --- a/frontend/src/components/viewer/ScrollAPIBridge.tsx +++ b/frontend/src/components/viewer/ScrollAPIBridge.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect } from 'react'; import { useScroll } from '@embedpdf/plugin-scroll/react'; import { useViewer } from '../../contexts/ViewerContext'; @@ -9,11 +9,6 @@ import { useViewer } from '../../contexts/ViewerContext'; export function ScrollAPIBridge() { const { provides: scroll, state: scrollState } = useScroll(); const { registerBridge, triggerImmediateScrollUpdate } = useViewer(); - - const [_localState, setLocalState] = useState({ - currentPage: 1, - totalPages: 0 - }); useEffect(() => { if (scroll && scrollState) { @@ -22,15 +17,8 @@ export function ScrollAPIBridge() { totalPages: scrollState.totalPages, }; - setLocalState(prevState => { - // Only update if state actually changed - if (prevState.currentPage !== newState.currentPage || prevState.totalPages !== newState.totalPages) { - // Trigger immediate update for responsive UI - triggerImmediateScrollUpdate(newState.currentPage, newState.totalPages); - return newState; - } - return prevState; - }); + // Trigger immediate update for responsive UI + triggerImmediateScrollUpdate(newState.currentPage, newState.totalPages); registerBridge('scroll', { state: newState, diff --git a/frontend/src/components/viewer/SearchInterface.tsx b/frontend/src/components/viewer/SearchInterface.tsx index 0712fbff7..ff91153ad 100644 --- a/frontend/src/components/viewer/SearchInterface.tsx +++ b/frontend/src/components/viewer/SearchInterface.tsx @@ -13,8 +13,9 @@ export function SearchInterface({ visible, onClose }: SearchInterfaceProps) { const { t } = useTranslation(); const viewerContext = React.useContext(ViewerContext); - const searchResults = viewerContext?.getSearchResults(); - const searchActiveIndex = viewerContext?.getSearchActiveIndex(); + const searchState = viewerContext?.getSearchState(); + const searchResults = searchState?.results; + const searchActiveIndex = searchState?.activeIndex; const searchActions = viewerContext?.searchActions; const [searchQuery, setSearchQuery] = useState(''); const [jumpToValue, setJumpToValue] = useState(''); diff --git a/frontend/src/components/viewer/SelectionAPIBridge.tsx b/frontend/src/components/viewer/SelectionAPIBridge.tsx index 2125a7242..f57c8dd78 100644 --- a/frontend/src/components/viewer/SelectionAPIBridge.tsx +++ b/frontend/src/components/viewer/SelectionAPIBridge.tsx @@ -9,19 +9,12 @@ export function SelectionAPIBridge() { const { provides: selection } = useSelectionCapability(); const { registerBridge } = useViewer(); const [hasSelection, setHasSelection] = useState(false); - - // Store state locally - const [_localState, setLocalState] = useState({ - hasSelection: false - }); useEffect(() => { if (selection) { - // Update local state const newState = { hasSelection }; - setLocalState(newState); // Register this bridge with ViewerContext registerBridge('selection', { @@ -38,7 +31,6 @@ export function SelectionAPIBridge() { const hasText = !!sel; setHasSelection(hasText); const updatedState = { hasSelection: hasText }; - setLocalState(updatedState); // Re-register with updated state registerBridge('selection', { state: updatedState, diff --git a/frontend/src/components/viewer/SpreadAPIBridge.tsx b/frontend/src/components/viewer/SpreadAPIBridge.tsx index 58a19aed6..81a2eaa99 100644 --- a/frontend/src/components/viewer/SpreadAPIBridge.tsx +++ b/frontend/src/components/viewer/SpreadAPIBridge.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect } from 'react'; import { useSpread, SpreadMode } from '@embedpdf/plugin-spread/react'; import { useViewer } from '../../contexts/ViewerContext'; @@ -8,21 +8,13 @@ import { useViewer } from '../../contexts/ViewerContext'; export function SpreadAPIBridge() { const { provides: spread, spreadMode } = useSpread(); const { registerBridge } = useViewer(); - - // Store state locally - const [_localState, setLocalState] = useState({ - spreadMode: SpreadMode.None, - isDualPage: false - }); useEffect(() => { if (spread) { - // Update local state const newState = { spreadMode, isDualPage: spreadMode !== SpreadMode.None }; - setLocalState(newState); // Register this bridge with ViewerContext registerBridge('spread', { diff --git a/frontend/src/components/viewer/ThumbnailSidebar.tsx b/frontend/src/components/viewer/ThumbnailSidebar.tsx index 02f257786..8a9b42bda 100644 --- a/frontend/src/components/viewer/ThumbnailSidebar.tsx +++ b/frontend/src/components/viewer/ThumbnailSidebar.tsx @@ -1,7 +1,6 @@ import React, { useState, useEffect } from 'react'; import { Box, ScrollArea } from '@mantine/core'; import { useViewer } from '../../contexts/ViewerContext'; -import '../../types/embedPdf'; interface ThumbnailSidebarProps { visible: boolean; @@ -19,39 +18,25 @@ export function ThumbnailSidebar({ visible, onToggle: _onToggle }: ThumbnailSide // Generate thumbnails when sidebar becomes visible useEffect(() => { if (!visible || scrollState.totalPages === 0) return; - - console.log('📄 ThumbnailSidebar useEffect triggered:', { - visible, - thumbnailAPI: !!thumbnailAPI, - totalPages: scrollState.totalPages, - existingThumbnails: Object.keys(thumbnails).length - }); - if (!thumbnailAPI) return; const generateThumbnails = async () => { - console.log('📄 Starting thumbnail generation for', scrollState.totalPages, 'pages'); - for (let pageIndex = 0; pageIndex < scrollState.totalPages; pageIndex++) { if (thumbnails[pageIndex]) continue; // Skip if already generated try { - console.log('📄 Attempting to generate thumbnail for page', pageIndex + 1); - const thumbTask = thumbnailAPI.renderThumb(pageIndex, 1.0); - console.log('📄 Received thumbTask:', thumbTask); + const thumbTask = (thumbnailAPI as any).renderThumb(pageIndex, 1.0); // Convert Task to Promise and handle properly thumbTask.toPromise().then((thumbBlob: Blob) => { - console.log('📄 Thumbnail generated successfully for page', pageIndex + 1, 'blob:', thumbBlob); const thumbUrl = URL.createObjectURL(thumbBlob); - console.log('📄 Created blob URL:', thumbUrl); setThumbnails(prev => ({ ...prev, [pageIndex]: thumbUrl })); }).catch((error: any) => { - console.error('📄 Failed to generate thumbnail for page', pageIndex + 1, error); + console.error('Failed to generate thumbnail for page', pageIndex + 1, error); setThumbnails(prev => ({ ...prev, [pageIndex]: 'error' diff --git a/frontend/src/components/viewer/ZoomAPIBridge.tsx b/frontend/src/components/viewer/ZoomAPIBridge.tsx index 568cbdf97..8cb0f4fcc 100644 --- a/frontend/src/components/viewer/ZoomAPIBridge.tsx +++ b/frontend/src/components/viewer/ZoomAPIBridge.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; import { useZoom } from '@embedpdf/plugin-zoom/react'; import { useViewer } from '../../contexts/ViewerContext'; @@ -7,21 +7,14 @@ import { useViewer } from '../../contexts/ViewerContext'; */ export function ZoomAPIBridge() { const { provides: zoom, state: zoomState } = useZoom(); - const { registerBridge } = useViewer(); + const { registerBridge, triggerImmediateZoomUpdate } = useViewer(); const hasSetInitialZoom = useRef(false); - // Store state locally - const [_localState, setLocalState] = useState({ - currentZoom: 1.4, - zoomPercent: 140 - }); - // Set initial zoom once when plugin is ready useEffect(() => { if (zoom && !hasSetInitialZoom.current) { hasSetInitialZoom.current = true; setTimeout(() => { - console.log('Setting initial zoom to 140%'); zoom.requestZoom(1.4); }, 50); } @@ -35,10 +28,9 @@ export function ZoomAPIBridge() { currentZoom: currentZoomLevel, zoomPercent: Math.round(currentZoomLevel * 100), }; - - console.log('ZoomAPIBridge - Raw zoom level:', currentZoomLevel, 'Rounded percent:', newState.zoomPercent); - - setLocalState(newState); + + // Trigger immediate update for responsive UI + triggerImmediateZoomUpdate(newState.zoomPercent); // Register this bridge with ViewerContext registerBridge('zoom', { diff --git a/frontend/src/contexts/ViewerContext.tsx b/frontend/src/contexts/ViewerContext.tsx index 41c91b842..2224a666d 100644 --- a/frontend/src/contexts/ViewerContext.tsx +++ b/frontend/src/contexts/ViewerContext.tsx @@ -1,4 +1,5 @@ import React, { createContext, useContext, useState, ReactNode, useRef } from 'react'; +import { SpreadMode } from '@embedpdf/plugin-spread/react'; // State interfaces - represent the shape of data from each bridge interface ScrollState { @@ -20,7 +21,7 @@ interface SelectionState { } interface SpreadState { - spreadMode: any; + spreadMode: SpreadMode; isDualPage: boolean; } @@ -28,10 +29,15 @@ interface RotationState { rotation: number; } +interface SearchState { + results: any[] | null; + activeIndex: number; +} + // Bridge registration interface - bridges register with state and API -interface BridgeRef { - state: any; - api: any; +interface BridgeRef { + state: TState; + api: TApi; } /** @@ -55,9 +61,8 @@ interface ViewerContextType { getSelectionState: () => SelectionState; getSpreadState: () => SpreadState; getRotationState: () => RotationState; - getSearchResults: () => any[] | null; - getSearchActiveIndex: () => number; - getThumbnailAPI: () => any; + getSearchState: () => SearchState; + getThumbnailAPI: () => unknown; // Immediate update callbacks registerImmediateZoomUpdate: (callback: (percent: number) => void) => void; @@ -65,6 +70,7 @@ interface ViewerContextType { // Internal - for bridges to trigger immediate updates triggerImmediateScrollUpdate: (currentPage: number, totalPages: number) => void; + triggerImmediateZoomUpdate: (zoomPercent: number) => void; // Action handlers - call EmbedPDF APIs directly scrollActions: { @@ -91,12 +97,12 @@ interface ViewerContextType { selectionActions: { copyToClipboard: () => void; getSelectedText: () => string; - getFormattedSelection: () => any; + getFormattedSelection: () => unknown; }; spreadActions: { - setSpreadMode: (mode: any) => void; - getSpreadMode: () => any; + setSpreadMode: (mode: SpreadMode) => void; + getSpreadMode: () => SpreadMode; toggleSpreadMode: () => void; }; @@ -130,14 +136,14 @@ export const ViewerProvider: React.FC = ({ children }) => { // Bridge registry - bridges register their state and APIs here const bridgeRefs = useRef({ - scroll: null as BridgeRef | null, - zoom: null as BridgeRef | null, - pan: null as BridgeRef | null, - selection: null as BridgeRef | null, - search: null as BridgeRef | null, - spread: null as BridgeRef | null, - rotation: null as BridgeRef | null, - thumbnail: null as BridgeRef | null, + scroll: null as BridgeRef | null, + zoom: null as BridgeRef | null, + pan: null as BridgeRef | null, + selection: null as BridgeRef | null, + search: null as BridgeRef | null, + spread: null as BridgeRef | null, + rotation: null as BridgeRef | null, + thumbnail: null as BridgeRef | null, }); // Immediate zoom callback for responsive display updates @@ -147,7 +153,7 @@ export const ViewerProvider: React.FC = ({ children }) => { const immediateScrollUpdateCallback = useRef<((currentPage: number, totalPages: number) => void) | null>(null); const registerBridge = (type: string, ref: BridgeRef) => { - bridgeRefs.current[type as keyof typeof bridgeRefs.current] = ref; + (bridgeRefs.current as any)[type] = ref; }; const toggleThumbnailSidebar = () => { @@ -172,19 +178,15 @@ export const ViewerProvider: React.FC = ({ children }) => { }; const getSpreadState = (): SpreadState => { - return bridgeRefs.current.spread?.state || { spreadMode: null, isDualPage: false }; + return bridgeRefs.current.spread?.state || { spreadMode: SpreadMode.None, isDualPage: false }; }; const getRotationState = (): RotationState => { return bridgeRefs.current.rotation?.state || { rotation: 0 }; }; - const getSearchResults = () => { - return bridgeRefs.current.search?.state?.results || null; - }; - - const getSearchActiveIndex = () => { - return bridgeRefs.current.search?.state?.activeIndex || 0; + const getSearchState = (): SearchState => { + return bridgeRefs.current.search?.state || { results: null, activeIndex: 0 }; }; const getThumbnailAPI = () => { @@ -194,32 +196,32 @@ export const ViewerProvider: React.FC = ({ children }) => { // Action handlers - call APIs directly const scrollActions = { scrollToPage: (page: number) => { - const api = bridgeRefs.current.scroll?.api; + const api = bridgeRefs.current.scroll?.api as any; if (api?.scrollToPage) { api.scrollToPage({ pageNumber: page }); } }, scrollToFirstPage: () => { - const api = bridgeRefs.current.scroll?.api; + const api = bridgeRefs.current.scroll?.api as any; if (api?.scrollToPage) { api.scrollToPage({ pageNumber: 1 }); } }, scrollToPreviousPage: () => { - const api = bridgeRefs.current.scroll?.api; + const api = bridgeRefs.current.scroll?.api as any; if (api?.scrollToPreviousPage) { api.scrollToPreviousPage(); } }, scrollToNextPage: () => { - const api = bridgeRefs.current.scroll?.api; + const api = bridgeRefs.current.scroll?.api as any; if (api?.scrollToNextPage) { api.scrollToNextPage(); } }, scrollToLastPage: () => { const scrollState = getScrollState(); - const api = bridgeRefs.current.scroll?.api; + const api = bridgeRefs.current.scroll?.api as any; if (api?.scrollToPage && scrollState.totalPages > 0) { api.scrollToPage({ pageNumber: scrollState.totalPages }); } @@ -228,7 +230,7 @@ export const ViewerProvider: React.FC = ({ children }) => { const zoomActions = { zoomIn: () => { - const api = bridgeRefs.current.zoom?.api; + const api = bridgeRefs.current.zoom?.api as any; if (api?.zoomIn) { // Update display immediately if callback is registered if (immediateZoomUpdateCallback.current) { @@ -240,7 +242,7 @@ export const ViewerProvider: React.FC = ({ children }) => { } }, zoomOut: () => { - const api = bridgeRefs.current.zoom?.api; + const api = bridgeRefs.current.zoom?.api as any; if (api?.zoomOut) { // Update display immediately if callback is registered if (immediateZoomUpdateCallback.current) { @@ -252,13 +254,13 @@ export const ViewerProvider: React.FC = ({ children }) => { } }, toggleMarqueeZoom: () => { - const api = bridgeRefs.current.zoom?.api; + const api = bridgeRefs.current.zoom?.api as any; if (api?.toggleMarqueeZoom) { api.toggleMarqueeZoom(); } }, requestZoom: (level: number) => { - const api = bridgeRefs.current.zoom?.api; + const api = bridgeRefs.current.zoom?.api as any; if (api?.requestZoom) { api.requestZoom(level); } @@ -267,19 +269,19 @@ export const ViewerProvider: React.FC = ({ children }) => { const panActions = { enablePan: () => { - const api = bridgeRefs.current.pan?.api; + const api = bridgeRefs.current.pan?.api as any; if (api?.enable) { api.enable(); } }, disablePan: () => { - const api = bridgeRefs.current.pan?.api; + const api = bridgeRefs.current.pan?.api as any; if (api?.disable) { api.disable(); } }, togglePan: () => { - const api = bridgeRefs.current.pan?.api; + const api = bridgeRefs.current.pan?.api as any; if (api?.toggle) { api.toggle(); } @@ -288,20 +290,20 @@ export const ViewerProvider: React.FC = ({ children }) => { const selectionActions = { copyToClipboard: () => { - const api = bridgeRefs.current.selection?.api; + const api = bridgeRefs.current.selection?.api as any; if (api?.copyToClipboard) { api.copyToClipboard(); } }, getSelectedText: () => { - const api = bridgeRefs.current.selection?.api; + const api = bridgeRefs.current.selection?.api as any; if (api?.getSelectedText) { return api.getSelectedText(); } return ''; }, getFormattedSelection: () => { - const api = bridgeRefs.current.selection?.api; + const api = bridgeRefs.current.selection?.api as any; if (api?.getFormattedSelection) { return api.getFormattedSelection(); } @@ -310,21 +312,21 @@ export const ViewerProvider: React.FC = ({ children }) => { }; const spreadActions = { - setSpreadMode: (mode: any) => { - const api = bridgeRefs.current.spread?.api; + setSpreadMode: (mode: SpreadMode) => { + const api = bridgeRefs.current.spread?.api as any; if (api?.setSpreadMode) { api.setSpreadMode(mode); } }, getSpreadMode: () => { - const api = bridgeRefs.current.spread?.api; + const api = bridgeRefs.current.spread?.api as any; if (api?.getSpreadMode) { return api.getSpreadMode(); } return null; }, toggleSpreadMode: () => { - const api = bridgeRefs.current.spread?.api; + const api = bridgeRefs.current.spread?.api as any; if (api?.toggleSpreadMode) { api.toggleSpreadMode(); } @@ -333,25 +335,25 @@ export const ViewerProvider: React.FC = ({ children }) => { const rotationActions = { rotateForward: () => { - const api = bridgeRefs.current.rotation?.api; + const api = bridgeRefs.current.rotation?.api as any; if (api?.rotateForward) { api.rotateForward(); } }, rotateBackward: () => { - const api = bridgeRefs.current.rotation?.api; + const api = bridgeRefs.current.rotation?.api as any; if (api?.rotateBackward) { api.rotateBackward(); } }, setRotation: (rotation: number) => { - const api = bridgeRefs.current.rotation?.api; + const api = bridgeRefs.current.rotation?.api as any; if (api?.setRotation) { api.setRotation(rotation); } }, getRotation: () => { - const api = bridgeRefs.current.rotation?.api; + const api = bridgeRefs.current.rotation?.api as any; if (api?.getRotation) { return api.getRotation(); } @@ -361,25 +363,25 @@ export const ViewerProvider: React.FC = ({ children }) => { const searchActions = { search: async (query: string) => { - const api = bridgeRefs.current.search?.api; + const api = bridgeRefs.current.search?.api as any; if (api?.search) { return api.search(query); } }, next: () => { - const api = bridgeRefs.current.search?.api; + const api = bridgeRefs.current.search?.api as any; if (api?.next) { api.next(); } }, previous: () => { - const api = bridgeRefs.current.search?.api; + const api = bridgeRefs.current.search?.api as any; if (api?.previous) { api.previous(); } }, clear: () => { - const api = bridgeRefs.current.search?.api; + const api = bridgeRefs.current.search?.api as any; if (api?.clear) { api.clear(); } @@ -400,6 +402,12 @@ export const ViewerProvider: React.FC = ({ children }) => { } }; + const triggerImmediateZoomUpdate = (zoomPercent: number) => { + if (immediateZoomUpdateCallback.current) { + immediateZoomUpdateCallback.current(zoomPercent); + } + }; + const value: ViewerContextType = { // UI state isThumbnailSidebarVisible, @@ -412,14 +420,14 @@ export const ViewerProvider: React.FC = ({ children }) => { getSelectionState, getSpreadState, getRotationState, - getSearchResults, - getSearchActiveIndex, + getSearchState, getThumbnailAPI, // Immediate updates registerImmediateZoomUpdate, registerImmediateScrollUpdate, triggerImmediateScrollUpdate, + triggerImmediateZoomUpdate, // Actions scrollActions, diff --git a/frontend/src/types/embedPdf.ts b/frontend/src/types/embedPdf.ts deleted file mode 100644 index 49ce2141c..000000000 --- a/frontend/src/types/embedPdf.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Types for EmbedPDF global APIs -export interface EmbedPdfZoomAPI { - zoomPercent: number; - zoomIn: () => void; - zoomOut: () => void; -} - -export interface EmbedPdfScrollAPI { - currentPage: number; - totalPages: number; - scrollToPage: (page: number) => void; - scrollToFirstPage: () => void; - scrollToPreviousPage: () => void; - scrollToNextPage: () => void; - scrollToLastPage: () => void; -} - -export interface EmbedPdfPanAPI { - isPanning: boolean; - togglePan: () => void; -} - -export interface EmbedPdfSpreadAPI { - toggleSpreadMode: () => void; -} - -export interface EmbedPdfRotateAPI { - rotateForward: () => void; - rotateBackward: () => void; - setRotation: (rotation: number) => void; - getRotation: () => number; -} - -export interface EmbedPdfControlsAPI { - pointer: () => void; -} - -export interface EmbedPdfThumbnailAPI { - thumbnailAPI: { - renderThumb: (pageIndex: number, scale: number) => { - toPromise: () => Promise; - }; - }; -} - -declare global { - interface Window { - embedPdfZoom?: EmbedPdfZoomAPI; - embedPdfScroll?: EmbedPdfScrollAPI; - embedPdfPan?: EmbedPdfPanAPI; - embedPdfSpread?: EmbedPdfSpreadAPI; - embedPdfRotate?: EmbedPdfRotateAPI; - embedPdfControls?: EmbedPdfControlsAPI; - embedPdfThumbnail?: EmbedPdfThumbnailAPI; - toggleThumbnailSidebar?: () => void; - } -} \ No newline at end of file