import { requireNativeView } from "expo"; import * as React from "react"; import type { ExpoPdfViewProps, ExpoPdfViewRef } from "./ExpoPdf.types"; // Methods are attached to the ref (per Expo Modules docs), not the component. // We cast the native view to a forwardRef-compatible component so TS allows `ref`. type ExpoPdfNativeRef = { next?: () => void | Promise; prev?: () => void | Promise; goToPage?: (page: number) => void | Promise; getPage?: () => number | Promise; getPageCount?: () => number | Promise; }; const NativeView = requireNativeView( "ExpoPdf", ) as unknown as React.ForwardRefExoticComponent< ExpoPdfViewProps & React.RefAttributes >; export default React.forwardRef( function ExpoPdfView(props, ref) { const { onPageChanged } = props; const nativeRef = React.useRef(null); const pageRef = React.useRef(1); const pageCountRef = React.useRef(0); const resolvedSource = props.source; const handleLoad = React.useCallback( (event: Parameters>[0]) => { pageCountRef.current = event.nativeEvent.pageCount; props.onLoad(event); }, [props], ); const handlePageChanged = React.useCallback( ( event: Parameters>[0], ) => { pageRef.current = event.nativeEvent.page; // Update pageCount if provided by native (iOS does send it) if (typeof (event as any).nativeEvent?.pageCount === "number") { pageCountRef.current = (event as any).nativeEvent.pageCount as number; } // Clear any outstanding requested page once native confirms the page. setRequestedPage(undefined); onPageChanged?.(event); }, [onPageChanged], ); React.useImperativeHandle(ref, () => ({ next: () => nativeRef.current?.next?.() ?? internalSetPage(pageRef.current + 1), prev: () => nativeRef.current?.prev?.() ?? internalSetPage(pageRef.current - 1), goToPage: (page: number) => nativeRef.current?.goToPage?.(page) ?? internalSetPage(page), getPage: () => pageRef.current, getPageCount: () => pageCountRef.current, })); const [requestedPage, setRequestedPage] = React.useState< number | undefined >(undefined); const internalSetPage = (page: number) => { // Optimistically update our local current page so repeated calls are monotonic pageRef.current = page; setRequestedPage(page); }; return ( ); }, );