From 9f8b46aa49bc46f33e02abf37f6fe454610de3ae Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 9 Oct 2026 19:44:57 +0200 Subject: [PATCH] u --- src/FillSpace.jsx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/FillSpace.jsx b/src/FillSpace.jsx index d346383..48b36cb 100644 --- a/src/FillSpace.jsx +++ b/src/FillSpace.jsx @@ -12,7 +12,8 @@ import { alpha } from '@mui/material/styles'; * @defaultExport * * @prop {React.Ref} [aboveRef] - Ref to the element immediately above the spacer. It is observed (not strictly required) so the spacer re-measures when that element's height changes. - * @prop {React.Ref} [belowRef] - Ref to the footer element below. Its height (plus top margin) is reserved so the footer stays visible without page scrolling. + * @prop {React.Ref | React.Ref[]} [belowRef] - Ref(s) to footer element(s) below. Their heights (plus top margins) are reserved so footers stay visible without page scrolling. + * @prop {number} [reserveBottom=0] - Extra px to reserve below (e.g. app-shell bottom padding, tile padding) so the spacer never overfills the viewport. * @prop {ReactNode} [measureElement] - When given, this element is used as the measurement unit of the spacer: its height is read from a hidden copy and it is repeated top-to-bottom to fill only the leftover space below `children` (like a repeating ruler/row pattern). When omitted, only `children` are rendered. * @prop {number} [measureGap=0] - Vertical gap (px) between repeated `measureElement` units. * @prop {(count: number) => void} [onMeasurement] - Called whenever the number of `measureElement` units that would fit in the whole spacer height changes, as if there were no `children` (i.e. the total row count the space could hold). Fires once after mount with the initial count. @@ -126,6 +127,7 @@ class FillSpace extends Component { const { belowRef, containerRef, + reserveBottom = 0, measureElement, measureGap = 0, minHeight = 0, @@ -141,13 +143,19 @@ class FillSpace extends Component { const abovePx = rect.top + window.scrollY; // Height to reserve for the footer below (its box + top margin). - const belowEl = belowRef?.current; + const belowList = Array.isArray(belowRef) ? belowRef : [belowRef]; let belowPx = 0; - if (belowEl && belowEl.offsetParent !== null) { - belowPx = belowEl.offsetHeight; - const marginTop = parseFloat(window.getComputedStyle(belowEl).marginTop); - belowPx += Number.isFinite(marginTop) ? marginTop : 0; + for (const ref of belowList) { + const belowEl = ref?.current; + if (belowEl && belowEl.offsetParent !== null) { + belowPx += belowEl.offsetHeight; + const marginTop = parseFloat(window.getComputedStyle(belowEl).marginTop); + belowPx += Number.isFinite(marginTop) ? marginTop : 0; + } } + // Extra trailing space (app-shell padding, tile padding) that must stay + // visible below the spacer so the page never scrolls. + belowPx += Number(reserveBottom) || 0; const containerEl = containerRef && 'current' in containerRef ? containerRef.current : containerRef; let available;