feat: enhance column width configuration and rendering
- Updated the column width handling in various components to support percentage-based widths, improving layout flexibility. - Adjusted input fields to enforce minimum and maximum width constraints, ensuring better user experience and preventing layout issues. - Enhanced the SortableColumnRow and related components to dynamically display width units, allowing for clearer configuration options. Made-with: Cursor
This commit is contained in:
@@ -3543,6 +3543,12 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
format: undefined, // 🆕 기본값
|
||||
}));
|
||||
|
||||
// 컬럼 너비 합계 계산 (작업 컬럼 제외, 100% 초과 시 스크롤)
|
||||
const leftTotalColWidth = columnsToShow.reduce((sum, col) => {
|
||||
const w = col.width && col.width <= 100 ? col.width : 0;
|
||||
return sum + w;
|
||||
}, 0);
|
||||
|
||||
// 🔧 그룹화된 데이터 렌더링
|
||||
const hasGroupedLeftActions = !isDesignMode && (
|
||||
(componentConfig.leftPanel?.showEdit !== false) ||
|
||||
@@ -3556,7 +3562,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<div className="bg-muted px-3 py-2 text-sm font-semibold">
|
||||
{group.groupKey} ({group.count}개)
|
||||
</div>
|
||||
<table className="min-w-full divide-y divide-border">
|
||||
<table className="divide-y divide-border table-fixed" style={{ width: leftTotalColWidth > 100 ? `${leftTotalColWidth}%` : '100%' }}>
|
||||
<thead className="bg-muted">
|
||||
<tr>
|
||||
{columnsToShow.map((col, idx) => (
|
||||
@@ -3564,8 +3570,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
key={idx}
|
||||
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap"
|
||||
style={{
|
||||
width: col.width ? `${col.width}px` : "auto",
|
||||
minWidth: "80px",
|
||||
width: col.width && col.width <= 100 ? `${col.width}%` : "auto",
|
||||
textAlign: col.align || "left",
|
||||
}}
|
||||
>
|
||||
@@ -3654,7 +3659,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
);
|
||||
return (
|
||||
<div className="overflow-auto">
|
||||
<table className="min-w-full divide-y divide-border">
|
||||
<table className="divide-y divide-border table-fixed" style={{ width: leftTotalColWidth > 100 ? `${leftTotalColWidth}%` : '100%' }}>
|
||||
<thead className="sticky top-0 z-10 bg-muted">
|
||||
<tr>
|
||||
{columnsToShow.map((col, idx) => (
|
||||
@@ -3662,8 +3667,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
key={idx}
|
||||
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap"
|
||||
style={{
|
||||
width: col.width ? `${col.width}px` : "auto",
|
||||
minWidth: "80px",
|
||||
width: col.width && col.width <= 100 ? `${col.width}%` : "auto",
|
||||
textAlign: col.align || "left",
|
||||
}}
|
||||
>
|
||||
@@ -4659,11 +4663,16 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
}));
|
||||
}
|
||||
|
||||
const tableMinWidth = columnsToShow.reduce((sum, col) => sum + (col.width || 100), 0) + 80;
|
||||
// 컬럼 너비 합계 계산 (작업 컬럼 제외, 100% 초과 시 스크롤)
|
||||
const rightTotalColWidth = columnsToShow.reduce((sum, col) => {
|
||||
const w = col.width && col.width <= 100 ? col.width : 0;
|
||||
return sum + w;
|
||||
}, 0);
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="min-h-0 flex-1 overflow-auto">
|
||||
<table style={{ minWidth: `${tableMinWidth}px` }}>
|
||||
<table className="table-fixed" style={{ width: rightTotalColWidth > 100 ? `${rightTotalColWidth}%` : '100%' }}>
|
||||
<thead className="sticky top-0 z-10">
|
||||
<tr className="border-b-2 border-border/60">
|
||||
{columnsToShow.map((col, idx) => (
|
||||
@@ -4671,8 +4680,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
key={idx}
|
||||
className="text-muted-foreground px-3 py-2 text-left text-xs font-semibold whitespace-nowrap"
|
||||
style={{
|
||||
width: col.width ? `${col.width}px` : "auto",
|
||||
minWidth: "80px",
|
||||
width: col.width && col.width <= 100 ? `${col.width}%` : "auto",
|
||||
textAlign: col.align || "left",
|
||||
}}
|
||||
>
|
||||
@@ -4683,7 +4691,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
{!isDesignMode &&
|
||||
((componentConfig.rightPanel?.editButton?.enabled ?? true) ||
|
||||
(componentConfig.rightPanel?.deleteButton?.enabled ?? true)) && (
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold">
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold" style={{ width: '80px' }}>
|
||||
작업
|
||||
</th>
|
||||
)}
|
||||
@@ -4762,7 +4770,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
{
|
||||
// 표시 컬럼 결정
|
||||
const rightColumns = componentConfig.rightPanel?.columns;
|
||||
let columnsToDisplay: { name: string; label: string; format?: string; bold?: boolean }[] = [];
|
||||
let columnsToDisplay: { name: string; label: string; format?: string; bold?: boolean; width?: number }[] = [];
|
||||
|
||||
if (rightColumns && rightColumns.length > 0) {
|
||||
// showInSummary가 false가 아닌 것만 메인 테이블에 표시
|
||||
@@ -4773,6 +4781,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
label: rightColumnLabels[col.name] || col.label || col.name,
|
||||
format: col.format,
|
||||
bold: col.bold,
|
||||
width: col.width,
|
||||
}));
|
||||
} else if (filteredData.length > 0) {
|
||||
columnsToDisplay = Object.keys(filteredData[0])
|
||||
@@ -4784,24 +4793,33 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
}));
|
||||
}
|
||||
|
||||
// 컬럼 너비 합계 계산 (작업 컬럼 제외, 100% 초과 시 스크롤)
|
||||
const displayTotalColWidth = columnsToDisplay.reduce((sum, col) => {
|
||||
const w = col.width && col.width <= 100 ? col.width : 0;
|
||||
return sum + w;
|
||||
}, 0);
|
||||
|
||||
const hasEditButton = !isDesignMode && (componentConfig.rightPanel?.editButton?.enabled ?? true);
|
||||
const hasDeleteButton = !isDesignMode && (componentConfig.rightPanel?.deleteButton?.enabled ?? true);
|
||||
const hasActions = hasEditButton || hasDeleteButton;
|
||||
|
||||
const tableMinW2 = columnsToDisplay.reduce((sum, col) => sum + (col.width || 100), 0) + 80;
|
||||
return filteredData.length > 0 ? (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="min-h-0 flex-1 overflow-auto">
|
||||
<table className="text-sm" style={{ minWidth: `${tableMinW2}px` }}>
|
||||
<table className="table-fixed text-sm" style={{ width: displayTotalColWidth > 100 ? `${displayTotalColWidth}%` : '100%' }}>
|
||||
<thead className="sticky top-0 z-10 bg-background">
|
||||
<tr className="border-b-2 border-border/60">
|
||||
{columnsToDisplay.map((col) => (
|
||||
<th key={col.name} className="text-muted-foreground px-3 py-2 text-left text-xs font-semibold">
|
||||
<th
|
||||
key={col.name}
|
||||
className="text-muted-foreground px-3 py-2 text-left text-xs font-semibold whitespace-nowrap"
|
||||
style={{ width: col.width && col.width <= 100 ? `${col.width}%` : "auto" }}
|
||||
>
|
||||
{col.label}
|
||||
</th>
|
||||
))}
|
||||
{hasActions && (
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold">작업</th>
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold" style={{ width: '80px' }}>작업</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
Reference in New Issue
Block a user