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;