add page scrolling

This commit is contained in:
2025-12-11 14:58:19 +00:00
parent f86aebc00b
commit de464461e6

View File

@@ -88,6 +88,9 @@ export class DeDocumentViewer extends DeesElement {
@state() @state()
accessor displayZoom: number = 100; accessor displayZoom: number = 100;
@state()
accessor currentPageDisplay: string = "1 / 1";
public static styles = [ public static styles = [
cssManager.defaultStyles, cssManager.defaultStyles,
css` css`
@@ -328,6 +331,19 @@ export class DeDocumentViewer extends DeesElement {
gap: 2px; gap: 2px;
} }
.page-nav {
display: flex;
align-items: center;
gap: 2px;
}
.page-indicator {
font-size: 12px;
color: var(--text-secondary);
min-width: 45px;
text-align: center;
}
.spacing-slider-container { .spacing-slider-container {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -585,6 +601,27 @@ export class DeDocumentViewer extends DeesElement {
<div class="controls__divider"></div> <div class="controls__divider"></div>
<!-- Page Navigation -->
<div class="page-nav">
<button
class="controls__button"
@click=${() => this.handlePreviousPage()}
title="Previous Page"
>
<dees-icon icon="lucide:chevronUp"></dees-icon>
</button>
<span class="page-indicator">${this.currentPageDisplay}</span>
<button
class="controls__button"
@click=${() => this.handleNextPage()}
title="Next Page"
>
<dees-icon icon="lucide:chevronDown"></dees-icon>
</button>
</div>
<div class="controls__divider"></div>
<!-- Print Button --> <!-- Print Button -->
<button <button
class="controls__button" class="controls__button"
@@ -669,6 +706,27 @@ export class DeDocumentViewer extends DeesElement {
this.pageGap = parseInt((e.target as HTMLInputElement).value, 10); this.pageGap = parseInt((e.target as HTMLInputElement).value, 10);
} }
private handlePreviousPage(): void {
const current = this.getCurrentPage();
if (current > 1) {
this.scrollToPage(current - 1);
}
}
private handleNextPage(): void {
const current = this.getCurrentPage();
const total = this.getPageCount();
if (current < total) {
this.scrollToPage(current + 1);
}
}
private updatePageIndicator(): void {
const current = this.getCurrentPage();
const total = this.getPageCount();
this.currentPageDisplay = `${current} / ${total || 1}`;
}
private async handlePrint(): Promise<void> { private async handlePrint(): Promise<void> {
// Create a print-specific container - hidden on screen, visible only in print // Create a print-specific container - hidden on screen, visible only in print
const printContainer = document.createElement("div"); const printContainer = document.createElement("div");
@@ -803,8 +861,11 @@ export class DeDocumentViewer extends DeesElement {
super.updated(changedProperties); super.updated(changedProperties);
if (changedProperties.has("letterData")) { if (changedProperties.has("letterData")) {
// Update display zoom after document renders // Update display zoom and page indicator after document renders
setTimeout(() => this.updateDisplayZoom(), 100); setTimeout(() => {
this.updateDisplayZoom();
this.updatePageIndicator();
}, 100);
} }
} }
@@ -823,9 +884,10 @@ export class DeDocumentViewer extends DeesElement {
setTimeout(() => this.updateDisplayZoom(), 200); setTimeout(() => this.updateDisplayZoom(), 200);
} }
// Handle viewport resize to update display zoom in auto mode // Handle viewport resize and scroll
const viewport = this.shadowRoot?.querySelector(".viewport"); const viewport = this.shadowRoot?.querySelector(".viewport");
if (viewport) { if (viewport) {
// Resize observer for zoom updates
const resizeObserver = new ResizeObserver(() => { const resizeObserver = new ResizeObserver(() => {
if (this.zoomMode === "auto" || this.zoomMode === "fit-width") { if (this.zoomMode === "auto" || this.zoomMode === "fit-width") {
this.updateDisplayZoom(); this.updateDisplayZoom();
@@ -833,7 +895,17 @@ export class DeDocumentViewer extends DeesElement {
}); });
resizeObserver.observe(viewport); resizeObserver.observe(viewport);
this.registerGarbageFunction(() => resizeObserver.disconnect()); this.registerGarbageFunction(() => resizeObserver.disconnect());
// Scroll listener for page indicator
const scrollHandler = () => {
this.updatePageIndicator();
};
viewport.addEventListener("scroll", scrollHandler);
this.registerGarbageFunction(() => viewport.removeEventListener("scroll", scrollHandler));
} }
// Initial page indicator update
setTimeout(() => this.updatePageIndicator(), 300);
} }
// ============================================ // ============================================
@@ -928,19 +1000,27 @@ export class DeDocumentViewer extends DeesElement {
* @param smooth - Whether to use smooth scrolling (default: true) * @param smooth - Whether to use smooth scrolling (default: true)
*/ */
public scrollToPage(pageNumber: number, smooth: boolean = true): void { public scrollToPage(pageNumber: number, smooth: boolean = true): void {
const viewport = this.shadowRoot?.querySelector(".viewport");
const doc = this.shadowRoot?.querySelector("dedocument-dedocument"); const doc = this.shadowRoot?.querySelector("dedocument-dedocument");
if (!doc) return; if (!viewport || !doc) return;
const pages = doc.shadowRoot?.querySelectorAll("dedocument-page"); const pages = doc.shadowRoot?.querySelectorAll("dedocument-page");
if (!pages || pages.length === 0) return; if (!pages || pages.length === 0) return;
const targetIndex = Math.min(Math.max(0, pageNumber - 1), pages.length - 1); const targetIndex = Math.min(Math.max(0, pageNumber - 1), pages.length - 1);
const targetPage = pages[targetIndex]; const targetPage = pages[targetIndex] as HTMLElement;
if (targetPage) { if (targetPage) {
targetPage.scrollIntoView({ // Calculate scroll position relative to viewport
// Account for the document's position within the viewport
const docRect = doc.getBoundingClientRect();
const pageRect = targetPage.getBoundingClientRect();
const pageOffsetFromDoc = pageRect.top - docRect.top;
// Scroll to the page position
viewport.scrollTo({
top: pageOffsetFromDoc,
behavior: smooth ? "smooth" : "instant", behavior: smooth ? "smooth" : "instant",
block: "start",
}); });
} }
} }