{
  "$schema": "https://ai.syncfusion.com/schema/registry-item.json",
  "name": "pdf-viewer-multi-format-viewer",
  "framework": "react",
  "type": "registry:component",
  "component": "PdfViewer",
  "variant": "multi-format-viewer",
  "dependencies": [
    "@syncfusion/ej2-react-buttons",
    "@syncfusion/ej2-react-inputs",
    "@syncfusion/ej2-react-pdfviewer",
    "@syncfusion/ej2-react-progressbar"
  ],
  "description": "PDF viewer that opens multi-format uploads via drop area with progress bar and conversion.",
  "meta": {
    "essentialStudioRelease": "2026 Volume 2 (v34.1.29)",
    "license": "commercial-or-community",
    "licenseNote": "The Syncfusion package is licensed. The composition in this file is source you own and edit. See https://ai.syncfusion.com/licensing.md",
    "requiresLicenseKey": true,
    "requiresServerEndpoint": true,
    "platformIndex": "https://ai.syncfusion.com/react/llms.txt",
    "skillPack": "syncfusion/react-ui-components-skills",
    "docs": "https://ai.syncfusion.com/gallery/react/ts/pdf-viewer-multi-format-viewer.md"
  },
  "files": [
    {
      "target": "src/components/pdf-viewer-multi-format-viewer/PdfViewer.tsx",
      "content": "/**\n * Default PDF Viewer sample\n */\nimport * as React from 'react';\nimport {\n  PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView,\n  ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner,PageOrganizer, Inject} from '@syncfusion/ej2-react-pdfviewer';\nimport { createElement, isNullOrUndefined } from '@syncfusion/ej2-base'\nimport { UploaderComponent } from '@syncfusion/ej2-react-inputs';\nimport { ButtonComponent } from '@syncfusion/ej2-react-buttons';\nimport { ProgressBarComponent, type ProgressTheme } from '@syncfusion/ej2-react-progressbar';\n\nconst SAMPLE_CSS = `\n#pdfviewer {\n    height: 640px;\n}\n\n#linear-pdfviewer {\n    width: fit-content;\n}\n\n#uploader-pdfviewer {\n    display: none;\n}\n\n.content-wrapper-pdfviewer {\n    border: 1px dashed #c3c3cc;\n    position: relative;\n    text-align: center;\n    padding: 20px 0 10px;\n}\n\n}`;\n\nfunction MultiFormatViewer() {\n     React.useEffect(() => {\n        rendereComplete();\n    }, []);\n  let viewer: PdfViewerComponent;\n  let allowedExtensions;\n  let parentElement;\n  let dropAreaRef = React.useRef<HTMLDivElement>(null);\n  let filesData;\n  let uploadObj = React.useRef<UploaderComponent>(null);\n  let linear = React.useRef<ProgressBarComponent>(null);\n  let pdfViewerProgressValue = 0;\n  let uploadProgressValue = 0;\n  const rendereComplete = () => {\n    uploadObj.current.dropArea = dropAreaRef.current;\n    document.getElementById('browse').onclick = () => {\n      document.getElementsByClassName('e-file-select-wrap')[0].querySelector('button').click();\n      return false;\n    };\n  }\n  allowedExtensions = '.doc, .docx, .rtf, .docm, .dotm, .dotx, .dot, .xls, .xlsx, .pptx, .pptm, .potx, .potm .jpeg, .png, .bmp, .pdf, .jpg';\n  const onSelect = (args) => {\n    linear.current.value == 0;\n    linear.current.refresh();\n    let extensions = ['doc', 'docx', 'rtf', 'docm', 'dotm', 'dotx', 'dot', 'xls', 'xlsx', 'pptx', 'pptm', 'potx', 'potm', 'jpeg', 'png', 'bmp', 'pdf','jpg'];\n    let progressBarContainer: any = document.getElementById(\"progressBar\") as HTMLElement;\n    let progressBar: any = document.getElementById(\"linearProgressBar\") as HTMLElement;\n    let progressMessage: any = document.getElementById(\"uploadedMessage\") as HTMLElement;\n    document.getElementById(\"fileDetails\").style.display = \"block\";\n    document.getElementById(\"FailedMessage\").style.display = \"none\";\n    var fileSizeValidation = document.getElementById(\"fileSizeValidation\");\n    progressBarContainer.style.display = \"block\";\n    progressBar.style.display = \"flex\";\n    progressMessage.style.display = \"none\";\n    fileSizeValidation.style.display = \"none\";\n    if (!uploadObj.current.element.querySelector('li')) {\n      filesData = [];\n    }\n    if (isNullOrUndefined(uploadObj.current.element.querySelector('.e-upload-files'))) {\n      parentElement = createElement('ul', {\n        className: 'e-upload-files',\n      });\n      document.getElementsByClassName('e-upload')[0].appendChild(parentElement);\n    }\n    var validFiles = args.filesData;\n    if (validFiles.length === 0) {\n      progressBarContainer.style.display = \"block\";\n      progressBar.style.display = \"none\";\n      progressMessage.style.display = \"block\";\n      args.cancel = true;\n      return;\n    }\n    if (!extensions.includes(validFiles[0].type)) {\n      document.getElementById(\"FailedMessage\").style.display = \"block\";\n      document.getElementById(\"fileDetails\").style.display = \"none\"\n      progressBar.style.display = \"none\";\n      progressMessage.style.display = \"none\";\n      document.getElementById('pdfviewer_container').style.display = 'none';\n      args.cancel = true;\n      return;\n    }\n    if (validFiles[0].type != \"pdf\" && validFiles[0].size > 4000000) {\n      fileSizeValidation.style.display = \"block\";\n      progressBar.style.display = \"none\";\n      document.getElementById(\"fileDetails\").style.display = \"none\";\n      document.getElementById('pdfviewer_container').style.display = 'none';\n      args.cancel = true;\n      return;\n    }\n    document.getElementById(\"fileName\").innerHTML = args.filesData[0].name;\n    viewer = (document.getElementById('pdfviewer') as any).ej2_instances[0];\n    viewer.downloadFileName = args.filesData[0].name;\n    viewer.exportAnnotationFileName = args.filesData[0].name;\n    let size = document.getElementById(\"fileSize\") as HTMLElement;\n    if ((args.filesData[0].size.toString()).length <= 7) {\n      size.innerHTML = ((args.filesData[0].size / 1024).toFixed(1)).toString() + \" KB\";\n    } else {\n      let kbsize = args.filesData[0].size / 1024;\n      size.innerHTML = ((kbsize / 1024).toFixed(1)).toString() + \" MB\";\n    }\n    document.getElementById(\"fileSize\");\n    formSelectedData(validFiles[0], uploadObj.current);\n    filesData = filesData.concat(validFiles);\n    const totalProgress = calculateTotalProgress();\n    updateProgressBar(totalProgress);\n    (document.getElementById(\"progress-status\") as any).innerHTML = totalProgress.toString() + \"%\";\n  }\n  const formSelectedData = (file, proxy) => {\n    var liEle = createElement('li', {\n      className: 'e-upload-file-list',\n      attrs: {\n        'data-file-name': file.name\n      },\n    });\n    readURL(liEle, file);\n    proxy.fileList.push(liEle);\n  }\n  const readURL = (li, args) => {\n    var file = args.rawFile;\n    var reader = new FileReader();\n    var type = args.type;\n    reader.addEventListener('load', function () {\n      let post = JSON.stringify({\n        'data': reader.result,\n        'type': type\n      })\n      const url = \"https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/LoadFile\"\n      let xhr = new XMLHttpRequest()\n      xhr.open('Post', url, true)\n      xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8')\n      xhr.upload.addEventListener('progress', (event) => {\n        if (event.lengthComputable) {\n          let progressValue = Math.round((event.loaded / event.total) * 100);\n          uploadProgressValue = progressValue;\n          const totalProgress = calculateTotalProgress();\n          updateProgressBar(totalProgress);\n          (document.getElementById(\"progress-status\") as any).innerHTML = totalProgress.toString() + \"%\";\n        }\n      })\n      xhr.onreadystatechange = function (event) {\n        if (xhr.responseText != \"\" && xhr.readyState === 4) {\n          if (xhr.status === 200) {\n            viewer = (document.getElementById('pdfviewer') as any).ej2_instances[0];\n            viewer.documentPath = '';\n            viewer.documentPath = xhr.responseText;\n            pdfViewerProgressValue = 20;\n            const totalProgress = calculateTotalProgress();\n            updateProgressBar(totalProgress);\n            document.getElementById(\"progress-status\").innerHTML = totalProgress.toString() + \"%\";\n            document.getElementById('pdfviewer_container').style.display = 'block';\n          } else {\n            console.error('Error:', xhr.statusText);\n          }\n        }\n      }.bind(this);\n      xhr.send(post);\n    },\n      false\n    );\n    if (file) {\n      reader.readAsDataURL(file);\n    }\n  };\n  const documentLoad = (args) => {\n    pdfViewerProgressValue = 100;\n    const totalProgress = calculateTotalProgress();\n    updateProgressBar(totalProgress);\n    (document.getElementById(\"progress-status\") as any).innerHTML = totalProgress.toString() + \"%\";\n    setTimeout(() => {\n      document.getElementById(\"linearProgressBar\").style.display = \"none\";\n      document.getElementById(\"uploadedMessage\").style.display = \"block\";\n      uploadProgressValue = 0;\n      pdfViewerProgressValue = 0;\n      linear.current.value = 0;\n    }, 1000);\n  };\n  const calculateTotalProgress = () => {\n    const totalProgress = (uploadProgressValue + pdfViewerProgressValue) / 2;\n    return totalProgress;\n  };\n  const updateProgressBar = (progress) => {\n    if (linear) {\n      linear.current.value = progress;\n    }\n  };\n  const progressLoad = (args) => {\n    let selectedTheme: string = location.hash.split('/')[1];\n    selectedTheme = selectedTheme ? selectedTheme : 'Material';\n    args.progressBar.theme = (selectedTheme.charAt(0).toUpperCase() +\n      selectedTheme.slice(1)).replace(/-dark/i, 'Dark').replace(/contrast/i, 'Contrast') as ProgressTheme;\n    if (args.progressBar.theme === 'HighContrast' || args.progressBar.theme === 'Bootstrap5Dark' || args.progressBar.theme === 'BootstrapDark' || args.progressBar.theme === 'FabricDark'\n      || args.progressBar.theme === 'TailwindDark' || args.progressBar.theme === 'MaterialDark' || args.progressBar.theme === 'FluentDark' || args.progressBar.theme === 'Material3Dark') {\n    }\n  };\n  const ajaxRequestSuccess = (args) => {\n    if (args.action === \"Load\") {\n      pdfViewerProgressValue = 50;\n      const totalProgress = calculateTotalProgress();\n      updateProgressBar(totalProgress);\n      document.getElementById(\"progress-status\").innerHTML = totalProgress.toString() + \"%\";\n    }\n  };\n  return (<div>\n    <div className='control-section' >\n        <style>{SAMPLE_CSS}</style>\n      <div className='content-wrapper-pdfviewer' ref={dropAreaRef} style={{ 'textAlign': 'center', 'marginBottom': '15px' }}>\n        <div style={{ 'height': 'auto', 'overflow': 'auto', marginBottom: '15px' }}>\n          <ButtonComponent id='browse'>Browse...</ButtonComponent>\n          <div>\n            <p style={{ 'margin': '10px' }}>OR</p>\n            <span id=\"drop\">Drop files (Word, Excel, PowerPoint, Image, PDF)</span>\n          </div>\n        </div>\n        <div id=\"progressBar\" style={{ display: 'none' }}>\n          <div id='fileDetails'>\n            <p id=\"fileName\"></p>\n            <p id=\"fileSize\"></p>\n          </div>\n          <div id='linearProgressBar' style={{ justifyContent: 'center', display: 'none' }}>\n            <ProgressBarComponent id=\"linear-pdfviewer\" ref={linear} type='Linear' width='250' height='60' animation={{ enable: false, duration: 2000, delay: 0 }} value={0} load={progressLoad.bind(this)}>\n            </ProgressBarComponent>\n            <span id='progress-status' style={{ padding: '18px 5px' }}></span>\n          </div>\n          <div id=\"uploadedMessage\" style={{ display: 'none', marginTop: '10px' }}>\n            <p style={{ color: 'rgb(110, 218, 110)' }}>File successfully uploaded...</p>\n          </div>\n          <div id=\"FailedMessage\" style={{ display: 'none', marginTop: '10px' }}>\n            <p style={{ color: 'red' }}>File not Supported!</p>\n          </div>\n          <div id=\"fileSizeValidation\" style={{ display: 'none', marginTop: '10px' }}>\n            <p style={{ color: 'rgb(203, 38, 38)' }}>Maximum file size is (4.0 MB) for this operation...</p>\n          </div>\n        </div>\n        <div id=\"uploader-pdfviewer\">\n          <UploaderComponent id='fileUpload' type='file' ref={uploadObj} multiple={false} selected={onSelect} allowedExtensions={allowedExtensions} ></UploaderComponent>\n        </div>\n      </div>\n      <div id='pdfviewer_container' style={{ display: 'none' }}>\n        {/* Render the PDF Viewer */}\n        <PdfViewerComponent id=\"pdfviewer\"\n          className=\"e-pv-multi-format-pdfviewer\"\n          resourceUrl=\"https://cdn.syncfusion.com/ej2/23.2.6/dist/ej2-pdfviewer-lib\"\n          toolbarSettings={{\n            showTooltip: true, toolbarItems: [\n              \"DownloadOption\",\n              \"UndoRedoTool\",\n              \"PageNavigationTool\",\n              \"MagnificationTool\",\n              \"PanTool\",\n              \"SelectionTool\",\n              \"CommentTool\",\n              \"SubmitForm\",\n              \"SearchOption\",\n              \"AnnotationEditTool\",\n              \"FormDesignerEditTool\",\n              \"PrintOption\"]\n          }}\n          documentLoad={documentLoad}\n          ajaxRequestSuccess={ajaxRequestSuccess}\n          zoomMode = \"FitToPage\"\n          style={{ 'height': '640px' }}>\n          <Inject services={[Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner,PageOrganizer]} />\n        </PdfViewerComponent>\n      </div>\n    </div>\n  </div>\n  );\n}\nexport default MultiFormatViewer;"
    }
  ]
}