import React, { CSSProperties } from "react";
import Table, { Column } from "./Table.js";
import FilterSelectTable, { FilterSelect } from "./FilterSelectTable.js";
import { ReportDecorator, CardDecorator } from "../storybook/index.js";
import fixtures, {
HumanUse,
Categorical,
getRandomCategorical,
} from "../../testing/fixtures/index.js";
import { styled } from "styled-components";
export default {
component: Table,
title: "Components/Table/Table",
decorators: [CardDecorator, ReportDecorator],
};
const TableStyled = styled.div`
.dark {
background-color: #000;
color: #eee;
}
.med {
background-color: #ddd;
}
.light {
background-color: #efefef;
}
.centered th:not(:first-child) {
text-align: center;
}
.centered td:not(:first-child) {
text-align: center;
}
.squeeze {
font-size: 11px;
}
`;
const Percent = new Intl.NumberFormat("en", {
style: "percent",
});
/**
* Types don't have to be specified for table Columns or data in simple use cases
* but it provides you with Intellisense and can help avoid unexpected behavior
* If the columns or data change they can/should be wrapped in React.useMemo to avoid
* extra renders or infinite call stack errors,
*/
export const simple = () => {
const columns: Column[] = [
{
Header: "Name",
accessor: "name",
},
{
Header: "Count",
accessor: "count",
},
];
return
;
};
export const squeeze = () => {
const Percent2 = new Intl.NumberFormat("en", {
style: "percent",
minimumFractionDigits: 2,
});
const columns: Column[] = [
{
Header: "ID",
accessor: "id",
},
{
Header: "Count",
Cell: () => Number.format(cell.value)
, // Not working?
accessor: "count",
},
{
Header: "High",
accessor: (row) => Percent2.format(row.high),
},
{
Header: "Med",
accessor: (row) => Percent2.format(row.med),
},
{
Header: "Low",
accessor: (row) => Percent2.format(row.low),
},
{
Header: "Comment",
accessor: "comment",
},
];
return (
);
};
/**** Centered */
export const centered = () => {
const columns: Column[] = [
{ Header: "Name", accessor: "fullName" },
{ Header: "Area", accessor: "value" },
{ Header: "Rank", accessor: "rank" },
];
return (
);
};
/**** Set width */
export const setWidth = () => {
const columns: Column[] = [
{ Header: "Name", accessor: "fullName", style: { width: "70%" } },
{ Header: "Area", accessor: "value" },
{ Header: "Rank", accessor: "rank" },
];
return ;
};
/**** Formatted column ****/
/**
* Beware the formatted value is what's used by sort function, Cell function can be better
*/
export const formattedPercColumn = () => {
const columns: Column[] = [
{
Header: "Name",
accessor: "name",
},
{
Header: "Count",
accessor: "count",
},
{
Header: "Percent of Activity",
accessor: (row) => Percent.format(row.perc),
},
];
return ;
};
/**** Paging */
export const paging = () => {
const columns: Column[] = [
{ Header: "Name", accessor: "fullName", style: { width: "60%" } }, // Fixed width prevents dynamic variation between pages
{ Header: "Area", accessor: "value", style: { width: "20%" } },
{ Header: "Rank", accessor: "rank" },
];
return (
);
};
/**** Style override */
// https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/data-driven-classes-and-styles?file=/src/App.js:3903-3909
export const configDrivenStyle = () => {
const columns: Column[] = [
{
Header: "Name",
style: { backgroundColor: "#000", color: "#eee" },
columns: [
{
Header: "Place Name",
accessor: "name",
style: { backgroundColor: "#efefef" },
},
],
},
{
Header: "Count",
accessor: "count",
style: { backgroundColor: "#ddd" },
},
];
return ;
};
/**** Class-driven styling */
export const classDrivenStyle = () => {
const columns: Column[] = React.useMemo(
() => [
{
Header: "Name",
className: "dark",
columns: [
{
Header: "Place Name",
accessor: "name",
className: "light",
},
],
},
{
Header: "Count",
accessor: "count",
className: "med",
},
],
[],
);
return (
);
};
/**** Data-driven styling */
/**
* Any prop can be overridden with these functions, for example onClick, onEnter
*/
export const dataDrivenProps = () => {
const columns: Column[] = [
{
Header: "Name",
accessor: "name",
},
{
Header: "Count",
accessor: "count",
},
];
const headerFn = (header) =>
header.id === "name" ? { style: { color: "green" } } : {};
const colFn = (column) =>
column.id === "count" ? { style: { fontStyle: "italic" } } : {};
const rowFn = (row) =>
row.values.count > 1
? { style: { fontWeight: "bold" } as CSSProperties }
: {};
const cellFn = (cell) =>
cell.column.id === "count" && cell.value > 1
? { style: { backgroundColor: "#aaa" } }
: {};
return (
);
};
/**** Filtering */
export const filterCheckboxes = () => {
const filterSelect: FilterSelect = {
type: "every",
filters: [
{
name: "Show only count < 500K",
defaultValue: false,
filterFn: (row) => row.count < 2_000_000,
},
{
name: "Show only odd IDs",
defaultValue: true,
filterFn: (row) => Number.parseInt(row.id) % 2 !== 0,
},
],
};
const columns: Column[] = [
{
Header: "ID",
accessor: "id",
},
{
Header: "Count",
accessor: "count",
},
];
return (
columns, [])}
data={getRandomCategorical()}
/>
);
};
export const tableWithTitle = () => {
const columns: Column[] = [
{
Header: "Name",
accessor: "name",
},
{
Header: "Count",
accessor: "count",
},
];
return (
);
};
export const tableWithDownload = () => {
const columns: Column[] = [
{
Header: "Name",
accessor: "name",
},
{
Header: "Count",
accessor: "count",
},
];
return (
);
};
export const tableWithNoData = () => {
const columns: Column[] = [
{
Header: "Name",
accessor: "name",
},
{
Header: "Count",
accessor: "count",
},
];
return (
);
};