import { useEffect, useRef } from "react" import { Table, ColumnDef } from "@tanstack/react-table" // 커스텀 메타 타입 정의 declare module '@tanstack/react-table' { interface ColumnMeta { paddingFactor?: number; excelHeader?: string; } } export function useAutoSizeColumns( table: Table, enabled: boolean = true ) { const hasResized = useRef(false) useEffect(() => { if (!enabled || hasResized.current) return // Wait for the table to render const timer = setTimeout(() => { const calculateColumnWidths = () => { const defaultMinWidth = 80 const defaultPadding = 24 const newColumnSizing: Record = {} // Process each visible column table.getAllColumns().forEach(column => { if (column.id === 'select' || column.id === 'actions') { // Fixed width for utility columns newColumnSizing[column.id] = column.id === 'select' ? 40 : 60 return } const columnId = column.id // Get column-specific padding from meta if available const paddingFactor = column.columnDef.meta?.paddingFactor || 1 const extraPadding = paddingFactor * defaultPadding // Get all cells for this column const headerElement = document.querySelector(`th[data-column-id="${columnId}"]`) const cells = document.querySelectorAll(`tbody td[data-column-id="${columnId}"]`) // Create measuring element const measureElement = document.createElement('div') measureElement.style.position = 'absolute' measureElement.style.visibility = 'hidden' measureElement.style.whiteSpace = 'nowrap' measureElement.style.font = headerElement ? window.getComputedStyle(headerElement).font : window.getComputedStyle(document.body).font document.body.appendChild(measureElement) // Measure header - 헤더 요소 자체의 너비를 직접 측정 let headerWidth = 0 if (headerElement) { // 1. 먼저 텍스트 콘텐츠 측정 const headerText = headerElement.textContent || "" measureElement.textContent = headerText headerWidth = measureElement.getBoundingClientRect().width // 2. 헤더에 아이콘이나 다른 요소가 있을 경우를 고려 // 헤더 요소의 실제 너비 확인 (텍스트외 요소 포함) const headerClientWidth = headerElement.querySelector('div')?.clientWidth || headerElement.clientWidth || 0 // 텍스트 너비와 실제 요소 너비 중 큰 값 선택 headerWidth = Math.max(headerWidth, headerClientWidth) } // 초기 최대 너비를 헤더 너비로 설정 let maxWidth = headerWidth // Measure cells (limit to first 20 for performance) Array.from(cells).slice(0, 20).forEach(cell => { const cellText = cell.textContent || "" measureElement.textContent = cellText const cellWidth = measureElement.getBoundingClientRect().width maxWidth = Math.max(maxWidth, cellWidth) }) // Clean up measuring element document.body.removeChild(measureElement) // Calculate final width let finalWidth = maxWidth + extraPadding const minWidth = column.columnDef.minSize || defaultMinWidth finalWidth = Math.max(finalWidth, minWidth) // Add to sizing object newColumnSizing[columnId] = finalWidth }) // Apply all column sizes at once table.setColumnSizing(newColumnSizing) hasResized.current = true } calculateColumnWidths() }, 100) // Short delay to ensure DOM is ready return () => clearTimeout(timer) }, [table, enabled]) return { resetAutoSize: () => { hasResized.current = false } } }