From ec5a950890c623297c716d09c7a625106469a702 Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:15:29 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[#13]=20canvas,=20svg=20render=EB=A5=BC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react-pdf/src/components/page/Canvas.tsx | 35 ++++++++++++++++-- .../react-pdf/src/components/page/Svg.tsx | 37 +++++++++++++++++-- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/packages/react-pdf/src/components/page/Canvas.tsx b/packages/react-pdf/src/components/page/Canvas.tsx index eda401f..f2a3e18 100644 --- a/packages/react-pdf/src/components/page/Canvas.tsx +++ b/packages/react-pdf/src/components/page/Canvas.tsx @@ -1,5 +1,34 @@ -import {memo} from 'react' +import {memo, useCallback} from 'react' -export const PageCanvas = memo(function PageCanvas() { - return null +import {usePdfContext} from '../../contexts/pdf' + +interface PageCanvasProps { + pageNumber: number +} + +export const PageCanvas = memo(function PageCanvas({pageNumber}: PageCanvasProps) { + const {pdf} = usePdfContext() + + const drawCanvas = useCallback( + async (canvas: HTMLCanvasElement | null) => { + if (!canvas) { + return + } + + const canvasContext = canvas.getContext('2d') + if (!canvasContext) { + return + } + + const page = await pdf.getPage(pageNumber) + const viewport = page.getViewport({scale: 1, rotation: 0}) + + canvas.width = viewport.width + canvas.height = viewport.height + page.render({canvasContext, viewport}) + }, + [pageNumber, pdf], + ) + + return }) diff --git a/packages/react-pdf/src/components/page/Svg.tsx b/packages/react-pdf/src/components/page/Svg.tsx index 1fd8ea1..5c06039 100644 --- a/packages/react-pdf/src/components/page/Svg.tsx +++ b/packages/react-pdf/src/components/page/Svg.tsx @@ -1,5 +1,36 @@ -import {memo} from 'react' +import {memo, useCallback} from 'react' -export const PageSvg = memo(function PageSvg() { - return null +import {usePdfContext} from '../../contexts/pdf' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import * as pdfjs from '../../pdfjs-dist/legacy/build/pdf' + +interface PageSvgProps { + pageNumber: number +} + +export const PageSvg = memo(function PageSvg({pageNumber}: PageSvgProps) { + const {pdf} = usePdfContext() + + const drawSvg = useCallback( + async (element: HTMLDivElement | null) => { + if (!element) { + return + } + + const page = await pdf.getPage(pageNumber) + const viewport = page.getViewport({scale: 1, rotation: 0}) + const operatorList = await page.getOperatorList() + + element.setAttribute('width', `${viewport.width}px`) + element.setAttribute('height', `${viewport.height}px`) + + const svgGfx = new pdfjs.SVGGraphics(page.commonObjs, page.objs) + const svg = await svgGfx.getSVG(operatorList, viewport) + element.appendChild(svg) + }, + [pageNumber, pdf], + ) + + return
}) From 148174d897319202e543bb714df96cf0a076dda0 Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:20:17 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[#13]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EC=A3=BC=EC=9E=85=EB=90=9C=20renderMode?= =?UTF-8?q?=20props=20=EB=A5=BC=20=EC=A0=9C=EA=B1=B0=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-pdf/src/contexts/pdf.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/react-pdf/src/contexts/pdf.tsx b/packages/react-pdf/src/contexts/pdf.tsx index e888577..dfff096 100644 --- a/packages/react-pdf/src/contexts/pdf.tsx +++ b/packages/react-pdf/src/contexts/pdf.tsx @@ -4,13 +4,12 @@ import type {PDFDocumentProxy} from '../pdfjs-dist/types/pdfjs' export interface PDFProviderContext { pdf: PDFDocumentProxy - renderMode?: 'canvas' | 'svg' } const Context = createContext(undefined) -export function PDFProvider({pdf, renderMode = 'canvas', children}: PropsWithChildren) { - const value = useMemo(() => ({pdf, renderMode}), [pdf, renderMode]) +export function PDFProvider({pdf, children}: PropsWithChildren) { + const value = useMemo(() => ({pdf}), [pdf]) return {children} } From 5cc069aee491c17a01cbb1a6c32abbf8f0e5ea66 Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:20:47 +0900 Subject: [PATCH 3/8] =?UTF-8?q?[#13]=20renderMode=EC=97=90=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20page=EB=A5=BC=20rendering=20=ED=95=98=EB=8A=94=20Pa?= =?UTF-8?q?ges=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-pdf/src/components/Pages.tsx | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 packages/react-pdf/src/components/Pages.tsx diff --git a/packages/react-pdf/src/components/Pages.tsx b/packages/react-pdf/src/components/Pages.tsx new file mode 100644 index 0000000..6f3513c --- /dev/null +++ b/packages/react-pdf/src/components/Pages.tsx @@ -0,0 +1,37 @@ +import {Fragment, memo, useCallback} from 'react' + +import {usePdfContext} from '../contexts/pdf' +import {PageCanvas} from './page/Canvas' +import {PageSvg} from './page/Svg' + +export interface PagesProps { + renderMode?: 'canvas' | 'svg' +} + +export const Pages = memo(function Pages({renderMode}: PagesProps) { + const {pdf} = usePdfContext() + + const renderPdf = useCallback(() => { + return Array.from({length: pdf.numPages}).map((_, index) => { + const pageNumber = index + 1 + return ( + + {renderMode === 'canvas' && } + {renderMode === 'svg' && } + + ) + }) + }, [pdf.numPages, renderMode]) + + const renderTextLayer = useCallback(() => {}, []) + + const renderAnnotationLayer = useCallback(() => {}, []) + + return ( + <> + {renderPdf()} + {renderTextLayer()} + {renderAnnotationLayer()} + + ) +}) From cdbaafce87538cec9fc2cd95c08caa6fd8c41900 Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:21:08 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[#13]=20useIsomorphicLayoutEffect=EB=A5=BC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-pdf/src/hooks/useIsomorphicLayoutEffect.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/react-pdf/src/hooks/useIsomorphicLayoutEffect.ts diff --git a/packages/react-pdf/src/hooks/useIsomorphicLayoutEffect.ts b/packages/react-pdf/src/hooks/useIsomorphicLayoutEffect.ts new file mode 100644 index 0000000..c1eab1a --- /dev/null +++ b/packages/react-pdf/src/hooks/useIsomorphicLayoutEffect.ts @@ -0,0 +1,3 @@ +import {useEffect, useLayoutEffect} from 'react' + +export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect From 15dfb0b8afb7cc4b7f7257d0083e03120fea7680 Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:21:25 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[#13]=20PDFViewer=EC=97=90=20Pages=EB=A5=BC?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react-pdf/src/components/PdfViewer.tsx | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/react-pdf/src/components/PdfViewer.tsx b/packages/react-pdf/src/components/PdfViewer.tsx index 718f12c..8fa9178 100644 --- a/packages/react-pdf/src/components/PdfViewer.tsx +++ b/packages/react-pdf/src/components/PdfViewer.tsx @@ -1,11 +1,15 @@ -import {ReactNode, useEffect, useState} from 'react' +import {ReactNode, useState} from 'react' -import {PDFProvider, PDFProviderContext} from '../contexts/pdf' +import {PDFProvider} from '../contexts/pdf' +import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect' import {PDFDocumentProxy} from '../pdfjs-dist/types/pdfjs' import {getPdfDocument} from '../utils/pdf' +import {Pages, PagesProps} from './Pages' -export type PDFViewerProps = Omit & { +export type PDFViewerProps = PagesProps & { pdfUrl: string + + header?: ReactNode footer?: ReactNode tokenize?: boolean onClickWords?: {target: string | RegExp; callback: () => void | Promise}[] @@ -20,10 +24,10 @@ export type PDFViewerProps = Omit & { } } -export function PDFViewer({pdfUrl, renderMode, options}: PDFViewerProps) { +export function PDFViewer({pdfUrl, renderMode = 'canvas', header, footer, options}: PDFViewerProps) { const [pdf, setPdf] = useState() - useEffect(() => { + useIsomorphicLayoutEffect(() => { async function init() { const pdfDocument = await getPdfDocument({ file: pdfUrl, @@ -48,5 +52,11 @@ export function PDFViewer({pdfUrl, renderMode, options}: PDFViewerProps) { return null } - return + return ( + + {header} + + {footer} + + ) } From d4f66a5e8de02b9ce76061b374bf174cb3d182ed Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:21:36 +0900 Subject: [PATCH 6/8] =?UTF-8?q?[#13]=20=EA=B5=AC=ED=98=84=EB=90=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=93=A4=EC=9D=84=20export=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-pdf/src/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/react-pdf/src/index.ts b/packages/react-pdf/src/index.ts index de0c912..5c26e7b 100644 --- a/packages/react-pdf/src/index.ts +++ b/packages/react-pdf/src/index.ts @@ -1 +1,8 @@ export * from './utils/pdf' +export * from './components/page/Canvas' +export * from './components/page/Svg' +export * from './components/layer/Annotation' +export * from './components/layer/Text' +export * from './components/Pages' +export * from './contexts/pdf' +export * from './components/PdfViewer' From 312db8424e01449e049a4fd6988577ea05dbf66d Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 22:21:54 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[#13]=20pdf=20viewer=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EB=B6=81=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react-pdf/storybook/pdf-viewer.stories.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 packages/react-pdf/storybook/pdf-viewer.stories.tsx diff --git a/packages/react-pdf/storybook/pdf-viewer.stories.tsx b/packages/react-pdf/storybook/pdf-viewer.stories.tsx new file mode 100644 index 0000000..41879be --- /dev/null +++ b/packages/react-pdf/storybook/pdf-viewer.stories.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +import {PDFViewer} from '../dist/cjs' + +const meta = { + title: 'React PDF', + component: 기본_PdfViewer, +} +export default meta + +const PDF_URL = + 'https://fs.pstatic.net/contents/resource/loan/personal-compare/required/0/1668583261818/gi_creditLoanNF_02.pdf' + +export function 기본_PdfViewer() { + return +} From acd663098ab09608ce5a7390c4f9bf65773245d0 Mon Sep 17 00:00:00 2001 From: oneweek-lee Date: Tue, 23 Apr 2024 23:03:32 +0900 Subject: [PATCH 8/8] =?UTF-8?q?[#13]=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81:=20=EC=9D=B4=EC=83=81=ED=95=9C=20=EB=AC=B8=EB=B2=95?= =?UTF-8?q?=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-pdf/src/components/Pages.tsx | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/react-pdf/src/components/Pages.tsx b/packages/react-pdf/src/components/Pages.tsx index 6f3513c..a3f3836 100644 --- a/packages/react-pdf/src/components/Pages.tsx +++ b/packages/react-pdf/src/components/Pages.tsx @@ -1,4 +1,4 @@ -import {Fragment, memo, useCallback} from 'react' +import {Fragment, PropsWithChildren, memo, useCallback} from 'react' import {usePdfContext} from '../contexts/pdf' import {PageCanvas} from './page/Canvas' @@ -8,10 +8,10 @@ export interface PagesProps { renderMode?: 'canvas' | 'svg' } -export const Pages = memo(function Pages({renderMode}: PagesProps) { +export const Pages = memo(function Pages({renderMode, children}: PropsWithChildren) { const {pdf} = usePdfContext() - const renderPdf = useCallback(() => { + const RenderPDF = useCallback(() => { return Array.from({length: pdf.numPages}).map((_, index) => { const pageNumber = index + 1 return ( @@ -23,15 +23,20 @@ export const Pages = memo(function Pages({renderMode}: PagesProps) { }) }, [pdf.numPages, renderMode]) - const renderTextLayer = useCallback(() => {}, []) + const RenderTextLayer = useCallback(() => { + return null + }, []) - const renderAnnotationLayer = useCallback(() => {}, []) + const RenderAnnotationLayer = useCallback(() => { + return null + }, []) return ( <> - {renderPdf()} - {renderTextLayer()} - {renderAnnotationLayer()} + + + + {children} ) })