2022-08-27 14:32:20 +02:00
|
|
|
import { useEffect, useRef, useState, MutableRefObject } from 'react';
|
|
|
|
import * as React from 'react';
|
2022-09-05 13:35:38 +02:00
|
|
|
import PdfDocument from './PdfDocument';
|
2022-08-04 11:12:22 +02:00
|
|
|
import Page from './Page';
|
2022-08-27 14:32:20 +02:00
|
|
|
import styled from 'styled-components';
|
|
|
|
import useScaledSize, { ScaledSizeParams } from './hooks/useScaledSize';
|
2022-08-28 13:18:51 +02:00
|
|
|
import useScrollSaver, { ScrollSaver } from './hooks/useScrollSaver';
|
2022-08-04 11:12:22 +02:00
|
|
|
|
|
|
|
|
2022-08-27 14:32:20 +02:00
|
|
|
const PagesHolder = styled.div<{ pageGap: number }>`
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
flex-flow: column;
|
2022-08-28 13:18:51 +02:00
|
|
|
min-width: 100%;
|
2022-09-11 15:58:32 +02:00
|
|
|
width: fit-content;
|
2022-09-05 13:35:38 +02:00
|
|
|
min-height: fit-content;
|
2022-08-27 14:32:20 +02:00
|
|
|
row-gap: ${(props)=> props.pageGap || 2}px;
|
|
|
|
`;
|
2022-08-04 11:12:22 +02:00
|
|
|
|
|
|
|
export interface VerticalPagesProps {
|
2022-09-05 13:35:38 +02:00
|
|
|
pdfDocument: PdfDocument;
|
2022-08-04 11:12:22 +02:00
|
|
|
isDarkTheme: boolean;
|
2022-08-27 14:32:20 +02:00
|
|
|
anchorPage?: number;
|
2022-09-11 15:58:32 +02:00
|
|
|
rememberScroll: boolean;
|
2022-08-27 14:32:20 +02:00
|
|
|
pdfId?: string;
|
2022-09-11 15:58:32 +02:00
|
|
|
zoom: number;
|
2022-08-27 14:32:20 +02:00
|
|
|
container: MutableRefObject<HTMLElement>;
|
2022-09-05 13:35:38 +02:00
|
|
|
pageGap: number;
|
2022-09-11 15:58:32 +02:00
|
|
|
widthPercent?: number;
|
|
|
|
showPageNumbers: boolean;
|
|
|
|
selectedPage?: number;
|
|
|
|
textSelectable: boolean;
|
|
|
|
onTextSelect?: (text: string)=> void;
|
|
|
|
onPageClick?: (page: number)=> void;
|
|
|
|
onActivePageChange?: (page: number)=> void;
|
|
|
|
onDoubleClick?: (page: number)=> void;
|
2022-08-04 11:12:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export default function VerticalPages(props: VerticalPagesProps) {
|
2022-08-27 14:32:20 +02:00
|
|
|
const [containerWidth, setContainerWidth] = useState<number>(null);
|
2022-08-04 11:12:22 +02:00
|
|
|
const innerContainerEl = useRef<HTMLDivElement>(null);
|
2022-08-28 13:18:51 +02:00
|
|
|
|
2022-08-27 14:32:20 +02:00
|
|
|
const scaledSize = useScaledSize({
|
2022-09-05 13:35:38 +02:00
|
|
|
pdfDocument: props.pdfDocument,
|
2022-08-27 14:32:20 +02:00
|
|
|
pdfId: props.pdfId,
|
|
|
|
containerWidth,
|
|
|
|
rememberScroll: props.rememberScroll,
|
|
|
|
anchorPage: props.anchorPage,
|
|
|
|
container: props.container,
|
|
|
|
innerContainerEl,
|
|
|
|
pageGap: props.pageGap,
|
2022-08-28 13:18:51 +02:00
|
|
|
zoom: props.zoom,
|
2022-08-27 14:32:20 +02:00
|
|
|
} as ScaledSizeParams);
|
|
|
|
|
2022-08-28 13:18:51 +02:00
|
|
|
useScrollSaver({
|
|
|
|
container: props.container,
|
|
|
|
scaledSize,
|
|
|
|
pdfId: props.pdfId,
|
|
|
|
rememberScroll: props.rememberScroll,
|
2022-09-05 13:35:38 +02:00
|
|
|
pdfDocument: props.pdfDocument,
|
|
|
|
pageGap: props.pageGap,
|
|
|
|
onActivePageChange: props.onActivePageChange,
|
2022-08-28 13:18:51 +02:00
|
|
|
} as ScrollSaver);
|
|
|
|
|
2022-08-27 14:32:20 +02:00
|
|
|
useEffect(() => {
|
2022-08-04 11:12:22 +02:00
|
|
|
let resizeTimer: number = null;
|
|
|
|
let cancelled = false;
|
2022-08-27 14:32:20 +02:00
|
|
|
|
|
|
|
const updateWidth = () => {
|
|
|
|
if (cancelled) return;
|
2022-09-11 15:58:32 +02:00
|
|
|
const factor = (props.widthPercent || 100) / 100;
|
|
|
|
setContainerWidth(props.container.current.clientWidth * factor);
|
2022-08-04 11:12:22 +02:00
|
|
|
};
|
2022-08-27 14:32:20 +02:00
|
|
|
|
2022-08-04 11:12:22 +02:00
|
|
|
const onResize = () => {
|
|
|
|
if (resizeTimer) {
|
|
|
|
clearTimeout(resizeTimer);
|
|
|
|
resizeTimer = null;
|
|
|
|
}
|
2022-08-27 14:32:20 +02:00
|
|
|
resizeTimer = window.setTimeout(updateWidth, 200);
|
2022-08-04 11:12:22 +02:00
|
|
|
};
|
2022-08-27 14:32:20 +02:00
|
|
|
|
|
|
|
updateWidth();
|
2022-08-04 11:12:22 +02:00
|
|
|
window.addEventListener('resize', onResize);
|
2022-08-27 14:32:20 +02:00
|
|
|
|
2022-08-04 11:12:22 +02:00
|
|
|
return () => {
|
|
|
|
cancelled = true;
|
|
|
|
window.removeEventListener('resize', onResize);
|
|
|
|
if (resizeTimer) {
|
|
|
|
clearTimeout(resizeTimer);
|
|
|
|
resizeTimer = null;
|
|
|
|
}
|
|
|
|
};
|
2022-09-11 15:58:32 +02:00
|
|
|
}, [props.container, props.pdfDocument, props.widthPercent]);
|
2022-08-27 14:32:20 +02:00
|
|
|
|
|
|
|
return (<PagesHolder pageGap={props.pageGap || 2} ref={innerContainerEl} >
|
|
|
|
{scaledSize ?
|
2022-09-05 13:35:38 +02:00
|
|
|
Array.from(Array(props.pdfDocument.pageCount).keys()).map((i: number) => {
|
2022-08-27 14:32:20 +02:00
|
|
|
// setting focusOnLoad only after scaledSize is set so that the container height is set correctly
|
2022-09-05 13:35:38 +02:00
|
|
|
return <Page pdfDocument={props.pdfDocument} pageNo={i + 1} focusOnLoad={scaledSize && props.anchorPage && props.anchorPage === i + 1}
|
2022-08-27 14:32:20 +02:00
|
|
|
isAnchored={props.anchorPage && props.anchorPage === i + 1}
|
|
|
|
showPageNumbers={props.showPageNumbers}
|
2022-09-11 15:58:32 +02:00
|
|
|
isSelected={scaledSize && props.selectedPage && props.selectedPage === i + 1}
|
|
|
|
onClick={props.onPageClick}
|
|
|
|
textSelectable={props.textSelectable}
|
|
|
|
onTextSelect={props.onTextSelect}
|
|
|
|
onDoubleClick={props.onDoubleClick}
|
2022-08-27 14:32:20 +02:00
|
|
|
isDarkTheme={props.isDarkTheme} scaledSize={scaledSize} container={props.container} key={i} />;
|
2023-08-22 12:58:53 +02:00
|
|
|
},
|
2022-10-26 17:04:08 +02:00
|
|
|
) : ''
|
2022-08-04 11:12:22 +02:00
|
|
|
}
|
2022-08-27 14:32:20 +02:00
|
|
|
</PagesHolder>);
|
2022-08-04 11:12:22 +02:00
|
|
|
}
|