summaryrefslogtreecommitdiff
path: root/components/data-table/data-table-resizer.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-03-26 00:37:41 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-03-26 00:37:41 +0000
commite0dfb55c5457aec489fc084c4567e791b4c65eb1 (patch)
tree68543a65d88f5afb3a0202925804103daa91bc6f /components/data-table/data-table-resizer.tsx
3/25 까지의 대표님 작업사항
Diffstat (limited to 'components/data-table/data-table-resizer.tsx')
-rw-r--r--components/data-table/data-table-resizer.tsx98
1 files changed, 98 insertions, 0 deletions
diff --git a/components/data-table/data-table-resizer.tsx b/components/data-table/data-table-resizer.tsx
new file mode 100644
index 00000000..9723a0b4
--- /dev/null
+++ b/components/data-table/data-table-resizer.tsx
@@ -0,0 +1,98 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "@/lib/utils"
+import { Header } from "@tanstack/react-table"
+
+interface DataTableResizerProps<TData, TValue>
+ extends React.HTMLAttributes<HTMLDivElement> {
+ header: Header<TData, TValue>
+}
+
+export function DataTableResizer<TData, TValue>({
+ header,
+ className,
+ ...props
+}: DataTableResizerProps<TData, TValue>) {
+ const contentRef = React.useRef<HTMLDivElement>(null)
+
+ // 더블클릭 시 너비 자동 조정 함수
+ const handleDoubleClick = React.useCallback(() => {
+ // 테이블 인스턴스 가져오기
+ const table = header.getContext().table
+
+ // 0. 몇 가지 기본 설정
+ const defaultMinWidth = 80 // 기본 최소 너비
+ const extraPadding = 24 // 여유 공간
+
+ // 헤더 타이틀 얻기 시도
+ const headerElement = contentRef.current?.closest('th')
+ const headerText = headerElement?.textContent || ""
+
+ // 1. 컬럼 ID 가져오기
+ const columnId = header.column.id
+
+ // 2. 테이블 바디에서 해당 ID를 가진 모든 셀 선택
+ const allCells = document.querySelectorAll(`tbody td[data-column-id="${columnId}"]`)
+
+ // 3. 최대 컨텐츠 너비 측정을 위한 임시 요소 생성
+ const measureElement = document.createElement('div')
+ measureElement.style.position = 'absolute'
+ measureElement.style.visibility = 'hidden'
+ measureElement.style.whiteSpace = 'nowrap' // 내용이 줄바꿈되지 않도록
+ measureElement.style.font = window.getComputedStyle(headerElement || document.body).font // 동일한 폰트 사용
+ document.body.appendChild(measureElement)
+
+ // 4. 헤더 너비 측정
+ measureElement.textContent = headerText
+ let maxWidth = measureElement.getBoundingClientRect().width
+
+ // 5. 모든 셀의 내용 너비 측정하고 최대값 찾기
+ Array.from(allCells).forEach(cell => {
+ const cellText = cell.textContent || ""
+ measureElement.textContent = cellText
+ const cellWidth = measureElement.getBoundingClientRect().width
+ maxWidth = Math.max(maxWidth, cellWidth)
+ })
+
+ // 6. 측정용 요소 제거
+ document.body.removeChild(measureElement)
+
+ // 7. 계산된 너비에 여유 공간 추가
+ let finalWidth = maxWidth + extraPadding
+
+ // 8. 최소 너비 적용
+ const minWidth = header.column.columnDef.minSize || defaultMinWidth
+ finalWidth = Math.max(finalWidth, minWidth)
+
+ // 9. 컬럼 사이즈 업데이트
+ const columnSizingInfo = table.getState().columnSizing
+ const updatedSizing = {
+ ...columnSizingInfo,
+ [columnId]: finalWidth
+ }
+
+ table.setColumnSizing(updatedSizing)
+ }, [header])
+
+ return (
+ <>
+ {/* 헤더 콘텐츠 참조를 위한 요소 */}
+ <div ref={contentRef} className="absolute opacity-0 pointer-events-none" />
+
+ {/* 리사이저 */}
+ <div
+ {...props}
+ onMouseDown={header.getResizeHandler()}
+ onTouchStart={header.getResizeHandler()}
+ onDoubleClick={handleDoubleClick} // 더블클릭 핸들러 추가
+ className={cn(
+ "absolute right-0 top-0 h-full w-1 cursor-col-resize bg-transparent hover:bg-gray-300 active:bg-gray-400",
+ header.column.getIsResizing() ? "bg-gray-400" : "",
+ className
+ )}
+ title="더블 클릭하여 내용에 맞게 크기 조정" // 힌트 추가
+ />
+ </>
+ )
+} \ No newline at end of file