diff --git a/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts b/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts index 5a68740938..30bc8b2390 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts +++ b/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts @@ -7,16 +7,17 @@ import type { RenderPdfText } from './document.ts' /** * Create a selectable overlay in a component-owned host. * @param host - absolute overlay matching the displayed canvas dimensions. - * @returns renderer that attaches the layer to `host` when its promise resolves; cancellation also releases its resize observer and DOM. + * @returns renderer that attaches the layer to `host` once its text is laid out, before its promise resolves; + * a cancelled layer is never attached, and cancellation also releases its resize observer and DOM. */ export function pdfTextRenderer(host: HTMLDivElement): RenderPdfText { return (page, viewport) => { let cancelled = false // PDF.js measures each text item against document styles; spans appended to a detached layer do not invalidate them. - const layer = new TextLayerBuilder({ pdfPage: page, onAppend: (div: HTMLDivElement) => { + const layer = new TextLayerBuilder({ pdfPage: page, onAppend: () => { // A cancellation after the text finishes but before this callback cannot stop the builder's continuation. if (cancelled) layer.cancel() - else host.append(div) + else host.append(container) } }) const container = layer.div container.style.setProperty('--total-scale-factor', String(viewport.scale * viewport.userUnit)) diff --git a/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts b/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts index 6c710c8e5f..eb89a377c9 100644 --- a/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts +++ b/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts @@ -25,7 +25,7 @@ import { pdfTextRenderer } from '../src/client/pdf/text.ts' afterEach(() => { vi.unstubAllGlobals(); vi.restoreAllMocks(); vi.clearAllMocks() }) -it('lays out text in a detached layer and attaches it once rendering finishes', async () => { +it('attaches the text layer only after rendering finishes', async () => { vi.stubGlobal('ResizeObserver', class { observe = vi.fn(); disconnect = vi.fn() }) const rendered = Promise.withResolvers() api.render.mockReturnValueOnce(rendered.promise)