diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-01 13:52:21 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-01 13:52:21 +0000 |
| commit | bac0228d21b7195065e9cddcc327ae33659c7bcc (patch) | |
| tree | 8f3016ae4533c8706d0c00a605d9b1d41968c2bc /components/client-data-table/data-table.tsx | |
| parent | 2fdce8d7a57c792bba0ac36fa554dca9c9cc31e3 (diff) | |
(대표님) 20250601까지 작업사항
Diffstat (limited to 'components/client-data-table/data-table.tsx')
| -rw-r--r-- | components/client-data-table/data-table.tsx | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/components/client-data-table/data-table.tsx b/components/client-data-table/data-table.tsx index b7851bb8..675fe192 100644 --- a/components/client-data-table/data-table.tsx +++ b/components/client-data-table/data-table.tsx @@ -27,7 +27,7 @@ import { TableHeader, TableRow, } from "@/components/ui/table" -import { getCommonPinningStyles } from "@/lib/data-table" +import { getCommonPinningStylesWithBorder } from "@/lib/data-table" import { ChevronRight, ChevronUp } from "lucide-react" import { ClientDataTableAdvancedToolbar } from "./data-table-toolbar" @@ -45,6 +45,8 @@ interface DataTableProps<TData, TValue> { maxHeight?: string | number /** 추가로 표시할 버튼/컴포넌트 */ children?: React.ReactNode + /** 선택 상태 초기화 트리거 */ + clearSelection?: boolean } export function ClientDataTable<TData, TValue>({ @@ -55,7 +57,8 @@ export function ClientDataTable<TData, TValue>({ compact = true, // 기본값 true children, maxHeight, - onSelectedRowsChange + onSelectedRowsChange, + clearSelection }: DataTableProps<TData, TValue>) { // (1) React Table 상태 @@ -66,10 +69,13 @@ export function ClientDataTable<TData, TValue>({ const [grouping, setGrouping] = React.useState<string[]>([]) const [columnSizing, setColumnSizing] = React.useState<ColumnSizingState>({}) const [columnPinning, setColumnPinning] = React.useState<ColumnPinningState>({ - left: ["TAG_NO", "TAG_DESC"], + left: ["select","TAG_NO", "TAG_DESC", "status"], right: ["update", 'actions'], }) + // 🎯 스크롤 상태 감지 추가 + const [isScrolled, setIsScrolled] = React.useState(false) + const table = useReactTable({ data, columns, @@ -113,6 +119,48 @@ export function ClientDataTable<TData, TValue>({ onSelectedRowsChange(selectedRows) }, [rowSelection, table, onSelectedRowsChange]) + // clearSelection prop이 변경되면 선택 상태 초기화 + React.useEffect(() => { + setRowSelection({}) + }, [clearSelection]) + + // 🎯 스크롤 핸들러 추가 + const handleScroll = (e: React.UIEvent<HTMLDivElement>) => { + const scrollLeft = e.currentTarget.scrollLeft + setIsScrolled(scrollLeft > 0) + } + + // 🎯 동적 핀 스타일 함수 (width 중복 제거) + const getPinnedStyle = (column: any, isHeader: boolean = false) => { + const baseStyle = getCommonPinningStylesWithBorder({ column }) + const pinnedSide = column.getIsPinned() + + // width를 제외한 나머지 스타일만 반환 + const { width, ...restBaseStyle } = baseStyle + + return { + ...restBaseStyle, + // 헤더는 핀 여부와 관계없이 항상 배경 유지 (sticky로 고정되어 있기 때문) + ...(isHeader && { + background: "hsl(var(--background))", + transition: "none", + }), + // 바디 셀은 핀된 경우에만 스크롤 상태에 따라 동적 변경 + ...(!isHeader && pinnedSide && { + background: isScrolled + ? "hsl(var(--background))" + : "transparent", + transition: "background-color 0.15s ease-out", + }), + } + } + + // 🎯 테이블 총 너비 계산 + const getTableWidth = React.useCallback(() => { + const totalSize = table.getCenterTotalSize() + table.getLeftTotalSize() + table.getRightTotalSize() + return Math.max(totalSize, 800) // 최소 800px 보장 + }, [table]) + // 컴팩트 모드를 위한 클래스 정의 const compactStyles = compact ? { row: "h-7", // 행 높이 축소 @@ -143,9 +191,17 @@ export function ClientDataTable<TData, TValue>({ </ClientDataTableAdvancedToolbar> <div className="rounded-md border"> - <div className="overflow-auto" style={{ maxHeight: maxHeight || '34rem' }} > + <div + className="overflow-auto" + style={{ maxHeight: maxHeight || '34rem' }} + onScroll={handleScroll} // 🎯 스크롤 이벤트 핸들러 추가 + > <UiTable - className="[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10 table-fixed" + className="[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10" + style={{ + width: getTableWidth(), // 🎯 동적 너비 계산 + minWidth: '100%' + }} > <TableHeader> {table.getHeaderGroups().map((headerGroup) => ( @@ -163,8 +219,8 @@ export function ClientDataTable<TData, TValue>({ data-column-id={header.column.id} className={compactStyles.header} style={{ - ...getCommonPinningStyles({ column: header.column }), - width: header.getSize() + ...getPinnedStyle(header.column, true), // 🎯 헤더임을 명시 + width: header.getSize() // 🎯 width 별도 설정 }} > <div style={{ position: "relative" }}> @@ -269,8 +325,8 @@ export function ClientDataTable<TData, TValue>({ data-column-id={cell.column.id} className={compactStyles.cell} style={{ - ...getCommonPinningStyles({ column: cell.column }), - width: cell.column.getSize() + ...getPinnedStyle(cell.column, false), // 🎯 바디 셀임을 명시 + width: cell.column.getSize() // 🎯 width 별도 설정 }} > {flexRender( |
