From 7b5ba74d8b72332b041582e5fbf7f4541788707c Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Sat, 20 Sep 2025 11:54:37 +0000 Subject: [PATCH] feat: Add context menu functionality for PDF components with options to view, copy URL, and download --- ts_web/elements/dees-pdf-preview/component.ts | 64 +++++++++++++++++++ ts_web/elements/dees-pdf-viewer/component.ts | 39 +++++++++++ ts_web/elements/dees-pdf/component.ts | 47 +++++++++++++- 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/ts_web/elements/dees-pdf-preview/component.ts b/ts_web/elements/dees-pdf-preview/component.ts index 789fb19..e8a0616 100644 --- a/ts_web/elements/dees-pdf-preview/component.ts +++ b/ts_web/elements/dees-pdf-preview/component.ts @@ -4,6 +4,8 @@ import { CanvasPool, type PooledCanvas } from '../dees-pdf-shared/CanvasPool.js' import { PerformanceMonitor, throttle } from '../dees-pdf-shared/utils.js'; import { previewStyles } from './styles.js'; import { demo as demoFunc } from './demo.js'; +import { DeesContextmenu } from '../dees-contextmenu.js'; +import '../dees-icon.js'; declare global { interface HTMLElementTagNameMap { @@ -287,4 +289,66 @@ export class DeesPdfPreview extends DeesElement { } } } + + /** + * Provide context menu items for right-click functionality + */ + public getContextMenuItems() { + const items: any[] = []; + + // If clickable, add option to view the PDF + if (this.clickable) { + items.push({ + name: 'View PDF', + iconName: 'lucide:Eye', + action: async () => { + this.handleClick(); + } + }); + items.push({ divider: true }); + } + + items.push( + { + 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(); + } + } + ); + + // Add page count info as a disabled item + if (this.pageCount > 0) { + items.push( + { divider: true }, + { + name: `${this.pageCount} page${this.pageCount > 1 ? 's' : ''}`, + iconName: 'lucide:FileText', + disabled: true, + action: async () => {} + } + ); + } + + return items; + } } \ No newline at end of file diff --git a/ts_web/elements/dees-pdf-viewer/component.ts b/ts_web/elements/dees-pdf-viewer/component.ts index 9fa9253..c6e3e24 100644 --- a/ts_web/elements/dees-pdf-viewer/component.ts +++ b/ts_web/elements/dees-pdf-viewer/component.ts @@ -3,6 +3,8 @@ import { DeesInputBase } from '../dees-input-base.js'; import { PdfManager } from '../dees-pdf-shared/PdfManager.js'; import { viewerStyles } from './styles.js'; import { demo as demoFunc } from './demo.js'; +import { DeesContextmenu } from '../dees-contextmenu.js'; +import '../dees-icon.js'; declare global { interface HTMLElementTagNameMap { @@ -383,4 +385,41 @@ export class DeesPdfViewer extends DeesElement { private printPdf() { window.open(this.pdfUrl, '_blank')?.print(); } + + /** + * Provide context menu items for right-click functionality + */ + 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 () => { + this.downloadPdf(); + } + }, + { + name: 'Print PDF', + iconName: 'lucide:Printer', + action: async () => { + this.printPdf(); + } + } + ]; + } } \ No newline at end of file diff --git a/ts_web/elements/dees-pdf/component.ts b/ts_web/elements/dees-pdf/component.ts index e555476..391952b 100644 --- a/ts_web/elements/dees-pdf/component.ts +++ b/ts_web/elements/dees-pdf/component.ts @@ -1,6 +1,8 @@ import { DeesElement, property, html, customElement, domtools, type TemplateResult, type CSSResult, } from '@design.estate/dees-element'; import { Deferred } from '@push.rocks/smartpromise'; +import { DeesContextmenu } from '../dees-contextmenu.js'; +import '../dees-icon.js'; // import type pdfjsTypes from 'pdfjs-dist'; @@ -26,6 +28,8 @@ export class DeesPdf extends DeesElement { public pdfUrl: string = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf'; + + constructor() { super(); @@ -49,9 +53,15 @@ export class DeesPdf extends DeesElement { #pdfcanvas { box-shadow: 0px 0px 5px #ccc; width: 100%; + cursor: pointer; } - + `; } @@ -69,6 +79,8 @@ export class DeesPdf extends DeesElement { } await DeesPdf.pdfJsReady; this.displayContent(); + + } public async displayContent() { @@ -112,4 +124,37 @@ export class DeesPdf extends DeesElement { } ); } + + /** + * 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(); + } + } + ]; + } } \ No newline at end of file