diff --git a/README.md b/README.md
index c71f728..0c4d31a 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ This package is source-only: consumers import directly from `src/` via the
| `dashgui/tiles` | `src/tiles/` | `Tile`, `TILE_SIZE`, `tileBaseSx` |
| `dashgui/ElevatedPill` | `src/ElevatedPill.jsx` | `ElevatedPill`, `ToggleElevatedPill`, `ActionElevatedPill` |
| `dashgui/SingleLineTextEdit` | `src/SingleLineTextEdit.jsx` | Centralized single-line text field |
-| `dashgui/FillSpace` | `src/FillSpace.jsx` | `FillSpace` — viewport-height spacer between header/footer refs; optional repeating `measureElement` |
+| `dashgui/FillSpace` | `src/FillSpace.jsx` | `FillSpace` — paginates `items` via `renderItem`, filling the viewport space between `aboveRef`/`belowRef`; wheel flips pages |
## Design rules
diff --git a/src/FillSpace.jsx b/src/FillSpace.jsx
index 5891f6f..498e423 100644
--- a/src/FillSpace.jsx
+++ b/src/FillSpace.jsx
@@ -260,13 +260,14 @@ class FillSpace extends Component {
// FillSpace owns current page, wheel-pagination and the pagination header.
// Caller feeds `items` plus one row element via `renderItem` (component
- // type or callback).
+ // type or callback). `items` may be undefined while data is loading.
const { pageSize, currentPage, viewportHeight } = this.state;
- const total = items.length;
+ const list = Array.isArray(items) ? items : [];
+ const total = list.length;
const pageCount = Math.max(1, Math.ceil(total / Math.max(1, pageSize)));
const safePage = Math.min(Math.max(1, currentPage), pageCount);
const offset = (safePage - 1) * pageSize;
- const pageItems = items.slice(offset, offset + pageSize);
+ const pageItems = list.slice(offset, offset + pageSize);
const showPagination = total > pageSize;
// Hidden data-free probe: measures `renderItem` itself (no data).
const probe = renderProbeElement(renderItem);
diff --git a/src/dev/mock-pages/FillSpaceMockPage.jsx b/src/dev/mock-pages/FillSpaceMockPage.jsx
index caf8d16..4984765 100644
--- a/src/dev/mock-pages/FillSpaceMockPage.jsx
+++ b/src/dev/mock-pages/FillSpaceMockPage.jsx
@@ -1,14 +1,32 @@
import { Component, createRef } from 'react';
import Box from '@mui/material/Box';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemText from '@mui/material/ListItemText';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import FillSpace from '../../FillSpace';
import { ComponentDocs } from '../ComponentDocs';
+/** Row renderer: component types are rendered as elements by FillSpace. */
+class Row extends Component {
+ render() {
+ const { item } = this.props;
+ return (
+
+
+
+ );
+ }
+}
+
+const SAMPLE_ITEMS = Array.from({ length: 40 }, (_, i) => ({
+ id: i + 1,
+ name: `Eintrag ${i + 1}`,
+}));
+
/**
- * Mock page exercising FillSpace: real content on top, and a repeating
- * `measureElement` filling only the leftover space down to the end of the
- * viewport.
+ * Mock page exercising FillSpace: header/footer refs, `items` + `renderItem`,
+ * wheel pagination and the built-in pagination header.
*/
class FillSpaceMockPage extends Component {
constructor(props) {
@@ -16,27 +34,26 @@ class FillSpaceMockPage extends Component {
this.ex1 = { header: createRef(), footer: createRef() };
this.ex2 = { header: createRef(), footer: createRef() };
this.ex3 = { header: createRef(), footer: createRef() };
- this.state = { fitCount: null };
}
render() {
- const { fitCount } = this.state;
return (
- FillSpace renders real content on top and repeats the measurement
- element until the end of the page.
+ FillSpace paginates items via a renderItem{' '}
+ row, measures the row height, fills the leftover viewport space and
+ flips pages on wheel scroll.
- {/* Main example: content + repeating fill to end of page */}
+ {/* Main example: items + renderItem to end of page */}
- Content + repeating element to end of page
+ Items + renderItem, filled to end of page
Header (measured)
@@ -44,65 +61,17 @@ class FillSpaceMockPage extends Component {
- Einheit
-
- }
- onMeasurement={(count) => this.setState({ fitCount: count })}
- >
-
-
- Echte Inhalte (children)
-
-
- Diese Zeilen stehen oben, darunter wiederholt sich die
- Einheit bis zum Seitenende.
-
-
-
- 📏 onMeasurement (würden ohne Inhalt passen):
-
-
- {fitCount != null ? `${fitCount} Einheiten` : '…'}
-
-
-
-
+ items={SAMPLE_ITEMS}
+ renderItem={Row}
+ reserveBottom={32}
+ minPageSize={5}
+ />
- Footer (measured)
+ Footer (reserved)
@@ -115,7 +84,7 @@ class FillSpaceMockPage extends Component {
Header
@@ -123,24 +92,15 @@ class FillSpaceMockPage extends Component {
-
-
- Minimum height of 200px enforced.
-
-
-
+ />
Footer
@@ -155,7 +115,7 @@ class FillSpaceMockPage extends Component {
Header
@@ -163,25 +123,15 @@ class FillSpaceMockPage extends Component {
-
-
- Green background shows actual spacer bounds; purple overlay
- shows full viewport coverage.
-
-
-
+ />
Footer
diff --git a/src/dev/screenshots/ScreenshotHarness.jsx b/src/dev/screenshots/ScreenshotHarness.jsx
index 4636e0a..4fc7ed5 100644
--- a/src/dev/screenshots/ScreenshotHarness.jsx
+++ b/src/dev/screenshots/ScreenshotHarness.jsx
@@ -2,6 +2,8 @@ import { Component, createRef } from 'react';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import Chip from '@mui/material/Chip';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemText from '@mui/material/ListItemText';
import Typography from '@mui/material/Typography';
import AddIcon from '@mui/icons-material/Add';
import FolderIcon from '@mui/icons-material/FolderOutlined';
@@ -307,8 +309,8 @@ class ScreenshotHarness extends Component {
}
/**
- * Deterministic FillSpace example for the screenshot harness. Bound with a
- * `maxHeight` so the reference is stable regardless of the viewport height.
+ * Deterministic FillSpace example for the screenshot harness:
+ * `items` + a component `renderItem`, bounded by above/below refs.
*/
class FillSpaceExample extends Component {
constructor(props) {
@@ -322,7 +324,7 @@ class FillSpaceExample extends Component {
Header (gemessen)
@@ -330,26 +332,15 @@ class FillSpaceExample extends Component {
-
-
- FillSpace füllt den Platz zwischen Header und Footer.
-
-
-
+ />
Footer (gemessen)
@@ -358,9 +349,36 @@ class FillSpaceExample extends Component {
}
}
+/** Row renderer used by the FillSpace harness examples. */
+class FillRow extends Component {
+ render() {
+ const { item } = this.props;
+ return (
+
+
+ Platzhalter
+
+ )
+ }
+ />
+
+ );
+ }
+}
+
+const FILL_SAMPLE_ITEMS = Array.from({ length: 24 }, (_, i) => ({
+ id: i + 1,
+ name: `Eintrag ${i + 1}`,
+}));
+
/**
- * FillSpace with a repeating measurement element plus real children on top,
- * for the screenshot harness. Bound with maxHeight so the reference is stable.
+ * FillSpace with `items` + a component `renderItem`, for the screenshot
+ * harness. Bounded by above/below refs so the reference is stable.
*/
class FillSpaceMeasureExample extends Component {
constructor(props) {
@@ -374,7 +392,7 @@ class FillSpaceMeasureExample extends Component {
Header
@@ -382,36 +400,15 @@ class FillSpaceMeasureExample extends Component {
- Einheit
-
- }
- measureGap={8}
+ items={FILL_SAMPLE_ITEMS}
+ renderItem={FillRow}
+ minPageSize={4}
minHeight={60}
- maxHeight={260}
- >
-
- Echte Inhalte
-
-
+ />
Footer