diff options
| author | joonhoekim <26rote@gmail.com> | 2025-03-25 15:55:45 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-03-25 15:55:45 +0900 |
| commit | 1a2241c40e10193c5ff7008a7b7b36cc1d855d96 (patch) | |
| tree | 8a5587f10ca55b162d7e3254cb088b323a34c41b /hooks/useAutoSizeColumns.ts | |
initial commit
Diffstat (limited to 'hooks/useAutoSizeColumns.ts')
| -rw-r--r-- | hooks/useAutoSizeColumns.ts | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/hooks/useAutoSizeColumns.ts b/hooks/useAutoSizeColumns.ts new file mode 100644 index 00000000..3750de97 --- /dev/null +++ b/hooks/useAutoSizeColumns.ts @@ -0,0 +1,86 @@ +// hooks/useAutoSizeColumns.ts +import { useEffect, useRef } from "react" +import { Table } from "@tanstack/react-table" + +export function useAutoSizeColumns<T>( + table: Table<T>, + 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<string, number> = {} + + // 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 as number || 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 + const headerText = headerElement?.textContent || "" + measureElement.textContent = headerText + let maxWidth = measureElement.getBoundingClientRect().width + + // 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 } } +}
\ No newline at end of file |
