add page scrolling
This commit is contained in:
@@ -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",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user