summaryrefslogtreecommitdiff
path: root/components/data-table/infinite-data-table.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/data-table/infinite-data-table.tsx')
-rw-r--r--components/data-table/infinite-data-table.tsx69
1 files changed, 60 insertions, 9 deletions
diff --git a/components/data-table/infinite-data-table.tsx b/components/data-table/infinite-data-table.tsx
index fcac56ee..b8764d62 100644
--- a/components/data-table/infinite-data-table.tsx
+++ b/components/data-table/infinite-data-table.tsx
@@ -6,7 +6,7 @@ import { ChevronRight, ChevronUp, Loader2 } from "lucide-react"
import { useIntersection } from "@mantine/hooks"
import { cn } from "@/lib/utils"
-import { getCommonPinningStyles } from "@/lib/data-table"
+import { getCommonPinningStylesWithBorder } from "@/lib/data-table"
import {
Table,
TableBody,
@@ -53,6 +53,9 @@ export function InfiniteDataTable<TData>({
useAutoSizeColumns(table, autoSizeColumns)
+ // 🎯 슀크둀 μƒνƒœ 감지 μΆ”κ°€
+ const [isScrolled, setIsScrolled] = React.useState(false)
+
// Intersection Observer for infinite scroll
const { ref: loadMoreRef, entry } = useIntersection({
threshold: 0.1,
@@ -65,21 +68,62 @@ export function InfiniteDataTable<TData>({
}
}, [entry?.isIntersecting, hasNextPage, isLoadingMore, onLoadMore])
+ // 🎯 슀크둀 ν•Έλ“€λŸ¬ μΆ”κ°€
+ 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",
cell: "py-1 px-2 text-sm",
+ header: "py-1 px-2 text-sm", // 헀더 μŠ€νƒ€μΌ μΆ”κ°€
+ headerRow: "h-8", // 헀더 ν–‰ 높이 μΆ”κ°€
groupRow: "py-1 bg-muted/20 text-sm",
emptyRow: "h-16",
} : {
row: "",
cell: "",
+ header: "", // 헀더 μŠ€νƒ€μΌ μΆ”κ°€
+ headerRow: "", // 헀더 ν–‰ 높이 μΆ”κ°€
groupRow: "bg-muted/20",
emptyRow: "h-24",
}
return (
- <div className={cn("w-full space-y-2.5 overflow-auto", className)} {...props}>
+ <div className={cn("w-full space-y-2.5", className)} {...props}>
{children}
{/* 총 개수 ν‘œμ‹œ */}
@@ -97,12 +141,19 @@ export function InfiniteDataTable<TData>({
<div
className="max-w-[100vw] overflow-auto"
style={{ maxHeight: maxHeight || '35rem' }}
+ onScroll={handleScroll} // 🎯 슀크둀 이벀트 ν•Έλ“€λŸ¬ μΆ”κ°€
>
- <Table className="[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10 table-fixed">
+ <Table
+ className="[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10"
+ style={{
+ width: getTableWidth(), // 🎯 동적 λ„ˆλΉ„ 계산
+ minWidth: '100%'
+ }}
+ >
{/* ν…Œμ΄λΈ” 헀더 */}
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
- <TableRow key={headerGroup.id} className={compact ? "h-8" : ""}>
+ <TableRow key={headerGroup.id} className={compactStyles.headerRow}>
{headerGroup.headers.map((header) => {
if (header.column.getIsGrouped()) {
return null
@@ -113,10 +164,10 @@ export function InfiniteDataTable<TData>({
key={header.id}
colSpan={header.colSpan}
data-column-id={header.column.id}
- className={compact ? "py-1 px-2 text-sm" : ""}
+ className={compactStyles.header}
style={{
- ...getCommonPinningStyles({ column: header.column }),
- width: header.getSize(),
+ ...getPinnedStyle(header.column, true), // 🎯 ν—€λ”μž„μ„ λͺ…μ‹œ
+ width: header.getSize(), // 🎯 width 별도 μ„€μ •
}}
>
<div style={{ position: "relative" }}>
@@ -211,8 +262,8 @@ export function InfiniteDataTable<TData>({
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(