| 
									
										
										
										
											2023-08-07 20:02:18 +02:00
										 |  |  | import { DeesElement, property, html, customElement, domtools, type TemplateResult, type CSSResult, } from '@design.estate/dees-element'; | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 19:13:29 +02:00
										 |  |  | import { Deferred } from '@push.rocks/smartpromise'; | 
					
						
							| 
									
										
										
										
											2025-09-20 11:54:37 +00:00
										 |  |  | import { DeesContextmenu } from '../dees-contextmenu.js'; | 
					
						
							|  |  |  | import '../dees-icon.js'; | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-07 02:57:30 +02:00
										 |  |  | // import type pdfjsTypes from 'pdfjs-dist';
 | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | declare global { | 
					
						
							|  |  |  |   interface HTMLElementTagNameMap { | 
					
						
							|  |  |  |     'dees-pdf': DeesPdf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-20 11:42:22 +00:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @deprecated Use DeesPdfViewer or DeesPdfPreview instead | 
					
						
							|  |  |  |  * - DeesPdfViewer: Full-featured PDF viewing with controls, navigation, zoom | 
					
						
							|  |  |  |  * - DeesPdfPreview: Lightweight, performance-optimized preview for grids | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  | @customElement('dees-pdf') | 
					
						
							|  |  |  | export class DeesPdf extends DeesElement { | 
					
						
							|  |  |  |   // DEMO
 | 
					
						
							|  |  |  |   public static demo = () => html` <dees-pdf></dees-pdf> `; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // INSTANCE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @property() | 
					
						
							|  |  |  |   public pdfUrl: string = | 
					
						
							|  |  |  |     'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-20 11:54:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |   constructor() { | 
					
						
							|  |  |  |     super(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // you have access to all kinds of things through this.
 | 
					
						
							|  |  |  |     // this.setAttribute('gotIt','true');
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public render(): TemplateResult { | 
					
						
							|  |  |  |     return html`
 | 
					
						
							|  |  |  |       <style> | 
					
						
							|  |  |  |         :host { | 
					
						
							| 
									
										
										
										
											2024-06-30 10:37:12 +02:00
										 |  |  |           font-family: 'Geist Sans', sans-serif; | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |           display: block; | 
					
						
							|  |  |  |           box-sizing: border-box; | 
					
						
							|  |  |  |           max-width: 800px; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         :host([hidden]) { | 
					
						
							|  |  |  |           display: none; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #pdfcanvas { | 
					
						
							|  |  |  |           box-shadow: 0px 0px 5px #ccc; | 
					
						
							|  |  |  |           width: 100%; | 
					
						
							| 
									
										
										
										
											2025-09-20 11:54:37 +00:00
										 |  |  |           cursor: pointer; | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       </style> | 
					
						
							| 
									
										
										
										
											2025-09-20 11:54:37 +00:00
										 |  |  |       <canvas | 
					
						
							|  |  |  |         id="pdfcanvas" | 
					
						
							|  |  |  |         .height=${0} | 
					
						
							|  |  |  |         .width=${0} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ></canvas> | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |     `;
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public static pdfJsReady: Promise<any>; | 
					
						
							| 
									
										
										
										
											2023-09-07 02:57:30 +02:00
										 |  |  |   public static pdfjsLib: any // typeof pdfjsTypes;
 | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |   public async connectedCallback() { | 
					
						
							|  |  |  |     super.connectedCallback(); | 
					
						
							|  |  |  |     if (!DeesPdf.pdfJsReady) { | 
					
						
							|  |  |  |       const pdfJsReadyDeferred = domtools.plugins.smartpromise.defer(); | 
					
						
							|  |  |  |       DeesPdf.pdfJsReady = pdfJsReadyDeferred.promise; | 
					
						
							| 
									
										
										
										
											2024-01-15 12:57:49 +01:00
										 |  |  |       // @ts-ignore
 | 
					
						
							|  |  |  |       DeesPdf.pdfjsLib = await import('https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/+esm'); | 
					
						
							|  |  |  |       DeesPdf.pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/build/pdf.worker.mjs'; | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |       pdfJsReadyDeferred.resolve(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     await DeesPdf.pdfJsReady; | 
					
						
							|  |  |  |     this.displayContent(); | 
					
						
							| 
									
										
										
										
											2025-09-20 11:54:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-30 23:15:32 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public async displayContent() { | 
					
						
							|  |  |  |     await DeesPdf.pdfJsReady; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Asynchronous download of PDF
 | 
					
						
							|  |  |  |     const loadingTask = DeesPdf.pdfjsLib.getDocument(this.pdfUrl); | 
					
						
							|  |  |  |     loadingTask.promise.then( | 
					
						
							|  |  |  |       (pdf) => { | 
					
						
							|  |  |  |         console.log('PDF loaded'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Fetch the first page
 | 
					
						
							|  |  |  |         const pageNumber = 1; | 
					
						
							|  |  |  |         pdf.getPage(pageNumber).then((page) => { | 
					
						
							|  |  |  |           console.log('Page loaded'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const scale = 10; | 
					
						
							|  |  |  |           const viewport = page.getViewport({ scale: scale }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // Prepare canvas using PDF page dimensions
 | 
					
						
							|  |  |  |           const canvas: any = this.shadowRoot.querySelector('#pdfcanvas'); | 
					
						
							|  |  |  |           const context = canvas.getContext('2d'); | 
					
						
							|  |  |  |           canvas.height = viewport.height; | 
					
						
							|  |  |  |           canvas.width = viewport.width; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // Render PDF page into canvas context
 | 
					
						
							|  |  |  |           const renderContext = { | 
					
						
							|  |  |  |             canvasContext: context, | 
					
						
							|  |  |  |             viewport: viewport, | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const renderTask = page.render(renderContext); | 
					
						
							|  |  |  |           renderTask.promise.then(function () { | 
					
						
							|  |  |  |             console.log('Page rendered'); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       (reason) => { | 
					
						
							|  |  |  |         // PDF loading error
 | 
					
						
							|  |  |  |         console.error(reason); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-09-20 11:54:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Provide context menu items for the global context menu handler | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   public getContextMenuItems() { | 
					
						
							|  |  |  |     return [ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: 'Open PDF in New Tab', | 
					
						
							|  |  |  |         iconName: 'lucide:ExternalLink', | 
					
						
							|  |  |  |         action: async () => { | 
					
						
							|  |  |  |           window.open(this.pdfUrl, '_blank'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { divider: true }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: 'Copy PDF URL', | 
					
						
							|  |  |  |         iconName: 'lucide:Copy', | 
					
						
							|  |  |  |         action: async () => { | 
					
						
							|  |  |  |           await navigator.clipboard.writeText(this.pdfUrl); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         name: 'Download PDF', | 
					
						
							|  |  |  |         iconName: 'lucide:Download', | 
					
						
							|  |  |  |         action: async () => { | 
					
						
							|  |  |  |           const link = document.createElement('a'); | 
					
						
							|  |  |  |           link.href = this.pdfUrl; | 
					
						
							|  |  |  |           link.download = this.pdfUrl.split('/').pop() || 'document.pdf'; | 
					
						
							|  |  |  |           link.click(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-09-20 11:42:22 +00:00
										 |  |  | } |