From 5e1902c12524230c62f8eed3eac2f421fbad74bb Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Fri, 15 Oct 2021 23:48:38 +0900 Subject: [PATCH 01/20] chore: add pdfjs-dist typings --- package.json | 1 + .../components/PdfViewer/PdfViewer.tsx | 20 +++++++++---------- .../components/PdfViewer/typings.d.ts | 1 - yarn.lock | 5 +++++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index f558ed0cb..7ccfb06b0 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/lodash": "^4.14.141", "@types/mustache": "^0.8.32", "@types/node": "^12.7.3", + "@types/pdfjs-dist": "^2.7.5", "@types/react": "^16.9.2", "@types/react-dom": "^16.9.0", "@types/react-resize-detector": "^4.2.0", diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index 753f263e1..9d4357de1 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -1,5 +1,5 @@ -import React, { SFC, useEffect, useRef, useState, useMemo } from 'react'; -import PdfjsLib from 'pdfjs-dist'; +import React, { FC, useEffect, useRef, useState, useMemo } from 'react'; +import PdfjsLib, { PDFDocumentProxy, PDFPageProxy, PDFPageViewport, PDFSource } from 'pdfjs-dist'; import PdfjsWorkerAsText from 'pdfjs-dist/build/pdf.worker.min.js'; import { settings } from 'carbon-components'; @@ -35,7 +35,7 @@ interface Props { setHideToolbarControls?: (disabled: boolean) => void; } -const PdfViewer: SFC = ({ +const PdfViewer: FC = ({ file, page, scale, @@ -46,8 +46,8 @@ const PdfViewer: SFC = ({ const canvasRef = useRef(null); // In order to prevent unnecessary re-loading, loaded file and page are stored in state - const [loadedFile, setLoadedFile] = useState(null); - const [loadedPage, setLoadedPage] = useState(null); + const [loadedFile, setLoadedFile] = useState(null); + const [loadedPage, setLoadedPage] = useState(null); useEffect(() => { let didCancel = false; @@ -95,7 +95,7 @@ const PdfViewer: SFC = ({ }, [loadedPage, scale]); useEffect(() => { - if (loadedPage && !loadedPage.then && viewport && canvasInfo) { + if (loadedPage && !(loadedPage as any).then && viewport && canvasInfo) { _renderPage(loadedPage, canvasRef.current!, viewport, canvasInfo); setLoading(false); } @@ -127,14 +127,14 @@ function _loadPdf(data: string): Promise { return PdfjsLib.getDocument({ data }).promise; } -function _loadPage(file: any, page: number): Promise { +function _loadPage(file: PDFDocumentProxy, page: number) { return file.getPage(page); } function _renderPage( - pdfPage: any, + pdfPage: PDFPageProxy, canvas: HTMLCanvasElement, - viewport: any, + viewport: PDFPageViewport, canvasInfo: CanvasInfo ): void { const canvasContext = canvas.getContext('2d'); @@ -148,7 +148,7 @@ function _renderPage( function setupPdfjs(): void { if (typeof Worker !== 'undefined') { const blob = new Blob([PdfjsWorkerAsText], { type: 'text/javascript' }); - const pdfjsWorker = new Worker(URL.createObjectURL(blob)); + const pdfjsWorker = new Worker(URL.createObjectURL(blob)) as any; // TODO is this usage correct? PdfjsLib.GlobalWorkerOptions.workerPort = pdfjsWorker; } else { PdfjsLib.GlobalWorkerOptions.workerSrc = PdfjsWorkerAsText; diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts index fa31151b5..21a04c613 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts @@ -1,2 +1 @@ -declare module 'pdfjs-dist'; declare module 'pdfjs-dist/build/pdf.worker.min.js'; diff --git a/yarn.lock b/yarn.lock index b99dd926d..c29f30314 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4615,6 +4615,11 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== +"@types/pdfjs-dist@^2.7.5": + version "2.7.5" + resolved "https://registry.yarnpkg.com/@types/pdfjs-dist/-/pdfjs-dist-2.7.5.tgz#53fc13e30b6bd18acdb3617fb6332a43225e0ffa" + integrity sha512-QdKChstEcREV+imniONC3JvSSFOeYv0RL12QOpzSfTpGg7xRAZcJXpWdJEtuH6FAPXX5V+sp9i/sBHJ9bsU7JA== + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" From 824c2d7e16de6e333645921550be12c7f02a3679 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Tue, 9 Nov 2021 16:04:37 +0900 Subject: [PATCH 02/20] fix: control PDF rendering tasks properly --- .../components/PdfViewer/PdfViewer.tsx | 66 +++++++++++++++---- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index 9d4357de1..5ab2ee420 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -1,8 +1,15 @@ import React, { FC, useEffect, useRef, useState, useMemo } from 'react'; -import PdfjsLib, { PDFDocumentProxy, PDFPageProxy, PDFPageViewport, PDFSource } from 'pdfjs-dist'; +import PdfjsLib, { + PDFDocumentProxy, + PDFPageProxy, + PDFPageViewport, + PDFRenderTask +} from 'pdfjs-dist'; import PdfjsWorkerAsText from 'pdfjs-dist/build/pdf.worker.min.js'; import { settings } from 'carbon-components'; +const { RenderingCancelledException } = PdfjsLib as any; + setupPdfjs(); interface Props { @@ -88,18 +95,45 @@ const PdfViewer: FC = ({ }; }, [loadedFile, page]); - const [viewport, canvasInfo] = useMemo(() => { - const viewport = loadedPage?.getViewport({ scale }); - const canvasInfo = viewport ? getCanvasInfo(viewport) : undefined; - return [viewport, canvasInfo]; - }, [loadedPage, scale]); + const currentPage = useMemo(() => { + const isPageValid = !!loadedPage && loadedPage.pageNumber === page; + if (isPageValid) { + const viewport = loadedPage?.getViewport({ scale }); + const canvasInfo = viewport ? getCanvasInfo(viewport) : undefined; + return { loadedPage, viewport, canvasInfo }; + } + return null; + }, [loadedPage, page, scale]); useEffect(() => { + let didCancel = false; + let task: PDFRenderTask | null = null; + + const { loadedPage, viewport, canvasInfo } = currentPage || {}; if (loadedPage && !(loadedPage as any).then && viewport && canvasInfo) { - _renderPage(loadedPage, canvasRef.current!, viewport, canvasInfo); - setLoading(false); + const render = async () => { + try { + task = _renderPage(loadedPage, canvasRef.current!, viewport, canvasInfo); + await task?.promise; + } catch (e) { + if (e instanceof RenderingCancelledException) { + // ignore + } else { + throw e; // rethrow unknown exception + } + } finally { + if (!didCancel) { + setLoading(false); + } + } + }; + render(); } - }, [loadedPage, viewport, canvasInfo, setLoading]); + return () => { + didCancel = true; + task?.cancel(); + }; + }, [loadedPage, currentPage, setLoading]); useEffect(() => { if (setHideToolbarControls) { @@ -107,6 +141,7 @@ const PdfViewer: FC = ({ } }, [setHideToolbarControls]); + const { canvasInfo } = currentPage || {}; return ( Date: Wed, 20 Oct 2021 13:47:13 +0900 Subject: [PATCH 03/20] feat: add pdf text layer support --- .../PdfViewer/PdfViewer.stories.tsx | 18 +- .../components/PdfViewer/PdfViewer.tsx | 54 ++++- .../PdfViewer/PdfViewerTextLayer.tsx | 207 ++++++++++++++++++ .../components/PdfViewer/typings.d.ts | 53 +++++ .../_document-preview-pdf-viewer.scss | 58 +++++ 5 files changed, 379 insertions(+), 11 deletions(-) create mode 100644 packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx index e6cdc54b1..6e7b31d12 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; -import { withKnobs, radios, number } from '@storybook/addon-knobs'; +import { withKnobs, radios, number, boolean } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; import PdfViewer from './PdfViewer'; import { document as doc } from 'components/DocumentPreview/__fixtures__/Art Effects.pdf'; @@ -32,6 +33,19 @@ storiesOf('DocumentPreview/components/PdfViewer', module) const zoom = radios(zoomKnob.label, zoomKnob.options, zoomKnob.defaultValue); const scale = parseFloat(zoom); + const showTextLayer = boolean('Show text layer', false); - return {}} />; + const setLoadingAction = action('setLoading'); + const setTextLayerInfoAction = action('setTextLayerInfo'); + + return ( + + ); }); diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index 5ab2ee420..d0ee15607 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -1,4 +1,5 @@ import React, { FC, useEffect, useRef, useState, useMemo } from 'react'; +import cx from 'classnames'; import PdfjsLib, { PDFDocumentProxy, PDFPageProxy, @@ -7,12 +8,15 @@ import PdfjsLib, { } from 'pdfjs-dist'; import PdfjsWorkerAsText from 'pdfjs-dist/build/pdf.worker.min.js'; import { settings } from 'carbon-components'; +import PdfViewerTextLayer, { PdfTextLayerInfo } from './PdfViewerTextLayer'; const { RenderingCancelledException } = PdfjsLib as any; setupPdfjs(); interface Props { + className?: string; + /** * PDF file data as base64-encoded string */ @@ -28,6 +32,16 @@ interface Props { */ scale: number; + /** + * Render text layer + */ + showTextLayer?: boolean; + + /** + * Text layer class name. Only applicable when showTextLayer is true + */ + textLayerClassName?: string; + /** * Callback invoked with page count, once `file` has been parsed */ @@ -40,15 +54,24 @@ interface Props { * Callback which is invoked with whether to enable/disable toolbar controls */ setHideToolbarControls?: (disabled: boolean) => void; + /** + * Callback for text layer info + */ + setTextLayerInfo?: (info: PdfTextLayerInfo | null) => any; } const PdfViewer: FC = ({ + className, file, page, scale, + showTextLayer, + textLayerClassName, setPageCount, setLoading, - setHideToolbarControls + setHideToolbarControls, + setTextLayerInfo, + children }) => { const canvasRef = useRef(null); @@ -141,15 +164,28 @@ const PdfViewer: FC = ({ } }, [setHideToolbarControls]); - const { canvasInfo } = currentPage || {}; + const classNameBase = `${settings.prefix}--document-preview-pdf-viewer`; + const { loadedPage: currentLoadedPage, canvasInfo } = currentPage || {}; return ( - +
+ + {showTextLayer && ( + + )} + {children} +
); }; diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx new file mode 100644 index 000000000..f6c38f08c --- /dev/null +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx @@ -0,0 +1,207 @@ +import React, { FC, useEffect, useRef, useState } from 'react'; +import cx from 'classnames'; +import PDFJSLib, { PDFPageProxy, PDFPageViewport, TextContent, TextContentItem } from 'pdfjs-dist'; +import { EventBus } from 'pdfjs-dist/lib/web/ui_utils'; +import { TextLayerBuilder } from 'pdfjs-dist/lib/web/text_layer_builder'; + +const { RenderingCancelledException } = PDFJSLib as any; + +interface Props { + className?: string; + + /** + * PDF page from pdfjs + */ + loadedPage: PDFPageProxy | null | undefined; + + /** + * Page number, starting at 1 + */ + page: number; + + /** + * Zoom factor, where `1` is equal to 100% + */ + scale: number; + + /** + * Callback for text layer info + */ + setTextLayerInfo?: (info: PdfTextLayerInfo | null) => any; +} + +export type PdfTextLayerInfo = { + /** + * PDF text content + */ + textContent: TextContent & { + styles: { [styleName: string]: CSSStyleDeclaration }; + }; + + /** + * Text span DOM elements rendered on the text layer + */ + textDivs: HTMLElement[]; + + /** + * Pdf page viewport used to render text items + */ + viewport: PDFPageViewport; + + /** + * Page number, starting at 1 + */ + page: number; +}; + +const PdfViewerTextLayer: FC = ({ + className, + loadedPage, + page = 1, + scale = 1, + setTextLayerInfo: setTextLayerInfoCallback = () => {} +}) => { + const textLayerRef = useRef(null); + const textLayerDiv = textLayerRef.current; + + const [textRenderInfo, setTextRenderInfo] = useState<{ + page: number; + scale: number; + textContent: TextContent; + viewport: PDFPageViewport; + } | null>(null); + + useEffect(() => { + async function loadTextInfo() { + const isPageReady = !!loadedPage && loadedPage.pageNumber === page; + if (isPageReady) { + const viewport = loadedPage.getViewport({ scale }); + const textContent = await loadedPage.getTextContent(); + setTextRenderInfo({ textContent, viewport, page, scale }); + } + } + loadTextInfo(); + }, [loadedPage, page, scale]); + + const textLayerBuilderRef = useRef(null); // ref for debugging purpose + const [textLayerInfo, setTextLayerInfo] = useState(null); + useEffect(() => { + let textLayerBuilder: TextLayerBuilder | null = null; + async function loadTextLayer() { + let textLayerInfo: PdfTextLayerInfo | null = null; + + if (textLayerDiv && textRenderInfo) { + const { textContent, viewport, scale, page } = textRenderInfo; + // prepare text layer + textLayerBuilder = textLayerBuilderRef.current = new TextLayerBuilder({ + textLayerDiv, + viewport, + eventBus: new EventBus(), + pageIndex: page - 1 + }); + textLayerBuilder.setTextContent(textContent); + + // render + textLayerDiv.innerHTML = ''; + try { + const deferredRenderEnd = (() => { + let resolve: null | Function = null; + const promise = new Promise(resolvePromise => { + resolve = resolvePromise; + }); + + const listener = () => { + resolve!(); + textLayerBuilder?.eventBus.off('textlayerrendered', listener); + }; + textLayerBuilder.eventBus.on('textlayerrendered', listener); + + return { promise }; + })(); + + textLayerBuilder.render(); + await deferredRenderEnd.promise; + + // fix text divs + _adjustTextDivs(textLayerBuilder.textDivs, textContent.items, scale); + + textLayerInfo = { + textContent, + textDivs: textLayerBuilder.textDivs, + viewport, + page + }; + } catch (e) { + if (e instanceof RenderingCancelledException) { + // ignore + return; + } else { + throw e; + } + } + } + setTextLayerInfo(textLayerInfo); + } + loadTextLayer(); + + return () => { + textLayerBuilder?.cancel(); + // should we set text items?? + }; + }, [textLayerDiv, textRenderInfo]); + + useEffect(() => { + setTextLayerInfoCallback(textLayerInfo); + }, [textLayerInfo, setTextLayerInfoCallback]); + + const rootClassName = cx(className, `textLayer`); + return ( +
+ ); +}; + +/** + * Adjust text span width + * @param textDivs + * @param textItems + * @param scale + */ +function _adjustTextDivs( + textDivs: HTMLElement[], + textItems: TextContentItem[] | null, + scale: number +): void { + const scaleXPattern = /scaleX\(([\d.]+)\)/; + (textDivs || []).forEach((textDivElm, index) => { + const textItem = textItems?.[index]; + if (!textItem) return; + + const expectedWidth = textItem.width * scale; + const actualWidth = textDivElm.getBoundingClientRect().width; + + function getScaleX(element: HTMLElement) { + const match = element.style.transform?.match(scaleXPattern); + if (match) { + return parseFloat(match[1]); + } + return null; + } + const currentScaleX = getScaleX(textDivElm); + if (currentScaleX && !isNaN(currentScaleX)) { + const newScale = `scaleX(${(expectedWidth / actualWidth) * currentScaleX})`; + textDivElm.style.transform = textDivElm.style.transform.replace(scaleXPattern, newScale); + } else { + const newScale = `scaleX(${expectedWidth / actualWidth})`; + textDivElm.style.transform = newScale; + } + }); +} + +export default PdfViewerTextLayer; diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts index 21a04c613..44544e96f 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/typings.d.ts @@ -1 +1,54 @@ declare module 'pdfjs-dist/build/pdf.worker.min.js'; + +// +// Declare modules and their types that is referred from PDF text layer rendering. +// Unused properties are commented out +// +declare module 'pdfjs-dist/lib/web/ui_utils' { + export class EventBus { + on(eventName: string, listener: any): void; + off(eventName: string, listener: any): void; + dispatch(eventName: string, args?: any): void; + } + // export function getGlobalEventBus(): EventBus; +} + +declare module 'pdfjs-dist/lib/web/text_layer_builder' { + import { EventBus } from 'pdfjs-dist/lib/web/ui_utils'; + import PdfjsLib from 'pdfjs-dist'; + + export class TextLayerBuilder { + constructor(options: TextLayerBuilder.Options); + + textLayerDiv: HTMLElement; + eventBus: EventBus; + textContent: PdfjsLib.TextContent | null; + // textContentItemsStr: any[]; + renderingDone: boolean; + // pageIdx: number; + pageNumber: number; + // matches: any[]; + // viewport: PdfjsLib.PDFPageViewport; + textDivs: HTMLElement[]; + // findController: any; + textLayerRenderTask: TextLayerRenderTask; + // enhanceTextSelection: any; + + render(timeout?: number): void; + cancel(): void; + // setTextContentStream(readableStream: any): void; + setTextContent(textContent: PdfjsLib.TextContent): void; + } + export const DefaultTextLayerFactory; + + declare namespace TextLayerBuilder { + export interface Options { + textLayerDiv: HTMLElement; + eventBus: EventBus; + pageIndex: number; + viewport: PdfjsLib.PDFPageViewport; + // findController?: any; + // enhanceTextSelection?: any; + } + } +} diff --git a/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss b/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss index 19169fe5f..f3bcda870 100644 --- a/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss +++ b/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss @@ -1,3 +1,61 @@ .#{$prefix}--document-preview-pdf-viewer { + position: relative; +} + +.#{$prefix}--document-preview-pdf-viewer--canvas { + transform-origin: left top 0px; +} + +.#{$prefix}--document-preview-pdf-viewer--text { transform-origin: left top 0px; + + // + // NOTE: import textLayer styles from ~pdfjs-dist/web/pdf_viewer.css + // @import "~pdfjs-dist/web/pdf_viewer" doesn't work for loading image + // + &.textLayer { + position: absolute; + text-align: initial; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + opacity: 0.2; + line-height: 1; + } + + &.textLayer span, + &.textLayer br { + color: transparent; + position: absolute; + white-space: pre; + cursor: text; + transform-origin: 0% 0%; + } + + &.textLayer ::selection { + background: rgba(0, 0, 255, 1); + } + + /* Avoids https://github.com/mozilla/pdf.js/issues/13840 in Chrome */ + &.textLayer br::selection { + background: transparent; + } + + &.textLayer .endOfContent { + display: block; + position: absolute; + left: 0; + top: 100%; + right: 0; + bottom: 0; + z-index: -1; + cursor: default; + user-select: none; + } + + &.textLayer .endOfContent.active { + top: 0; + } } From 9f0dcd527061452bcbe2f73449c8855a6ef5e77b Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Tue, 16 Nov 2021 22:33:28 +0900 Subject: [PATCH 04/20] fix: apply review comments --- .../components/PdfViewer/PdfViewer.tsx | 28 ++++++------- .../PdfViewer/PdfViewerTextLayer.tsx | 41 +++++++------------ .../_document-preview-pdf-viewer.scss | 3 +- 3 files changed, 30 insertions(+), 42 deletions(-) diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index d0ee15607..209b371d1 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -79,6 +79,7 @@ const PdfViewer: FC = ({ const [loadedFile, setLoadedFile] = useState(null); const [loadedPage, setLoadedPage] = useState(null); + // load PDF file useEffect(() => { let didCancel = false; @@ -100,6 +101,7 @@ const PdfViewer: FC = ({ }; }, [file, setPageCount]); + // load page from PDF file useEffect(() => { let didCancel = false; @@ -118,21 +120,18 @@ const PdfViewer: FC = ({ }; }, [loadedFile, page]); - const currentPage = useMemo(() => { - const isPageValid = !!loadedPage && loadedPage.pageNumber === page; - if (isPageValid) { - const viewport = loadedPage?.getViewport({ scale }); - const canvasInfo = viewport ? getCanvasInfo(viewport) : undefined; - return { loadedPage, viewport, canvasInfo }; - } - return null; - }, [loadedPage, page, scale]); + // extract canvas size of the current page + const [viewport, canvasInfo] = useMemo(() => { + const viewport = loadedPage?.getViewport({ scale }); + const canvasInfo = viewport ? getCanvasInfo(viewport) : undefined; + return [viewport, canvasInfo]; + }, [loadedPage, scale]); + // render the current page useEffect(() => { let didCancel = false; let task: PDFRenderTask | null = null; - const { loadedPage, viewport, canvasInfo } = currentPage || {}; if (loadedPage && !(loadedPage as any).then && viewport && canvasInfo) { const render = async () => { try { @@ -140,7 +139,8 @@ const PdfViewer: FC = ({ await task?.promise; } catch (e) { if (e instanceof RenderingCancelledException) { - // ignore + // Ignore. Rendering is interrupted by the effect cleanup method + // and another rendering will be taken place soon } else { throw e; // rethrow unknown exception } @@ -156,7 +156,7 @@ const PdfViewer: FC = ({ didCancel = true; task?.cancel(); }; - }, [loadedPage, currentPage, setLoading]); + }, [loadedPage, viewport, canvasInfo, setLoading]); useEffect(() => { if (setHideToolbarControls) { @@ -165,7 +165,6 @@ const PdfViewer: FC = ({ }, [setHideToolbarControls]); const classNameBase = `${settings.prefix}--document-preview-pdf-viewer`; - const { loadedPage: currentLoadedPage, canvasInfo } = currentPage || {}; return (
= ({ {showTextLayer && ( diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx index f6c38f08c..e05a596ee 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx @@ -14,11 +14,6 @@ interface Props { */ loadedPage: PDFPageProxy | null | undefined; - /** - * Page number, starting at 1 - */ - page: number; - /** * Zoom factor, where `1` is equal to 100% */ @@ -57,7 +52,6 @@ export type PdfTextLayerInfo = { const PdfViewerTextLayer: FC = ({ className, loadedPage, - page = 1, scale = 1, setTextLayerInfo: setTextLayerInfoCallback = () => {} }) => { @@ -71,20 +65,21 @@ const PdfViewerTextLayer: FC = ({ viewport: PDFPageViewport; } | null>(null); + // load text content from the page useEffect(() => { async function loadTextInfo() { - const isPageReady = !!loadedPage && loadedPage.pageNumber === page; - if (isPageReady) { + if (loadedPage) { const viewport = loadedPage.getViewport({ scale }); const textContent = await loadedPage.getTextContent(); - setTextRenderInfo({ textContent, viewport, page, scale }); + setTextRenderInfo({ textContent, viewport, page: loadedPage.pageNumber, scale }); } } loadTextInfo(); - }, [loadedPage, page, scale]); + }, [loadedPage, scale]); const textLayerBuilderRef = useRef(null); // ref for debugging purpose const [textLayerInfo, setTextLayerInfo] = useState(null); + // render text content useEffect(() => { let textLayerBuilder: TextLayerBuilder | null = null; async function loadTextLayer() { @@ -104,23 +99,16 @@ const PdfViewerTextLayer: FC = ({ // render textLayerDiv.innerHTML = ''; try { - const deferredRenderEnd = (() => { - let resolve: null | Function = null; - const promise = new Promise(resolvePromise => { - resolve = resolvePromise; - }); - + const deferredRenderEndPromise = new Promise(resolve => { const listener = () => { - resolve!(); + resolve(undefined); textLayerBuilder?.eventBus.off('textlayerrendered', listener); }; - textLayerBuilder.eventBus.on('textlayerrendered', listener); - - return { promise }; - })(); + textLayerBuilder?.eventBus.on('textlayerrendered', listener); + }); textLayerBuilder.render(); - await deferredRenderEnd.promise; + await deferredRenderEndPromise; // fix text divs _adjustTextDivs(textLayerBuilder.textDivs, textContent.items, scale); @@ -133,20 +121,21 @@ const PdfViewerTextLayer: FC = ({ }; } catch (e) { if (e instanceof RenderingCancelledException) { - // ignore + // Ignore. Rendering is interrupted by useEffect cleanup method. + // Another rendering starts soon return; } else { - throw e; + throw e; // rethrow unknown exception } } } setTextLayerInfo(textLayerInfo); } + loadTextLayer(); return () => { textLayerBuilder?.cancel(); - // should we set text items?? }; }, [textLayerDiv, textRenderInfo]); @@ -168,7 +157,7 @@ const PdfViewerTextLayer: FC = ({ }; /** - * Adjust text span width + * Adjust text span width based on scale * @param textDivs * @param textItems * @param scale diff --git a/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss b/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss index f3bcda870..bcce8911c 100644 --- a/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss +++ b/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss @@ -38,7 +38,8 @@ background: rgba(0, 0, 255, 1); } - /* Avoids https://github.com/mozilla/pdf.js/issues/13840 in Chrome */ + // Avoid unexpected text selection box in Chrome + // see https://github.com/mozilla/pdf.js/issues/13840 &.textLayer br::selection { background: transparent; } From cc0644610267820f1a210f2f89c172f6439108d1 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 18 Nov 2021 11:48:22 +0900 Subject: [PATCH 05/20] refactor: extract text rendering hook --- .../PdfViewer/PdfViewerTextLayer.tsx | 75 ++++++++++++------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx index e05a596ee..097a6d0ac 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx @@ -49,6 +49,20 @@ export type PdfTextLayerInfo = { page: number; }; +type PdfTextContentInfo = { + /** extracted PDF text content */ + textContent: TextContent; + + /** @see Props['scale'] */ + scale: number; + + /** @see PdfTextLayerInfo['viewport'] */ + viewport: PDFPageViewport; + + /** @see PdfTextLayerInfo['page'] */ + page: number; +}; + const PdfViewerTextLayer: FC = ({ className, loadedPage, @@ -58,27 +72,46 @@ const PdfViewerTextLayer: FC = ({ const textLayerRef = useRef(null); const textLayerDiv = textLayerRef.current; - const [textRenderInfo, setTextRenderInfo] = useState<{ - page: number; - scale: number; - textContent: TextContent; - viewport: PDFPageViewport; - } | null>(null); - // load text content from the page + const [textContentInfo, setTextContentInfo] = useState(null); useEffect(() => { async function loadTextInfo() { if (loadedPage) { const viewport = loadedPage.getViewport({ scale }); const textContent = await loadedPage.getTextContent(); - setTextRenderInfo({ textContent, viewport, page: loadedPage.pageNumber, scale }); + setTextContentInfo({ textContent, viewport, page: loadedPage.pageNumber, scale }); } } loadTextInfo(); }, [loadedPage, scale]); + // render text content + const [renderedTextInfo, setRenderedTextInfo] = useState(null); + useTextLayerRendering(textLayerDiv, textContentInfo, setRenderedTextInfo); + + useEffect(() => { + setTextLayerInfoCallback(renderedTextInfo); + }, [renderedTextInfo, setTextLayerInfoCallback]); + + const rootClassName = cx(className, `textLayer`); + return ( +
+ ); +}; + +function useTextLayerRendering( + textLayerDiv: HTMLDivElement | null, + textRenderInfo: PdfTextContentInfo | null, + setRenderedTextInfo?: (info: PdfTextLayerInfo | null) => any +) { const textLayerBuilderRef = useRef(null); // ref for debugging purpose - const [textLayerInfo, setTextLayerInfo] = useState(null); // render text content useEffect(() => { let textLayerBuilder: TextLayerBuilder | null = null; @@ -129,7 +162,9 @@ const PdfViewerTextLayer: FC = ({ } } } - setTextLayerInfo(textLayerInfo); + if (setRenderedTextInfo) { + setRenderedTextInfo(textLayerInfo); + } } loadTextLayer(); @@ -137,24 +172,8 @@ const PdfViewerTextLayer: FC = ({ return () => { textLayerBuilder?.cancel(); }; - }, [textLayerDiv, textRenderInfo]); - - useEffect(() => { - setTextLayerInfoCallback(textLayerInfo); - }, [textLayerInfo, setTextLayerInfoCallback]); - - const rootClassName = cx(className, `textLayer`); - return ( -
- ); -}; + }, [setRenderedTextInfo, textLayerDiv, textRenderInfo]); +} /** * Adjust text span width based on scale From de5731fad760918ea523ab3d6318bf5757d807da Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Fri, 19 Nov 2021 23:46:04 +0900 Subject: [PATCH 06/20] refactor: extract async func call hook --- .../PdfViewer/PdfViewer.stories.tsx | 4 +- .../components/PdfViewer/PdfViewer.tsx | 114 ++++--------- .../PdfViewer/PdfViewerTextLayer.tsx | 160 +++++++----------- .../PdfViewer/useAsyncFunctionCall.ts | 46 +++++ 4 files changed, 144 insertions(+), 180 deletions(-) create mode 100644 packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx index 6e7b31d12..11a3d0f08 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx @@ -36,7 +36,7 @@ storiesOf('DocumentPreview/components/PdfViewer', module) const showTextLayer = boolean('Show text layer', false); const setLoadingAction = action('setLoading'); - const setTextLayerInfoAction = action('setTextLayerInfo'); + const setRenderedTextAction = action('setRenderedText'); return ( ); }); diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index 209b371d1..4a0de76ef 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect, useRef, useState, useMemo } from 'react'; +import React, { FC, useEffect, useRef, useMemo, useCallback } from 'react'; import cx from 'classnames'; import PdfjsLib, { PDFDocumentProxy, @@ -8,9 +8,8 @@ import PdfjsLib, { } from 'pdfjs-dist'; import PdfjsWorkerAsText from 'pdfjs-dist/build/pdf.worker.min.js'; import { settings } from 'carbon-components'; -import PdfViewerTextLayer, { PdfTextLayerInfo } from './PdfViewerTextLayer'; - -const { RenderingCancelledException } = PdfjsLib as any; +import PdfViewerTextLayer, { PdfRenderedText } from './PdfViewerTextLayer'; +import useAsyncFunctionCall from './useAsyncFunctionCall'; setupPdfjs(); @@ -57,7 +56,7 @@ interface Props { /** * Callback for text layer info */ - setTextLayerInfo?: (info: PdfTextLayerInfo | null) => any; + setRenderedText?: (info: PdfRenderedText | null) => any; } const PdfViewer: FC = ({ @@ -70,93 +69,48 @@ const PdfViewer: FC = ({ setPageCount, setLoading, setHideToolbarControls, - setTextLayerInfo, + setRenderedText, children }) => { const canvasRef = useRef(null); - // In order to prevent unnecessary re-loading, loaded file and page are stored in state - const [loadedFile, setLoadedFile] = useState(null); - const [loadedPage, setLoadedPage] = useState(null); - - // load PDF file - useEffect(() => { - let didCancel = false; - - async function loadPdf(): Promise { - if (file) { - const newPdf = await _loadPdf(file); - if (!didCancel) { - setLoadedFile(newPdf); - if (setPageCount) { - setPageCount(newPdf.numPages); - } - } - } - } - loadPdf(); - - return (): void => { - didCancel = true; - }; - }, [file, setPageCount]); - - // load page from PDF file - useEffect(() => { - let didCancel = false; - - async function loadPage(): Promise { - if (loadedFile && page > 0) { - const newPage = await _loadPage(loadedFile, page); - if (!didCancel) { - setLoadedPage(newPage); - } - } - } - loadPage(); - - return (): void => { - didCancel = true; - }; - }, [loadedFile, page]); + const loadedFile = useAsyncFunctionCall( + useCallback(async () => (file ? await _loadPdf(file) : null), [file]) + ); + const loadedPage = useAsyncFunctionCall( + useCallback( + async () => (loadedFile && page > 0 ? await _loadPage(loadedFile, page) : null), + [loadedFile, page] + ) + ); - // extract canvas size of the current page const [viewport, canvasInfo] = useMemo(() => { const viewport = loadedPage?.getViewport({ scale }); const canvasInfo = viewport ? getCanvasInfo(viewport) : undefined; return [viewport, canvasInfo]; }, [loadedPage, scale]); - // render the current page - useEffect(() => { - let didCancel = false; - let task: PDFRenderTask | null = null; - - if (loadedPage && !(loadedPage as any).then && viewport && canvasInfo) { - const render = async () => { - try { - task = _renderPage(loadedPage, canvasRef.current!, viewport, canvasInfo); + // render page + useAsyncFunctionCall( + useCallback( + async (abortSignal: AbortSignal) => { + if (loadedPage && !(loadedPage as any).then && viewport && canvasInfo) { + const task = _renderPage(loadedPage, canvasRef.current!, viewport, canvasInfo); + abortSignal.addEventListener('abort', () => task?.cancel()); await task?.promise; - } catch (e) { - if (e instanceof RenderingCancelledException) { - // Ignore. Rendering is interrupted by the effect cleanup method - // and another rendering will be taken place soon - } else { - throw e; // rethrow unknown exception - } - } finally { - if (!didCancel) { - setLoading(false); - } + + setLoading(false); } - }; - render(); + }, + [canvasInfo, loadedPage, setLoading, viewport] + ) + ); + + useEffect(() => { + if (setPageCount && loadedFile) { + setPageCount(loadedFile.numPages); } - return () => { - didCancel = true; - task?.cancel(); - }; - }, [loadedPage, viewport, canvasInfo, setLoading]); + }, [loadedFile, setPageCount]); useEffect(() => { if (setHideToolbarControls) { @@ -179,7 +133,7 @@ const PdfViewer: FC = ({ className={cx(`${classNameBase}--text`, textLayerClassName)} loadedPage={loadedPage} scale={scale} - setTextLayerInfo={setTextLayerInfo} + setRenderedText={setRenderedText} /> )} {children} @@ -192,7 +146,7 @@ PdfViewer.defaultProps = { scale: 1 }; -function _loadPdf(data: string): Promise { +function _loadPdf(data: string): Promise { return PdfjsLib.getDocument({ data }).promise; } diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx index 097a6d0ac..e6f536076 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx @@ -1,10 +1,9 @@ -import React, { FC, useEffect, useRef, useState } from 'react'; +import React, { FC, useEffect, useRef, useCallback } from 'react'; import cx from 'classnames'; -import PDFJSLib, { PDFPageProxy, PDFPageViewport, TextContent, TextContentItem } from 'pdfjs-dist'; +import { PDFPageProxy, PDFPageViewport, TextContent, TextContentItem } from 'pdfjs-dist'; import { EventBus } from 'pdfjs-dist/lib/web/ui_utils'; import { TextLayerBuilder } from 'pdfjs-dist/lib/web/text_layer_builder'; - -const { RenderingCancelledException } = PDFJSLib as any; +import useAsyncFunctionCall from './useAsyncFunctionCall'; interface Props { className?: string; @@ -22,10 +21,10 @@ interface Props { /** * Callback for text layer info */ - setTextLayerInfo?: (info: PdfTextLayerInfo | null) => any; + setRenderedText?: (info: PdfRenderedText | null) => any; } -export type PdfTextLayerInfo = { +export type PdfRenderedText = { /** * PDF text content */ @@ -49,49 +48,56 @@ export type PdfTextLayerInfo = { page: number; }; -type PdfTextContentInfo = { - /** extracted PDF text content */ - textContent: TextContent; - - /** @see Props['scale'] */ - scale: number; - - /** @see PdfTextLayerInfo['viewport'] */ - viewport: PDFPageViewport; - - /** @see PdfTextLayerInfo['page'] */ - page: number; -}; - const PdfViewerTextLayer: FC = ({ className, loadedPage, scale = 1, - setTextLayerInfo: setTextLayerInfoCallback = () => {} + setRenderedText = () => {} }) => { const textLayerRef = useRef(null); const textLayerDiv = textLayerRef.current; // load text content from the page - const [textContentInfo, setTextContentInfo] = useState(null); - useEffect(() => { - async function loadTextInfo() { + const loadedText = useAsyncFunctionCall( + useCallback(async () => { if (loadedPage) { const viewport = loadedPage.getViewport({ scale }); const textContent = await loadedPage.getTextContent(); - setTextContentInfo({ textContent, viewport, page: loadedPage.pageNumber, scale }); + return { textContent, viewport, page: loadedPage.pageNumber, scale }; } - } - loadTextInfo(); - }, [loadedPage, scale]); + return null; + }, [loadedPage, scale]) + ); // render text content - const [renderedTextInfo, setRenderedTextInfo] = useState(null); - useTextLayerRendering(textLayerDiv, textContentInfo, setRenderedTextInfo); + const renderedText = useAsyncFunctionCall( + useCallback( + async (signal: AbortSignal) => { + if (textLayerDiv && loadedText) { + const { textContent, viewport, scale, page } = loadedText; + + const builder = new TextLayerBuilder({ + textLayerDiv, + viewport, + eventBus: new EventBus(), + pageIndex: page - 1 + }); + signal.addEventListener('abort', () => builder.cancel()); + + await _renderTextLayer(builder, textContent, textLayerDiv, scale); + return { textContent, viewport, page, textDivs: builder.textDivs }; + } + return undefined; + }, + [loadedText, textLayerDiv] + ) + ); useEffect(() => { - setTextLayerInfoCallback(renderedTextInfo); - }, [renderedTextInfo, setTextLayerInfoCallback]); + if (renderedText !== undefined) { + setRenderedText(renderedText); + } + }, [renderedText, setRenderedText]); const rootClassName = cx(className, `textLayer`); return ( @@ -99,80 +105,38 @@ const PdfViewerTextLayer: FC = ({ className={rootClassName} ref={textLayerRef} style={{ - width: `${textContentInfo?.viewport?.width ?? 0}px`, - height: `${textContentInfo?.viewport?.height ?? 0}px` + width: `${loadedText?.viewport?.width ?? 0}px`, + height: `${loadedText?.viewport?.height ?? 0}px` }} /> ); }; -function useTextLayerRendering( - textLayerDiv: HTMLDivElement | null, - textRenderInfo: PdfTextContentInfo | null, - setRenderedTextInfo?: (info: PdfTextLayerInfo | null) => any +/** + * Render text into DOM using the text layer builder + */ +async function _renderTextLayer( + builder: TextLayerBuilder, + textContent: TextContent, + textLayerDiv: HTMLDivElement, + scale: number ) { - const textLayerBuilderRef = useRef(null); // ref for debugging purpose - // render text content - useEffect(() => { - let textLayerBuilder: TextLayerBuilder | null = null; - async function loadTextLayer() { - let textLayerInfo: PdfTextLayerInfo | null = null; - - if (textLayerDiv && textRenderInfo) { - const { textContent, viewport, scale, page } = textRenderInfo; - // prepare text layer - textLayerBuilder = textLayerBuilderRef.current = new TextLayerBuilder({ - textLayerDiv, - viewport, - eventBus: new EventBus(), - pageIndex: page - 1 - }); - textLayerBuilder.setTextContent(textContent); - - // render - textLayerDiv.innerHTML = ''; - try { - const deferredRenderEndPromise = new Promise(resolve => { - const listener = () => { - resolve(undefined); - textLayerBuilder?.eventBus.off('textlayerrendered', listener); - }; - textLayerBuilder?.eventBus.on('textlayerrendered', listener); - }); - - textLayerBuilder.render(); - await deferredRenderEndPromise; - - // fix text divs - _adjustTextDivs(textLayerBuilder.textDivs, textContent.items, scale); - - textLayerInfo = { - textContent, - textDivs: textLayerBuilder.textDivs, - viewport, - page - }; - } catch (e) { - if (e instanceof RenderingCancelledException) { - // Ignore. Rendering is interrupted by useEffect cleanup method. - // Another rendering starts soon - return; - } else { - throw e; // rethrow unknown exception - } - } - } - if (setRenderedTextInfo) { - setRenderedTextInfo(textLayerInfo); - } - } + builder.setTextContent(textContent); + + // render + textLayerDiv.innerHTML = ''; + const deferredRenderEndPromise = new Promise(resolve => { + const listener = () => { + resolve(undefined); + builder?.eventBus.off('textlayerrendered', listener); + }; + builder?.eventBus.on('textlayerrendered', listener); + }); - loadTextLayer(); + builder.render(); + await deferredRenderEndPromise; - return () => { - textLayerBuilder?.cancel(); - }; - }, [setRenderedTextInfo, textLayerDiv, textRenderInfo]); + _adjustTextDivs(builder.textDivs, textContent.items, scale); } /** diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts new file mode 100644 index 000000000..6f3d5f929 --- /dev/null +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts @@ -0,0 +1,46 @@ +import { useEffect, useState } from 'react'; + +type AsyncFunc = (signal: AbortSignal) => Promise; +type AsyncFuncReturnType = T extends AsyncFunc ? U : never; + +/** + * Call async function WRAPPED BY `useCallback` and return its result + * + * @param asyncFunction async function wrapped by `useCallback`. + * Take one parameter `setCancellable` to set _cancellable_ of the current async call. + * @returns the result of the async function + */ +function useAsyncFunctionCall, ReturnType = AsyncFuncReturnType>( + asyncFunction: Func +): ReturnType | undefined { + const [result, setResult] = useState(); + + useEffect(() => { + let state: 'pending' | 'fulfilled' | 'rejected' = 'pending'; + const abortController = new AbortController(); + + asyncFunction(abortController.signal) + .then((promiseResult: ReturnType) => { + state = 'fulfilled'; + if (!abortController.signal.aborted && promiseResult !== undefined) { + setResult(promiseResult); + } + }) + .catch(err => { + state = 'rejected'; + if (!abortController.signal.aborted) { + throw err; + } + }); + + return (): void => { + if (state === 'pending') { + abortController.abort(); + } + }; + }, [asyncFunction]); + + return result; +} + +export default useAsyncFunctionCall; From f64fa0774851b7aa2bb7aa375321d1937b283941 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Wed, 24 Nov 2021 10:51:53 +0900 Subject: [PATCH 07/20] fix: revise how to import css from pdfjs --- .../_document-preview-pdf-viewer.scss | 54 +----------- .../document-preview/_pdfjs_web_mixins.scss | 83 +++++++++++++++++++ 2 files changed, 86 insertions(+), 51 deletions(-) create mode 100644 packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss diff --git a/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss b/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss index bcce8911c..dce987167 100644 --- a/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss +++ b/packages/discovery-styles/scss/components/document-preview/_document-preview-pdf-viewer.scss @@ -1,5 +1,8 @@ +@import './pdfjs_web_mixins'; + .#{$prefix}--document-preview-pdf-viewer { position: relative; + @include pdfjsTextLayer; } .#{$prefix}--document-preview-pdf-viewer--canvas { @@ -8,55 +11,4 @@ .#{$prefix}--document-preview-pdf-viewer--text { transform-origin: left top 0px; - - // - // NOTE: import textLayer styles from ~pdfjs-dist/web/pdf_viewer.css - // @import "~pdfjs-dist/web/pdf_viewer" doesn't work for loading image - // - &.textLayer { - position: absolute; - text-align: initial; - left: 0; - top: 0; - right: 0; - bottom: 0; - overflow: hidden; - opacity: 0.2; - line-height: 1; - } - - &.textLayer span, - &.textLayer br { - color: transparent; - position: absolute; - white-space: pre; - cursor: text; - transform-origin: 0% 0%; - } - - &.textLayer ::selection { - background: rgba(0, 0, 255, 1); - } - - // Avoid unexpected text selection box in Chrome - // see https://github.com/mozilla/pdf.js/issues/13840 - &.textLayer br::selection { - background: transparent; - } - - &.textLayer .endOfContent { - display: block; - position: absolute; - left: 0; - top: 100%; - right: 0; - bottom: 0; - z-index: -1; - cursor: default; - user-select: none; - } - - &.textLayer .endOfContent.active { - top: 0; - } } diff --git a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss new file mode 100644 index 000000000..abac06472 --- /dev/null +++ b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss @@ -0,0 +1,83 @@ +@mixin pdfjsTextLayer { + // CSS from ~pdfjs-dist/web/pdf_viewer.css for scoped style + + // BEGIN-QUOTE --- awk '/^\/\*/,/\*\//' + /* Copyright 2014 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // END-QUOTE + + // BEGIN-QUOTE --- awk '/^\.textLayer/,/}/' + .textLayer { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + opacity: 0.2; + line-height: 1; + } + .textLayer > span { + color: transparent; + position: absolute; + white-space: pre; + cursor: text; + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + } + .textLayer .highlight { + margin: -1px; + padding: 1px; + + background-color: rgb(180, 0, 170); + border-radius: 4px; + } + .textLayer .highlight.begin { + border-radius: 4px 0px 0px 4px; + } + .textLayer .highlight.end { + border-radius: 0px 4px 4px 0px; + } + .textLayer .highlight.middle { + border-radius: 0px; + } + .textLayer .highlight.selected { + background-color: rgb(0, 100, 0); + } + .textLayer ::-moz-selection { + background: rgb(0, 0, 255); + } + .textLayer ::selection { + background: rgb(0, 0, 255); + } + .textLayer .endOfContent { + display: block; + position: absolute; + left: 0px; + top: 100%; + right: 0px; + bottom: 0px; + z-index: -1; + cursor: default; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + .textLayer .endOfContent.active { + top: 0px; + } + // END-QUOTE +} // end mixin From 3c08df91e4938c7a7483b7c26ee4c52bca94b9f6 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Wed, 24 Nov 2021 11:29:44 +0900 Subject: [PATCH 08/20] fix: install @types/pdfjs-dist to yarn2 --- .../discovery-react-components/package.json | 1 + yarn.lock | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/discovery-react-components/package.json b/packages/discovery-react-components/package.json index 91f4d4191..49e64485a 100644 --- a/packages/discovery-react-components/package.json +++ b/packages/discovery-react-components/package.json @@ -43,6 +43,7 @@ "react-virtualized": "9.21.1" }, "devDependencies": { + "@types/pdfjs-dist": "^2.10.378", "cross-env": "^7.0.3", "css-loader": "^3.4.2", "madge": "^5.0.1", diff --git a/yarn.lock b/yarn.lock index f7460da53..513c03d4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2267,10 +2267,11 @@ __metadata: languageName: node linkType: hard -"@ibm-watson/discovery-react-components@^1.5.0-beta.1, @ibm-watson/discovery-react-components@workspace:packages/discovery-react-components": +"@ibm-watson/discovery-react-components@^1.5.0-beta.2, @ibm-watson/discovery-react-components@workspace:packages/discovery-react-components": version: 0.0.0-use.local resolution: "@ibm-watson/discovery-react-components@workspace:packages/discovery-react-components" dependencies: + "@types/pdfjs-dist": ^2.10.378 classnames: ^2.2.6 cross-env: ^7.0.3 css-loader: ^3.4.2 @@ -2298,7 +2299,7 @@ __metadata: languageName: unknown linkType: soft -"@ibm-watson/discovery-styles@^1.5.0-beta.1, @ibm-watson/discovery-styles@workspace:packages/discovery-styles": +"@ibm-watson/discovery-styles@^1.5.0-beta.2, @ibm-watson/discovery-styles@workspace:packages/discovery-styles": version: 0.0.0-use.local resolution: "@ibm-watson/discovery-styles@workspace:packages/discovery-styles" peerDependencies: @@ -4938,6 +4939,15 @@ __metadata: languageName: node linkType: hard +"@types/pdfjs-dist@npm:^2.10.378": + version: 2.10.378 + resolution: "@types/pdfjs-dist@npm:2.10.378" + dependencies: + pdfjs-dist: "*" + checksum: 36dd6010f7d23a995efdf11ea4ecb56f371f8bfb3e83a5c311666726e13238597ed1519701d0e2e6fb297270d01ad6aece9582b036fd4cb3aa301e61ea364978 + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.3 resolution: "@types/prop-types@npm:15.7.3" @@ -10236,8 +10246,8 @@ __metadata: resolution: "discovery-search-app@workspace:examples/discovery-search-app" dependencies: "@carbon/icons": ^10.5.0 - "@ibm-watson/discovery-react-components": ^1.5.0-beta.1 - "@ibm-watson/discovery-styles": ^1.5.0-beta.1 + "@ibm-watson/discovery-react-components": ^1.5.0-beta.2 + "@ibm-watson/discovery-styles": ^1.5.0-beta.2 body-parser: ^1.19.0 carbon-components: ^10.6.0 carbon-components-react: ^7.7.0 @@ -19518,6 +19528,18 @@ __metadata: languageName: node linkType: hard +"pdfjs-dist@npm:*": + version: 2.11.338 + resolution: "pdfjs-dist@npm:2.11.338" + peerDependencies: + worker-loader: ^3.0.8 + peerDependenciesMeta: + worker-loader: + optional: true + checksum: 1b946a3eeb3312a79e12b4e0aa066bb2b98487b9ee329666edc840a194602595cf84de9a3f6dbb023b808699a6ebb0cd06e751314fc4c0ffa56f7be12855d296 + languageName: node + linkType: hard + "pdfjs-dist@npm:^2.2.228": version: 2.2.228 resolution: "pdfjs-dist@npm:2.2.228" From c72222159d280202a567f2d33291f121d8b1973c Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Wed, 24 Nov 2021 12:07:45 +0900 Subject: [PATCH 09/20] feat: add script to update style --- packages/discovery-styles/package.json | 1 + .../discovery-styles/scripts/update-styles.sh | 19 +++++++++++++++++++ .../document-preview/_pdfjs_web_mixins.scss | 8 ++++---- 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100755 packages/discovery-styles/scripts/update-styles.sh diff --git a/packages/discovery-styles/package.json b/packages/discovery-styles/package.json index 3bbdf2c64..7c6b9e05f 100644 --- a/packages/discovery-styles/package.json +++ b/packages/discovery-styles/package.json @@ -7,6 +7,7 @@ "repository": "https://github.com/watson-developer-cloud/discovery-components", "main": "scss/index.scss", "scripts": { + "prebuild": "scripts/update-styles.sh", "build": "node-sass --importer=../../node_modules/node-sass-tilde-importer --source-map=true scss/index.scss css/index.css", "prepublish": "yarn run build", "start": "yarn run build -- --watch", diff --git a/packages/discovery-styles/scripts/update-styles.sh b/packages/discovery-styles/scripts/update-styles.sh new file mode 100755 index 000000000..2c112101f --- /dev/null +++ b/packages/discovery-styles/scripts/update-styles.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +PDFJS_WEB_CSS=../../node_modules/pdfjs-dist/web/pdf_viewer.css +PDFJS_SCSS=scss/components/document-preview/_pdfjs_web_mixins.scss + +function update_pdfjs_scss() { + key=$1 + tmp=$PDFJS_SCSS.tmp + + sed -e "/BEGIN-QUOTE $key/q" $PDFJS_SCSS > $tmp + cat >> $tmp + sed -ne "/END-QUOTE $key/,\$p" $PDFJS_SCSS >> $tmp + cp $tmp $PDFJS_SCSS; + rm $tmp; +} + +cat $PDFJS_WEB_CSS | awk '/^\/\*/,/\*\//' | update_pdfjs_scss "COMMENT" +cat $PDFJS_WEB_CSS | awk '/^\.textLayer/,/}/' | update_pdfjs_scss "TEXT-LAYER" +../../node_modules/.bin/prettier --write $PDFJS_SCSS diff --git a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss index abac06472..37e94e1c8 100644 --- a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss +++ b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss @@ -1,7 +1,7 @@ @mixin pdfjsTextLayer { // CSS from ~pdfjs-dist/web/pdf_viewer.css for scoped style - // BEGIN-QUOTE --- awk '/^\/\*/,/\*\//' + // BEGIN-QUOTE COMMENT /* Copyright 2014 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +16,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - // END-QUOTE + // END-QUOTE COMMENT - // BEGIN-QUOTE --- awk '/^\.textLayer/,/}/' + // BEGIN-QUOTE TEXT-LAYER .textLayer { position: absolute; left: 0; @@ -79,5 +79,5 @@ .textLayer .endOfContent.active { top: 0px; } - // END-QUOTE + // END-QUOTE TEXT-LAYER } // end mixin From 69ff0425f2a74f9b35ad7191cc50b945366fd319 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Wed, 24 Nov 2021 12:50:02 +0900 Subject: [PATCH 10/20] refactor: revise script for importing css --- .../discovery-styles/scripts/update-styles.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/discovery-styles/scripts/update-styles.sh b/packages/discovery-styles/scripts/update-styles.sh index 2c112101f..49ab2c595 100755 --- a/packages/discovery-styles/scripts/update-styles.sh +++ b/packages/discovery-styles/scripts/update-styles.sh @@ -3,17 +3,18 @@ PDFJS_WEB_CSS=../../node_modules/pdfjs-dist/web/pdf_viewer.css PDFJS_SCSS=scss/components/document-preview/_pdfjs_web_mixins.scss -function update_pdfjs_scss() { - key=$1 - tmp=$PDFJS_SCSS.tmp +function replace_quote() { + file=$1 + key=$2 + tmp=$file.tmp - sed -e "/BEGIN-QUOTE $key/q" $PDFJS_SCSS > $tmp + sed -e "/BEGIN-QUOTE $key/q" $file > $tmp cat >> $tmp - sed -ne "/END-QUOTE $key/,\$p" $PDFJS_SCSS >> $tmp - cp $tmp $PDFJS_SCSS; + sed -ne "/END-QUOTE $key/,\$p" $file >> $tmp + cp $tmp $file; rm $tmp; } -cat $PDFJS_WEB_CSS | awk '/^\/\*/,/\*\//' | update_pdfjs_scss "COMMENT" -cat $PDFJS_WEB_CSS | awk '/^\.textLayer/,/}/' | update_pdfjs_scss "TEXT-LAYER" +cat $PDFJS_WEB_CSS | awk '/^\/\*/,/\*\//' | replace_quote $PDFJS_SCSS "COMMENT" +cat $PDFJS_WEB_CSS | awk '/^\.textLayer/,/}/' | replace_quote $PDFJS_SCSS "TEXT-LAYER" ../../node_modules/.bin/prettier --write $PDFJS_SCSS From 17feb71be4ba83ea4d43dac0a3c22f6429b6d0e9 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 20:43:19 +0900 Subject: [PATCH 11/20] fix: use postcss to manupulate pdfjs-web css --- .../scripts/generate-pdfjs_web_mixin.js | 41 +++++++++++++++++++ .../discovery-styles/scripts/update-styles.sh | 24 ++++------- .../document-preview/_pdfjs_web_mixins.scss | 18 +++++--- 3 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js diff --git a/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js b/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js new file mode 100644 index 000000000..68265ccfc --- /dev/null +++ b/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js @@ -0,0 +1,41 @@ +/** + * Generate mixin SCSS for pdfjs web.css .textLayer styles + * + * Usage: node + */ +const postcss = require('postcss'); +const fs = require('fs'); + +const originalPdfjsWebCss = process.argv[2]; +const mixinPdfjsWebScss = process.argv[3]; + +// load teh original style +const cssText = fs.readFileSync(originalPdfjsWebCss, { encoding: 'utf-8' }); +const cssRoot = postcss.parse(cssText); + +// remove rules not related to .textLayer +cssRoot.walkRules(rule => { + if (rule.selector.includes('.textLayer')) { + return; + } + rule.remove(); +}); + +// keep copyright comment +cssRoot.walkComments(comment => { + if (comment.text.includes('Copyright')) { + return; + } + comment.remove(); +}); + +// write mixin scss +const generatedCss = ` +/* DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED FROM \`update-styles.sh\`. */ +@mixin pdfjsTextLayer { + // CSS from ~pdfjs-dist/web/pdf_viewer.css for scoped style + ${cssRoot.toString()} +} +`; + +fs.writeFileSync(mixinPdfjsWebScss, generatedCss, { encoding: 'utf-8' }); diff --git a/packages/discovery-styles/scripts/update-styles.sh b/packages/discovery-styles/scripts/update-styles.sh index 49ab2c595..423191ce1 100755 --- a/packages/discovery-styles/scripts/update-styles.sh +++ b/packages/discovery-styles/scripts/update-styles.sh @@ -1,20 +1,10 @@ #!/bin/sh +BASEDIR=$(dirname "$0")/.. +PDFJS_WEB_CSS=$BASEDIR/../../node_modules/pdfjs-dist/web/pdf_viewer.css +PDFJS_SCSS=$BASEDIR/scss/components/document-preview/_pdfjs_web_mixins.scss -PDFJS_WEB_CSS=../../node_modules/pdfjs-dist/web/pdf_viewer.css -PDFJS_SCSS=scss/components/document-preview/_pdfjs_web_mixins.scss +# generate PDFJS_SCSS +node $BASEDIR/scripts/generate-pdfjs_web_mixin.js "$PDFJS_WEB_CSS" "$PDFJS_SCSS" -function replace_quote() { - file=$1 - key=$2 - tmp=$file.tmp - - sed -e "/BEGIN-QUOTE $key/q" $file > $tmp - cat >> $tmp - sed -ne "/END-QUOTE $key/,\$p" $file >> $tmp - cp $tmp $file; - rm $tmp; -} - -cat $PDFJS_WEB_CSS | awk '/^\/\*/,/\*\//' | replace_quote $PDFJS_SCSS "COMMENT" -cat $PDFJS_WEB_CSS | awk '/^\.textLayer/,/}/' | replace_quote $PDFJS_SCSS "TEXT-LAYER" -../../node_modules/.bin/prettier --write $PDFJS_SCSS +# perttier +../../node_modules/.bin/prettier --write "$PDFJS_SCSS" diff --git a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss index 37e94e1c8..22f31964b 100644 --- a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss +++ b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss @@ -1,7 +1,6 @@ +/* DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED FROM `update-styles.sh`. */ @mixin pdfjsTextLayer { // CSS from ~pdfjs-dist/web/pdf_viewer.css for scoped style - - // BEGIN-QUOTE COMMENT /* Copyright 2014 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - // END-QUOTE COMMENT - // BEGIN-QUOTE TEXT-LAYER .textLayer { position: absolute; left: 0; @@ -29,6 +26,7 @@ opacity: 0.2; line-height: 1; } + .textLayer > span { color: transparent; position: absolute; @@ -37,6 +35,7 @@ -webkit-transform-origin: 0% 0%; transform-origin: 0% 0%; } + .textLayer .highlight { margin: -1px; padding: 1px; @@ -44,24 +43,31 @@ background-color: rgb(180, 0, 170); border-radius: 4px; } + .textLayer .highlight.begin { border-radius: 4px 0px 0px 4px; } + .textLayer .highlight.end { border-radius: 0px 4px 4px 0px; } + .textLayer .highlight.middle { border-radius: 0px; } + .textLayer .highlight.selected { background-color: rgb(0, 100, 0); } + .textLayer ::-moz-selection { background: rgb(0, 0, 255); } + .textLayer ::selection { background: rgb(0, 0, 255); } + .textLayer .endOfContent { display: block; position: absolute; @@ -76,8 +82,8 @@ -ms-user-select: none; user-select: none; } + .textLayer .endOfContent.active { top: 0px; } - // END-QUOTE TEXT-LAYER -} // end mixin +} From 158b8a23aab35d607d40498d85da65f1ae60cb32 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 20:49:45 +0900 Subject: [PATCH 12/20] fix: add comment to the style update script --- packages/discovery-styles/scripts/update-styles.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/discovery-styles/scripts/update-styles.sh b/packages/discovery-styles/scripts/update-styles.sh index 423191ce1..7c0e47dbb 100755 --- a/packages/discovery-styles/scripts/update-styles.sh +++ b/packages/discovery-styles/scripts/update-styles.sh @@ -1,9 +1,18 @@ #!/bin/sh +# +# This script updates PDF text layer CSS from the `pdfjs-dist` npm package +# +# When you upgrade the `pdfjs-dist` package, you have to run this script +# to include the style changes. +# +# Usage: $ scripts/update-styles.sh +# - You must run `yarn` to install `pdfjs-dist` package before running +# BASEDIR=$(dirname "$0")/.. + +# pdfjs textLayer styles PDFJS_WEB_CSS=$BASEDIR/../../node_modules/pdfjs-dist/web/pdf_viewer.css PDFJS_SCSS=$BASEDIR/scss/components/document-preview/_pdfjs_web_mixins.scss - -# generate PDFJS_SCSS node $BASEDIR/scripts/generate-pdfjs_web_mixin.js "$PDFJS_WEB_CSS" "$PDFJS_SCSS" # perttier From 0705d2ea2000e2b956df2affe57bedacd1d9eca0 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 20:58:11 +0900 Subject: [PATCH 13/20] refactor: move useAsyncFunctionCall to utils --- .../src/components/DocumentPreview/DocumentPreview.tsx | 1 + .../DocumentPreview/components/PdfViewer/PdfViewer.tsx | 2 +- .../components/PdfViewer/PdfViewerTextLayer.tsx | 4 ++-- .../PdfViewer => utils}/useAsyncFunctionCall.ts | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) rename packages/discovery-react-components/src/{components/DocumentPreview/components/PdfViewer => utils}/useAsyncFunctionCall.ts (88%) diff --git a/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx b/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx index b06e33612..13813ab7b 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx @@ -154,6 +154,7 @@ function PreviewDocument({ const ErrorBoundDocumentPreview: any = withErrorBoundary(DocumentPreview); ErrorBoundDocumentPreview.PreviewToolbar = PreviewToolbar; ErrorBoundDocumentPreview.PreviewDocument = PreviewDocument; +ErrorBoundDocumentPreview.PdfViewerHighlight = PdfViewerHighlight; export default ErrorBoundDocumentPreview; export { ErrorBoundDocumentPreview as DocumentPreview }; diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index 4a0de76ef..dc34badf7 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -9,7 +9,7 @@ import PdfjsLib, { import PdfjsWorkerAsText from 'pdfjs-dist/build/pdf.worker.min.js'; import { settings } from 'carbon-components'; import PdfViewerTextLayer, { PdfRenderedText } from './PdfViewerTextLayer'; -import useAsyncFunctionCall from './useAsyncFunctionCall'; +import useAsyncFunctionCall from 'utils/useAsyncFunctionCall'; setupPdfjs(); diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx index e6f536076..21277ee2e 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx @@ -3,7 +3,7 @@ import cx from 'classnames'; import { PDFPageProxy, PDFPageViewport, TextContent, TextContentItem } from 'pdfjs-dist'; import { EventBus } from 'pdfjs-dist/lib/web/ui_utils'; import { TextLayerBuilder } from 'pdfjs-dist/lib/web/text_layer_builder'; -import useAsyncFunctionCall from './useAsyncFunctionCall'; +import useAsyncFunctionCall from 'utils/useAsyncFunctionCall'; interface Props { className?: string; @@ -127,7 +127,7 @@ async function _renderTextLayer( textLayerDiv.innerHTML = ''; const deferredRenderEndPromise = new Promise(resolve => { const listener = () => { - resolve(undefined); + resolve(); builder?.eventBus.off('textlayerrendered', listener); }; builder?.eventBus.on('textlayerrendered', listener); diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts b/packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts similarity index 88% rename from packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts rename to packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts index 6f3d5f929..c5077d4d1 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/useAsyncFunctionCall.ts +++ b/packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts @@ -16,25 +16,25 @@ function useAsyncFunctionCall, ReturnType = AsyncFun const [result, setResult] = useState(); useEffect(() => { - let state: 'pending' | 'fulfilled' | 'rejected' = 'pending'; + let resolved = false; const abortController = new AbortController(); asyncFunction(abortController.signal) .then((promiseResult: ReturnType) => { - state = 'fulfilled'; + resolved = false; if (!abortController.signal.aborted && promiseResult !== undefined) { setResult(promiseResult); } }) .catch(err => { - state = 'rejected'; + resolved = false; if (!abortController.signal.aborted) { throw err; } }); return (): void => { - if (state === 'pending') { + if (!resolved) { abortController.abort(); } }; From 9e9cad5058d02d827f27971ef3d80d80072790fa Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 20:59:06 +0900 Subject: [PATCH 14/20] fix: name of package script --- packages/discovery-styles/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discovery-styles/package.json b/packages/discovery-styles/package.json index 7c6b9e05f..ceeb66d32 100644 --- a/packages/discovery-styles/package.json +++ b/packages/discovery-styles/package.json @@ -7,7 +7,7 @@ "repository": "https://github.com/watson-developer-cloud/discovery-components", "main": "scss/index.scss", "scripts": { - "prebuild": "scripts/update-styles.sh", + "update-style": "scripts/update-styles.sh", "build": "node-sass --importer=../../node_modules/node-sass-tilde-importer --source-map=true scss/index.scss css/index.css", "prepublish": "yarn run build", "start": "yarn run build -- --watch", From 052336a81b92576ce11101ffc70766fdce6bda64 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 21:44:14 +0900 Subject: [PATCH 15/20] fix: apply CI comment --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 8f1c45781..6da07fa05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2271,13 +2271,13 @@ __metadata: version: 0.0.0-use.local resolution: "@ibm-watson/discovery-react-components@workspace:packages/discovery-react-components" dependencies: - "@types/pdfjs-dist": ^2.10.378 "@storybook/addon-actions": ^5.3.21 "@storybook/addon-docs": ^5.3.21 "@storybook/addon-knobs": ^5.3.21 "@storybook/core": ^5.3.21 "@storybook/react": ^5.3.21 "@storybook/source-loader": ^5.3.21 + "@types/pdfjs-dist": ^2.10.378 classnames: ^2.2.6 cross-env: ^7.0.3 css-loader: ^3.4.2 From e081c92ee35042ab074f196f5e0218247c179ce9 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 22:42:53 +0900 Subject: [PATCH 16/20] fix: fix broken logic --- .../src/utils/useAsyncFunctionCall.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts b/packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts index c5077d4d1..fe97a789e 100644 --- a/packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts +++ b/packages/discovery-react-components/src/utils/useAsyncFunctionCall.ts @@ -21,13 +21,13 @@ function useAsyncFunctionCall, ReturnType = AsyncFun asyncFunction(abortController.signal) .then((promiseResult: ReturnType) => { - resolved = false; + resolved = true; if (!abortController.signal.aborted && promiseResult !== undefined) { setResult(promiseResult); } }) .catch(err => { - resolved = false; + resolved = true; if (!abortController.signal.aborted) { throw err; } From 68d895dbaa4952e502318ff2a56e969ba5195d44 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Thu, 2 Dec 2021 22:49:59 +0900 Subject: [PATCH 17/20] fix: remove unused code --- .../src/components/DocumentPreview/DocumentPreview.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx b/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx index 13813ab7b..b06e33612 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/DocumentPreview.tsx @@ -154,7 +154,6 @@ function PreviewDocument({ const ErrorBoundDocumentPreview: any = withErrorBoundary(DocumentPreview); ErrorBoundDocumentPreview.PreviewToolbar = PreviewToolbar; ErrorBoundDocumentPreview.PreviewDocument = PreviewDocument; -ErrorBoundDocumentPreview.PdfViewerHighlight = PdfViewerHighlight; export default ErrorBoundDocumentPreview; export { ErrorBoundDocumentPreview as DocumentPreview }; From 8c82fae7f89a722606f042998db2097a37daed96 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Fri, 3 Dec 2021 13:57:50 +0900 Subject: [PATCH 18/20] fix: apply review comments around pdfjs css --- packages/discovery-styles/package.json | 8 ++++++-- .../scripts/generate-pdfjs_web_mixin.js | 4 ++-- .../{update-styles.sh => update-styles-from-pdfjs.sh} | 6 +++--- .../components/document-preview/_pdfjs_web_mixins.scss | 2 +- yarn.lock | 10 ++++++++++ 5 files changed, 22 insertions(+), 8 deletions(-) rename packages/discovery-styles/scripts/{update-styles.sh => update-styles-from-pdfjs.sh} (77%) diff --git a/packages/discovery-styles/package.json b/packages/discovery-styles/package.json index ceeb66d32..e8c84e651 100644 --- a/packages/discovery-styles/package.json +++ b/packages/discovery-styles/package.json @@ -7,11 +7,11 @@ "repository": "https://github.com/watson-developer-cloud/discovery-components", "main": "scss/index.scss", "scripts": { - "update-style": "scripts/update-styles.sh", "build": "node-sass --importer=../../node_modules/node-sass-tilde-importer --source-map=true scss/index.scss css/index.css", "prepublish": "yarn run build", "start": "yarn run build -- --watch", - "analyze": "yarn run g:analyze css/index.css" + "analyze": "yarn run g:analyze css/index.css", + "update-styles-from-pdfjs": "scripts/update-styles-from-pdfjs.sh" }, "files": [ "css/**/*", @@ -25,5 +25,9 @@ }, "publishConfig": { "access": "public" + }, + "devDependencies": { + "@types/prettier": "^2", + "prettier": "^2.4.1" } } diff --git a/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js b/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js index 68265ccfc..ef99bdf52 100644 --- a/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js +++ b/packages/discovery-styles/scripts/generate-pdfjs_web_mixin.js @@ -9,7 +9,7 @@ const fs = require('fs'); const originalPdfjsWebCss = process.argv[2]; const mixinPdfjsWebScss = process.argv[3]; -// load teh original style +// load the original style const cssText = fs.readFileSync(originalPdfjsWebCss, { encoding: 'utf-8' }); const cssRoot = postcss.parse(cssText); @@ -31,7 +31,7 @@ cssRoot.walkComments(comment => { // write mixin scss const generatedCss = ` -/* DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED FROM \`update-styles.sh\`. */ +/* DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED FROM \`update-styles-from-pdfjs.sh\`. */ @mixin pdfjsTextLayer { // CSS from ~pdfjs-dist/web/pdf_viewer.css for scoped style ${cssRoot.toString()} diff --git a/packages/discovery-styles/scripts/update-styles.sh b/packages/discovery-styles/scripts/update-styles-from-pdfjs.sh similarity index 77% rename from packages/discovery-styles/scripts/update-styles.sh rename to packages/discovery-styles/scripts/update-styles-from-pdfjs.sh index 7c0e47dbb..d4cf33c89 100755 --- a/packages/discovery-styles/scripts/update-styles.sh +++ b/packages/discovery-styles/scripts/update-styles-from-pdfjs.sh @@ -13,7 +13,7 @@ BASEDIR=$(dirname "$0")/.. # pdfjs textLayer styles PDFJS_WEB_CSS=$BASEDIR/../../node_modules/pdfjs-dist/web/pdf_viewer.css PDFJS_SCSS=$BASEDIR/scss/components/document-preview/_pdfjs_web_mixins.scss -node $BASEDIR/scripts/generate-pdfjs_web_mixin.js "$PDFJS_WEB_CSS" "$PDFJS_SCSS" +yarn node $BASEDIR/scripts/generate-pdfjs_web_mixin.js "$PDFJS_WEB_CSS" "$PDFJS_SCSS" -# perttier -../../node_modules/.bin/prettier --write "$PDFJS_SCSS" +# prettier +yarn run prettier --write "$PDFJS_SCSS" diff --git a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss index 22f31964b..f8d96b2f4 100644 --- a/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss +++ b/packages/discovery-styles/scss/components/document-preview/_pdfjs_web_mixins.scss @@ -1,4 +1,4 @@ -/* DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED FROM `update-styles.sh`. */ +/* DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED FROM `update-styles-from-pdfjs.sh`. */ @mixin pdfjsTextLayer { // CSS from ~pdfjs-dist/web/pdf_viewer.css for scoped style /* Copyright 2014 Mozilla Foundation diff --git a/yarn.lock b/yarn.lock index 6da07fa05..f901dc1f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2308,6 +2308,9 @@ __metadata: "@ibm-watson/discovery-styles@^1.5.0-beta.2, @ibm-watson/discovery-styles@workspace:packages/discovery-styles": version: 0.0.0-use.local resolution: "@ibm-watson/discovery-styles@workspace:packages/discovery-styles" + dependencies: + "@types/prettier": ^2 + prettier: ^2.4.1 peerDependencies: carbon-components: ">= 10.6.0 < 11" languageName: unknown @@ -4954,6 +4957,13 @@ __metadata: languageName: node linkType: hard +"@types/prettier@npm:^2": + version: 2.4.2 + resolution: "@types/prettier@npm:2.4.2" + checksum: 76e230b2d11028af11fe12e09b2d5b10b03738e9abf819ae6ebb0f78cac13d39f860755ce05ac3855b608222518d956628f5d00322dc206cc6d1f2d8d1519f1e + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.3 resolution: "@types/prop-types@npm:15.7.3" From 2c28bd939b35ff4dd334115f425e2ee3b9bcf49f Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Fri, 3 Dec 2021 14:19:06 +0900 Subject: [PATCH 19/20] fix: pdfjs typings version --- packages/discovery-react-components/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/discovery-react-components/package.json b/packages/discovery-react-components/package.json index 59e406ec5..1fde74fe7 100644 --- a/packages/discovery-react-components/package.json +++ b/packages/discovery-react-components/package.json @@ -43,13 +43,13 @@ "react-virtualized": "9.21.1" }, "devDependencies": { - "@types/pdfjs-dist": "^2.10.378", "@storybook/addon-actions": "^5.3.21", "@storybook/addon-docs": "^5.3.21", "@storybook/addon-knobs": "^5.3.21", "@storybook/core": "^5.3.21", "@storybook/react": "^5.3.21", "@storybook/source-loader": "^5.3.21", + "@types/pdfjs-dist": "^2.1.7", "cross-env": "^7.0.3", "css-loader": "^3.4.2", "madge": "^5.0.1", diff --git a/yarn.lock b/yarn.lock index f901dc1f1..5fb35b26a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2277,7 +2277,7 @@ __metadata: "@storybook/core": ^5.3.21 "@storybook/react": ^5.3.21 "@storybook/source-loader": ^5.3.21 - "@types/pdfjs-dist": ^2.10.378 + "@types/pdfjs-dist": ^2.1.7 classnames: ^2.2.6 cross-env: ^7.0.3 css-loader: ^3.4.2 @@ -4948,12 +4948,12 @@ __metadata: languageName: node linkType: hard -"@types/pdfjs-dist@npm:^2.10.378": - version: 2.10.378 - resolution: "@types/pdfjs-dist@npm:2.10.378" +"@types/pdfjs-dist@npm:^2.1.7": + version: 2.10.377 + resolution: "@types/pdfjs-dist@npm:2.10.377" dependencies: pdfjs-dist: "*" - checksum: 36dd6010f7d23a995efdf11ea4ecb56f371f8bfb3e83a5c311666726e13238597ed1519701d0e2e6fb297270d01ad6aece9582b036fd4cb3aa301e61ea364978 + checksum: c4623b60e334dfcc50bc584d35977f13edd95646e139df8ae3cb52338e919dbdaf443454055368eb535cf3d1cc3f2f62463c3d883ab85c60ea9acf98e794aba1 languageName: node linkType: hard From 032842c30c71c263a72f37c62dfcdaa43b5da982 Mon Sep 17 00:00:00 2001 From: Susumu Fukuda Date: Fri, 3 Dec 2021 14:57:28 +0900 Subject: [PATCH 20/20] fix: apply review comments --- .../discovery-react-components/package.json | 2 +- .../PdfViewer/PdfViewer.stories.tsx | 4 +- .../components/PdfViewer/PdfViewer.tsx | 44 +++++++------------ .../PdfViewer/PdfViewerTextLayer.tsx | 10 ++--- .../components/PdfViewer/types.ts | 11 +++++ yarn.lock | 24 +++------- 6 files changed, 36 insertions(+), 59 deletions(-) create mode 100644 packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/types.ts diff --git a/packages/discovery-react-components/package.json b/packages/discovery-react-components/package.json index 1fde74fe7..0f5baa81a 100644 --- a/packages/discovery-react-components/package.json +++ b/packages/discovery-react-components/package.json @@ -49,7 +49,7 @@ "@storybook/core": "^5.3.21", "@storybook/react": "^5.3.21", "@storybook/source-loader": "^5.3.21", - "@types/pdfjs-dist": "^2.1.7", + "@types/pdfjs-dist": "2.1.7", "cross-env": "^7.0.3", "css-loader": "^3.4.2", "madge": "^5.0.1", diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx index 11a3d0f08..9284c5c16 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; -import { withKnobs, radios, number, boolean } from '@storybook/addon-knobs'; +import { withKnobs, radios, number } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; import PdfViewer from './PdfViewer'; import { document as doc } from 'components/DocumentPreview/__fixtures__/Art Effects.pdf'; @@ -33,7 +33,6 @@ storiesOf('DocumentPreview/components/PdfViewer', module) const zoom = radios(zoomKnob.label, zoomKnob.options, zoomKnob.defaultValue); const scale = parseFloat(zoom); - const showTextLayer = boolean('Show text layer', false); const setLoadingAction = action('setLoading'); const setRenderedTextAction = action('setRenderedText'); @@ -43,7 +42,6 @@ storiesOf('DocumentPreview/components/PdfViewer', module) file={atob(doc)} page={page} scale={scale} - showTextLayer={showTextLayer} setLoading={setLoadingAction} setRenderedText={setRenderedTextAction} /> diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx index dc34badf7..ea37114a6 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewer.tsx @@ -4,16 +4,18 @@ import PdfjsLib, { PDFDocumentProxy, PDFPageProxy, PDFPageViewport, + PDFPromise, PDFRenderTask } from 'pdfjs-dist'; import PdfjsWorkerAsText from 'pdfjs-dist/build/pdf.worker.min.js'; import { settings } from 'carbon-components'; -import PdfViewerTextLayer, { PdfRenderedText } from './PdfViewerTextLayer'; import useAsyncFunctionCall from 'utils/useAsyncFunctionCall'; +import PdfViewerTextLayer, { PdfRenderedText } from './PdfViewerTextLayer'; +import { PdfDisplayProps } from './types'; setupPdfjs(); -interface Props { +type Props = PdfDisplayProps & { className?: string; /** @@ -22,22 +24,7 @@ interface Props { file: string; /** - * Page number, starting at 1 - */ - page: number; - - /** - * Zoom factor, where `1` is equal to 100% - */ - scale: number; - - /** - * Render text layer - */ - showTextLayer?: boolean; - - /** - * Text layer class name. Only applicable when showTextLayer is true + * Text layer class name */ textLayerClassName?: string; @@ -57,14 +44,13 @@ interface Props { * Callback for text layer info */ setRenderedText?: (info: PdfRenderedText | null) => any; -} +}; const PdfViewer: FC = ({ className, file, page, scale, - showTextLayer, textLayerClassName, setPageCount, setLoading, @@ -128,14 +114,12 @@ const PdfViewer: FC = ({ width={canvasInfo?.canvasWidth} height={canvasInfo?.canvasHeight} /> - {showTextLayer && ( - - )} + {children}
); @@ -146,7 +130,7 @@ PdfViewer.defaultProps = { scale: 1 }; -function _loadPdf(data: string): Promise { +function _loadPdf(data: string): PDFPromise { return PdfjsLib.getDocument({ data }).promise; } @@ -175,6 +159,7 @@ function setupPdfjs(): void { if (typeof Worker !== 'undefined') { const blob = new Blob([PdfjsWorkerAsText], { type: 'text/javascript' }); const pdfjsWorker = new Worker(URL.createObjectURL(blob)) as any; + // @ts-expect-error Upgrading pdfjs-dist and its typings would resolve the issue PdfjsLib.GlobalWorkerOptions.workerPort = pdfjsWorker; } else { PdfjsLib.GlobalWorkerOptions.workerSrc = PdfjsWorkerAsText; @@ -199,4 +184,5 @@ function getCanvasInfo(viewport: any): CanvasInfo { return { width, height, canvasWidth, canvasHeight, canvasScale }; } +export type PdfViewerProps = Props; export default PdfViewer; diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx index 21277ee2e..5c76fb515 100644 --- a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/PdfViewerTextLayer.tsx @@ -4,8 +4,9 @@ import { PDFPageProxy, PDFPageViewport, TextContent, TextContentItem } from 'pdf import { EventBus } from 'pdfjs-dist/lib/web/ui_utils'; import { TextLayerBuilder } from 'pdfjs-dist/lib/web/text_layer_builder'; import useAsyncFunctionCall from 'utils/useAsyncFunctionCall'; +import { PdfDisplayProps } from './types'; -interface Props { +type Props = Pick & { className?: string; /** @@ -13,16 +14,11 @@ interface Props { */ loadedPage: PDFPageProxy | null | undefined; - /** - * Zoom factor, where `1` is equal to 100% - */ - scale: number; - /** * Callback for text layer info */ setRenderedText?: (info: PdfRenderedText | null) => any; -} +}; export type PdfRenderedText = { /** diff --git a/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/types.ts b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/types.ts new file mode 100644 index 000000000..063a65818 --- /dev/null +++ b/packages/discovery-react-components/src/components/DocumentPreview/components/PdfViewer/types.ts @@ -0,0 +1,11 @@ +export type PdfDisplayProps = { + /** + * Page number, starting at 1 + */ + page: number; + + /** + * Zoom factor, where `1` is equal to 100% + */ + scale: number; +}; diff --git a/yarn.lock b/yarn.lock index 5fb35b26a..6ebd9e514 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2277,7 +2277,7 @@ __metadata: "@storybook/core": ^5.3.21 "@storybook/react": ^5.3.21 "@storybook/source-loader": ^5.3.21 - "@types/pdfjs-dist": ^2.1.7 + "@types/pdfjs-dist": 2.1.7 classnames: ^2.2.6 cross-env: ^7.0.3 css-loader: ^3.4.2 @@ -4948,12 +4948,10 @@ __metadata: languageName: node linkType: hard -"@types/pdfjs-dist@npm:^2.1.7": - version: 2.10.377 - resolution: "@types/pdfjs-dist@npm:2.10.377" - dependencies: - pdfjs-dist: "*" - checksum: c4623b60e334dfcc50bc584d35977f13edd95646e139df8ae3cb52338e919dbdaf443454055368eb535cf3d1cc3f2f62463c3d883ab85c60ea9acf98e794aba1 +"@types/pdfjs-dist@npm:2.1.7": + version: 2.1.7 + resolution: "@types/pdfjs-dist@npm:2.1.7" + checksum: 14ca335658a85ab5cab908f3ef3ec104cb62487acc2465bb74b6d0430cd720dca30a8804440e152967b1dd7fb384c65ef05da1702a1ec87b905c0f5c73bbe653 languageName: node linkType: hard @@ -19544,18 +19542,6 @@ __metadata: languageName: node linkType: hard -"pdfjs-dist@npm:*": - version: 2.11.338 - resolution: "pdfjs-dist@npm:2.11.338" - peerDependencies: - worker-loader: ^3.0.8 - peerDependenciesMeta: - worker-loader: - optional: true - checksum: 1b946a3eeb3312a79e12b4e0aa066bb2b98487b9ee329666edc840a194602595cf84de9a3f6dbb023b808699a6ebb0cd06e751314fc4c0ffa56f7be12855d296 - languageName: node - linkType: hard - "pdfjs-dist@npm:^2.2.228": version: 2.2.228 resolution: "pdfjs-dist@npm:2.2.228"