import { Key, ReactNode, TdHTMLAttributes } from 'react';
import { CSSObject } from '@emotion/styled';
import type { VirtualItem } from '@tanstack/react-virtual';
import { CSSValueWithLength } from '../../styles';
export type SortDirection = 'asc' | 'desc' | 'default';
export type ColumnAlign = 'left' | 'right' | 'center';
export type Scroll = {
x?: CSSValueWithLength;
y?: CSSValueWithLength;
};
export type CellValue = Value;
export type CellAttributes = {
hidden?: boolean;
/**
* 테이블 셀의 disabled 상태를 제어합니다.
* - row.disabled가 true인 경우, cellAttributes에서 disabled: false를 반환하면 해당 셀만 활성화됩니다.
* - row.disabled가 false인 경우, cellAttributes에서 disabled: true를 반환하면 해당 셀만 비활성화됩니다.
* - cellAttributes에서 disabled를 반환하지 않으면 row.disabled 값에 따라 결정됩니다.
*/
disabled?: boolean;
style?: CSSObject;
};
export type RowSelectState = ((row: DataType, index: number) => boolean) | Array | null;
export type CellAttributesProps = (row: DataType, index?: number, rows?: DataTableRowsType) => Pick, 'rowSpan' | 'colSpan'> & CellAttributes;
export type DataTableSelectableRows = boolean | {
cellAttributes?: CellAttributesProps;
};
export type DataTableRenderExpandedRow = (row: DataType, index: number) => ReactNode | null;
export type CellProps = ({ row, value, index, rows, }: {
row: DataType;
value: CellValue;
index: number;
rows: DataTableRowsType;
}) => ReactNode;
export type CellSize = 'small' | 'medium' | 'large';
export type DataTableColumnBase = {
/**
* 테이블 컬럼 텍스트
*/
text: ReactNode;
/**
* Column Sort 여부
*/
sortable?: boolean;
/**
* Column 너비를 지정할 수 있습니다.
* - minWidth 속성없이 사용된다면 자동으로 해당 width값으로 minWidth 처리됩니다.
* - table-layout 'auto'일 경우
* - 모든 셀의 너비가 고정된다면 모든 셀의 너비를 더한 값보다 브라우저 크기가 커질때 동적으로 변할 수 있습니다.
* - 특정 셀의 너비를 필수로 고정해야한다면 모든 셀의 너비를 지정하지 않고 고정할 셀만 너비를 지정하세요. 너비를 지정하지 않은 셀들은 가변으로, 지정된 셀은 너비를 보장할 수 있습니다.
*/
width?: number;
/**
* Column 최소 너비를 지정할 수 있습니다.
* - width 속성없이 minWidth만 사용된다면 가변 너비를 가지되 최소 너비를 보장합니다.
* - width 속성과 함께 사용된다면 해당 width값으로 너비를 기본을 가지되 작아질 경우 minWidth 최소 너비를 보장합니다.
*/
minWidth?: number;
/**
* 가로 스크롤 발생시 Column 고정 여부
* - true일 경우 width값 지정이 필수 입니다.
* - columnGroup이 있을 경우 적용되지 않습니다.
*/
fixed?: boolean;
/**
* 컬럼 정렬을 지정할 수 있습니다.
* @default 'left'
*/
align?: ColumnAlign;
/**
* 셀 정렬을 지정할 수 있습니다.
* - 지정하지 않을 경우 컬럼 정렬값을 따릅니다.
* @default 'left'
*/
cellAlign?: ColumnAlign;
/**
* 노출과 순서 조정 불가 여부
*/
disabled?: boolean;
};
export interface DataTableColumnType extends DataTableColumnBase {
id: Extract;
/**
* 테이블 셀의 속성을 지정할 수 있습니다.
* - (row: DataType, index: number, rows: DataTableRowsType) => CellAttributes & { rowSpan?: number, colSpan?: number }
*/
cellAttributes?: CellAttributesProps;
/**
* 테이블 컬럼에 해당하는 셀 렌더를 지정할 수 있습니다.
* - 해당 컬럼의 row, cell value, index를 받을 수 있습니다.
* - 반환값은 ReactNode여야 합니다.
* - ({ row, value, index }: { row: DataType; value: CellValue; index: number }) => ReactNode
*/
cell?: CellProps;
/**
* 테이블 컬럼의 셀의 Stack wrapper 렌더링 여부를 지정합니다.
* false로 설정하면 Stack wrapper가 렌더링되지 않습니다.
* true로 설정하면 Stack wrapper가 렌더링됩니다.
* 기본 값은 true입니다. 추후에 wrapper가 필요 없어져서 제거하게 될 경우를 대비해 Stack이
* 꼭 필요한 경우에는 true를 명시적으로 지정해주세요.
*/
wrapper?: boolean;
}
export interface DataTableColumnGroupType extends Omit, 'id'> {
columnGroup: DataTableColumnsType;
}
export type DataTableColumnsType = Array | DataTableColumnGroupType>;
export type DataTableRowType = DataType & {
/**
* @deprecated
* rowSelectionKeyExtractor를 사용을 권장합니다.
*/
key?: Key;
selectable?: boolean;
/**
* 테이블 로우의 disabled 여부를 지정합니다. selectable 보다 우선합니다.
*/
disabled?: boolean;
expandable?: boolean;
};
export type DataTableRowsType = Array>;
export type DataTableMode = 'container' | 'page';
export interface DataTableStickyHeaderConfig {
/** sticky header 모드. 'page'는 viewport에 고정되는 floating header. */
mode: 'page';
/**
* page sticky header의 상단 고정 offset(px). 예: 고정 상단바 높이.
* @default 0
*/
offset?: number;
}
export interface DataTableProps {
className?: string;
/**
* 테이블 컬럼 목록
* - useMemo를 통한 메모이제이션된 값을 권장합니다.
*/
columns: DataTableColumnsType;
/**
* 테이블 로우 목록
* - useMemo를 통한 메모이제이션된 값을 권장합니다.
*/
rows: DataTableRowsType;
/**
* 테이블 스크롤 영역 너비/높이를 지정할 수 있습니다.
* - { x: number | string, y: number | string }
* - x: 가로 스크롤을 설정하고 스크롤 영역의 너비를 지정합니다.
* - y: 세로 스크롤을 설정하고 스크롤 영역의 높이를 지정합니다.
* - stickyHeader를 객체로 전달한 page mode에서는 viewport 스크롤을 기준으로 하므로 y는 무시됩니다.
* - stickyHeader를 객체로 전달한 page mode에서도 x는 floating header 동기화에 사용됩니다.
* - x 사용시 table-layout이 fixed 처리됩니다.(기본 auto)
* - y 기본값은 600px입니다.
*/
scroll?: Scroll;
/**
* 테이블 sticky header 설정입니다.
*
* true(기본): 테이블 박스 내부 스크롤에 헤더를 고정합니다.
* false: sticky header를 비활성화합니다.
* { mode: 'page' }: viewport 스크롤 기준 floating header를 렌더링합니다. offset으로 상단 여백을 지정합니다.
*
* @default true
*/
stickyHeader?: boolean | DataTableStickyHeaderConfig;
/**
* 테이블 Loading 여부
* @default false
*/
loading?: boolean;
/**
* Sort 대상 컬럼 아이디
*/
sortBy?: string;
sortDirection?: SortDirection;
/**
* Row Selection 사용 유무
* - true거나 값이 지정된 경우 각 테이블 로우는 고유 key가 존재해야 합니다.
* - cellAttributes가 지정된 경우 체크박스 셀을 렌더링할 때 해당 함수를 호출합니다.
*/
selectableRows?: DataTableSelectableRows;
/**
* Row 클릭으로 Selection 사용 유무
* - 먼저 selectableRows가 true여야 하며, Row 클릭으로도 선택/해제가 가능합니다.
* - 해당 옵션 사용시 ROW 내부에 버튼, 링크 등 추가적인 클릭이벤트가 있을 경우 stopPropagation 처리가 필요합니다.
*/
clickableRows?: boolean;
/**
* Row 선택 상태 정보
* - 이하 두가지 타입으로 로우 셀렉 상태를 받습니다.
* - ((row: DataType) => boolean): 함수형태로 전달할 경우 해당 조건에 일치하는 row 목록 선택 상태가 업데이트됩니다.
* - Key[]: 키목록으로 전달할 경우 해당 키를 포함하는 row 목록 선택 상태가 업데이트됩니다.
*/
rowSelection?: RowSelectState;
/**
* Row All Select 사용 유무
* - selectableRows true가 선행되어야 하며 column의 전체 선택 체크박스 disabled 여부를 선택할 수 있습니다.
*/
hideSelectAll?: boolean;
/**
* 자동 Row 전체 select 상태 초기화 여부
* - rows 변경시 자동으로 row 선택이 초기화됩니다.
* @default true
*/
autoResetRowSelection?: boolean;
/**
* Table 데이터가 없을 경우 노출되는 텍스트를 지정할 수 있습니다.
* @default '데이터가 없습니다'
*/
noDataText?: ReactNode;
/**
* Table 데이터가 없을 경우 노출되는 텍스트의 상하 여백입니다.
* @default 120
*/
noDataPadding?: number;
/**
* 테이블의 컬럼 리사이즈 활성화 여부
* - width값 지정된 컬럼은 resize가 불가합니다.
* - table-layout이 fixed 처리됩니다.(기본 auto)
* @default false
*/
resize?: boolean;
/**
* 테이블 로우 호버 스타일 사용 유무
* - column cellAttributes 스타일 커스텀시 로우 전체 호버 스타일을 제한할 수 있습니다.
* - rowspan to highlight all relevant rows 이슈 처리전 임시 props으로 사용할 수 있습니다.
* @default true
*/
cellHoverStyle?: boolean;
/**
* 테이블 로우 disabled 스타일 사용 유무
* - column cellAttributes 스타일 커스텀시 로우 전체 disabled 스타일을 제한할 수 있습니다.
* @default true
*/
cellDisabledStyle?: boolean;
/**
* expandableButton 노출 유무
* @default true
*/
expandableButton?: boolean;
/**
* 테이블 로우 확장 상태
* - 각 테이블 로우에 고유 key가 존재해야 합니다.
*/
rowExpansion?: RowSelectState;
/**
* 확장된 로우의 키 리스트를 전달합니다.
*/
onExpandRows?: (expandedRowKeys: Key[]) => void;
/**
* 열 하위에 확장된 Row를 렌더링합니다.
* - 각 테이블 로우에 고유 key가 존재해야 합니다.
* - row의 expanded 값으로 row의 확장 여부를 전달합니다.
*/
renderExpandedRow?: DataTableRenderExpandedRow;
/**
* 각 row의 하단에 구분자를 추가할 수 있습니다.
* - (row, index) => true 이면 해당 row 하단에 구분자가 추가됩니다.
*/
dividerRows?: (row: DataType, index: number) => boolean;
/**
* Row 배경색을 지정하는 함수 혹은 컬러값을 전달합니다.
* hover는 auto code 정책을 따릅니다.
*/
rowColor?: (row: DataType, index: number) => (string | undefined) | string;
/**
* Row 고유 key를 지정하는 함수를 전달합니다.
* 지정되지 않은 경우 index를 사용합니다.
*/
rowKeyExtractor?: (row: DataType, index: number) => Key;
/**
* Row의 기능(selectable, expandable)의 동작하는 key를 지정하는 함수를 전달합니다.
* 지정되지 않은 경우 row.key를 사용합니다.
*/
rowSelectionKeyExtractor?: (row: DataType, index: number) => Key;
/**
* Sort 이벤트, 대상 Column 아이디를 전달합니다.
*/
onSortBy?: (sortBy: string) => void;
/**
* Select 이벤트, 선택된 rows, rows key 리스트를 전달합니다.
*/
onSelectRows?: (selectedRowKeys: Key[], selectedRows: DataTableRowsType) => void;
/**
* 테이블 컨테이너 ref를 set하기 위한 함수
*/
setContainerRef?: (node: HTMLDivElement | null) => void;
/**
* @internal
* 가상화 테이블에 사용되는 props입니다. 직접 사용하지 말아주세요.
* 가상화된 테이블을 사용하기 위해서는 VirtualizedDataTable를 사용해주세요.
*/
virtualizedProps?: {
virtualizedItems: VirtualItem[];
beforePadding: number;
afterPadding: number;
};
}
export interface DataTableState {
allSelected?: boolean;
selectedRows?: Map>;
emitSelectedEvent?: boolean;
autoResetRowSelection?: boolean;
expandedRows?: Key[];
emitExpandedEvent?: boolean;
}
export interface DataTableRowSelectionRecord {
row: DataTableRowType;
index: number;
key: Key;
}
export interface SelectRowsAction {
type: 'SELECT_ROWS';
rows: DataTableRowsType;
}
export interface SelectRowAction {
type: 'SELECT_ROW';
rows: DataTableRowsType;
row: DataTableRowType;
index: number;
selected: boolean;
}
export interface SelectControlledRowAction {
type: 'SELECT_CONTROLLED_ROW';
controlledRows: {
row: DataTableRowType;
index: number;
}[];
rows: DataTableRowsType;
}
export interface ResetSelectRowsAction {
type: 'RESET_SELECTED_ROWS';
}
export interface CheckAllSelectedRowsAction {
type: 'CHECK_ALL_SELECTED_ROWS';
rows: DataTableRowsType;
}
export interface ExpandedRowAction {
type: 'EXPAND_ROW';
row: DataTableRowType;
index: number;
expanded: boolean;
}
export interface ExpandControlledRowAction {
type: 'EXPAND_CONTROLLED_ROW';
expandedRows: {
row: DataTableRowType;
index: number;
}[];
rows: DataTableRowsType;
}
export type DataTableAction = SelectRowsAction | SelectRowAction | SelectControlledRowAction | ResetSelectRowsAction | CheckAllSelectedRowsAction | ExpandedRowAction | ExpandControlledRowAction;