Files
Agent-System-Frontend/src/previewfit.ts
T
weichenandCursor d384a3d778 Make the preview pane the only scrolling preview
Why: The pane pinned .ui-fp to the column height, and the docx fit host then clipped overflow, so the right-hand preview could not scroll. The fullscreen DocViewer was a second shell around the same FilePreview.
Evidence: npx vitest run (17 files, 82 tests) and npx tsc --noEmit passed. Headless Chromium laid out a 1400px docx host inside a 764px pane (body scrollHeight 1400) and a pdf iframe that filled that pane.
Impact: .preview-pane-body is the scroll owner. Docx refit also watches page height. The overlay viewer is gone; expand/restore and text edit/save live on the pane.
Refs: Agent-System-Dev#196, Agent-System-Frontend#44
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-05 04:41:20 +00:00

54 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// docx 分页纸面按预览栏宽度等比缩小。只缩不放:栏宽够放下整页时保持 100%。
// gutter 与 styles.css 里 .docx-wrapper 的左右 padding(12px + 12px)对齐。
export function computeFitScale(containerWidth: number, pageWidth: number, gutter: number): number {
if (!Number.isFinite(containerWidth) || !Number.isFinite(pageWidth) || pageWidth <= 0) return 1
if (!Number.isFinite(gutter)) return 1
const available = containerWidth - gutter
if (!(available > 0)) return 1
return Math.min(1, available / pageWidth)
}
const PAGE_GUTTER_PX = 24
/** host 是 docx-preview 的渲染根(内含 .docx-wrapper);el 是用来量栏宽的元素。
* 拖动分隔条时 el 变宽,ResizeObserver 重算。返回的函数卸下监听并清掉行内缩放。 */
export function fitPagesToWidth(host: HTMLElement, el: HTMLElement): () => void {
const apply = () => {
const wrapper = host.querySelector<HTMLElement>('.docx-wrapper')
const page = host.querySelector<HTMLElement>('section.docx')
if (!wrapper || !page) return
const scale = computeFitScale(el.clientWidth, page.offsetWidth, PAGE_GUTTER_PX)
wrapper.style.transformOrigin = 'top left'
wrapper.style.transform = scale < 1 ? `scale(${scale})` : ''
const nextHeight = `${Math.round(wrapper.offsetHeight * scale)}px`
if (host.style.height !== nextHeight) host.style.height = nextHeight
host.style.overflow = 'hidden'
host.style.minHeight = '0'
}
apply()
if (typeof ResizeObserver === 'undefined') {
return () => clearFit(host)
}
const observer = new ResizeObserver(() => apply())
observer.observe(el)
// 页内图片后加载只改变页纸高度,不改变栏宽。el 变宽和 wrapper 变高都要重算宿主高度。
const wrapper = host.querySelector<HTMLElement>('.docx-wrapper')
if (wrapper && wrapper !== el) observer.observe(wrapper)
return () => {
observer.disconnect()
clearFit(host)
}
}
function clearFit(host: HTMLElement) {
const wrapper = host.querySelector<HTMLElement>('.docx-wrapper')
if (wrapper) {
wrapper.style.transform = ''
wrapper.style.transformOrigin = ''
}
host.style.height = ''
host.style.overflow = ''
host.style.minHeight = ''
}