Skip to content

Commit

Permalink
Merge pull request #212 from Mezzanine-UI/feat/table-refactor
Browse files Browse the repository at this point in the history
<Table /> refactor
  • Loading branch information
travor20814 authored Dec 6, 2023
2 parents 8a72938 + b0a927e commit 80b024c
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 52 deletions.
49 changes: 44 additions & 5 deletions packages/core/src/table/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ export interface TableDataSourceWithID extends TableRecord<unknown> {

export type TableDataSource = TableDataSourceWithKey | TableDataSourceWithID;

export type TableColumn<SourceType> = {
dataIndex: string;
export interface TableColumnBase<SourceType> {
/** Column's primary key */
key?: string;
dataIndex?: string;
render?(source: SourceType, index: number, column: ExpandedTableColumn): any;
title?: string;
render?(source: SourceType, index: number, column: TableColumn<SourceType>): any;
renderTitle?(classes: typeof tableClasses): any;
renderTooltipTitle?(source: SourceType): string;
// == Custom column style ==
Expand All @@ -64,7 +66,11 @@ export type TableColumn<SourceType> = {
width?: number;
// == Feature sorting ==
sorter?(a: any, b: any): number;
onSorted?(dataIndex: string, sortedType: string): void;
/**
* The `key` is automatically generated by mzn. If you need a more specific key,
* please provide `key` within the column.
*/
onSorted?(key: string, sortedType: string): void;
// == Feature editing ==
editable?: boolean;
setCellProps?(record: SourceType): TableRecord<unknown>;
Expand All @@ -73,7 +79,40 @@ export type TableColumn<SourceType> = {
ellipsis?: boolean;
/** force display tooltip whenever content is hovered */
forceShownTooltipWhenHovered?: boolean;
};
}

export interface TableColumnDataIndexAndTitle<SourceType> extends TableColumnBase<SourceType> {
dataIndex: string;
render?: never;
title: string;
renderTitle?: never;
}

export interface TableColumnDataIndexAndRenderTitle<SourceType> extends TableColumnBase<SourceType> {
dataIndex: string;
render?: never;
title?: never;
renderTitle(classes: typeof tableClasses): any;
}

export interface TableColumnRenderAndTitle<SourceType> extends TableColumnBase<SourceType> {
dataIndex?: never;
render(source: SourceType, index: number, column: ExpandedTableColumn): any;
title: string;
renderTitle?: never;
}

export interface TableColumnRenderAndRenderTitle<SourceType> extends TableColumnBase<SourceType> {
dataIndex?: never;
render(source: SourceType, index: number, column: ExpandedTableColumn): any;
title?: never;
renderTitle(classes: typeof tableClasses): any;
}

export type TableColumn<SourceType> = TableColumnDataIndexAndTitle<SourceType>
| TableColumnDataIndexAndRenderTitle<SourceType>
| TableColumnRenderAndTitle<SourceType>
| TableColumnRenderAndRenderTitle<SourceType>;

export type ExpandedTableColumn = Omit<TableColumn<TableRecord<unknown>>,
'title' |
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/Table/Table.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const defaultSources: DataType[] = [{
}];

const defaultColumns: TableColumn<DataType>[] = [{
key: 'foo',
dataIndex: 'foo',
title: 'foo',
}];
Expand Down
11 changes: 6 additions & 5 deletions packages/react/src/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,19 @@ const columns: TableColumn<DataType>[] = [{
return -1;
},
// eslint-disable-next-line no-console
onSorted: (dataIndex, sortedType) => { console.log(dataIndex, sortedType); },
onSorted: (key, sortedType) => { console.log(key, sortedType); },
}, {
title: 'Address',
dataIndex: 'address',
}, {
key: 'age-column',
title: 'Age',
dataIndex: 'age',
renderTooltipTitle: (source) => `${source.name} is age ${source.age}.`,
forceShownTooltipWhenHovered: true,
sorter: (a: number, b: number) => b - a,
// eslint-disable-next-line no-console
onSorted: (dataIndex, sortedType) => { console.log(dataIndex, sortedType); },
onSorted: (key, sortedType) => { console.log(key, sortedType); },
width: 80,
}, {
title: 'Tel',
Expand Down Expand Up @@ -474,7 +475,6 @@ export const WithActions = () => {
title: 'Age',
dataIndex: 'age',
}, {
dataIndex: '',
renderTitle: renderHeaderActions,
render: renderRowActions,
// styling
Expand Down Expand Up @@ -616,7 +616,7 @@ export const WithRefresh = () => {
export const ExpandedWithString = () => {
const customizedColumns: TableColumn<DataType>[] = [{
title: 'Name',
dataIndex: 'name',
render: (source) => source.key,
}, {
title: 'Address',
dataIndex: 'address',
Expand Down Expand Up @@ -790,7 +790,7 @@ export const Editable = () => {
</Select>
) : (
<Input
defaultValue={get(rowData, dataIndex) as string}
defaultValue={dataIndex ? get(rowData, dataIndex) as string : ''}
fullWidth
inputProps={{
type: inputType,
Expand Down Expand Up @@ -845,6 +845,7 @@ export const Editable = () => {
/** actions column */
return {
...column,
dataIndex: undefined,
render: renderRowActions,
};
}
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/Table/TableBody.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const defaultSources: DataType[] = [{
}];

const defaultColumns: TableColumn<DataType>[] = [{
key: 'foo',
dataIndex: 'foo',
title: 'foo',
}];
Expand Down
12 changes: 11 additions & 1 deletion packages/react/src/Table/TableBodyRow.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,16 @@ describe('<TableBodyRow />', () => {

it('ellipsis control should set to true by default, and false when no data/disabled', () => {
const columns: TableColumn<DataType>[] = [{
key: 'name',
dataIndex: 'name',
title: 'name',
}, {
key: 'not-existed',
dataIndex: 'not-existed',
title: 'bar',
ellipsis: true,
}, {
key: 'name',
dataIndex: 'name',
title: 'foo',
ellipsis: false,
Expand Down Expand Up @@ -118,6 +121,7 @@ describe('<TableBodyRow />', () => {

describe('columns are given', () => {
const columns: TableColumn<DataType>[] = [{
key: 'name',
dataIndex: 'name',
title: 'foo',
headerClassName: undefined,
Expand All @@ -127,11 +131,12 @@ describe('<TableBodyRow />', () => {
width: 80,
align: 'center',
}, {
dataIndex: 'bar',
key: 'bar',
title: 'bar',
align: 'start',
render: () => 'bar-render',
}, {
key: 'foo.bar',
dataIndex: 'foo.bar',
title: 'foo',
}];
Expand Down Expand Up @@ -301,8 +306,10 @@ describe('<TableBodyRow />', () => {
name: 'bar',
}],
columns: [{
key: 'name',
dataIndex: 'name',
}, {
key: 'name2',
dataIndex: 'name',
}],
}),
Expand Down Expand Up @@ -351,8 +358,10 @@ describe('<TableBodyRow />', () => {
expandedRowRender: () => ({
dataSource: [],
columns: [{
key: 'name',
dataIndex: 'name',
}, {
key: 'name2',
dataIndex: 'name',
}],
}),
Expand Down Expand Up @@ -391,6 +400,7 @@ describe('<TableBodyRow />', () => {
describe('exceptions handle', () => {
it('column.width/column.align not given', () => {
const columns: TableColumn<DataType>[] = [{
key: 'name',
dataIndex: 'name',
title: 'name',
}];
Expand Down
9 changes: 5 additions & 4 deletions packages/react/src/Table/TableBodyRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,15 @@ const TableBodyRow = forwardRef<HTMLTableRowElement, TableBodyRowProps>(
</td>
) : null}
{(columns ?? []).map((column: TableColumn<TableRecord<unknown>>, idx) => {
const ellipsis = !!(get(rowData, column.dataIndex)) && (column.ellipsis ?? true);
const autoGrabData = column.dataIndex ? get(rowData, column.dataIndex) : '';
const ellipsis = !!(autoGrabData) && (column.ellipsis ?? true);
const tooltipTitle = (
column.renderTooltipTitle?.(rowData) ?? get(rowData, column.dataIndex)
column.renderTooltipTitle?.(rowData) ?? autoGrabData
) as (string | number);

return (
<td
key={`${column.dataIndex}-${column.title}-${(rowData.key || rowData.id)}`}
key={`${idx + 1}-${(rowData.key || rowData.id)}`}
className={cx(
classes.bodyRowCellWrapper,
isFirstColumnShouldSticky && idx === 0 && classes.bodyRowCellWrapperFixed,
Expand All @@ -173,7 +174,7 @@ const TableBodyRow = forwardRef<HTMLTableRowElement, TableBodyRowProps>(
rowData,
rowIndex,
column,
) || get(rowData, column.dataIndex)}
) || autoGrabData}
</TableCell>
</TableEditRenderWrapper>
</td>
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/Table/TableContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface RowSelectionContext extends Pick<TableRowSelection, 'actions'>

/** typeof sorting */
export interface SortingContext {
onSort(v: Pick<TableColumn<TableRecord<unknown>>, 'dataIndex' | 'sorter' | 'onSorted'>): void;
onSort(v: Pick<TableColumn<TableRecord<unknown>>, 'key' | 'dataIndex' | 'sorter' | 'onSorted'>): void;
onResetAll(): void;
sortedOn: string;
sortedType: string;
Expand Down
7 changes: 6 additions & 1 deletion packages/react/src/Table/TableExpandedTable.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ const dataSource: DataType[] = [{
}];

const columns: TableColumn<DataType>[] = [{
key: 'name',
dataIndex: 'name',
title: 'name',
width: 80,
align: 'center',
}, {
key: 'age',
dataIndex: 'age',
title: 'foo',
ellipsis: false,
Expand All @@ -49,9 +51,12 @@ const expandedSources: DataType[] = [{
}];

const expandedColumns: TableColumn<DataType>[] = [{
key: 'name',
dataIndex: 'name',
title: '',
}, {
dataIndex: 'name',
key: 'name',
title: '',
render: () => 'render name',
}];

Expand Down
14 changes: 6 additions & 8 deletions packages/react/src/Table/TableExpandedTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import {
import {
tableClasses as classes,
TableDataSource,
TableColumn,
ExpandedTableColumn,
TableRecord,
getColumnStyle,
getCellStyle,
} from '@mezzanine-ui/core/table';
Expand Down Expand Up @@ -50,16 +48,16 @@ const TableExpandedTable = forwardRef<HTMLDivElement, TableExpandedTableProps>(f
>
<TableExpandable showIcon={false} />
{((renderedExpandedContent.columns || columns) ?? [])
.map((column: TableColumn<TableRecord<unknown>>, index: number) => {
const ellipsis = !!(get(source, column.dataIndex)) && (column.ellipsis ?? true);
.map((column: ExpandedTableColumn, index: number) => {
const autoGrabData = column.dataIndex ? get(source, column.dataIndex) : '';
const ellipsis = !!(autoGrabData) && (column.ellipsis ?? true);
const tooltipTitle = (
column.renderTooltipTitle?.(source) ?? get(source, column.dataIndex)
column.renderTooltipTitle?.(source) ?? autoGrabData
) as (string | number);

return (
<div
// eslint-disable-next-line react/no-array-index-key
key={`${column.dataIndex}-${index}`}
key={`${index + 1}`}
className={cx(
classes.bodyRowCellWrapper,
column.bodyClassName,
Expand All @@ -76,7 +74,7 @@ const TableExpandedTable = forwardRef<HTMLDivElement, TableExpandedTableProps>(f
source,
sourceIndex,
column,
) || get(source, column.dataIndex)}
) || autoGrabData}
</TableCell>
</div>
);
Expand Down
4 changes: 3 additions & 1 deletion packages/react/src/Table/TableHeader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('<TableHeader />', () => {

describe('columns are given', () => {
const columns: TableColumn<DataType>[] = [{
key: 'foo',
dataIndex: 'foo',
title: 'foo',
headerClassName: undefined,
Expand All @@ -44,8 +45,8 @@ describe('<TableHeader />', () => {
width: 80,
align: 'center',
}, {
key: 'bar',
dataIndex: 'bar',
title: 'bar',
align: 'start',
renderTitle: () => 'bar',
sorter: () => 1,
Expand Down Expand Up @@ -158,6 +159,7 @@ describe('<TableHeader />', () => {
describe('exceptions handle', () => {
it('column.width/column.align not given', () => {
const columns: TableColumn<DataType>[] = [{
key: 'foo',
dataIndex: 'foo',
title: 'foo',
}];
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/Table/TableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const TableHeader = forwardRef<HTMLTableRowElement, NativeElementPropsWithoutKey
) : null}
{(columns ?? []).map((column: TableColumn<TableRecord<unknown>>, idx) => (
<th
key={`${column.dataIndex}-${column.title}`}
key={`${idx + 1}`}
className={cx(
classes.headerCellWrapper,
isFirstColumnShouldSticky && idx === 0 && classes.headerCellWrapperFixed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('<TableEditRenderWrapper />', () => {
}}
>
<TableEditRenderWrapper
key="edit"
dataIndex={defaultDataIndex}
rowData={defaultRowData}
setCellProps={setCellProps}
Expand Down
10 changes: 5 additions & 5 deletions packages/react/src/Table/editable/TableEditRenderWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/* eslint-disable react/jsx-no-useless-fragment */
import {
useContext,
Fragment,
} from 'react';
import { TableColumn, TableDataSource, TableRecord } from '@mezzanine-ui/core/table';
import { TableColumnBase, TableDataSource, TableRecord } from '@mezzanine-ui/core/table';
import { TableComponentContext } from '../TableContext';
import { NativeElementPropsWithoutKeyAndRef } from '../../utils/jsx-types';

export interface EditableBodyCellProps
extends
NativeElementPropsWithoutKeyAndRef<'div'>,
TableColumn<TableRecord<unknown>> {
TableColumnBase<TableRecord<unknown>> {
rowData: TableDataSource;
}

Expand Down Expand Up @@ -42,9 +42,9 @@ function TableEditRenderWrapper({
}

return (
<Fragment>
<>
{children}
</Fragment>
</>
);
}

Expand Down
Loading

0 comments on commit 80b024c

Please sign in to comment.