테이블 틀고정기능
This commit is contained in:
@@ -687,7 +687,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
const [isTableOptionsOpen, setIsTableOptionsOpen] = useState(false);
|
||||
const [showGridLines, setShowGridLines] = useState(true);
|
||||
const [viewMode, setViewMode] = useState<"table" | "card" | "grouped-card">("table");
|
||||
const [frozenColumns, setFrozenColumns] = useState<string[]>([]);
|
||||
// 체크박스 컬럼은 항상 기본 틀고정
|
||||
const [frozenColumns, setFrozenColumns] = useState<string[]>(
|
||||
(tableConfig.checkbox?.enabled ?? true) ? ["__checkbox__"] : []
|
||||
);
|
||||
const [frozenColumnCount, setFrozenColumnCount] = useState<number>(0);
|
||||
|
||||
// 🆕 Search Panel (통합 검색) 관련 상태
|
||||
const [globalSearchTerm, setGlobalSearchTerm] = useState("");
|
||||
@@ -1022,6 +1026,19 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
getColumnUniqueValues, // 고유 값 조회 함수 등록
|
||||
onGroupSumChange: setGroupSumConfig, // 그룹별 합산 설정
|
||||
// 틀고정 컬럼 관련
|
||||
frozenColumnCount, // 현재 틀고정 컬럼 수
|
||||
onFrozenColumnCountChange: (count: number) => {
|
||||
setFrozenColumnCount(count);
|
||||
// 체크박스 컬럼은 항상 틀고정에 포함
|
||||
const checkboxColumn = (tableConfig.checkbox?.enabled ?? true) ? ["__checkbox__"] : [];
|
||||
// 표시 가능한 컬럼 중 처음 N개를 틀고정 컬럼으로 설정
|
||||
const visibleCols = columnsToRegister
|
||||
.filter((col) => col.visible !== false)
|
||||
.map((col) => col.columnName || col.field);
|
||||
const newFrozenColumns = [...checkboxColumn, ...visibleCols.slice(0, count)];
|
||||
setFrozenColumns(newFrozenColumns);
|
||||
},
|
||||
// 탭 관련 정보 (탭 내부의 테이블인 경우)
|
||||
parentTabId,
|
||||
parentTabsComponentId,
|
||||
@@ -2879,6 +2896,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
sortDirection,
|
||||
groupByColumns,
|
||||
frozenColumns,
|
||||
frozenColumnCount, // 틀고정 컬럼 수 저장
|
||||
showGridLines,
|
||||
headerFilters: Object.fromEntries(
|
||||
Object.entries(headerFilters).map(([key, set]) => [key, Array.from(set as Set<string>)]),
|
||||
@@ -2900,6 +2918,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
sortDirection,
|
||||
groupByColumns,
|
||||
frozenColumns,
|
||||
frozenColumnCount,
|
||||
showGridLines,
|
||||
headerFilters,
|
||||
localPageSize,
|
||||
@@ -2920,7 +2939,15 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
if (state.sortColumn !== undefined) setSortColumn(state.sortColumn);
|
||||
if (state.sortDirection) setSortDirection(state.sortDirection);
|
||||
if (state.groupByColumns) setGroupByColumns(state.groupByColumns);
|
||||
if (state.frozenColumns) setFrozenColumns(state.frozenColumns);
|
||||
if (state.frozenColumns) {
|
||||
// 체크박스 컬럼이 항상 포함되도록 보장
|
||||
const checkboxColumn = (tableConfig.checkbox?.enabled ?? true) ? "__checkbox__" : null;
|
||||
const restoredFrozenColumns = checkboxColumn && !state.frozenColumns.includes(checkboxColumn)
|
||||
? [checkboxColumn, ...state.frozenColumns]
|
||||
: state.frozenColumns;
|
||||
setFrozenColumns(restoredFrozenColumns);
|
||||
}
|
||||
if (state.frozenColumnCount !== undefined) setFrozenColumnCount(state.frozenColumnCount); // 틀고정 컬럼 수 복원
|
||||
if (state.showGridLines !== undefined) setShowGridLines(state.showGridLines);
|
||||
if (state.headerFilters) {
|
||||
const filters: Record<string, Set<string>> = {};
|
||||
@@ -5590,7 +5617,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
if (isFrozen && frozenIndex > 0) {
|
||||
for (let i = 0; i < frozenIndex; i++) {
|
||||
const frozenCol = frozenColumns[i];
|
||||
const frozenColWidth = columnWidths[frozenCol] || 150;
|
||||
// 체크박스 컬럼은 48px 고정
|
||||
const frozenColWidth = frozenCol === "__checkbox__" ? 48 : (columnWidths[frozenCol] || 150);
|
||||
leftPosition += frozenColWidth;
|
||||
}
|
||||
}
|
||||
@@ -5609,7 +5637,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
column.sortable !== false &&
|
||||
column.columnName !== "__checkbox__" &&
|
||||
"hover:bg-muted/70 cursor-pointer transition-colors",
|
||||
isFrozen && "sticky z-60 shadow-[2px_0_4px_rgba(0,0,0,0.1)]",
|
||||
isFrozen && "sticky z-40 shadow-[2px_0_4px_rgba(0,0,0,0.1)]",
|
||||
// 🆕 Column Reordering 스타일
|
||||
isColumnDragEnabled &&
|
||||
column.columnName !== "__checkbox__" &&
|
||||
@@ -5901,7 +5929,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
if (isFrozen && frozenIndex > 0) {
|
||||
for (let i = 0; i < frozenIndex; i++) {
|
||||
const frozenCol = frozenColumns[i];
|
||||
const frozenColWidth = columnWidths[frozenCol] || 150;
|
||||
// 체크박스 컬럼은 48px 고정
|
||||
const frozenColWidth = frozenCol === "__checkbox__" ? 48 : (columnWidths[frozenCol] || 150);
|
||||
leftPosition += frozenColWidth;
|
||||
}
|
||||
}
|
||||
@@ -5914,7 +5943,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
column.columnName === "__checkbox__"
|
||||
? "px-0 py-1"
|
||||
: "px-2 py-1 sm:px-4 sm:py-1.5",
|
||||
isFrozen && "bg-background sticky z-10 shadow-[2px_0_4px_rgba(0,0,0,0.05)]",
|
||||
isFrozen && "sticky z-20 shadow-[2px_0_4px_rgba(0,0,0,0.08)]",
|
||||
)}
|
||||
style={{
|
||||
textAlign:
|
||||
@@ -5929,7 +5958,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
: `${100 / visibleColumns.length}%`,
|
||||
minWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
|
||||
maxWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
|
||||
...(isFrozen && { left: `${leftPosition}px` }),
|
||||
...(isFrozen && {
|
||||
left: `${leftPosition}px`,
|
||||
backgroundColor: "hsl(var(--background))",
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{column.columnName === "__checkbox__"
|
||||
@@ -6061,7 +6093,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
if (isFrozen && frozenIndex > 0) {
|
||||
for (let i = 0; i < frozenIndex; i++) {
|
||||
const frozenCol = frozenColumns[i];
|
||||
const frozenColWidth = columnWidths[frozenCol] || 150;
|
||||
// 체크박스 컬럼은 48px 고정
|
||||
const frozenColWidth = frozenCol === "__checkbox__" ? 48 : (columnWidths[frozenCol] || 150);
|
||||
leftPosition += frozenColWidth;
|
||||
}
|
||||
}
|
||||
@@ -6074,7 +6107,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
className={cn(
|
||||
"text-foreground overflow-hidden text-xs font-normal text-ellipsis whitespace-nowrap sm:text-sm",
|
||||
column.columnName === "__checkbox__" ? "px-0 py-1" : "px-2 py-1 sm:px-4 sm:py-1.5",
|
||||
isFrozen && "bg-background sticky z-10 shadow-[2px_0_4px_rgba(0,0,0,0.05)]",
|
||||
isFrozen && "sticky z-20 shadow-[2px_0_4px_rgba(0,0,0,0.08)]",
|
||||
// 🆕 포커스된 셀 스타일
|
||||
isCellFocused && !editingCell && "ring-primary bg-primary/5 ring-2 ring-inset",
|
||||
// 🆕 편집 중인 셀 스타일
|
||||
@@ -6101,7 +6134,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
column.columnName === "__checkbox__" ? "48px" : `${100 / visibleColumns.length}%`,
|
||||
minWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
|
||||
maxWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
|
||||
...(isFrozen && { left: `${leftPosition}px` }),
|
||||
...(isFrozen && {
|
||||
left: `${leftPosition}px`,
|
||||
backgroundColor: "hsl(var(--background))",
|
||||
}),
|
||||
}}
|
||||
onClick={(e) => handleCellClick(index, colIndex, e)}
|
||||
onDoubleClick={() =>
|
||||
@@ -6222,7 +6258,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
if (isFrozen && frozenIndex > 0) {
|
||||
for (let i = 0; i < frozenIndex; i++) {
|
||||
const frozenCol = frozenColumns[i];
|
||||
const frozenColWidth = columnWidths[frozenCol] || 150;
|
||||
// 체크박스 컬럼은 48px 고정
|
||||
const frozenColWidth = frozenCol === "__checkbox__" ? 48 : (columnWidths[frozenCol] || 150);
|
||||
leftPosition += frozenColWidth;
|
||||
}
|
||||
}
|
||||
@@ -6237,7 +6274,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
className={cn(
|
||||
"text-foreground text-xs font-semibold sm:text-sm",
|
||||
column.columnName === "__checkbox__" ? "px-0 py-2" : "px-2 py-2 sm:px-4",
|
||||
isFrozen && "bg-muted/80 sticky z-10 shadow-[2px_0_4px_rgba(0,0,0,0.05)]",
|
||||
isFrozen && "sticky z-20 shadow-[2px_0_4px_rgba(0,0,0,0.08)]",
|
||||
)}
|
||||
style={{
|
||||
textAlign: isNumeric ? "right" : column.align || "left",
|
||||
@@ -6247,7 +6284,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
: columnWidth
|
||||
? `${columnWidth}px`
|
||||
: undefined,
|
||||
...(isFrozen && { left: `${leftPosition}px` }),
|
||||
...(isFrozen && {
|
||||
left: `${leftPosition}px`,
|
||||
backgroundColor: "hsl(var(--muted) / 0.8)",
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{summary ? (
|
||||
|
||||
Reference in New Issue
Block a user