List pagination component
Automatically break a list into "pages" based on a max height
by evan
HTML
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
CSS
* {
box-sizing: border-box;
}
body {
background: white;
}
section {
}
section div {
margin-bottom: 8px;
}
section div:last-child {
margin-bottom: 0;
}
article {
border: 3px solid blue;
page-break-after: always;
page-break-inside: avoid;
}
article:last-of-type {
page-break-after: auto;
}
Babel + JSX
const states = [
"Alabama",
"Alaska",
"Arizona",
"Arkansas",
"California",
"Colorado",
"Connecticut",
"Delaware",
"Florida",
"Georgia",
"Hawaii",
"Idaho",
"Illinois",
"Indiana",
"Iowa",
"Kansas",
"Kentucky",
"Louisiana",
"Maine",
"Maryland",
"Massachusetts",
"Michigan",
"Minnesota",
"Mississippi",
"Missouri",
"Montana",
"Nebraska",
"Nevada",
"New Hampshire",
"New Jersey",
"New Mexico",
"New York",
"North Carolina",
"North Dakota",
"Ohio",
"Oklahoma",
"Oregon",
"Pennsylvania",
"Rhode Island",
"South Carolina",
"South Dakota",
"Tennessee",
"Texas",
"Utah",
"Vermont",
"Virginia",
"Washington",
"West Virginia",
"Wisconsin",
"Wyoming",
];
class StatesContainer extends React.Component {
render() {
const {page, totalPages} = this.props;
return (
<article>
<header>Page {page + 1} of {totalPages}</header>
{
this.props.states.map(state => (
<h1 key={state}>{state}</h1>
))
}
<footer>
{page + 1 < totalPages &&
<span>Continues next page...</span>
}
</footer>
</article>
);
}
}
class MaxHeightContainer extends React.Component {
constructor(props) {
super();
this.state = {
groups: [[]],
items: 0,
activeGroup: 0
};
this.measure = this.measure.bind(this);
}
componentDidUpdate() {
setTimeout(this.measure, 0);
//this.measure();
}
componentDidMount() {
setTimeout(this.measure, 0);
//this.measure();
}
measure(el, i) {
const {maxHeight, values} = this.props;
const {groups, items, activeGroup} = this.state;
if (items >= values.length) {
if (this.props.onDone) {
this.props.onDone();
}
} else if (this.el.getBoundingClientRect().height < maxHeight) {
// if there's space left add another item
groups[activeGroup].push(values[items]);
this.setState({
items: items + 1,
groups
});
} else {
// else move the last...