This commit is contained in:
Timothy Jaeryang Baek
2026-08-24 18:06:59 -04:00
parent 98ee2bdfd3
commit fd8cc2ba4a
14 changed files with 117 additions and 18 deletions
@@ -2,6 +2,7 @@
import DOMPurify from 'dompurify';
import { getContext, onDestroy, onMount, tick } from 'svelte';
import type { Readable } from 'svelte/store';
import { clampDocumentTargetPage } from '$lib/utils/documentPreview';
import Spinner from './Spinner.svelte';
@@ -13,6 +14,7 @@
export let data: ArrayBuffer | null = null;
export let className = '';
export let targetPage: number | null = null;
let outerContainer: HTMLDivElement;
let containerEl: HTMLDivElement;
@@ -84,6 +86,16 @@
updateFitScale();
};
const scrollToTargetPage = async () => {
if (!containerEl) return;
const pages = containerEl.querySelectorAll('section.docx');
const page = clampDocumentTargetPage(targetPage, pages.length);
if (!page) return;
await tick();
(pages[page - 1] as HTMLElement | undefined)?.scrollIntoView({ block: 'start' });
};
const renderDocx = async (arrayBuffer: ArrayBuffer | null) => {
const currentRender = ++renderId;
clearPreview();
@@ -112,6 +124,7 @@
});
await tick();
updateFitScale();
await scrollToTargetPage();
} catch (e) {
console.error('Error rendering DOCX preview:', e);
@@ -130,6 +143,10 @@
$: if (mounted) renderDocx(data);
$: if (!loading && targetPage && !fallbackHtml) {
void scrollToTargetPage();
}
onMount(() => {
mounted = true;
void tick().then(() => {
+19 -1
View File
@@ -1,12 +1,14 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount, onDestroy, tick } from 'svelte';
import pdfWorkerUrl from 'pdfjs-dist/build/pdf.worker.mjs?url';
import panzoom, { type PanZoom } from 'panzoom';
import { clampDocumentTargetPage } from '$lib/utils/documentPreview';
import Spinner from './Spinner.svelte';
export let url: string | null = null;
export let data: ArrayBuffer | Uint8Array | null = null;
export let className = 'w-full h-[70vh]';
export let targetPage: number | null = null;
type PdfDocument = import('pdfjs-dist').PDFDocumentProxy;
type PdfTextLayer = InstanceType<typeof import('pdfjs-dist').TextLayer>;
@@ -98,6 +100,17 @@
}
};
const scrollToTargetPage = async () => {
if (!outerContainer || !sceneElement || !pdfDoc) return;
const page = clampDocumentTargetPage(targetPage, pdfDoc.numPages);
if (!page) return;
await tick();
const pageWrapper = sceneElement.querySelectorAll('.pdf-page-wrapper')[page - 1] as
HTMLElement | undefined;
pageWrapper?.scrollIntoView({ block: 'start' });
};
// Re-render existing canvases at a new zoom level (preserves panzoom transform)
const rerenderPages = async (forZoom: number) => {
if (!pdfDoc || !sceneElement) return;
@@ -223,6 +236,7 @@
lastRenderedZoom = 1;
initPanzoom();
await scrollToTargetPage();
};
const loadPdf = async () => {
@@ -258,6 +272,10 @@
loadPdf();
});
$: if (!loading && pdfDoc && targetPage) {
void scrollToTargetPage();
}
onDestroy(() => {
if (rerenderTimer) clearTimeout(rerenderTimer);
pzInstance?.dispose();
+17 -1
View File
@@ -1,10 +1,12 @@
<script lang="ts">
import { onDestroy, onMount, tick } from 'svelte';
import panzoom, { type PanZoom } from 'panzoom';
import { clampDocumentTargetPage } from '$lib/utils/documentPreview';
export let slides: string[] = [];
export let currentSlide = 0;
export let className = '';
export let targetPage: number | null = null;
let rootEl: HTMLDivElement;
let stageEl: HTMLElement;
@@ -22,6 +24,8 @@
let wheelDelta = 0;
let lastWheelNavigationAt = 0;
let lastScrolledSlide = -1;
let appliedTargetPage: number | null = null;
let appliedTargetSlides: string[] | null = null;
let thumbnailButtons: Array<HTMLButtonElement | undefined> = [];
const slideShortcutKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
const wheelNavigationThreshold = 80;
@@ -158,7 +162,7 @@
const transform = pzInstance?.getTransform();
if (transform && Math.abs(transform.scale - 1) >= 0.01) {
e.preventDefault();
pzInstance?.moveBy(-e.deltaX, -e.deltaY);
pzInstance?.moveBy(-e.deltaX, -e.deltaY, false);
zoomLevel = pzInstance?.getTransform().scale ?? 1;
return;
}
@@ -203,6 +207,18 @@
void tick().then(scrollSelectedThumbnailIntoView);
}
$: if (
mounted &&
targetPage &&
slides.length > 0 &&
(targetPage !== appliedTargetPage || slides !== appliedTargetSlides)
) {
appliedTargetPage = targetPage;
appliedTargetSlides = slides;
const page = clampDocumentTargetPage(targetPage, slides.length);
if (page) selectSlide(page - 1);
}
onDestroy(() => {
pzInstance?.dispose();
resizeObserver?.disconnect();