@ligangyan/react-pdf
Advanced tools
Comparing version 9.1.1 to 9.1.2-SNAPSHOT
import LinkService from './LinkService.js'; | ||
import type { EventProps } from 'make-event-props'; | ||
import type { ClassName, DocumentCallback, ExternalLinkRel, ExternalLinkTarget, File, ImageResourcesPath, NodeOrRenderer, OnDocumentLoadError, OnDocumentLoadProgress, OnDocumentLoadSuccess, OnError, OnItemClickArgs, OnPasswordCallback, Options, PasswordResponse, RenderMode, ScrollPageIntoViewArgs } from './shared/types.js'; | ||
import type { ClassName, DocumentCallback, ExternalLinkRel, ExternalLinkTarget, File, ImageResourcesPath, NodeOrRenderer, OnDocumentLoadError, OnDocumentLoadProgress, OnDocumentLoadSuccess, OnError, OnItemClickArgs, OnPasswordCallback, Options, PasswordResponse, RenderMode, ScrollPageIntoViewArgs, XYWHP } from './shared/types.js'; | ||
type OnItemClick = (args: OnItemClickArgs) => void; | ||
@@ -123,3 +123,2 @@ type OnPassword = (callback: OnPasswordCallback, reason: PasswordResponse) => void; | ||
onSourceSuccess?: OnSourceSuccess; | ||
onCurrentPageNumberChange?: (currentPageNumber: number) => void; | ||
/** | ||
@@ -151,2 +150,3 @@ * An object in which additional parameters to be passed to PDF.js can be defined. Most notably: | ||
rotate?: number | null; | ||
highlight?: XYWHP[]; | ||
} & EventProps<DocumentCallback | false | undefined>; | ||
@@ -153,0 +153,0 @@ /** |
@@ -65,3 +65,2 @@ "use strict"; | ||
const useResolver_js_1 = __importDefault(require("./shared/hooks/useResolver.js")); | ||
const Page_js_1 = __importDefault(require("./Page.js")); | ||
const { PDFDataRangeTransport } = pdfjs; | ||
@@ -92,3 +91,3 @@ const defaultOnPassword = (callback, reason) => { | ||
const Document = (0, react_1.forwardRef)(function Document(_a, ref) { | ||
var { children, className, error = 'Failed to load PDF file.', externalLinkRel, externalLinkTarget, file, inputRef, imageResourcesPath, loading = 'Loading PDF…', noData = 'No PDF file specified.', onItemClick, onLoadError: onLoadErrorProps, onLoadProgress, onLoadSuccess: onLoadSuccessProps, onPassword = defaultOnPassword, onSourceError: onSourceErrorProps, onSourceSuccess: onSourceSuccessProps, onCurrentPageNumberChange: onCurrentPageNumberChangeProps, options, renderMode, rotate } = _a, otherProps = __rest(_a, ["children", "className", "error", "externalLinkRel", "externalLinkTarget", "file", "inputRef", "imageResourcesPath", "loading", "noData", "onItemClick", "onLoadError", "onLoadProgress", "onLoadSuccess", "onPassword", "onSourceError", "onSourceSuccess", "onCurrentPageNumberChange", "options", "renderMode", "rotate"]); | ||
var { children, className, error = 'Failed to load PDF file.', externalLinkRel, externalLinkTarget, file, inputRef, imageResourcesPath, loading = 'Loading PDF…', noData = 'No PDF file specified.', onItemClick, onLoadError: onLoadErrorProps, onLoadProgress, onLoadSuccess: onLoadSuccessProps, onPassword = defaultOnPassword, onSourceError: onSourceErrorProps, onSourceSuccess: onSourceSuccessProps, options, renderMode, rotate, highlight } = _a, otherProps = __rest(_a, ["children", "className", "error", "externalLinkRel", "externalLinkTarget", "file", "inputRef", "imageResourcesPath", "loading", "noData", "onItemClick", "onLoadError", "onLoadProgress", "onLoadSuccess", "onPassword", "onSourceError", "onSourceSuccess", "options", "renderMode", "rotate", "highlight"]); | ||
const [sourceState, sourceDispatch] = (0, useResolver_js_1.default)(); | ||
@@ -102,4 +101,2 @@ const { value: source, error: sourceError } = sourceState; | ||
const prevOptions = (0, react_1.useRef)(undefined); | ||
const containerRef = (0, react_1.useRef)(null); | ||
const [currentPageNumber, setCurrentPageNumber] = (0, react_1.useState)(null); | ||
if (file && file !== prevFile.current && isParameterObject(file)) { | ||
@@ -325,56 +322,9 @@ (0, warning_1.default)(!(0, dequal_1.dequal)(file, prevFile.current), `File prop passed to <Document /> changed, but it's equal to previous one. This might result in unnecessary reloads. Consider memoizing the value passed to "file" prop.`); | ||
unregisterPage, | ||
currentPageNumber, | ||
setCurrentPageNumber, | ||
}), [imageResourcesPath, onItemClick, pdf, registerPage, renderMode, rotate, unregisterPage, currentPageNumber, setCurrentPageNumber]); | ||
highlight, | ||
}), [imageResourcesPath, onItemClick, pdf, registerPage, renderMode, rotate, unregisterPage, highlight]); | ||
const eventProps = (0, react_1.useMemo)(() => (0, make_event_props_1.default)(otherProps, () => pdf), | ||
// biome-ignore lint/correctness/useExhaustiveDependencies: FIXME | ||
[otherProps, pdf]); | ||
const handleScroll = () => { | ||
if (!containerRef.current) { | ||
return; | ||
} | ||
const container = containerRef.current; | ||
const scrollTop = container.scrollTop; | ||
const pageHeight = container.clientHeight; | ||
// console.log('scrollTop:', scrollTop); | ||
// console.log('pageHeight:', pageHeight); | ||
// Calculate the current page based on the scroll position | ||
const newPageNumber = Math.floor(scrollTop / pageHeight) + 1; | ||
// currentPageNumber = newPageNumber; | ||
setCurrentPageNumber(newPageNumber); | ||
// console.log('Current Page:', newPageNumber); | ||
if (onCurrentPageNumberChangeProps) { | ||
onCurrentPageNumberChangeProps(newPageNumber); | ||
} | ||
}; | ||
const [searchText, setSearchText] = (0, react_1.useState)('Free'); | ||
function highlightPattern(text, pattern) { | ||
return text.replace(pattern, (value) => `<mark>${value}</mark>`); | ||
} | ||
// const textRenderer = useCallback( | ||
// (textItem: any) => highlightPattern(textItem.str, searchText), | ||
// [searchText] | ||
// ); | ||
const textRenderer = (textItem) => highlightPattern(textItem.str, searchText); | ||
function renderChildren() { | ||
if (!pdf || pdf.numPages === 0) { | ||
return null; | ||
} | ||
return ((0, jsx_runtime_1.jsx)(DocumentContext_js_1.default.Provider, { value: childContext, children: Array.from(new Array(pdf.numPages), (_el, index) => ((0, jsx_runtime_1.jsx)(Page_js_1.default | ||
// customHighlightRender={(p) => { | ||
// if (p.str === 'Useful Links') { | ||
// return true; | ||
// } else { | ||
// return false; | ||
// } | ||
// }} | ||
, { | ||
// customHighlightRender={(p) => { | ||
// if (p.str === 'Useful Links') { | ||
// return true; | ||
// } else { | ||
// return false; | ||
// } | ||
// }} | ||
customTextRenderer: textRenderer, height: 500, pageNumber: index + 1 }, `page_${index + 1}`))) })); | ||
return (0, jsx_runtime_1.jsx)(DocumentContext_js_1.default.Provider, { value: childContext, children: children }); | ||
} | ||
@@ -393,40 +343,8 @@ function renderContent() { | ||
} | ||
// return null; | ||
const checkVisibility = () => { | ||
const targetElement = document.getElementById('target-div'); | ||
if (targetElement) { | ||
console.log(targetElement); | ||
// const rect = targetElement.getBoundingClientRect(); | ||
// // Check if the div is in the viewport | ||
// const isInViewport = | ||
// rect.top >= 0 && | ||
// rect.left >= 0 && | ||
// rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && | ||
// rect.right <= (window.innerWidth || document.documentElement.clientWidth); | ||
// setIsVisible(isInViewport); | ||
} | ||
else { | ||
console.log('targetElement not found'); | ||
} | ||
}; | ||
// useEffect(() => { | ||
// // Attach scroll event listener | ||
// window.addEventListener('scroll', checkVisibility); | ||
// // Check visibility initially | ||
// checkVisibility(); | ||
// // Cleanup on unmount | ||
// return () => { | ||
// window.removeEventListener('scroll', checkVisibility); | ||
// }; | ||
// }, []); | ||
return ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, clsx_1.default)('react-pdf__Document', className), | ||
// Assertion is needed for React 18 compatibility | ||
// ref={inputRef as React.Ref<HTMLDivElement>} | ||
style: { | ||
ref: inputRef, style: { | ||
['--scale-factor']: '1', | ||
height: '500px', | ||
overflow: 'auto', | ||
backgroundColor: 'lightgray' | ||
} }, eventProps, { ref: containerRef, onScroll: handleScroll, children: renderContent() }))); | ||
} }, eventProps, { children: renderContent() }))); | ||
}); | ||
exports.default = Document; |
import type { PDFDocumentProxy } from 'pdfjs-dist'; | ||
import type { EventProps } from 'make-event-props'; | ||
import type { ClassName, CustomRenderer, CustomTextRenderer, CustomHighlightRender, NodeOrRenderer, OnGetAnnotationsError, OnGetAnnotationsSuccess, OnGetStructTreeError, OnGetStructTreeSuccess, OnGetTextError, OnGetTextSuccess, OnPageLoadError, OnPageLoadSuccess, OnRenderAnnotationLayerError, OnRenderAnnotationLayerSuccess, OnRenderError, OnRenderSuccess, OnRenderTextLayerError, OnRenderTextLayerSuccess, PageCallback, RenderMode } from './shared/types.js'; | ||
import type { ClassName, CustomRenderer, CustomTextRenderer, NodeOrRenderer, OnGetAnnotationsError, OnGetAnnotationsSuccess, OnGetStructTreeError, OnGetStructTreeSuccess, OnGetTextError, OnGetTextSuccess, OnPageLoadError, OnPageLoadSuccess, OnRenderAnnotationLayerError, OnRenderAnnotationLayerSuccess, OnRenderError, OnRenderSuccess, OnRenderTextLayerError, OnRenderTextLayerSuccess, PageCallback, RenderMode } from './shared/types.js'; | ||
export type PageProps = { | ||
@@ -41,3 +41,2 @@ _className?: string; | ||
customTextRenderer?: CustomTextRenderer; | ||
customHighlightRender?: CustomHighlightRender; | ||
/** | ||
@@ -197,3 +196,2 @@ * The ratio between physical pixels and device-independent pixels (DIPs) on the current device. | ||
/** | ||
* | ||
* pdf object obtained from `<Document />`'s `onLoadSuccess` callback function. | ||
@@ -200,0 +198,0 @@ * |
@@ -44,3 +44,3 @@ "use strict"; | ||
const mergedProps = Object.assign(Object.assign({}, documentContext), props); | ||
const { _className = 'react-pdf__Page', _enableRegisterUnregisterPage = true, canvasBackground, canvasRef, children, className, customRenderer: CustomRenderer, customTextRenderer, customHighlightRender, devicePixelRatio, error = 'Failed to load the page.', height, inputRef, loading = 'Loading page…', noData = 'No page specified.', onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onGetStructTreeError: onGetStructTreeErrorProps, onGetStructTreeSuccess: onGetStructTreeSuccessProps, onGetTextError: onGetTextErrorProps, onGetTextSuccess: onGetTextSuccessProps, onLoadError: onLoadErrorProps, onLoadSuccess: onLoadSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, onRenderError: onRenderErrorProps, onRenderSuccess: onRenderSuccessProps, onRenderTextLayerError: onRenderTextLayerErrorProps, onRenderTextLayerSuccess: onRenderTextLayerSuccessProps, pageIndex: pageIndexProps, pageNumber: pageNumberProps, pdf, registerPage, renderAnnotationLayer: renderAnnotationLayerProps = true, renderForms = false, renderMode = 'canvas', renderTextLayer: renderTextLayerProps = true, rotate: rotateProps, scale: scaleProps = defaultScale, unregisterPage, width } = mergedProps, otherProps = __rest(mergedProps, ["_className", "_enableRegisterUnregisterPage", "canvasBackground", "canvasRef", "children", "className", "customRenderer", "customTextRenderer", "customHighlightRender", "devicePixelRatio", "error", "height", "inputRef", "loading", "noData", "onGetAnnotationsError", "onGetAnnotationsSuccess", "onGetStructTreeError", "onGetStructTreeSuccess", "onGetTextError", "onGetTextSuccess", "onLoadError", "onLoadSuccess", "onRenderAnnotationLayerError", "onRenderAnnotationLayerSuccess", "onRenderError", "onRenderSuccess", "onRenderTextLayerError", "onRenderTextLayerSuccess", "pageIndex", "pageNumber", "pdf", "registerPage", "renderAnnotationLayer", "renderForms", "renderMode", "renderTextLayer", "rotate", "scale", "unregisterPage", "width"]); | ||
const { _className = 'react-pdf__Page', _enableRegisterUnregisterPage = true, canvasBackground, canvasRef, children, className, customRenderer: CustomRenderer, customTextRenderer, devicePixelRatio, error = 'Failed to load the page.', height, inputRef, loading = 'Loading page…', noData = 'No page specified.', onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onGetStructTreeError: onGetStructTreeErrorProps, onGetStructTreeSuccess: onGetStructTreeSuccessProps, onGetTextError: onGetTextErrorProps, onGetTextSuccess: onGetTextSuccessProps, onLoadError: onLoadErrorProps, onLoadSuccess: onLoadSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, onRenderError: onRenderErrorProps, onRenderSuccess: onRenderSuccessProps, onRenderTextLayerError: onRenderTextLayerErrorProps, onRenderTextLayerSuccess: onRenderTextLayerSuccessProps, pageIndex: pageIndexProps, pageNumber: pageNumberProps, pdf, registerPage, renderAnnotationLayer: renderAnnotationLayerProps = true, renderForms = false, renderMode = 'canvas', renderTextLayer: renderTextLayerProps = true, rotate: rotateProps, scale: scaleProps = defaultScale, unregisterPage, width } = mergedProps, otherProps = __rest(mergedProps, ["_className", "_enableRegisterUnregisterPage", "canvasBackground", "canvasRef", "children", "className", "customRenderer", "customTextRenderer", "devicePixelRatio", "error", "height", "inputRef", "loading", "noData", "onGetAnnotationsError", "onGetAnnotationsSuccess", "onGetStructTreeError", "onGetStructTreeSuccess", "onGetTextError", "onGetTextSuccess", "onLoadError", "onLoadSuccess", "onRenderAnnotationLayerError", "onRenderAnnotationLayerSuccess", "onRenderError", "onRenderSuccess", "onRenderTextLayerError", "onRenderTextLayerSuccess", "pageIndex", "pageNumber", "pdf", "registerPage", "renderAnnotationLayer", "renderForms", "renderMode", "renderTextLayer", "rotate", "scale", "unregisterPage", "width"]); | ||
const [pageState, pageDispatch] = (0, useResolver_js_1.default)(); | ||
@@ -154,3 +154,2 @@ const { value: page, error: pageError } = pageState; | ||
customTextRenderer, | ||
customHighlightRender, | ||
devicePixelRatio, | ||
@@ -181,3 +180,2 @@ onGetAnnotationsError: onGetAnnotationsErrorProps, | ||
customTextRenderer, | ||
customHighlightRender, | ||
devicePixelRatio, | ||
@@ -184,0 +182,0 @@ onGetAnnotationsErrorProps, |
@@ -47,3 +47,18 @@ "use strict"; | ||
const mergedProps = Object.assign(Object.assign({}, documentContext), pageContext); | ||
const { imageResourcesPath, linkService, onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, page, pdf, renderForms, rotate, scale = 1, } = mergedProps; | ||
const { imageResourcesPath, linkService, onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, page, pdf, renderForms, rotate, scale = 1, pageNumber, highlight, } = mergedProps; | ||
const XYWHPToScaledLTWHP = (xywhp, height, scale) => { | ||
const scaledXYWHP = { | ||
x: xywhp.x * scale, | ||
y: xywhp.y * scale, | ||
width: xywhp.width * scale, | ||
height: xywhp.height * scale, | ||
}; | ||
return { | ||
left: scaledXYWHP.x, | ||
top: height - scaledXYWHP.y - scaledXYWHP.height, | ||
width: scaledXYWHP.width, | ||
height: scaledXYWHP.height, | ||
pageNumber: xywhp.pageNumber, | ||
}; | ||
}; | ||
(0, tiny_invariant_1.default)(pdf, 'Attempted to load page annotations, but no document was specified. Wrap <Page /> in a <Document /> or pass explicit `pdf` prop.'); | ||
@@ -149,2 +164,31 @@ (0, tiny_invariant_1.default)(page, 'Attempted to load page annotations, but no page was specified.'); | ||
layer.innerHTML = ''; | ||
if (highlight) { | ||
const { width, height, scale } = clonedViewport; | ||
for (let i = 0; i < highlight.length; i++) { | ||
const h = highlight[i]; | ||
if (!h) { | ||
return; | ||
} | ||
const ltwhp = XYWHPToScaledLTWHP(h, height, scale); | ||
if (!ltwhp) { | ||
return; | ||
} | ||
if (ltwhp.pageNumber !== pageNumber) { | ||
return; | ||
} | ||
const highlightDiv = document.createElement('div'); | ||
highlightDiv.className = 'highlight11'; | ||
highlightDiv.style.left = `${ltwhp.left}px`; | ||
highlightDiv.style.top = `${ltwhp.top}px`; // 设置注释位置 | ||
highlightDiv.style.width = `${ltwhp.width}px`; // 设置注释宽度 | ||
highlightDiv.style.height = `${ltwhp.height}px`; // 设置注释高度 | ||
highlightDiv.style.position = 'absolute'; | ||
highlightDiv.style.mixBlendMode = 'multiply'; | ||
highlightDiv.style.backgroundColor = 'rgba(180,187,254)'; // 半透明的黄色背景模拟高亮 | ||
highlightDiv.style.opacity = '0.5'; | ||
highlightDiv.style.borderRadius = '2px'; | ||
highlightDiv.style.pointerEvents = 'none'; // 确保高亮不影响用户点击 | ||
layer.appendChild(highlightDiv); | ||
} | ||
} | ||
try { | ||
@@ -151,0 +195,0 @@ new pdfjs.AnnotationLayer(annotationLayerParameters).render(renderParameters); |
@@ -45,10 +45,5 @@ "use strict"; | ||
function TextLayer() { | ||
// const documentContext = useDocumentContext(); | ||
const pageContext = (0, usePageContext_js_1.default)(); | ||
(0, tiny_invariant_1.default)(pageContext, 'Unable to find Page context.'); | ||
// invariant(documentContext, 'Unable to find Document context.'); | ||
const { customTextRenderer, customHighlightRender, onGetTextError, onGetTextSuccess, onRenderTextLayerError, onRenderTextLayerSuccess, page, pageIndex, pageNumber, rotate, scale, } = pageContext; | ||
// const { | ||
// currentPageNumber | ||
// } = documentContext; | ||
const { customTextRenderer, onGetTextError, onGetTextSuccess, onRenderTextLayerError, onRenderTextLayerSuccess, page, pageIndex, pageNumber, rotate, scale, } = pageContext; | ||
(0, tiny_invariant_1.default)(page, 'Attempted to load page text content, but no page was specified.'); | ||
@@ -170,31 +165,2 @@ const [textContentState, textContentDispatch] = (0, useResolver_js_1.default)(); | ||
const layerChildren = layer.querySelectorAll('[role="presentation"]'); | ||
if (customHighlightRender) { | ||
let index = 0; | ||
textContent.items.forEach((item, itemIndex) => { | ||
if (!isTextItem(item)) { | ||
return; | ||
} | ||
const child = layerChildren[index]; | ||
if (!child) { | ||
return; | ||
} | ||
// if (currentPageNumber !== pageNumber) { | ||
// console.log('currentPageNumber !== pageNumber', currentPageNumber, pageNumber); | ||
// return; | ||
// } | ||
// console.log('currentPageNumber === pageNumber', currentPageNumber, pageNumber); | ||
const needsHighlight = customHighlightRender(Object.assign({ pageIndex, | ||
pageNumber, | ||
itemIndex }, item)); | ||
if (!needsHighlight) { | ||
return; | ||
} | ||
console.log('needsHighlight', item); | ||
//if needsHighlight is true, add background color to the text style | ||
const styleString = child.getAttribute('style'); | ||
child.setAttribute('style', styleString + 'background-color: yellow; color: inherit;'); | ||
// child.innerHTML = `<mark>${item.str}</mark>`; | ||
// index += item.str && item.hasEOL ? 2 : 1; | ||
}); | ||
} | ||
if (customTextRenderer) { | ||
@@ -201,0 +167,0 @@ let index = 0; |
@@ -48,7 +48,2 @@ import type { PDFDataRangeTransport, PDFDocumentProxy, PDFPageProxy, PasswordResponses } from 'pdfjs-dist'; | ||
} & TextItem) => string; | ||
export type CustomHighlightRender = (props: { | ||
pageIndex: number; | ||
pageNumber: number; | ||
itemIndex: number; | ||
} & TextItem) => boolean; | ||
export type DocumentCallback = PDFDocumentProxy; | ||
@@ -92,4 +87,3 @@ export type File = string | ArrayBuffer | Blob | Source | null; | ||
unregisterPage: UnregisterPage; | ||
currentPageNumber?: number | null; | ||
setCurrentPageNumber?: (pageNumber: number) => void; | ||
highlight?: XYWHP[] | null; | ||
} | null; | ||
@@ -100,3 +94,2 @@ export type PageContextType = { | ||
customTextRenderer?: CustomTextRenderer; | ||
customHighlightRender?: CustomHighlightRender; | ||
devicePixelRatio?: number; | ||
@@ -130,2 +123,16 @@ onGetAnnotationsError?: OnGetAnnotationsError; | ||
}; | ||
export type XYWHP = { | ||
x: number; | ||
y: number; | ||
width: number; | ||
height: number; | ||
pageNumber: number; | ||
}; | ||
export type LTWHP = { | ||
left: number; | ||
top: number; | ||
width: number; | ||
height: number; | ||
pageNumber: number; | ||
}; | ||
export {}; |
import LinkService from './LinkService.js'; | ||
import type { EventProps } from 'make-event-props'; | ||
import type { ClassName, DocumentCallback, ExternalLinkRel, ExternalLinkTarget, File, ImageResourcesPath, NodeOrRenderer, OnDocumentLoadError, OnDocumentLoadProgress, OnDocumentLoadSuccess, OnError, OnItemClickArgs, OnPasswordCallback, Options, PasswordResponse, RenderMode, ScrollPageIntoViewArgs } from './shared/types.js'; | ||
import type { ClassName, DocumentCallback, ExternalLinkRel, ExternalLinkTarget, File, ImageResourcesPath, NodeOrRenderer, OnDocumentLoadError, OnDocumentLoadProgress, OnDocumentLoadSuccess, OnError, OnItemClickArgs, OnPasswordCallback, Options, PasswordResponse, RenderMode, ScrollPageIntoViewArgs, XYWHP } from './shared/types.js'; | ||
type OnItemClick = (args: OnItemClickArgs) => void; | ||
@@ -123,3 +123,2 @@ type OnPassword = (callback: OnPasswordCallback, reason: PasswordResponse) => void; | ||
onSourceSuccess?: OnSourceSuccess; | ||
onCurrentPageNumberChange?: (currentPageNumber: number) => void; | ||
/** | ||
@@ -151,2 +150,3 @@ * An object in which additional parameters to be passed to PDF.js can be defined. Most notably: | ||
rotate?: number | null; | ||
highlight?: XYWHP[]; | ||
} & EventProps<DocumentCallback | false | undefined>; | ||
@@ -153,0 +153,0 @@ /** |
@@ -23,3 +23,3 @@ 'use client'; | ||
import { jsx as _jsx } from "react/jsx-runtime"; | ||
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; | ||
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'; | ||
import makeEventProps from 'make-event-props'; | ||
@@ -38,3 +38,2 @@ import makeCancellable from 'make-cancellable-promise'; | ||
import useResolver from './shared/hooks/useResolver.js'; | ||
import Page from "./Page.js"; | ||
const { PDFDataRangeTransport } = pdfjs; | ||
@@ -65,3 +64,3 @@ const defaultOnPassword = (callback, reason) => { | ||
const Document = forwardRef(function Document(_a, ref) { | ||
var { children, className, error = 'Failed to load PDF file.', externalLinkRel, externalLinkTarget, file, inputRef, imageResourcesPath, loading = 'Loading PDF…', noData = 'No PDF file specified.', onItemClick, onLoadError: onLoadErrorProps, onLoadProgress, onLoadSuccess: onLoadSuccessProps, onPassword = defaultOnPassword, onSourceError: onSourceErrorProps, onSourceSuccess: onSourceSuccessProps, onCurrentPageNumberChange: onCurrentPageNumberChangeProps, options, renderMode, rotate } = _a, otherProps = __rest(_a, ["children", "className", "error", "externalLinkRel", "externalLinkTarget", "file", "inputRef", "imageResourcesPath", "loading", "noData", "onItemClick", "onLoadError", "onLoadProgress", "onLoadSuccess", "onPassword", "onSourceError", "onSourceSuccess", "onCurrentPageNumberChange", "options", "renderMode", "rotate"]); | ||
var { children, className, error = 'Failed to load PDF file.', externalLinkRel, externalLinkTarget, file, inputRef, imageResourcesPath, loading = 'Loading PDF…', noData = 'No PDF file specified.', onItemClick, onLoadError: onLoadErrorProps, onLoadProgress, onLoadSuccess: onLoadSuccessProps, onPassword = defaultOnPassword, onSourceError: onSourceErrorProps, onSourceSuccess: onSourceSuccessProps, options, renderMode, rotate, highlight } = _a, otherProps = __rest(_a, ["children", "className", "error", "externalLinkRel", "externalLinkTarget", "file", "inputRef", "imageResourcesPath", "loading", "noData", "onItemClick", "onLoadError", "onLoadProgress", "onLoadSuccess", "onPassword", "onSourceError", "onSourceSuccess", "options", "renderMode", "rotate", "highlight"]); | ||
const [sourceState, sourceDispatch] = useResolver(); | ||
@@ -75,4 +74,2 @@ const { value: source, error: sourceError } = sourceState; | ||
const prevOptions = useRef(undefined); | ||
const containerRef = useRef(null); | ||
const [currentPageNumber, setCurrentPageNumber] = useState(null); | ||
if (file && file !== prevFile.current && isParameterObject(file)) { | ||
@@ -298,56 +295,9 @@ warning(!dequal(file, prevFile.current), `File prop passed to <Document /> changed, but it's equal to previous one. This might result in unnecessary reloads. Consider memoizing the value passed to "file" prop.`); | ||
unregisterPage, | ||
currentPageNumber, | ||
setCurrentPageNumber, | ||
}), [imageResourcesPath, onItemClick, pdf, registerPage, renderMode, rotate, unregisterPage, currentPageNumber, setCurrentPageNumber]); | ||
highlight, | ||
}), [imageResourcesPath, onItemClick, pdf, registerPage, renderMode, rotate, unregisterPage, highlight]); | ||
const eventProps = useMemo(() => makeEventProps(otherProps, () => pdf), | ||
// biome-ignore lint/correctness/useExhaustiveDependencies: FIXME | ||
[otherProps, pdf]); | ||
const handleScroll = () => { | ||
if (!containerRef.current) { | ||
return; | ||
} | ||
const container = containerRef.current; | ||
const scrollTop = container.scrollTop; | ||
const pageHeight = container.clientHeight; | ||
// console.log('scrollTop:', scrollTop); | ||
// console.log('pageHeight:', pageHeight); | ||
// Calculate the current page based on the scroll position | ||
const newPageNumber = Math.floor(scrollTop / pageHeight) + 1; | ||
// currentPageNumber = newPageNumber; | ||
setCurrentPageNumber(newPageNumber); | ||
// console.log('Current Page:', newPageNumber); | ||
if (onCurrentPageNumberChangeProps) { | ||
onCurrentPageNumberChangeProps(newPageNumber); | ||
} | ||
}; | ||
const [searchText, setSearchText] = useState('Free'); | ||
function highlightPattern(text, pattern) { | ||
return text.replace(pattern, (value) => `<mark>${value}</mark>`); | ||
} | ||
// const textRenderer = useCallback( | ||
// (textItem: any) => highlightPattern(textItem.str, searchText), | ||
// [searchText] | ||
// ); | ||
const textRenderer = (textItem) => highlightPattern(textItem.str, searchText); | ||
function renderChildren() { | ||
if (!pdf || pdf.numPages === 0) { | ||
return null; | ||
} | ||
return (_jsx(DocumentContext.Provider, { value: childContext, children: Array.from(new Array(pdf.numPages), (_el, index) => (_jsx(Page | ||
// customHighlightRender={(p) => { | ||
// if (p.str === 'Useful Links') { | ||
// return true; | ||
// } else { | ||
// return false; | ||
// } | ||
// }} | ||
, { | ||
// customHighlightRender={(p) => { | ||
// if (p.str === 'Useful Links') { | ||
// return true; | ||
// } else { | ||
// return false; | ||
// } | ||
// }} | ||
customTextRenderer: textRenderer, height: 500, pageNumber: index + 1 }, `page_${index + 1}`))) })); | ||
return _jsx(DocumentContext.Provider, { value: childContext, children: children }); | ||
} | ||
@@ -366,40 +316,8 @@ function renderContent() { | ||
} | ||
// return null; | ||
const checkVisibility = () => { | ||
const targetElement = document.getElementById('target-div'); | ||
if (targetElement) { | ||
console.log(targetElement); | ||
// const rect = targetElement.getBoundingClientRect(); | ||
// // Check if the div is in the viewport | ||
// const isInViewport = | ||
// rect.top >= 0 && | ||
// rect.left >= 0 && | ||
// rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && | ||
// rect.right <= (window.innerWidth || document.documentElement.clientWidth); | ||
// setIsVisible(isInViewport); | ||
} | ||
else { | ||
console.log('targetElement not found'); | ||
} | ||
}; | ||
// useEffect(() => { | ||
// // Attach scroll event listener | ||
// window.addEventListener('scroll', checkVisibility); | ||
// // Check visibility initially | ||
// checkVisibility(); | ||
// // Cleanup on unmount | ||
// return () => { | ||
// window.removeEventListener('scroll', checkVisibility); | ||
// }; | ||
// }, []); | ||
return (_jsx("div", Object.assign({ className: clsx('react-pdf__Document', className), | ||
// Assertion is needed for React 18 compatibility | ||
// ref={inputRef as React.Ref<HTMLDivElement>} | ||
style: { | ||
ref: inputRef, style: { | ||
['--scale-factor']: '1', | ||
height: '500px', | ||
overflow: 'auto', | ||
backgroundColor: 'lightgray' | ||
} }, eventProps, { ref: containerRef, onScroll: handleScroll, children: renderContent() }))); | ||
} }, eventProps, { children: renderContent() }))); | ||
}); | ||
export default Document; |
import type { PDFDocumentProxy } from 'pdfjs-dist'; | ||
import type { EventProps } from 'make-event-props'; | ||
import type { ClassName, CustomRenderer, CustomTextRenderer, CustomHighlightRender, NodeOrRenderer, OnGetAnnotationsError, OnGetAnnotationsSuccess, OnGetStructTreeError, OnGetStructTreeSuccess, OnGetTextError, OnGetTextSuccess, OnPageLoadError, OnPageLoadSuccess, OnRenderAnnotationLayerError, OnRenderAnnotationLayerSuccess, OnRenderError, OnRenderSuccess, OnRenderTextLayerError, OnRenderTextLayerSuccess, PageCallback, RenderMode } from './shared/types.js'; | ||
import type { ClassName, CustomRenderer, CustomTextRenderer, NodeOrRenderer, OnGetAnnotationsError, OnGetAnnotationsSuccess, OnGetStructTreeError, OnGetStructTreeSuccess, OnGetTextError, OnGetTextSuccess, OnPageLoadError, OnPageLoadSuccess, OnRenderAnnotationLayerError, OnRenderAnnotationLayerSuccess, OnRenderError, OnRenderSuccess, OnRenderTextLayerError, OnRenderTextLayerSuccess, PageCallback, RenderMode } from './shared/types.js'; | ||
export type PageProps = { | ||
@@ -41,3 +41,2 @@ _className?: string; | ||
customTextRenderer?: CustomTextRenderer; | ||
customHighlightRender?: CustomHighlightRender; | ||
/** | ||
@@ -197,3 +196,2 @@ * The ratio between physical pixels and device-independent pixels (DIPs) on the current device. | ||
/** | ||
* | ||
* pdf object obtained from `<Document />`'s `onLoadSuccess` callback function. | ||
@@ -200,0 +198,0 @@ * |
@@ -38,3 +38,3 @@ 'use client'; | ||
const mergedProps = Object.assign(Object.assign({}, documentContext), props); | ||
const { _className = 'react-pdf__Page', _enableRegisterUnregisterPage = true, canvasBackground, canvasRef, children, className, customRenderer: CustomRenderer, customTextRenderer, customHighlightRender, devicePixelRatio, error = 'Failed to load the page.', height, inputRef, loading = 'Loading page…', noData = 'No page specified.', onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onGetStructTreeError: onGetStructTreeErrorProps, onGetStructTreeSuccess: onGetStructTreeSuccessProps, onGetTextError: onGetTextErrorProps, onGetTextSuccess: onGetTextSuccessProps, onLoadError: onLoadErrorProps, onLoadSuccess: onLoadSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, onRenderError: onRenderErrorProps, onRenderSuccess: onRenderSuccessProps, onRenderTextLayerError: onRenderTextLayerErrorProps, onRenderTextLayerSuccess: onRenderTextLayerSuccessProps, pageIndex: pageIndexProps, pageNumber: pageNumberProps, pdf, registerPage, renderAnnotationLayer: renderAnnotationLayerProps = true, renderForms = false, renderMode = 'canvas', renderTextLayer: renderTextLayerProps = true, rotate: rotateProps, scale: scaleProps = defaultScale, unregisterPage, width } = mergedProps, otherProps = __rest(mergedProps, ["_className", "_enableRegisterUnregisterPage", "canvasBackground", "canvasRef", "children", "className", "customRenderer", "customTextRenderer", "customHighlightRender", "devicePixelRatio", "error", "height", "inputRef", "loading", "noData", "onGetAnnotationsError", "onGetAnnotationsSuccess", "onGetStructTreeError", "onGetStructTreeSuccess", "onGetTextError", "onGetTextSuccess", "onLoadError", "onLoadSuccess", "onRenderAnnotationLayerError", "onRenderAnnotationLayerSuccess", "onRenderError", "onRenderSuccess", "onRenderTextLayerError", "onRenderTextLayerSuccess", "pageIndex", "pageNumber", "pdf", "registerPage", "renderAnnotationLayer", "renderForms", "renderMode", "renderTextLayer", "rotate", "scale", "unregisterPage", "width"]); | ||
const { _className = 'react-pdf__Page', _enableRegisterUnregisterPage = true, canvasBackground, canvasRef, children, className, customRenderer: CustomRenderer, customTextRenderer, devicePixelRatio, error = 'Failed to load the page.', height, inputRef, loading = 'Loading page…', noData = 'No page specified.', onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onGetStructTreeError: onGetStructTreeErrorProps, onGetStructTreeSuccess: onGetStructTreeSuccessProps, onGetTextError: onGetTextErrorProps, onGetTextSuccess: onGetTextSuccessProps, onLoadError: onLoadErrorProps, onLoadSuccess: onLoadSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, onRenderError: onRenderErrorProps, onRenderSuccess: onRenderSuccessProps, onRenderTextLayerError: onRenderTextLayerErrorProps, onRenderTextLayerSuccess: onRenderTextLayerSuccessProps, pageIndex: pageIndexProps, pageNumber: pageNumberProps, pdf, registerPage, renderAnnotationLayer: renderAnnotationLayerProps = true, renderForms = false, renderMode = 'canvas', renderTextLayer: renderTextLayerProps = true, rotate: rotateProps, scale: scaleProps = defaultScale, unregisterPage, width } = mergedProps, otherProps = __rest(mergedProps, ["_className", "_enableRegisterUnregisterPage", "canvasBackground", "canvasRef", "children", "className", "customRenderer", "customTextRenderer", "devicePixelRatio", "error", "height", "inputRef", "loading", "noData", "onGetAnnotationsError", "onGetAnnotationsSuccess", "onGetStructTreeError", "onGetStructTreeSuccess", "onGetTextError", "onGetTextSuccess", "onLoadError", "onLoadSuccess", "onRenderAnnotationLayerError", "onRenderAnnotationLayerSuccess", "onRenderError", "onRenderSuccess", "onRenderTextLayerError", "onRenderTextLayerSuccess", "pageIndex", "pageNumber", "pdf", "registerPage", "renderAnnotationLayer", "renderForms", "renderMode", "renderTextLayer", "rotate", "scale", "unregisterPage", "width"]); | ||
const [pageState, pageDispatch] = useResolver(); | ||
@@ -148,3 +148,2 @@ const { value: page, error: pageError } = pageState; | ||
customTextRenderer, | ||
customHighlightRender, | ||
devicePixelRatio, | ||
@@ -175,3 +174,2 @@ onGetAnnotationsError: onGetAnnotationsErrorProps, | ||
customTextRenderer, | ||
customHighlightRender, | ||
devicePixelRatio, | ||
@@ -178,0 +176,0 @@ onGetAnnotationsErrorProps, |
@@ -18,3 +18,18 @@ 'use client'; | ||
const mergedProps = Object.assign(Object.assign({}, documentContext), pageContext); | ||
const { imageResourcesPath, linkService, onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, page, pdf, renderForms, rotate, scale = 1, } = mergedProps; | ||
const { imageResourcesPath, linkService, onGetAnnotationsError: onGetAnnotationsErrorProps, onGetAnnotationsSuccess: onGetAnnotationsSuccessProps, onRenderAnnotationLayerError: onRenderAnnotationLayerErrorProps, onRenderAnnotationLayerSuccess: onRenderAnnotationLayerSuccessProps, page, pdf, renderForms, rotate, scale = 1, pageNumber, highlight, } = mergedProps; | ||
const XYWHPToScaledLTWHP = (xywhp, height, scale) => { | ||
const scaledXYWHP = { | ||
x: xywhp.x * scale, | ||
y: xywhp.y * scale, | ||
width: xywhp.width * scale, | ||
height: xywhp.height * scale, | ||
}; | ||
return { | ||
left: scaledXYWHP.x, | ||
top: height - scaledXYWHP.y - scaledXYWHP.height, | ||
width: scaledXYWHP.width, | ||
height: scaledXYWHP.height, | ||
pageNumber: xywhp.pageNumber, | ||
}; | ||
}; | ||
invariant(pdf, 'Attempted to load page annotations, but no document was specified. Wrap <Page /> in a <Document /> or pass explicit `pdf` prop.'); | ||
@@ -120,2 +135,31 @@ invariant(page, 'Attempted to load page annotations, but no page was specified.'); | ||
layer.innerHTML = ''; | ||
if (highlight) { | ||
const { width, height, scale } = clonedViewport; | ||
for (let i = 0; i < highlight.length; i++) { | ||
const h = highlight[i]; | ||
if (!h) { | ||
return; | ||
} | ||
const ltwhp = XYWHPToScaledLTWHP(h, height, scale); | ||
if (!ltwhp) { | ||
return; | ||
} | ||
if (ltwhp.pageNumber !== pageNumber) { | ||
return; | ||
} | ||
const highlightDiv = document.createElement('div'); | ||
highlightDiv.className = 'highlight11'; | ||
highlightDiv.style.left = `${ltwhp.left}px`; | ||
highlightDiv.style.top = `${ltwhp.top}px`; // 设置注释位置 | ||
highlightDiv.style.width = `${ltwhp.width}px`; // 设置注释宽度 | ||
highlightDiv.style.height = `${ltwhp.height}px`; // 设置注释高度 | ||
highlightDiv.style.position = 'absolute'; | ||
highlightDiv.style.mixBlendMode = 'multiply'; | ||
highlightDiv.style.backgroundColor = 'rgba(180,187,254)'; // 半透明的黄色背景模拟高亮 | ||
highlightDiv.style.opacity = '0.5'; | ||
highlightDiv.style.borderRadius = '2px'; | ||
highlightDiv.style.pointerEvents = 'none'; // 确保高亮不影响用户点击 | ||
layer.appendChild(highlightDiv); | ||
} | ||
} | ||
try { | ||
@@ -122,0 +166,0 @@ new pdfjs.AnnotationLayer(annotationLayerParameters).render(renderParameters); |
@@ -9,3 +9,2 @@ 'use client'; | ||
import * as pdfjs from 'pdfjs-dist'; | ||
import useDocumentContext from "../shared/hooks/useDocumentContext.js"; | ||
import usePageContext from '../shared/hooks/usePageContext.js'; | ||
@@ -18,10 +17,5 @@ import useResolver from '../shared/hooks/useResolver.js'; | ||
export default function TextLayer() { | ||
// const documentContext = useDocumentContext(); | ||
const pageContext = usePageContext(); | ||
invariant(pageContext, 'Unable to find Page context.'); | ||
// invariant(documentContext, 'Unable to find Document context.'); | ||
const { customTextRenderer, customHighlightRender, onGetTextError, onGetTextSuccess, onRenderTextLayerError, onRenderTextLayerSuccess, page, pageIndex, pageNumber, rotate, scale, } = pageContext; | ||
// const { | ||
// currentPageNumber | ||
// } = documentContext; | ||
const { customTextRenderer, onGetTextError, onGetTextSuccess, onRenderTextLayerError, onRenderTextLayerSuccess, page, pageIndex, pageNumber, rotate, scale, } = pageContext; | ||
invariant(page, 'Attempted to load page text content, but no page was specified.'); | ||
@@ -143,31 +137,2 @@ const [textContentState, textContentDispatch] = useResolver(); | ||
const layerChildren = layer.querySelectorAll('[role="presentation"]'); | ||
if (customHighlightRender) { | ||
let index = 0; | ||
textContent.items.forEach((item, itemIndex) => { | ||
if (!isTextItem(item)) { | ||
return; | ||
} | ||
const child = layerChildren[index]; | ||
if (!child) { | ||
return; | ||
} | ||
// if (currentPageNumber !== pageNumber) { | ||
// console.log('currentPageNumber !== pageNumber', currentPageNumber, pageNumber); | ||
// return; | ||
// } | ||
// console.log('currentPageNumber === pageNumber', currentPageNumber, pageNumber); | ||
const needsHighlight = customHighlightRender(Object.assign({ pageIndex, | ||
pageNumber, | ||
itemIndex }, item)); | ||
if (!needsHighlight) { | ||
return; | ||
} | ||
console.log('needsHighlight', item); | ||
//if needsHighlight is true, add background color to the text style | ||
const styleString = child.getAttribute('style'); | ||
child.setAttribute('style', styleString + 'background-color: yellow; color: inherit;'); | ||
// child.innerHTML = `<mark>${item.str}</mark>`; | ||
// index += item.str && item.hasEOL ? 2 : 1; | ||
}); | ||
} | ||
if (customTextRenderer) { | ||
@@ -174,0 +139,0 @@ let index = 0; |
@@ -48,7 +48,2 @@ import type { PDFDataRangeTransport, PDFDocumentProxy, PDFPageProxy, PasswordResponses } from 'pdfjs-dist'; | ||
} & TextItem) => string; | ||
export type CustomHighlightRender = (props: { | ||
pageIndex: number; | ||
pageNumber: number; | ||
itemIndex: number; | ||
} & TextItem) => boolean; | ||
export type DocumentCallback = PDFDocumentProxy; | ||
@@ -92,4 +87,3 @@ export type File = string | ArrayBuffer | Blob | Source | null; | ||
unregisterPage: UnregisterPage; | ||
currentPageNumber?: number | null; | ||
setCurrentPageNumber?: (pageNumber: number) => void; | ||
highlight?: XYWHP[] | null; | ||
} | null; | ||
@@ -100,3 +94,2 @@ export type PageContextType = { | ||
customTextRenderer?: CustomTextRenderer; | ||
customHighlightRender?: CustomHighlightRender; | ||
devicePixelRatio?: number; | ||
@@ -130,2 +123,16 @@ onGetAnnotationsError?: OnGetAnnotationsError; | ||
}; | ||
export type XYWHP = { | ||
x: number; | ||
y: number; | ||
width: number; | ||
height: number; | ||
pageNumber: number; | ||
}; | ||
export type LTWHP = { | ||
left: number; | ||
top: number; | ||
width: number; | ||
height: number; | ||
pageNumber: number; | ||
}; | ||
export {}; |
{ | ||
"name": "@ligangyan/react-pdf", | ||
"version": "9.1.1", | ||
"version": "9.1.2-SNAPSHOT", | ||
"description": "Display PDFs in your React app as easily as if they were images.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -76,6 +76,2 @@ import type { | ||
export type CustomHighlightRender = ( | ||
props: { pageIndex: number; pageNumber: number; itemIndex: number } & TextItem, | ||
) => boolean; | ||
export type DocumentCallback = PDFDocumentProxy; | ||
@@ -144,4 +140,3 @@ | ||
unregisterPage: UnregisterPage; | ||
currentPageNumber?: number | null; | ||
setCurrentPageNumber?: (pageNumber: number) => void; | ||
highlight?: XYWHP[] | null; | ||
} | null; | ||
@@ -153,3 +148,2 @@ | ||
customTextRenderer?: CustomTextRenderer; | ||
customHighlightRender?: CustomHighlightRender; | ||
devicePixelRatio?: number; | ||
@@ -185,1 +179,18 @@ onGetAnnotationsError?: OnGetAnnotationsError; | ||
}; | ||
export type XYWHP ={ | ||
x: number; | ||
y: number; | ||
width: number; | ||
height: number; | ||
pageNumber: number; | ||
} | ||
export type LTWHP = { | ||
left: number; | ||
top: number; | ||
width: number; | ||
height: number; | ||
pageNumber: number; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
558624
12563
2