Skip to content

Commit

Permalink
fix: add a key prop for the table column
Browse files Browse the repository at this point in the history
This change allows the user to pass a key prop when a dataKey is not
applicable for that given column. This could be used for columns that
compose data from multiple columns, actions, or decorative columns.

Similar to the `dataKey`, The `key` needs to be unique.
  • Loading branch information
haideralsh committed Oct 30, 2023
1 parent 0096f6c commit 36e9db3
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 27 deletions.
5 changes: 3 additions & 2 deletions src/Table/BaseTable.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { boolean, text } from "@storybook/addon-knobs";
import { action } from "@storybook/addon-actions";
import { Box, DropdownButton, DropdownMenu, Button, Text } from "..";
import { getMockRows, mockColumns } from "./Table.mock-utils";
import { ColumnType } from "./Table.types";
import { Table } from ".";

const dateToString = ({ cellData }) => {
Expand All @@ -29,7 +30,7 @@ const dropdownCellRenderer = ({ cellData }) => (
</Box>
);

const columns = [
const columns: ColumnType[] = [
{ label: "Date", dataKey: "date" },
{ label: "Expected Quantity", dataKey: "expectedQuantity" },
{ label: "Actual Quantity", dataKey: "actualQuantity", align: "right" },
Expand Down Expand Up @@ -183,7 +184,7 @@ const columnsWithFormatter = [
{ label: "Actual Quantity", dataKey: "actualQuantity" },
];

const columnsWithAlignment = [
const columnsWithAlignment: ColumnType[] = [
{ label: "Date", dataKey: "date" },
{ label: "Expected Eaches", dataKey: "expectedQuantity" },
{ label: "Actual Eaches", dataKey: "actualQuantity", align: "right" },
Expand Down
3 changes: 1 addition & 2 deletions src/Table/Table.story.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable react/prop-types */
import React from "react";
import { action } from "@storybook/addon-actions";
import { boolean, number } from "@storybook/addon-knobs";
Expand Down Expand Up @@ -50,7 +49,7 @@ const columnsWithEverything = [
{ label: "Note", dataKey: "note", width: "45%" },
{
label: "",
dataKey: "actions",
key: "actions",
width: "5%",
cellRenderer: dropdownCellRenderer,
},
Expand Down
31 changes: 17 additions & 14 deletions src/Table/Table.types.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
import { Key, CSSProperties } from "react";
import PropTypes from "prop-types";

export type RowType = any;
export type RowType = unknown;

export type CellInfoType = {
cellData: any;
cellData: unknown;
column: ColumnType;
row: RowType;
};

type ColumnInfoType = {
align?: string;
align?: ColumnAlignment;
label: string;
dataKey?: string;
width?: string;
dataKey?: Key;
width?: CSSProperties["width"];
};

type ColumnAlignment = "left" | "right" | "center";

export type ColumnType = {
align?: string;
align?: ColumnAlignment;
label?: string;
dataKey?: string;
cellFormatter?: (cell: CellInfoType) => React.ReactNode | JSX.Element;
cellRenderer?: (cell: CellInfoType) => React.ReactNode | JSX.Element;
headerRenderer?: (column: ColumnInfoType) => React.ReactNode | JSX.Element;
headerFormatter?: (column: ColumnInfoType) => React.ReactNode | JSX.Element;
width?: string;
};
cellFormatter?: (cell: CellInfoType) => React.ReactNode;
cellRenderer?: (cell: CellInfoType) => React.ReactNode;
headerRenderer?: (column: ColumnInfoType) => React.ReactNode;
headerFormatter?: (column: ColumnInfoType) => React.ReactNode;
width?: string | number;
} & ({ key: Key; dataKey?: never | undefined } | { dataKey: Key; key?: never | undefined });

export const columnPropType = PropTypes.shape({
align: PropTypes.oneOf(["right", "left", "center"]),
label: PropTypes.string,
dataKey: PropTypes.string,
dataKey: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
key: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
cellFormatter: PropTypes.func,
cellRenderer: PropTypes.func,
headerRenderer: PropTypes.func,
Expand Down
12 changes: 9 additions & 3 deletions src/Table/TableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { Box } from "../Box";
import { DefaultNDSThemeType } from "../theme.type";
import { rowsPropType, columnsPropType, rowPropType } from "./Table.types";
import TableCell from "./TableCell";
import { DefaultNDSThemeType } from "../theme.type";

const StyledMessageContainer = styled(Box)(({ theme }) => ({
padding: `${theme.space.x3} 0`,
Expand Down Expand Up @@ -64,8 +64,14 @@ const TableBodyRow = ({
onMouseEnter,
}: TableBodyRowProps) => {
const renderAllCells = () =>
columns.map((column) => (
<TableCell key={column.dataKey} row={row} column={column} cellData={row[column.dataKey]} compact={compact} />
columns.map((column, index) => (
<TableCell
key={column.dataKey ?? column.key ?? index}
row={row}
column={column}
cellData={row[column.dataKey]}
compact={compact}
/>
));
return (
<>
Expand Down
20 changes: 15 additions & 5 deletions src/Table/TableFoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import styled from "styled-components";
import TableCell from "./TableCell";
import StyledTh from "./StyledTh";
import { columnsPropType, rowsPropType, rowPropType } from "./Table.types";
import { columnsPropType, rowsPropType, rowPropType, ColumnType, RowType } from "./Table.types";

const StyledFooterRow = styled.tr(({ theme }) => ({
"&:first-of-type": {
Expand Down Expand Up @@ -31,7 +31,7 @@ const TableFooterRow = ({ row, columns, loading, compact }) => {
) : (
!loading && (
<TableCell
key={column.dataKey}
key={column.dataKey ?? column.key ?? index}
row={row}
column={{
dataKey: column.dataKey,
Expand All @@ -55,9 +55,19 @@ TableFooterRow.propTypes = {
compact: PropTypes.bool.isRequired,
};

const TableFoot = ({ columns, rows, keyField, loading, compact }) => (
<tfoot>{renderRows(rows, columns, keyField, loading, compact)}</tfoot>
);
const TableFoot = ({
columns,
rows,
keyField,
loading,
compact,
}: {
columns: ColumnType[];
rows: RowType[];
keyField?: string;
loading?: boolean;
compact?: boolean;
}) => <tfoot>{renderRows(rows, columns, keyField, loading, compact)}</tfoot>;

TableFoot.propTypes = {
columns: columnsPropType.isRequired,
Expand Down
2 changes: 1 addition & 1 deletion src/Table/TableHead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const TableHead: React.FC<TableHeadProps> = ({ columns, compact, sticky }) => {
allColumns.map((column) => (
<StyledTh
scope="col"
key={column.dataKey}
key={column.dataKey ?? column.key ?? index}
width={column.width}
compact={compact}
data-testid="table-head"
Expand Down

0 comments on commit 36e9db3

Please sign in to comment.