{
  "$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/js/pdf-viewer-multi-format-viewer.md"
  },
  "files": [
    {
      "target": "src/components/pdf-viewer-multi-format-viewer/PdfViewer.jsx",
      "content": "import * as React from 'react';\nimport { PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, 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 } from '@syncfusion/ej2-react-progressbar';\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;\n    let allowedExtensions;\n    let parentElement;\n    let dropAreaRef = React.useRef(null);\n    let filesData;\n    let uploadObj = React.useRef(null);\n    let linear = React.useRef(null);\n    const [style, setStyle] = React.useState({ color: \"\" });\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 = document.getElementById(\"progressBar\");\n        let progressBar = document.getElementById(\"linearProgressBar\");\n        let progressMessage = document.getElementById(\"uploadedMessage\");\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').ej2_instances[0];\n        viewer.downloadFileName = args.filesData[0].name;\n        viewer.exportAnnotationFileName = args.filesData[0].name;\n        let size = document.getElementById(\"fileSize\");\n        if ((args.filesData[0].size.toString()).length <= 7) {\n            size.innerHTML = ((args.filesData[0].size / 1024).toFixed(1)).toString() + \" KB\";\n        }\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\").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\").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').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                    }\n                    else {\n                        console.error('Error:', xhr.statusText);\n                    }\n                }\n            }.bind(this);\n            xhr.send(post);\n        }, false);\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\").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 = 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');\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            setStyle({ color: \"White\" });\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\" className=\"e-pv-multi-format-pdfviewer\" resourceUrl=\"https://cdn.syncfusion.com/ej2/23.2.6/dist/ej2-pdfviewer-lib\" 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} ajaxRequestSuccess={ajaxRequestSuccess} zoomMode=\"FitToPage\" 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}\nexport default MultiFormatViewer;"
    }
  ]
}