Honor sizing-probe verdicts in height emission; pin lottie mount heights

- heightFlows() bails when the capture probe proved a height authored-
  explicit (hAuto=false, hFill=false), so circular parent/child flow
  reasoning can no longer drop 100vh heroes to 0px; the probe verdict now
  vetoes the drop through both OR'd paths at the call site
- Space-distributing flex columns (space-between/around/evenly, center,
  flex-end) disqualify the content-driven read - the box height is load-
  bearing for the distribution
- Lottie mounts pin their captured per-viewport height like other replaced
  content, so aspect-fit runtime svgs can't inflate past the captured box
- DittoLottie forwards the placeholder's data-cid onto the runtime svg/
  canvas so the media stays addressable after the swap

240 tests pass (9 new), typecheck clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samraaj Bath
2026-07-03 23:43:36 -07:00
co-authored by Claude Fable 5
parent 6a930d57b1
commit d5a713d31f
6 changed files with 209 additions and 7 deletions
+14 -1
View File
@@ -154,10 +154,23 @@ export default function DittoLottie({ spec }: { spec: LottieSpec }) {
rendererSettings: { preserveAspectRatio: "xMidYMid meet" },
});
// Swap only once the animation is genuinely ready: reveal the live render and remove
// every original child (the placeholder) so the two never stack.
// every original child (the placeholder) so the two never stack. Before discarding the
// placeholder, forward its data-cid onto the runtime-rendered svg/canvas so the media
// node stays addressable by cid after the swap (it would otherwise mount without one).
const reveal = () => {
mount.style.opacity = "1";
// The captured placeholder is an svg/canvas (or wraps one) carrying its own data-cid.
let placeholderCid: string | null = null;
for (const child of Array.from(el.childNodes)) {
if (child === mount || placeholderCid !== null || !(child instanceof Element)) continue;
const media = child.matches("svg, canvas") ? child : child.querySelector("svg, canvas");
placeholderCid = (media ?? child).getAttribute("data-cid");
}
for (const child of Array.from(el.childNodes)) if (child !== mount) el.removeChild(child);
if (placeholderCid) {
const rendered = mount.querySelector("svg, canvas");
if (rendered) rendered.setAttribute("data-cid", placeholderCid);
}
mount.style.position = "";
mount.style.inset = "";
};