fix(capture): preserve PhotoStage preview aspect on first paint

Contain-fit waits for a real parent width, uses ResizeObserver, and shrinks
width when maxH would otherwise stretch the CSS box. Pure fitDisplay is
covered by node tests.
This commit is contained in:
2026-09-14 16:37:00 +00:00
parent 0e94b1fd2a
commit b781ffeb66
6 changed files with 568 additions and 21 deletions
+17
View File
@@ -0,0 +1,17 @@
// Contain-fit of an image into a parent width with a height cap. Pure and
// display-only; all measurement math stays on source pixels.
// Null when the parent is not laid out yet (clientWidth 0) — the caller must
// not finalize CSS size until it is, to avoid a wrong-aspect flash.
export function fitDisplay(
parentW: number, imgW: number, imgH: number, maxH: number,
): { fitW: number; fitH: number } | null {
if (parentW <= 0 || imgW <= 0 || imgH <= 0) return null;
const fitW = parentW;
let fitH = (imgH / imgW) * fitW;
if (fitH > maxH) {
// Cap height and shrink width to preserve aspect; never stretch.
fitH = maxH;
return { fitW: (fitH * imgW) / imgH, fitH };
}
return { fitW, fitH };
}