From 36e9db3a7f3f2b275f49240651053f8851ee538a Mon Sep 17 00:00:00 2001 From: Haider Alshamma Date: Mon, 30 Oct 2023 11:47:08 -0400 Subject: [PATCH] fix: add a key prop for the table column 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. --- src/Table/BaseTable.story.tsx | 5 +++-- src/Table/Table.story.tsx | 3 +-- src/Table/Table.types.ts | 31 +++++++++++++++++-------------- src/Table/TableBody.tsx | 12 +++++++++--- src/Table/TableFoot.tsx | 20 +++++++++++++++----- src/Table/TableHead.tsx | 2 +- 6 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/Table/BaseTable.story.tsx b/src/Table/BaseTable.story.tsx index bc8a0b56a..5ef729655 100644 --- a/src/Table/BaseTable.story.tsx +++ b/src/Table/BaseTable.story.tsx @@ -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 }) => { @@ -29,7 +30,7 @@ const dropdownCellRenderer = ({ cellData }) => ( ); -const columns = [ +const columns: ColumnType[] = [ { label: "Date", dataKey: "date" }, { label: "Expected Quantity", dataKey: "expectedQuantity" }, { label: "Actual Quantity", dataKey: "actualQuantity", align: "right" }, @@ -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" }, diff --git a/src/Table/Table.story.tsx b/src/Table/Table.story.tsx index 1dcb9b03b..7166fcd2d 100644 --- a/src/Table/Table.story.tsx +++ b/src/Table/Table.story.tsx @@ -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"; @@ -50,7 +49,7 @@ const columnsWithEverything = [ { label: "Note", dataKey: "note", width: "45%" }, { label: "", - dataKey: "actions", + key: "actions", width: "5%", cellRenderer: dropdownCellRenderer, }, diff --git a/src/Table/Table.types.ts b/src/Table/Table.types.ts index 6b38c109b..85e8f47e9 100644 --- a/src/Table/Table.types.ts +++ b/src/Table/Table.types.ts @@ -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, diff --git a/src/Table/TableBody.tsx b/src/Table/TableBody.tsx index b6680847d..8be0c1242 100644 --- a/src/Table/TableBody.tsx +++ b/src/Table/TableBody.tsx @@ -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`, @@ -64,8 +64,14 @@ const TableBodyRow = ({ onMouseEnter, }: TableBodyRowProps) => { const renderAllCells = () => - columns.map((column) => ( - + columns.map((column, index) => ( + )); return ( <> diff --git a/src/Table/TableFoot.tsx b/src/Table/TableFoot.tsx index 99d56c086..832681981 100644 --- a/src/Table/TableFoot.tsx +++ b/src/Table/TableFoot.tsx @@ -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": { @@ -31,7 +31,7 @@ const TableFooterRow = ({ row, columns, loading, compact }) => { ) : ( !loading && ( ( - {renderRows(rows, columns, keyField, loading, compact)} -); +const TableFoot = ({ + columns, + rows, + keyField, + loading, + compact, +}: { + columns: ColumnType[]; + rows: RowType[]; + keyField?: string; + loading?: boolean; + compact?: boolean; +}) => {renderRows(rows, columns, keyField, loading, compact)}; TableFoot.propTypes = { columns: columnsPropType.isRequired, diff --git a/src/Table/TableHead.tsx b/src/Table/TableHead.tsx index d492764c7..c8cd4063b 100644 --- a/src/Table/TableHead.tsx +++ b/src/Table/TableHead.tsx @@ -23,7 +23,7 @@ const TableHead: React.FC = ({ columns, compact, sticky }) => { allColumns.map((column) => (