u
This commit is contained in:
@@ -55,10 +55,12 @@ function renderProbeElement(renderItem) {
|
||||
class FillSpace extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const minSize = Math.max(1, Number(props.minPageSize) || 10);
|
||||
const maxSize = Number(props.maxPageSize) > 0 ? Number(props.maxPageSize) : Infinity;
|
||||
this.state = {
|
||||
unitHeight: 0,
|
||||
viewportHeight: null,
|
||||
pageSize: Number(props.minPageSize) || 10,
|
||||
pageSize: Math.min(maxSize, minSize),
|
||||
currentPage: 1,
|
||||
};
|
||||
this.ref = null;
|
||||
@@ -79,8 +81,13 @@ class FillSpace extends Component {
|
||||
if (prevProps.renderItem !== this.props.renderItem) {
|
||||
this._probeMeasure();
|
||||
}
|
||||
if (prevProps.minPageSize !== this.props.minPageSize) {
|
||||
this.setState({ pageSize: Number(this.props.minPageSize) || 10 });
|
||||
if (
|
||||
prevProps.minPageSize !== this.props.minPageSize ||
|
||||
prevProps.maxPageSize !== this.props.maxPageSize
|
||||
) {
|
||||
const minSize = Math.max(1, Number(this.props.minPageSize) || 10);
|
||||
const maxSize = Number(this.props.maxPageSize) > 0 ? Number(this.props.maxPageSize) : Infinity;
|
||||
this.setState({ pageSize: Math.min(maxSize, minSize) });
|
||||
}
|
||||
if (
|
||||
prevProps.aboveRef !== this.props.aboveRef ||
|
||||
@@ -165,7 +172,8 @@ class FillSpace extends Component {
|
||||
|
||||
/** Only measures the height of the `renderItem` probe. Nothing else. */
|
||||
_probeMeasure() {
|
||||
const h = this.probeRef?.offsetHeight;
|
||||
const firstRow = this.ref?.querySelector('[data-fill-row]');
|
||||
const h = this.probeRef?.offsetHeight || firstRow?.offsetHeight;
|
||||
if (h > 0 && h !== this.state.unitHeight) {
|
||||
this.setState({ unitHeight: h }, () => this._viewportMeasure());
|
||||
}
|
||||
@@ -197,14 +205,20 @@ class FillSpace extends Component {
|
||||
available = Math.max(0, window.innerHeight - rect.top - belowPx);
|
||||
}
|
||||
const minSize = Math.max(1, Number(minPageSize) || 10);
|
||||
const maxSize = Number(this.props.maxPageSize) > 0 ? Number(this.props.maxPageSize) : Infinity;
|
||||
const { unitHeight } = this.state;
|
||||
const nextPageSize =
|
||||
const calculated =
|
||||
unitHeight > 0 ? Math.max(minSize, Math.floor(available / unitHeight)) : minSize;
|
||||
const nextPageSize = Math.min(maxSize, calculated);
|
||||
const nextViewportHeight =
|
||||
Number.isFinite(maxSize) && unitHeight > 0
|
||||
? Math.min(available, nextPageSize * unitHeight)
|
||||
: available;
|
||||
if (
|
||||
available !== this.state.viewportHeight ||
|
||||
nextViewportHeight !== this.state.viewportHeight ||
|
||||
nextPageSize !== this.state.pageSize
|
||||
) {
|
||||
this.setState({ viewportHeight: available, pageSize: nextPageSize });
|
||||
this.setState({ viewportHeight: nextViewportHeight, pageSize: nextPageSize });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +264,8 @@ class FillSpace extends Component {
|
||||
minHeight,
|
||||
maxHeight,
|
||||
minPageSize,
|
||||
maxPageSize,
|
||||
listRef,
|
||||
onPageChange,
|
||||
onWheel,
|
||||
debug = false,
|
||||
@@ -275,60 +291,54 @@ class FillSpace extends Component {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
// Fixed single-line bar: the header height must not depend on the
|
||||
// page count. Otherwise the first fit (e.g. "1-17") pushes the
|
||||
// spacer down, the available height shrinks, and a second pass
|
||||
// flips to "1-15". One pass: constant 44px, real values always
|
||||
// rendered (only visibility is gated), no placeholder numbers.
|
||||
sx={{ mb: 1, height: 44, overflow: 'hidden' }}
|
||||
>
|
||||
{showPagination ? (
|
||||
<Box
|
||||
aria-hidden={!showPagination || undefined}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'nowrap',
|
||||
gap: 1,
|
||||
width: '100%',
|
||||
height: 44,
|
||||
visibility: showPagination ? 'visible' : 'hidden',
|
||||
pointerEvents: showPagination ? 'auto' : 'none',
|
||||
}}
|
||||
sx={{ mb: 1, height: 44, overflow: 'hidden' }}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
noWrap
|
||||
sx={{ flexShrink: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }}
|
||||
>
|
||||
{total === 0 ? '0' : `${offset + 1}–${Math.min(offset + pageSize, total)}`} von{' '}
|
||||
{total}
|
||||
</Typography>
|
||||
<Pagination
|
||||
count={pageCount}
|
||||
page={safePage}
|
||||
onChange={(_e, page) => this._goToPage(page)}
|
||||
color="primary"
|
||||
size="large"
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
<Box
|
||||
sx={{
|
||||
flexShrink: 0,
|
||||
maxWidth: '100%',
|
||||
overflowX: 'auto',
|
||||
scrollbarWidth: 'none',
|
||||
'&::-webkit-scrollbar': { display: 'none' },
|
||||
'& .MuiPagination-ul': { flexWrap: 'nowrap' },
|
||||
'& .MuiPaginationItem-root': {
|
||||
minWidth: 44,
|
||||
height: 44,
|
||||
fontSize: '1rem',
|
||||
},
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'nowrap',
|
||||
gap: 1,
|
||||
width: '100%',
|
||||
height: 44,
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
noWrap
|
||||
sx={{ flexShrink: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }}
|
||||
>
|
||||
{total === 0 ? '0' : `${offset + 1}–${Math.min(offset + pageSize, total)}`} von{' '}
|
||||
{total}
|
||||
</Typography>
|
||||
<Pagination
|
||||
count={pageCount}
|
||||
page={safePage}
|
||||
onChange={(_e, page) => this._goToPage(page)}
|
||||
color="primary"
|
||||
size="large"
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
sx={{
|
||||
flexShrink: 0,
|
||||
maxWidth: '100%',
|
||||
overflowX: 'auto',
|
||||
scrollbarWidth: 'none',
|
||||
'&::-webkit-scrollbar': { display: 'none' },
|
||||
'& .MuiPagination-ul': { flexWrap: 'nowrap' },
|
||||
'& .MuiPaginationItem-root': {
|
||||
minWidth: 44,
|
||||
height: 44,
|
||||
fontSize: '1rem',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
) : null}
|
||||
<Box
|
||||
ref={(el) => {
|
||||
this.ref = el;
|
||||
@@ -357,7 +367,7 @@ class FillSpace extends Component {
|
||||
]}
|
||||
>
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<List dense disablePadding sx={{ width: '100%' }}>
|
||||
<List ref={listRef} dense disablePadding sx={{ width: '100%' }}>
|
||||
{pageItems.map((item, i) => (
|
||||
<Box key={item?.id ?? offset + i} data-fill-row sx={{ width: '100%' }}>
|
||||
{renderRowElement(renderItem, item, offset + i)}
|
||||
|
||||
Reference in New Issue
Block a user