import solara, ipyreact from pathlib import Path import base64 import requests def pdf_url_to_base64(url): response = requests.get(url) if response.status_code == 200: pdf_bytes = response.content base64_encoded = base64.b64encode(pdf_bytes).decode("utf-8") return base64_encoded else: print("Failed to fetch PDF from URL:", url) return None ipyreact.define_module("ts-pdf", "./tp.mjs") ipyreact.define_import_map({ "pdfjs-dist": "https://esm.sh/pdfjs-dist@2.16.105/build/pdf.worker.js", }) @solara.component def PDFViewer(type,pdf): if type=="bytes": pdf_bytes=pdf else: pdf_bytes=pdf_url_to_base64(pdf) app = ipyreact.ValueWidget(_esm= """ import React, { useEffect } from 'react'; import { AnnotEventDetail, CustomStampEventDetail, TsPdfViewer, TsPdfViewerOptions } from 'ts-pdf'; const PdfViewerComponent = () => { useEffect(() => { const mobileVhHack = () => { const vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`); }; mobileVhHack(); window.addEventListener("resize", mobileVhHack); return () => { window.removeEventListener("resize", mobileVhHack); }; }, []); var arrayBuffer = base64ToArrayBuffer('"""+pdf_bytes+"""'); function base64ToArrayBuffer(base64) { var binaryString = window.atob(base64); var binaryLen = binaryString.length; var bytes = new Uint8Array(binaryLen); for (var i = 0; i < binaryLen; i++) { var ascii = binaryString.charCodeAt(i); bytes[i] = ascii; } return bytes; } var blob = new Blob([arrayBuffer], {type: "application/pdf"}); var link = window.URL.createObjectURL(blob); useEffect(() => { const run = async () => { const options: TsPdfViewerOptions = { containerSelector: "#pdf-main-container", workerSource: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/build/pdf.worker.js", userName: "corran", fileButtons: ["close", "save"], comparableFileButtons: ["open", "close"], annotChangeCallback: (detail: AnnotEventDetail) => { if (detail.type === "focus" || detail.type === "select" || detail.type === "render") { return; } console.log(detail); }, customStampChangeCallback: (detail: CustomStampEventDetail) => { // console.log(JSON.stringify(detail.stamp)); }, }; const viewer = new TsPdfViewer(options); // viewer.importAnnotationsFromJson(dtos); // }, 5000); // for debug window["pdfViewer"] = viewer; await viewer.openPdfAsync(link); }; run(); // Clean up function return () => { // Perform any cleanup of the effect here }; }, []); return (