{"version":3,"sources":["jsdelivr-header.js","/npm/react-file-previewer@0.6.3/src/utils/setZoomIn.js","/npm/react-file-previewer@0.6.3/src/utils/setZoomOut.js","/npm/react-file-previewer@0.6.3/src/utils/getFilename.js","/npm/react-file-previewer@0.6.3/src/utils/getFileProp.js","/npm/react-file-previewer@0.6.3/src/utils/setNewRotation.js","/npm/react-file-previewer@0.6.3/src/utils/useViewportSize.js","/npm/react-file-previewer@0.6.3/src/utils/getFitToScreenScale.js","/npm/react-file-previewer@0.6.3/src/Button.js","/npm/react-file-previewer@0.6.3/src/PageCount.js","/npm/react-file-previewer@0.6.3/src/PreviewBarLeft.js","/npm/react-file-previewer@0.6.3/src/PreviewBarRight.js","/npm/react-file-previewer@0.6.3/src/PreviewBar.js","/npm/react-file-previewer@0.6.3/src/ViewportControl.js","/npm/react-file-previewer@0.6.3/src/utils/isPDF.js","/npm/react-file-previewer@0.6.3/src/PDFViewer.js","/npm/react-file-previewer@0.6.3/src/ImageViewer.js","/npm/react-file-previewer@0.6.3/src/ViewportContent.js","/npm/react-file-previewer@0.6.3/src/FilePreviewer.js","/npm/react-file-previewer@0.6.3/src/FilePreviewerThumbnail.js"],"names":[],"mappings":"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","file":"/npm/react-file-previewer@0.6.3/dist/index.cjs.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.37.0.\n * Original file: /npm/react-file-previewer@0.6.3/dist/index.cjs.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import * as R from 'ramda';\n\nconst SCALE_FACTOR = 0.25;\n\n/**\n * Scale the document by 25%.\n *\n * @param  {Object} files\n * @return {Object}\n */\nconst setZoomIn = R.converge(R.assoc('scale'), [\n  R.compose(\n    R.map(R.add(SCALE_FACTOR)),\n    R.when(R.is(Number), R.of),\n    R.propOr([1], 'scale'),\n  ),\n  R.identity,\n]);\n\nexport default setZoomIn;\n","import * as R from 'ramda';\n\nconst SCALE_FACTOR = 0.25;\n\n/**\n * Reduce the document scale by 25%.\n *\n * @param  {Object} files\n * @return {Object}\n */\nconst setZoomOut = R.converge(R.assoc('scale'), [\n  R.compose(\n    R.map(R.subtract(R.__, SCALE_FACTOR)),\n    R.when(R.is(Number), R.of),\n    R.propOr([1], 'scale'),\n  ),\n  R.identity,\n]);\n\nexport default setZoomOut;\n","import * as R from 'ramda';\nimport { extension } from 'mime-types';\n\nconst DEFAULT_NAME = 'download.pdf';\n\n/**\n * Get the name to download this file.\n *\n * @param  {Object} file\n * @return {String}\n */\nconst getFilename = R.cond([\n  [R.has('name'), R.prop('name')],\n  [R.has('mimeType'), R.o(extension, R.prop('mimeType'))],\n  [R.T, R.always(DEFAULT_NAME)],\n]);\n\nexport default getFilename;\n","import * as R from 'ramda';\n\n/**\n * Read the file `url`, in case it matches a base64 url.\n *\n * @param  {Object} file\n * @return {Object}\n */\nconst getFileDataInBase64 = R.compose(\n  R.prop('groups'),\n  R.match(/^data:(?<mimeType>[a-z]+\\/[a-z]+);base64,(?<data>.*)/),\n  R.propOr('', 'url'),\n);\n\n/**\n * Get the `file` from the properties, in the correct format.\n *\n * @param {Object} props\n */\nconst getFileProp = props => {\n  // Check if the file url is base64.\n  if (getFileDataInBase64(props.file)) {\n    // Update the file to include the data and mimeType extracted from the url.\n    return getFileDataInBase64(props.file);\n  }\n\n  return props.file;\n};\n\nexport default getFileProp;\n","import * as R from 'ramda';\n\n/**\n * Rotate the file 90 degrees.\n *\n * @param  {Object} files\n * @return {Object}\n */\nconst setNewRotation = R.converge(R.assoc('rotate'), [\n  R.compose(R.modulo(R.__, 360), R.add(90), R.propOr(0, 'rotate')),\n  R.identity,\n]);\n\nexport default setNewRotation;\n","import { pathOr } from 'ramda';\nimport { useState, useEffect } from 'react';\n\nconst useViewportSize = viewportElem => {\n  const isClient = typeof window === 'object';\n\n  const [size, setSize] = useState({\n    width: pathOr(0, ['current', 'clientWidth'], viewportElem),\n    height: pathOr(0, ['current', 'clientHeight'], viewportElem),\n  });\n\n  useEffect(() => {\n    setSize({\n      width: pathOr(0, ['current', 'clientWidth'], viewportElem),\n      height: pathOr(0, ['current', 'clientHeight'], viewportElem),\n    });\n  }, [viewportElem]);\n\n  useEffect(() => {\n    if (!isClient) {\n      return false;\n    }\n\n    function handleResize() {\n      setSize({\n        width: pathOr(0, ['current', 'clientWidth'], viewportElem),\n        height: pathOr(0, ['current', 'clientHeight'], viewportElem),\n      });\n    }\n\n    window.addEventListener('resize', handleResize);\n    return () => window.removeEventListener('resize', handleResize);\n  }, [viewportElem]);\n\n  return size;\n};\n\nexport default useViewportSize;\n","// Make sure to leave a padding.\nconst PADDING = 12 * 4;\n\n// Get the preview bar height.\nconst PREVIEW_BAR_HEIGHT = 52;\n\nconst getViewportWidth = viewportElem =>\n  viewportElem.width || viewportElem.clientWidth;\n\n/**\n * Get the viewport height, with its constraints.\n *\n * @param  {Object} viewportElem\n * @return {Number}\n */\nconst getViewportHeight = viewportElem =>\n  (viewportElem.height || viewportElem.clientHeight) -\n  PREVIEW_BAR_HEIGHT -\n  PADDING;\n\n/**\n * Get the `scale` attribute for the \"fit to screen\" option.\n *\n * @param  {Object} viewportElem\n * @param  {Object} contentElem\n * @return {Number}\n */\nexport const getFitToScreenScale = (viewportElem, contentElem) => {\n  // Get the viewport ratio.\n  const viewportWidth = getViewportWidth(viewportElem);\n  const viewportHeight = getViewportHeight(viewportElem);\n  const viewportRatio = viewportWidth / viewportHeight;\n\n  // Get the content ratio.\n  const contentWidth = contentElem.width || contentElem.offsetWidth;\n  const contentHeight = contentElem.height || contentElem.offsetHeight;\n  const contentRatio = contentWidth / contentHeight;\n\n  if (contentHeight > viewportHeight && contentWidth > viewportWidth) {\n    const heightRatio = viewportHeight / contentHeight;\n    const widthRatio = viewportWidth / contentWidth;\n\n    return Math.min(widthRatio, heightRatio);\n  }\n\n  if (contentHeight > viewportHeight) {\n    return viewportHeight / contentHeight;\n  }\n\n  if (contentWidth > viewportWidth) {\n    return viewportWidth / contentWidth;\n  }\n\n  // Get the scaling ratio in `0.25` steps.\n  return (\n    Math.round(\n      (viewportRatio > contentRatio\n        ? viewportHeight / contentHeight\n        : viewportWidth / contentWidth) * 4,\n    ) / 4\n  );\n};\n\n/**\n * Get the `scale` attribute for the \"fit to width\" option.\n *\n * @param  {Object} viewportElem\n * @param  {Object} contentElem\n * @return {Number}\n */\nexport const getFitToWidthScale = (viewportElem, contentElem) => {\n  // Get the viewport ratio.\n  const viewportWidth = getViewportWidth(viewportElem);\n\n  // Get the content ratio.\n  const contentWidth = contentElem.width || contentElem.offsetWidth;\n\n  // Get the scaling ratio, after removing the padding.\n  return (viewportWidth - PADDING) / contentWidth;\n};\n\nexport default getFitToWidthScale;\n","import React from 'react';\n\nconst Button = ({ children, onClick, disabled }) => (\n  <button\n    type=\"button\"\n    onClick={onClick}\n    disabled={disabled}\n    className=\"preview-button\"\n  >\n    {children}\n  </button>\n);\n\nexport default Button;\n","import React from 'react';\n\nconst PageCount = ({ current, total }) => (\n  <span className=\"preview-pagecount\">\n    {current + 1} of {total}\n  </span>\n);\n\nexport default PageCount;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport ChevronUp from 'mdi-material-ui/ChevronUp';\nimport ChevronDown from 'mdi-material-ui/ChevronDown';\n\nimport Button from './Button';\nimport PageCount from './PageCount';\n\nconst PreviewBarLeft = props => {\n  return (\n    <div className=\"preview-bar-left\">\n      {/* Page to go up means going back. */}\n      <Button onClick={props.onPageUp} disabled={props.currentPage === 0}>\n        <ChevronUp />\n      </Button>\n\n      {/* Page to go down means going next. */}\n      <Button\n        onClick={props.onPageDown}\n        disabled={props.currentPage + 1 === props.totalPages}\n      >\n        <ChevronDown />\n      </Button>\n\n      <PageCount current={props.currentPage} total={props.totalPages} />\n    </div>\n  );\n};\n\nPreviewBarLeft.propTypes = {\n  totalPages: PropTypes.number.isRequired,\n  currentPage: PropTypes.number.isRequired,\n  onPageUp: PropTypes.func.isRequired,\n  onPageDown: PropTypes.func.isRequired,\n};\n\nexport default PreviewBarLeft;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport Download from 'mdi-material-ui/Download';\nimport RotateRight from 'mdi-material-ui/RotateRight';\n\nimport Button from './Button';\n\nconst PreviewBarRight = props => (\n  <div className=\"preview-bar-left\">\n    <Button onClick={props.onRotate}>\n      <RotateRight />\n    </Button>\n\n    <Button onClick={props.onDownload}>\n      <Download />\n    </Button>\n  </div>\n);\n\nPreviewBarRight.propTypes = {\n  onRotate: PropTypes.func.isRequired,\n  onDownload: PropTypes.func.isRequired,\n};\n\nexport default PreviewBarRight;\n","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport PreviewBarLeft from './PreviewBarLeft';\nimport PreviewBarRight from './PreviewBarRight';\n\nconst PreviewBar = props => {\n  if (props.hidden) {\n    return null;\n  }\n\n  return (\n    <div className=\"preview-bar\">\n      <PreviewBarLeft\n        onPageUp={props.onPageUp}\n        onPageDown={props.onPageDown}\n        totalPages={props.totalPages}\n        currentPage={props.currentPage}\n      />\n\n      <PreviewBarRight\n        onRotate={props.onRotate}\n        onDownload={props.onDownload}\n      />\n    </div>\n  );\n};\n\nPreviewBar.propTypes = {\n  onPageUp: PropTypes.func.isRequired,\n  onRotate: PropTypes.func.isRequired,\n  onPageDown: PropTypes.func.isRequired,\n  onDownload: PropTypes.func.isRequired,\n  totalPages: PropTypes.number.isRequired,\n  currentPage: PropTypes.number.isRequired,\n  hidden: PropTypes.bool,\n};\n\nexport default PreviewBar;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport PlusBox from 'mdi-material-ui/PlusBox';\nimport MinusBox from 'mdi-material-ui/MinusBox';\nimport ArrowExpandHorizontal from 'mdi-material-ui/ArrowExpandHorizontal';\n\nimport Button from './Button';\n\nconst ViewportControl = props => {\n  if (props.hidden) {\n    return null;\n  }\n\n  return (\n    <div className=\"preview-icons\">\n      <Button onClick={props.onZoomIn}>\n        <PlusBox />\n      </Button>\n\n      <Button onClick={props.onZoomOut} className=\"preview-icons\">\n        <MinusBox />\n      </Button>\n\n      <Button onClick={props.onFitToScreen} className=\"preview-icons\">\n        <ArrowExpandHorizontal />\n      </Button>\n    </div>\n  );\n};\n\nViewportControl.propTypes = {\n  onZoomIn: PropTypes.func.isRequired,\n  onZoomOut: PropTypes.func.isRequired,\n  onFitToScreen: PropTypes.func.isRequired,\n  hidden: PropTypes.bool,\n};\n\nexport default ViewportControl;\n","import * as R from 'ramda';\n\n/**\n * Check if a file is a pdf.\n *\n * @param  {Object}\n * @return {Boolean}\n */\nconst isPDF = R.either(\n  R.o(R.endsWith('.pdf'), R.propOr('', 'url')),\n  R.propEq('mimeType', 'application/pdf'),\n);\n\nexport default isPDF;\n","import * as R from 'ramda';\nimport PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport { Document, Page, pdfjs } from 'react-pdf';\nimport { useInView } from 'react-intersection-observer';\n\n// Get the pdf.js worker from cloudflare content delivery network.\npdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf.worker.js`;\n\nconst PDFPage = ({ index, onPageChange, scale = 1 }) => {\n  const [ref, inView] = useInView({ threshold: 0.5 });\n\n  useEffect(() => {\n    if (inView) onPageChange(index);\n  }, [inView]);\n\n  return (\n    <div ref={ref} className=\"preview-pdf-page\" data-pdfpage={index}>\n      <Page pageIndex={index} scale={scale} />\n    </div>\n  );\n};\n\nconst PDFViewer = ({ file, totalPages, onLoadSuccess, onPageChange }) => {\n  return (\n    <Document\n      rotate={file.rotate}\n      onLoadSuccess={onLoadSuccess}\n      file={file.url || `data:${file.mimeType};base64,${file.data}`}\n      options={{\n        cMapPacked: true,\n        cMapUrl: `//cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/cmaps/`,\n      }}\n    >\n      {R.times(\n        index => (\n          <PDFPage\n            key={index}\n            index={index}\n            onPageChange={onPageChange}\n            scale={Array.isArray(file.scale) ? file.scale[index] : file.scale}\n          />\n        ),\n        totalPages,\n      )}\n    </Document>\n  );\n};\n\nPDFViewer.propTypes = {\n  file: PropTypes.shape({\n    url: PropTypes.string,\n    data: PropTypes.string,\n    name: PropTypes.string,\n    mimeType: PropTypes.string,\n  }),\n  totalPages: PropTypes.number,\n  onPageChange: PropTypes.func.isRequired,\n  onLoadSuccess: PropTypes.func.isRequired,\n};\n\nexport default PDFViewer;\n","import PropTypes from 'prop-types';\nimport { propOr, pathOr } from 'ramda';\nimport React, { useState, useRef } from 'react';\n\n/**\n * Get the scale for this image.\n *\n * @param  {Object} file\n * @return {Number}\n */\nconst getScale = pathOr(1, ['scale', 0]);\n\n/**\n * Get the rotation for this image.\n *\n * @param  {Object} file\n * @return {Number}\n */\nconst getRotation = propOr(0, 'rotate');\n\nconst getResponseLikePDF = imgRef => {\n  const { clientWidth, clientHeight } = imgRef.current;\n\n  return {\n    numPages: 1,\n    getPage: () => ({\n      getViewport: () => ({\n        width: clientWidth,\n        height: clientHeight,\n      }),\n    }),\n  };\n};\n\n/**\n * `ImageViewer` react component.\n *\n * @param  {Object}   params\n * @param  {Object}   params.file\n * @param  {String}   params.file.url\n * @param  {String}   params.file.data\n * @param  {Array}    params.file.scale\n * @param  {Number}   params.file.rotate\n * @param  {String}   params.file.mimeType\n * @param  {Array}    params.originalSizes\n * @param  {Function} params.onLoadSuccess\n */\nconst ImageViewer = ({ file, originalSizes, onLoadSuccess }) => {\n  const imgRef = useRef(null);\n  const [isLoading, setLoading] = useState(true);\n\n  const onLoad = () => {\n    // Execute the callback.\n    onLoadSuccess(getResponseLikePDF(imgRef));\n\n    // Set the loading state to false.\n    setLoading(false);\n  };\n\n  const scaleImage =\n    !originalSizes[0] || !getScale(file)\n      ? {}\n      : {\n          width: originalSizes[0].width * getScale(file),\n          height: originalSizes[0].height * getScale(file),\n        };\n\n  return (\n    <img\n      ref={imgRef}\n      onLoad={onLoad}\n      src={file.url || `data:${file.mimeType};base64,${file.data}`}\n      style={{\n        ...scaleImage,\n        opacity: isLoading ? 0 : 1,\n        transform: `rotate(${getRotation(file)}deg)`,\n      }}\n    />\n  );\n};\n\nImageViewer.propTypes = {\n  file: PropTypes.shape({\n    url: PropTypes.string,\n    data: PropTypes.string,\n    scale: PropTypes.array,\n    rotate: PropTypes.number,\n    mimeType: PropTypes.string,\n  }),\n  originalSizes: PropTypes.array,\n  onLoadSuccess: PropTypes.func.isRequired,\n};\n\nexport default ImageViewer;\n","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport isPDF from './utils/isPDF';\nimport PDFViewer from './PDFViewer';\nimport ImageViewer from './ImageViewer';\n\nconst ViewportContent = ({\n  file,\n  totalPages,\n  containerRef,\n  onPageChange,\n  originalSizes,\n  onLoadSuccess,\n}) => (\n  <div ref={containerRef} className={'preview-content'}>\n    <div className=\"preview-file\">\n      {isPDF(file) ? (\n        <PDFViewer\n          file={file}\n          totalPages={totalPages}\n          onPageChange={onPageChange}\n          onLoadSuccess={onLoadSuccess}\n        />\n      ) : (\n        <ImageViewer\n          file={file}\n          onLoadSuccess={onLoadSuccess}\n          originalSizes={originalSizes}\n        />\n      )}\n    </div>\n  </div>\n);\n\nViewportContent.propTypes = {\n  file: PropTypes.shape({\n    url: PropTypes.string,\n    data: PropTypes.string,\n    name: PropTypes.string,\n    mimeType: PropTypes.string,\n  }),\n  totalPages: PropTypes.number,\n  onPageChange: PropTypes.func.isRequired,\n  onLoadSuccess: PropTypes.func.isRequired,\n};\n\nexport default ViewportContent;\n","import * as R from 'ramda';\nimport saveFile from 'file-saver';\nimport PropTypes from 'prop-types';\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport setZoomIn from './utils/setZoomIn';\nimport setZoomOut from './utils/setZoomOut';\nimport getFilename from './utils/getFilename';\nimport getFileProp from './utils/getFileProp';\nimport setNewRotation from './utils/setNewRotation';\nimport useViewportSize from './utils/useViewportSize';\nimport getFitToScreenScale from './utils/getFitToScreenScale';\n\nimport PreviewBar from './PreviewBar';\nimport ViewportControl from './ViewportControl';\nimport ViewportContent from './ViewportContent';\n\n/**\n * `FilePreviewer` react component.\n *\n * @param  {Object}   props\n * @param  {Function} props.onClick\n * @param  {Object}   props.file\n * @param  {String}   props.file.url\n * @param  {String}   props.file.data\n * @param  {String}   props.file.name\n * @param  {String}   props.file.mimeType\n * @return {Object}\n */\nconst FilePreviewer = props => {\n  const [totalPages, setTotalPages] = useState(1);\n  const [currentPage, setCurrentPage] = useState(0);\n  const [file, setFile] = useState(getFileProp(props));\n  const [originalSizes, setOriginalSizes] = useState([]);\n  const [usingFitToScreen, setUsingFitToScreen] = useState(false);\n\n  const viewportRef = useRef(null);\n  const containerRef = useRef(null);\n  const viewportSize = useViewportSize(viewportRef);\n\n  useEffect(() => {\n    // Reset all the attributes when the file prop changes.\n    setTotalPages(1);\n    setCurrentPage(0);\n    setOriginalSizes([]);\n    setFile(getFileProp(props));\n  }, [props.file]);\n\n  /**\n   * Handler. Scroll to the pervious page and update the index.\n   *\n   * @return {void}\n   */\n  const onPageUp = () => {\n    const previousIndex = R.clamp(0, totalPages, currentPage - 1);\n\n    setCurrentPage(previousIndex);\n\n    const previousPage = document.querySelector(\n      `div[data-pdfpage=\"${previousIndex}\"]`,\n    );\n\n    // Scroll the viewport to the page position.\n    containerRef.current.scrollTop = previousPage.offsetTop - 10;\n  };\n\n  /**\n   * Handler. Scroll to the next page and update the index.\n   *\n   * @return {void}\n   */\n  const onPageDown = () => {\n    const nextIndex = R.clamp(0, totalPages, currentPage + 1);\n\n    setCurrentPage(nextIndex);\n\n    const nextPage = document.querySelector(`div[data-pdfpage=\"${nextIndex}\"]`);\n\n    // Scroll the viewport to the page position.\n    containerRef.current.scrollTop = nextPage.offsetTop - 10;\n  };\n\n  /**\n   * Handler. Scale all the pages or image\n   * up by a factor of 0.25.\n   *\n   * @return {void}\n   */\n  const onZoomIn = () => {\n    setUsingFitToScreen(false);\n    setFile(setZoomIn(file));\n  };\n\n  /**\n   * Handler. Scale all the pages or image\n   * down by a factor of 0.25.\n   *\n   * @return {void}\n   */\n  const onZoomOut = () => {\n    setUsingFitToScreen(false);\n    setFile(setZoomOut(file));\n  };\n\n  /**\n   * Handler. Rotate the PDF (all pages) or Image.\n   *\n   * @return {void}\n   */\n  const onRotate = () => {\n    setFile(setNewRotation(file));\n  };\n\n  /**\n   * Handler. Fit to screen.\n   *\n   * (This activates the \"using fit to screen\" mode, which\n   * makes the document or image resize based on the viewport size.)\n   *\n   * @return {void}\n   */\n  const onFitToScreen = () => {\n    setUsingFitToScreen(true);\n\n    // Get the \"fit to screen\" scale.\n    const newScale = originalSizes.map(originalSize =>\n      getFitToScreenScale(viewportSize, originalSize),\n    );\n\n    setFile(prevValue => R.assoc('scale', newScale, prevValue));\n  };\n\n  /**\n   * Handler. Download the current file, it can be a\n   * PDF or Image, as `url` or `base64` content.\n   *\n   * @return {void}\n   */\n  const onDownload = () => {\n    const url = file.url || `data:${file.mimeType};base64,${file.data}`;\n    return saveFile(url, getFilename(file));\n  };\n\n  /**\n   * Handler. Callback after the PDF gets\n   * processed successfully by `react-pdf`.\n   *\n   * @param  {Object} file\n   * @return {void}\n   */\n  const onLoadSuccess = file => {\n    // Wait until the original sizes gets calculated.\n    const promises = R.times(async i => {\n      // Wait until the original sizes gets calculated.\n      const page = await file.getPage(i + 1);\n      return R.pick(['width', 'height'], page.getViewport({ scale: 1 }));\n    }, file.numPages);\n\n    // Set the original sizes for this file.\n    Promise.all(promises).then(setOriginalSizes);\n\n    setTotalPages(file.numPages);\n    setUsingFitToScreen(true);\n  };\n\n  // Set an effect to process the file resizing when the\n  // viewport sizes changes and it's using \"fit to screen\".\n  useEffect(() => {\n    // Check if it's using \"fit to screen\".\n    if (usingFitToScreen) {\n      // Get the \"fit to screen\" scale.\n      const newScale = originalSizes.map(originalSize =>\n        getFitToScreenScale(viewportSize, originalSize),\n      );\n\n      // Update the scale.\n      setFile(prevValue => R.assoc('scale', newScale, prevValue));\n    }\n\n    return () => {};\n  }, [usingFitToScreen, originalSizes, viewportSize]);\n\n  return (\n    <div ref={viewportRef} onClick={props.onClick} className=\"preview-wrapper\">\n      <PreviewBar\n        onPageUp={onPageUp}\n        onRotate={onRotate}\n        totalPages={totalPages}\n        onDownload={onDownload}\n        onPageDown={onPageDown}\n        currentPage={currentPage}\n        hidden={props.hideControls}\n      />\n\n      <ViewportContent\n        file={file}\n        totalPages={totalPages}\n        containerRef={containerRef}\n        originalSizes={originalSizes}\n        onPageChange={setCurrentPage}\n        onLoadSuccess={onLoadSuccess}\n      />\n\n      <ViewportControl\n        onZoomIn={onZoomIn}\n        onZoomOut={onZoomOut}\n        onFitToScreen={onFitToScreen}\n        hidden={props.hideControls}\n      />\n    </div>\n  );\n};\n\nFilePreviewer.propTypes = {\n  file: PropTypes.shape({\n    url: PropTypes.string,\n    mimeType: PropTypes.string,\n    data: PropTypes.string,\n    name: PropTypes.string,\n  }).isRequired,\n  onClick: PropTypes.func,\n  hideControls: PropTypes.bool,\n};\n\nFilePreviewer.defaultProps = {\n  onClick: () => {},\n};\n\nexport default FilePreviewer;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Document, Page, pdfjs } from 'react-pdf';\n\nimport isPDF from './utils/isPDF';\nimport getFileProp from './utils/getFileProp';\n\nconst RenderPDF = ({ src }) => (\n  <Document\n    file={src}\n    options={{\n      cMapPacked: true,\n      cMapUrl: `//cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/cmaps/`,\n    }}\n  >\n    <Page pageNumber={1} width={80} height={85} />\n  </Document>\n);\n\n/**\n * `FilePreviewerThumbnail` react component.\n *\n * @param  {Object}   props\n * @param  {Object}   props.file\n * @param  {String}   props.file.url\n * @param  {String}   props.file.data\n * @param  {String}   props.file.mimeType\n * @param  {Function} props.onClick\n * @return {Object}\n */\nconst FilePreviewerThumbnail = props => {\n  const file = getFileProp(props);\n  const fileSrc = file.url || `data:${file.mimeType};base64,${file.data}`;\n\n  return (\n    <div\n      style={props.style}\n      onClick={props.onClick}\n      className=\"thumbnail-wrapper\"\n    >\n      {isPDF(file) ? <RenderPDF src={fileSrc} /> : <img src={fileSrc} />}\n    </div>\n  );\n};\n\nFilePreviewerThumbnail.propTypes = {\n  file: PropTypes.shape({\n    url: PropTypes.string,\n    mimeType: PropTypes.string,\n    data: PropTypes.string,\n  }).isRequired,\n  style: PropTypes.object,\n  onClick: PropTypes.func,\n};\n\nFilePreviewerThumbnail.defaultProps = {\n  style: {},\n  onClick: () => {},\n};\n\nexport default FilePreviewerThumbnail;\n"]}