u
This commit is contained in:
@@ -54,6 +54,21 @@ function renderRowElement(renderItem, item, index) {
|
|||||||
return renderItem(item, index);
|
return renderItem(item, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data-free probe of the row height, rendered hidden. Class components
|
||||||
|
* (e.g. `renderItem={ArtikelMarke}`) tolerate empty props
|
||||||
|
* (`brand`/`item` undefined) and keep a fixed height (40px thumb /
|
||||||
|
* text field), so the probe measures the row without depending on the
|
||||||
|
* first data element. Plain callbacks are NOT probed — calling arbitrary
|
||||||
|
* user code with `undefined` could throw — they fall back to the first
|
||||||
|
* rendered data row.
|
||||||
|
*/
|
||||||
|
function renderProbeElement(renderItem) {
|
||||||
|
if (!isRowComponent(renderItem)) return null;
|
||||||
|
const Row = renderItem;
|
||||||
|
return <Row brand={undefined} item={undefined} index={0} disabled />;
|
||||||
|
}
|
||||||
|
|
||||||
class FillSpace extends Component {
|
class FillSpace extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -74,6 +89,7 @@ class FillSpace extends Component {
|
|||||||
this.ref = null;
|
this.ref = null;
|
||||||
this.contentRef = null;
|
this.contentRef = null;
|
||||||
this.unitRef = null;
|
this.unitRef = null;
|
||||||
|
this.probeRef = null;
|
||||||
this.paginationRef = null;
|
this.paginationRef = null;
|
||||||
this.wheelAcc = 0;
|
this.wheelAcc = 0;
|
||||||
this.observer = null;
|
this.observer = null;
|
||||||
@@ -232,13 +248,19 @@ class FillSpace extends Component {
|
|||||||
contentHeight = this.contentRef.offsetHeight;
|
contentHeight = this.contentRef.offsetHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paginated: first rendered row is the measure element. Legacy: hidden copy.
|
// Paginated: hidden probe rendered from `renderItem` itself (no data).
|
||||||
|
// Legacy: hidden copy.
|
||||||
const paginated = Array.isArray(items) && typeof renderItem === 'function';
|
const paginated = Array.isArray(items) && typeof renderItem === 'function';
|
||||||
let unitHeight = this.state.unitHeight;
|
let unitHeight = this.state.unitHeight;
|
||||||
if (paginated) {
|
if (paginated) {
|
||||||
const firstRow = this.contentRef?.querySelector?.('[data-fill-row]') ?? this.contentRef?.firstElementChild;
|
const probeH = this.probeRef?.offsetHeight;
|
||||||
const h = firstRow?.offsetHeight;
|
if (probeH > 0) {
|
||||||
if (h > 0) unitHeight = h;
|
unitHeight = probeH;
|
||||||
|
} else {
|
||||||
|
const firstRow = this.contentRef?.querySelector?.('[data-fill-row]') ?? this.contentRef?.firstElementChild;
|
||||||
|
const h = firstRow?.offsetHeight;
|
||||||
|
if (h > 0) unitHeight = h;
|
||||||
|
}
|
||||||
if (!(unitHeight > 0) && measureElement != null && this.unitRef) {
|
if (!(unitHeight > 0) && measureElement != null && this.unitRef) {
|
||||||
const fallback = this.unitRef.offsetHeight;
|
const fallback = this.unitRef.offsetHeight;
|
||||||
if (fallback > 0) unitHeight = fallback;
|
if (fallback > 0) unitHeight = fallback;
|
||||||
@@ -476,7 +498,7 @@ class FillSpace extends Component {
|
|||||||
|
|
||||||
/** Pagination header + one page of rows. Wheel over the list flips pages. */
|
/** Pagination header + one page of rows. Wheel over the list flips pages. */
|
||||||
renderPaginated({ minHeight, maxHeight, debug, measureGap, sx, rest }) {
|
renderPaginated({ minHeight, maxHeight, debug, measureGap, sx, rest }) {
|
||||||
const { items, renderItem, onWheel } = this.props;
|
const { items, renderItem, measureElement, onWheel } = this.props;
|
||||||
const { height, pageSize, currentPage, measured } = this.state;
|
const { height, pageSize, currentPage, measured } = this.state;
|
||||||
const total = items.length;
|
const total = items.length;
|
||||||
const pageCount = Math.max(1, Math.ceil(total / Math.max(1, pageSize)));
|
const pageCount = Math.max(1, Math.ceil(total / Math.max(1, pageSize)));
|
||||||
@@ -485,6 +507,9 @@ class FillSpace extends Component {
|
|||||||
const pageItems = items.slice(offset, offset + pageSize);
|
const pageItems = items.slice(offset, offset + pageSize);
|
||||||
// Hidden until the fit is measured — no "1–10" flash on load.
|
// Hidden until the fit is measured — no "1–10" flash on load.
|
||||||
const showPagination = measured && total > pageSize;
|
const showPagination = measured && total > pageSize;
|
||||||
|
// Hidden data-free probe: measures `renderItem` itself (no data), so
|
||||||
|
// the first pass already uses the final row height — one pass, no flip.
|
||||||
|
const probe = renderProbeElement(renderItem) ?? measureElement;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -588,6 +613,28 @@ class FillSpace extends Component {
|
|||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
</Box>
|
</Box>
|
||||||
|
{probe != null ? (
|
||||||
|
<Box
|
||||||
|
ref={(el) => {
|
||||||
|
this.probeRef = el;
|
||||||
|
}}
|
||||||
|
aria-hidden
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: '100%',
|
||||||
|
visibility: 'hidden',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<List dense disablePadding sx={{ width: '100%' }}>
|
||||||
|
<Box data-fill-row sx={{ width: '100%' }}>
|
||||||
|
{probe}
|
||||||
|
</Box>
|
||||||
|
</List>
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
</Box>
|
</Box>
|
||||||
{debug ? (
|
{debug ? (
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
Reference in New Issue
Block a user