"use client" import * as React from "react" import { flexRender, type Table as TanstackTable } from "@tanstack/react-table" import { ChevronRight, ChevronUp } from "lucide-react" import { cn } from "@/lib/utils" import { getCommonPinningStylesWithBorder } from "@/lib/data-table" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { DataTablePagination } from "@/components/data-table/data-table-pagination" import { DataTableResizer } from "@/components/data-table/data-table-resizer" import { useAutoSizeColumns } from "@/hooks/useAutoSizeColumns" interface DataTableProps extends React.HTMLAttributes { table: TanstackTable floatingBar?: React.ReactNode | null autoSizeColumns?: boolean compact?: boolean // 컴팩트 모드 옵션 추가 } // ✅ compactStyles를 정적으로 정의 (매번 새로 생성 방지) const COMPACT_STYLES = { row: "h-7", // 행 높이 축소 cell: "py-1 px-2 text-sm", // 셀 패딩 축소 및 폰트 크기 조정 groupRow: "py-1 bg-muted/20 text-sm", // 그룹 행 패딩 축소 emptyRow: "h-16", // 데이터 없을 때 행 높이 조정 header: "py-1 px-2 text-sm", // 헤더 패딩 축소 headerHeight: "h-8", // 헤더 높이 축소 }; const NORMAL_STYLES = { row: "", cell: "", groupRow: "bg-muted/20", emptyRow: "h-24", header: "", headerHeight: "", }; /** * 멀티 그룹핑 + 그룹 토글 + 그룹 컬럼/헤더 숨김 + Indent + 리사이징 + 컴팩트 모드 */ export function DataTable({ table, floatingBar = null, autoSizeColumns = true, compact = false, // 기본값은 false로 설정 children, className, maxHeight, ...props }: DataTableProps & { maxHeight?: string | number }) { useAutoSizeColumns(table, autoSizeColumns) // ✅ compactStyles를 useMemo로 메모이제이션 const compactStyles = React.useMemo(() => compact ? COMPACT_STYLES : NORMAL_STYLES, [compact] ); const stableChildren = React.useMemo(() => { console.log("📦 DataTable children 메모이제이션됨"); return children; }, [children]); return (
{stableChildren}
{/* 테이블 헤더 */} {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { if (header.column.getIsGrouped()) { return null } return (
{header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} {header.column.getCanResize() && ( )}
) })}
))}
{/* 테이블 바디 */} {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => { // 그룹핑 헤더 Row if (row.getIsGrouped()) { const groupingColumnId = row.groupingColumnId ?? "" const groupingColumn = table.getColumn(groupingColumnId) let columnLabel = groupingColumnId if (groupingColumn) { const headerDef = groupingColumn.columnDef.meta?.excelHeader if (typeof headerDef === "string") { columnLabel = headerDef } } return ( {row.getCanExpand() && ( )} {columnLabel}: {row.getValue(groupingColumnId)} ({row.subRows.length} rows) ) } // 일반 Row return ( {row.getVisibleCells().map((cell) => { if (cell.column.getIsGrouped()) { return null } return ( {flexRender( cell.column.columnDef.cell, cell.getContext() )} ) })} ) }) ) : ( // 데이터가 없을 때 No results. )}
{/* Pagination */} {/* Floating Bar (선택된 행 있을 때) */} {table.getFilteredSelectedRowModel().rows.length > 0 && floatingBar}
) }