Skip to content

Commit

Permalink
Reduced props accepted by ColumnHeader (#2287)
Browse files Browse the repository at this point in the history
  • Loading branch information
smmr-dn authored Oct 9, 2024
1 parent 3fd7ee1 commit 36a8bbd
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 76 deletions.
100 changes: 44 additions & 56 deletions packages/itwinui-react/src/core/Table/ColumnHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,80 +9,64 @@ import {
LineClamp,
SvgSortDown,
SvgSortUp,
useMergedRefs,
type PolymorphicForwardRefComponent,
} from '../../utils/index.js';
import type {
ColumnInstance,
HeaderGroup,
TableKeyedProps,
TableState,
} from '../../react-table/react-table.js';
import { SELECTION_CELL_ID } from './columns/index.js';
import { FilterToggle } from './filters/FilterToggle.js';
import { getCellStyle, getSubRowStyle, getStickyStyle } from './utils.js';
import {
getCellStyle,
getSubRowStyle,
getStickyStyle,
TableInstanceContext,
} from './utils.js';
import cx from 'classnames';

type ColumnHeaderProps<
T extends Record<string, unknown> = Record<string, unknown>,
> = TableKeyedProps & {
columnRefs: React.MutableRefObject<Record<string, HTMLDivElement>>;
column: HeaderGroup<T>;
index: number;
type ColumnHeaderProps = TableKeyedProps & {
column: HeaderGroup<Record<string, unknown>>;
areFiltersSet: boolean;
hasAnySubRows: boolean;
headers: HeaderGroup<T>[];
state: TableState<T>;
data: T[];
isResizable: boolean;
columnResizeMode: 'fit' | 'expand';
enableColumnReordering: boolean;
density: string | undefined;
visibleColumns: ColumnInstance<T>[];
columnHasExpanders: boolean;
isLast: boolean;
isTableEmpty: boolean;
};

export const ColumnHeader = <
T extends Record<string, unknown> = Record<string, unknown>,
>(
props: ColumnHeaderProps<T>,
): JSX.Element => {
export const ColumnHeader = React.forwardRef((props, forwardedRef) => {
const {
columnRefs,
column,
index,
areFiltersSet,
hasAnySubRows,
headers,
state,
data,
isResizable,
columnResizeMode,
enableColumnReordering,
density,
visibleColumns,
columnHasExpanders,
isLast,
isTableEmpty,
...rest
} = props;

const isHeaderDirectClick = React.useRef(false);
const instance = React.useContext(TableInstanceContext);

const COLUMN_MIN_WIDTHS = {
default: 72,
withExpander: 108, // expander column should be wider to accommodate the expander icon
};

const showFilterButton = (column: HeaderGroup<T>) =>
(data.length !== 0 || areFiltersSet) && column.canFilter && !!column.Filter;
const showFilterButton = (column: HeaderGroup<Record<string, unknown>>) =>
(!isTableEmpty || areFiltersSet) && column.canFilter && !!column.Filter;

const showSortButton = (column: HeaderGroup<T>) =>
data.length !== 0 && column.canSort;
const showSortButton = (column: HeaderGroup<Record<string, unknown>>) =>
!isTableEmpty && column.canSort;

const { onClick, ...restSortProps } = column.getSortByToggleProps();

const columnHasExpanders =
hasAnySubRows &&
index ===
headers.findIndex(
(c) => c.id !== SELECTION_CELL_ID, // first non-selection column is the expander column
);

if ([undefined, 0].includes(column.minWidth)) {
// override "undefined" or zero min-width with default value
column.minWidth = columnHasExpanders
Expand All @@ -107,9 +91,9 @@ export const ColumnHeader = <
column.columnClassName,
),
style: {
...getCellStyle(column, !!state.isTableResizing),
...getCellStyle(column, !!instance?.state.isTableResizing),
...(columnHasExpanders && getSubRowStyle({ density })),
...getStickyStyle(column, visibleColumns),
...getStickyStyle(column, instance?.visibleColumns ?? []),
flexWrap: 'wrap',
columnGap: 'var(--iui-size-xs)',
},
Expand All @@ -121,14 +105,16 @@ export const ColumnHeader = <
{...rest}
key={columnProps.key}
title={undefined}
ref={React.useCallback(
(el: HTMLDivElement) => {
if (el) {
columnRefs.current[column.id] = el;
column.resizeWidth = el.getBoundingClientRect().width;
}
},
[column, columnRefs],
ref={useMergedRefs(
React.useCallback(
(el?: HTMLDivElement) => {
if (el) {
column.resizeWidth = el.getBoundingClientRect().width;
}
},
[column],
),
forwardedRef,
)}
onMouseDown={() => {
isHeaderDirectClick.current = true;
Expand Down Expand Up @@ -183,7 +169,7 @@ export const ColumnHeader = <
)}
{isResizable &&
column.isResizerVisible &&
(index !== headers.length - 1 || columnResizeMode === 'expand') && (
(!isLast || columnResizeMode === 'expand') && (
<Box
{...column.getResizerProps()}
className='iui-table-resizer'
Expand All @@ -195,13 +181,15 @@ export const ColumnHeader = <
{enableColumnReordering && !column.disableReordering && (
<Box className='iui-table-reorder-bar' slot='resizers' />
)}
{column.sticky === 'left' && state.sticky.isScrolledToRight && (
<Box className='iui-table-cell-shadow-right' slot='shadows' />
)}
{column.sticky === 'right' && state.sticky.isScrolledToLeft && (
<Box className='iui-table-cell-shadow-left' slot='shadows' />
)}
{column.sticky === 'left' &&
instance?.state.sticky.isScrolledToRight && (
<Box className='iui-table-cell-shadow-right' slot='shadows' />
)}
{column.sticky === 'right' &&
instance?.state.sticky.isScrolledToLeft && (
<Box className='iui-table-cell-shadow-left' slot='shadows' />
)}
</>
</Box>
);
};
}) as PolymorphicForwardRefComponent<'div', ColumnHeaderProps>;
35 changes: 21 additions & 14 deletions packages/itwinui-react/src/core/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import type {
ActionType,
TableInstance,
Column,
ColumnInstance,
} from '../../react-table/react-table.js';
import { ProgressRadial } from '../ProgressIndicators/ProgressRadial.js';
import {
Expand All @@ -40,7 +39,7 @@ import {
useVirtualScroll,
} from '../../utils/index.js';
import type { CommonProps } from '../../utils/index.js';
import { TableColumnsContext } from './utils.js';
import { TableInstanceContext } from './utils.js';
import { TableRowMemoized } from './TableRowMemoized.js';
import type { TableFilterValue } from './filters/index.js';
import { customFilterFunctions } from './filters/customFilterFunctions.js';
Expand Down Expand Up @@ -639,7 +638,6 @@ export const Table = <
gotoPage,
setPageSize,
flatHeaders,
visibleColumns,
setGlobalFilter,
} = instance;

Expand Down Expand Up @@ -950,7 +948,9 @@ export const Table = <
}, []);

return (
<TableColumnsContext.Provider value={instance.columns as ColumnInstance[]}>
<TableInstanceContext.Provider
value={instance as TableInstance<Record<string, unknown>>}
>
<Box
ref={useMergedRefs<HTMLDivElement>(
tableRef,
Expand Down Expand Up @@ -1000,22 +1000,29 @@ export const Table = <
{headerGroup.headers.map((column, index) => {
const dragAndDropProps = column.getDragAndDropProps();
return (
<ColumnHeader<T>
<ColumnHeader
{...dragAndDropProps}
key={dragAndDropProps.key || column.id || index}
columnRefs={columnRefs}
column={column}
index={index}
column={column as HeaderGroup<Record<string, unknown>>}
areFiltersSet={areFiltersSet}
hasAnySubRows={hasAnySubRows}
headers={headerGroup.headers}
state={state}
data={data}
columnHasExpanders={
hasAnySubRows &&
index ===
headerGroup.headers.findIndex(
(c) => c.id !== SELECTION_CELL_ID, // first non-selection column is the expander column
)
}
isLast={index === headerGroup.headers.length - 1}
isTableEmpty={data.length === 0}
isResizable={isResizable}
columnResizeMode={columnResizeMode}
enableColumnReordering={enableColumnReordering}
density={density}
visibleColumns={visibleColumns}
ref={(el) => {
if (el) {
columnRefs.current[column.id] = el;
}
}}
/>
);
})}
Expand Down Expand Up @@ -1115,7 +1122,7 @@ export const Table = <
)}
{paginatorRenderer?.(paginatorRendererProps)}
</Box>
</TableColumnsContext.Provider>
</TableInstanceContext.Provider>
);
};
if (process.env.NODE_ENV === 'development') {
Expand Down
8 changes: 4 additions & 4 deletions packages/itwinui-react/src/core/Table/cells/DefaultCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { defaultColumn } from 'react-table';
import type { CellRendererProps } from '../../../react-table/react-table.js';
import cx from 'classnames';
import { Box, LineClamp, ShadowRoot } from '../../../utils/index.js';
import { TableColumnsContext } from '../utils.js';
import { TableInstanceContext } from '../utils.js';

export type DefaultCellProps<T extends Record<string, unknown>> = {
/**
Expand Down Expand Up @@ -46,12 +46,12 @@ export type DefaultCellProps<T extends Record<string, unknown>> = {
export const DefaultCell = <T extends Record<string, unknown>>(
props: DefaultCellProps<T>,
) => {
const instanceColumns = React.useContext(TableColumnsContext);
const instance = React.useContext(TableInstanceContext);
const isCustomCell = React.useMemo(
() =>
instanceColumns.find(({ id }) => props.cellProps.column.id === id)
instance?.columns.find(({ id }) => props.cellProps.column.id === id)
?.Cell !== defaultColumn.Cell,
[instanceColumns, props.cellProps.column.id],
[instance, props.cellProps.column.id],
);

const {
Expand Down
9 changes: 7 additions & 2 deletions packages/itwinui-react/src/core/Table/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import type { ColumnInstance } from '../../react-table/react-table.js';
import type {
ColumnInstance,
TableInstance,
} from '../../react-table/react-table.js';

export const getCellStyle = <T extends Record<string, unknown>>(
column: ColumnInstance<T>,
Expand Down Expand Up @@ -82,4 +85,6 @@ export const getSubRowStyle = ({ density = 'default', depth = 1 }) => {
} satisfies React.CSSProperties;
};

export const TableColumnsContext = React.createContext<ColumnInstance[]>([]);
export const TableInstanceContext = React.createContext<
TableInstance<Record<string, unknown>> | undefined
>(undefined);

0 comments on commit 36a8bbd

Please sign in to comment.