Skip to content

Instantly share code, notes, and snippets.

@andyshora
Created February 23, 2021 15:15
Show Gist options
  • Save andyshora/d82f9e832ce071afaf04903603ba1981 to your computer and use it in GitHub Desktop.
Save andyshora/d82f9e832ce071afaf04903603ba1981 to your computer and use it in GitHub Desktop.
import React from "react"
import styled from "styled-components"
import { makeStyles } from "@material-ui/core/styles"
import { Table, TableBody, TablePagination } from "@material-ui/core"
import { animated, interpolate, Trail } from "react-spring/renderprops"
import Stars from "../Stars"
import {
StyledTableCell,
StyledTableRow,
SortableTableHead
} from "./TableParts"
const NumericValue = styled.span`
font-family: "Courier New", Courier, "Lucida Sans Typewriter";
`
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
if (b[orderBy] < a[orderBy]) {
return -1
}
if (b[orderBy] > a[orderBy]) {
return 1
}
return 0
}
type Order = "asc" | "desc"
function getComparator<Key extends keyof any>(
order: Order,
orderBy: Key
): (
a: { [key in Key]: number | string },
b: { [key in Key]: number | string }
) => number {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy)
}
function stableSort<T>(array: T[], comparator: (a: T, b: T) => number) {
const stabilizedThis = array.map((el, index) => [el, index] as [T, number])
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0])
if (order !== 0) return order
return a[1] - b[1]
})
return stabilizedThis.map(el => el[0])
}
function createData(
name: string,
rating: number,
fat: number,
carbs: number,
protein: number
) {
return { name, rating, fat, carbs, protein }
}
const rows = [
createData("Frozen yoghurt", 2, 6.0, 24, 4.0),
createData("Ice cream sandwich", 4, 9.0, 37, 4.3),
createData("Eclair", 5, 16.0, 24, 6.0),
createData("Cupcake", 1, 3.7, 67, 4.3),
createData("Gingerbread", 5, 16.0, 49, 3.9),
createData("Jam Tart", 3, 16.0, 49, 3.9)
]
const useStyles = makeStyles({
table: {
minWidth: 700
}
})
const headCells = [
{
id: "name",
numeric: false,
label: "Dessert (100g serving)"
},
{ id: "rating", numeric: true, align: "left", label: "Rating" },
{ id: "fat", numeric: true, label: "Fat (g)" },
{ id: "carbs", numeric: true, label: "Carbs (g)" },
{ id: "protein", numeric: true, label: "Protein (g)" }
]
const AnimatedRow = animated(StyledTableRow)
export default function SortableTableExample() {
const classes = useStyles()
const [order, setOrder] = React.useState<Order>("asc")
const [orderBy, setOrderBy] = React.useState<string>("rating")
const [page, setPage] = React.useState(0)
const [dense, setDense] = React.useState(false)
const [rowsPerPage, setRowsPerPage] = React.useState(50)
const handleRequestSort = (
event: React.MouseEvent<unknown>,
property: string
) => {
const isAsc = orderBy === property && order === "asc"
setOrder(isAsc ? "desc" : "asc")
setOrderBy(property)
}
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage)
}
return (
<div>
<Table className={classes.table} aria-label="customized table">
<SortableTableHead
classes={classes}
headCells={headCells}
order={order}
orderBy={orderBy}
onRequestSort={handleRequestSort}
rowCount={rows.length}
/>
<TableBody>
<Trail
native
items={stableSort(rows, getComparator(order, orderBy)).slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage
)}
keys={item => item.name}
from={{ opacity: 0, y: -40 }}
to={{ opacity: 1, y: 0 }}
>
{row => ({ opacity, y }) => (
<AnimatedRow
style={{
transform: interpolate([y], y => `translate3d(0, ${y}%, 0)`),
opacity
}}
hover
role="checkbox"
tabIndex={-1}
key={row.name}
>
<StyledTableCell component="th" scope="row">
{row.name}
</StyledTableCell>
<StyledTableCell>
<Stars max={5} value={row.rating} />
</StyledTableCell>
<StyledTableCell align="right">
<NumericValue>{row.fat}</NumericValue>
</StyledTableCell>
<StyledTableCell align="right">
<NumericValue>{row.carbs}</NumericValue>
</StyledTableCell>
<StyledTableCell align="right">
<NumericValue>{row.protein}</NumericValue>
</StyledTableCell>
</AnimatedRow>
)}
</Trail>
</TableBody>
</Table>
<TablePagination
rowsPerPageOptions={[25, 50, 100, 200]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment