jskim-node #421

Merged
kjs merged 33 commits from jskim-node into main 2026-03-18 17:43:51 +09:00
5 changed files with 124 additions and 92 deletions
Showing only changes of commit 13b2ebaf1f - Show all commits

View File

@ -359,20 +359,10 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
return `${actualHeight}px`;
}
// 런타임 모드에서 컴포넌트 타입별 높이 처리
// 런타임 모드: ResponsiveGridRenderer가 ratio 기반으로 래퍼 높이를 설정하므로,
// 안쪽 컴포넌트는 "100%"로 래퍼를 채워야 비율이 정확하게 맞음
if (!isDesignMode) {
const compType = (component as any).componentType || component.componentConfig?.type || "";
// 테이블: 부모 flex 컨테이너가 높이 관리 (flex: 1)
const flexGrowTypes = [
"table-list", "v2-table-list",
"split-panel-layout", "split-panel-layout2",
"v2-split-panel-layout", "screen-split-panel",
"v2-tab-container", "tab-container",
"tabs-widget", "v2-tabs-widget",
];
if (flexGrowTypes.some(t => compType === t)) {
return "100%";
}
const autoHeightTypes = [
"table-search-widget", "v2-table-search-widget",
"flow-widget",
@ -380,9 +370,11 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
if (autoHeightTypes.some(t => compType === t || compType.includes(t))) {
return "auto";
}
// 나머지 모든 타입: 래퍼의 비율 스케일링을 따르도록 100%
return "100%";
}
// 1순위: size.height가 있으면 우선 사용
// 디자인 모드: 고정 픽셀 사용 (캔버스 내 절대 좌표 배치)
if (size?.height && size.height > 0) {
if (component.componentConfig?.type === "table-list") {
return `${Math.max(size.height, 200)}px`;
@ -390,17 +382,14 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
return `${size.height}px`;
}
// 2순위: componentStyle.height (컴포넌트 정의에서 온 기본 스타일)
if (componentStyle?.height) {
return typeof componentStyle.height === "number" ? `${componentStyle.height}px` : componentStyle.height;
}
// 3순위: 기본값
if (component.componentConfig?.type === "table-list") {
return "200px";
}
// 기본 높이
return "10px";
};

View File

@ -1410,7 +1410,7 @@ export const ButtonPrimaryComponent: React.FC<ButtonPrimaryComponentProps> = ({
const buttonElementStyle: React.CSSProperties = {
width: buttonWidth,
height: buttonHeight,
minHeight: "32px", // 🔧 최소 높이를 32px로 줄임
minHeight: undefined, // 비율 스케일링 시 래퍼 높이를 정확히 따르도록 제거
// 커스텀 테두리 스타일 (StyleEditor 설정 우선, shorthand 사용 안 함)
borderWidth: style?.borderWidth || "0",
borderStyle: (style?.borderStyle as React.CSSProperties["borderStyle"]) || (style?.borderWidth ? "solid" : "none"),

View File

@ -22,6 +22,7 @@ import {
FileSpreadsheet,
List,
PanelRight,
GripVertical,
} from "lucide-react";
import { dataApi } from "@/lib/api/data";
import { entityJoinApi } from "@/lib/api/entityJoin";
@ -313,10 +314,11 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
const [rightFilters, setRightFilters] = useState<TableFilter[]>([]);
const [rightGrouping, setRightGrouping] = useState<string[]>([]);
const [rightColumnVisibility, setRightColumnVisibility] = useState<ColumnVisibility[]>([]);
// 우측 패널 컬럼 헤더 드래그 (디자인 모드에서 순서 변경)
// 우측 패널 컬럼 헤더 드래그 (디자인 + 런타임 순서 변경)
const [rightDraggedColumnIndex, setRightDraggedColumnIndex] = useState<number | null>(null);
const [rightDropTargetColumnIndex, setRightDropTargetColumnIndex] = useState<number | null>(null);
const [rightDragSource, setRightDragSource] = useState<"main" | number | null>(null);
const [runtimeColumnOrder, setRuntimeColumnOrder] = useState<Record<string, number[]>>({});
// 데이터 상태
const [leftData, setLeftData] = useState<any[]>([]);
@ -2544,55 +2546,67 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
handleRightColumnDragEnd();
return;
}
if (!onUpdateComponent) {
handleRightColumnDragEnd();
return;
}
const rightPanel = componentConfig.rightPanel || {};
if (source === "main") {
const allColumns = rightPanel.columns || [];
const visibleColumns = allColumns.filter((c: any) => c.showInSummary !== false);
const hiddenColumns = allColumns.filter((c: any) => c.showInSummary === false);
if (fromIdx < 0 || fromIdx >= visibleColumns.length || targetIndex < 0 || targetIndex >= visibleColumns.length) {
handleRightColumnDragEnd();
return;
if (onUpdateComponent) {
// 디자인 모드: config에 영구 저장
const rightPanel = componentConfig.rightPanel || {};
if (source === "main") {
const allColumns = rightPanel.columns || [];
const visibleColumns = allColumns.filter((c: any) => c.showInSummary !== false);
const hiddenColumns = allColumns.filter((c: any) => c.showInSummary === false);
if (fromIdx < 0 || fromIdx >= visibleColumns.length || targetIndex < 0 || targetIndex >= visibleColumns.length) {
handleRightColumnDragEnd();
return;
}
const reordered = [...visibleColumns];
const [removed] = reordered.splice(fromIdx, 1);
reordered.splice(targetIndex, 0, removed);
const columns = [...reordered, ...hiddenColumns];
onUpdateComponent({
...component,
componentConfig: {
...componentConfig,
rightPanel: { ...rightPanel, columns },
},
});
} else {
const tabs = [...(rightPanel.additionalTabs || [])];
const tabConfig = tabs[source];
if (!tabConfig || !Array.isArray(tabConfig.columns)) {
handleRightColumnDragEnd();
return;
}
const allTabCols = tabConfig.columns;
const visibleTabCols = allTabCols.filter((c: any) => c.showInSummary !== false);
const hiddenTabCols = allTabCols.filter((c: any) => c.showInSummary === false);
if (fromIdx < 0 || fromIdx >= visibleTabCols.length || targetIndex < 0 || targetIndex >= visibleTabCols.length) {
handleRightColumnDragEnd();
return;
}
const reordered = [...visibleTabCols];
const [removed] = reordered.splice(fromIdx, 1);
reordered.splice(targetIndex, 0, removed);
const columns = [...reordered, ...hiddenTabCols];
const newTabs = tabs.map((t, i) => (i === source ? { ...t, columns } : t));
onUpdateComponent({
...component,
componentConfig: {
...componentConfig,
rightPanel: { ...rightPanel, additionalTabs: newTabs },
},
});
}
const reordered = [...visibleColumns];
const [removed] = reordered.splice(fromIdx, 1);
reordered.splice(targetIndex, 0, removed);
const columns = [...reordered, ...hiddenColumns];
onUpdateComponent({
...component,
componentConfig: {
...componentConfig,
rightPanel: { ...rightPanel, columns },
},
});
} else {
const tabs = [...(rightPanel.additionalTabs || [])];
const tabConfig = tabs[source];
if (!tabConfig || !Array.isArray(tabConfig.columns)) {
handleRightColumnDragEnd();
return;
}
const allTabCols = tabConfig.columns;
const visibleTabCols = allTabCols.filter((c: any) => c.showInSummary !== false);
const hiddenTabCols = allTabCols.filter((c: any) => c.showInSummary === false);
if (fromIdx < 0 || fromIdx >= visibleTabCols.length || targetIndex < 0 || targetIndex >= visibleTabCols.length) {
handleRightColumnDragEnd();
return;
}
const reordered = [...visibleTabCols];
const [removed] = reordered.splice(fromIdx, 1);
reordered.splice(targetIndex, 0, removed);
const columns = [...reordered, ...hiddenTabCols];
const newTabs = tabs.map((t, i) => (i === source ? { ...t, columns } : t));
onUpdateComponent({
...component,
componentConfig: {
...componentConfig,
rightPanel: { ...rightPanel, additionalTabs: newTabs },
},
// 런타임 모드: 로컬 상태로 순서 변경
const key = String(source);
setRuntimeColumnOrder((prev) => {
const existing = prev[key];
const maxLen = 100;
const order = existing || Array.from({ length: maxLen }, (_, i) => i);
const reordered = [...order];
const [removed] = reordered.splice(fromIdx, 1);
reordered.splice(targetIndex, 0, removed);
return { ...prev, [key]: reordered };
});
}
handleRightColumnDragEnd();
@ -2604,9 +2618,29 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
component,
onUpdateComponent,
handleRightColumnDragEnd,
setRuntimeColumnOrder,
],
);
// 런타임 컬럼 순서 적용 헬퍼
const applyRuntimeOrder = useCallback(
<T,>(columns: T[], source: "main" | number): T[] => {
const key = String(source);
const order = runtimeColumnOrder[key];
if (!order) return columns;
const result: T[] = [];
for (const idx of order) {
if (idx < columns.length) result.push(columns[idx]);
}
// order에 없는 나머지 컬럼 추가
for (let i = 0; i < columns.length; i++) {
if (!order.includes(i)) result.push(columns[i]);
}
return result.length > 0 ? result : columns;
},
[runtimeColumnOrder],
);
// 수정 모달 저장
const handleEditModalSave = useCallback(async () => {
const tableName =
@ -3946,11 +3980,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{resizable && (
<div
onMouseDown={handleMouseDown}
className="group flex w-1.5 cursor-col-resize flex-col items-center justify-center gap-0.5 bg-border transition-colors hover:bg-primary"
className="group flex w-1.5 cursor-col-resize flex-col items-center justify-center gap-0.5 bg-border/60 transition-colors hover:bg-primary/25"
aria-label="분할선 드래그"
>
<div className="h-7 w-0.5 rounded-full bg-muted-foreground/40 transition-colors group-hover:bg-primary-foreground/80" />
<div className="h-7 w-0.5 rounded-full bg-muted-foreground/40 transition-colors group-hover:bg-primary-foreground/80" />
<div className="h-7 w-0.5 rounded-full bg-muted-foreground/30 transition-opacity group-hover:opacity-70" />
</div>
)}
@ -4107,7 +4140,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
// showInSummary가 false가 아닌 것만 메인 테이블에 표시
const tabSummaryColumns = tabColumns.filter((col: any) => col.showInSummary !== false);
const tabIndex = activeTabIndex - 1;
const canDragTabColumns = isDesignMode && tabSummaryColumns.length > 0 && !!onUpdateComponent;
const canDragTabColumns = tabSummaryColumns.length > 0;
return (
<div className="h-full overflow-auto">
<table className="w-full text-sm">
@ -4120,7 +4153,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<th
key={col.name}
className={cn(
"text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em]",
"group/th text-muted-foreground relative px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em]",
isDropTarget && "border-l-[3px] border-l-primary bg-primary/5",
canDragTabColumns && "cursor-grab active:cursor-grabbing",
isDragging && "opacity-50",
@ -4131,6 +4164,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
onDragEnd={handleRightColumnDragEnd}
onDrop={(e) => canDragTabColumns && handleRightColumnDrop(e, idx, tabIndex)}
>
{canDragTabColumns && <GripVertical className="text-muted-foreground/30 group-hover/th:text-muted-foreground/60 absolute top-1/2 left-0.5 h-3 w-3 -translate-y-1/2 transition-opacity" />}
{col.label || col.name}
</th>
);
@ -4158,7 +4192,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<tr
className={cn(
"group/action cursor-pointer border-b border-border/50 transition-[background] duration-75",
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/50 hover:bg-accent" : "hover:bg-accent",
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/20 hover:bg-accent" : "hover:bg-accent",
)}
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
>
@ -4243,7 +4277,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
// showInSummary가 false가 아닌 것만 메인 테이블에 표시
const listSummaryColumns = tabColumns.filter((col: any) => col.showInSummary !== false);
const listTabIndex = activeTabIndex - 1;
const canDragListTabColumns = isDesignMode && listSummaryColumns.length > 0 && !!onUpdateComponent;
const canDragListTabColumns = listSummaryColumns.length > 0;
return (
<div className="h-full overflow-auto">
<table className="w-full text-sm">
@ -4256,7 +4290,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<th
key={col.name}
className={cn(
"text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em]",
"group/th text-muted-foreground relative px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em]",
isDropTarget && "border-l-[3px] border-l-primary bg-primary/5",
canDragListTabColumns && "cursor-grab active:cursor-grabbing",
isDragging && "opacity-50",
@ -4267,6 +4301,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
onDragEnd={handleRightColumnDragEnd}
onDrop={(e) => canDragListTabColumns && handleRightColumnDrop(e, idx, listTabIndex)}
>
{canDragListTabColumns && <GripVertical className="text-muted-foreground/30 group-hover/th:text-muted-foreground/60 absolute top-1/2 left-0.5 h-3 w-3 -translate-y-1/2 transition-opacity" />}
{col.label || col.name}
</th>
);
@ -4293,7 +4328,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<tr
className={cn(
"group/action cursor-pointer border-b border-border/50 transition-[background] duration-75",
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/50 hover:bg-accent" : "hover:bg-accent",
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/20 hover:bg-accent" : "hover:bg-accent",
)}
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
>
@ -4646,6 +4681,14 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
}));
}
// 런타임 컬럼 순서 적용
if (!isDesignMode && runtimeColumnOrder["main"]) {
const keyColCount = columnsToShow.filter((c: any) => c._isKeyColumn).length;
const keyCols = columnsToShow.slice(0, keyColCount);
const dataCols = columnsToShow.slice(keyColCount);
columnsToShow = [...keyCols, ...applyRuntimeOrder(dataCols, "main")];
}
// 컬럼 너비 합계 계산 (작업 컬럼 제외, 100% 초과 시 스크롤)
const rightTotalColWidth = columnsToShow.reduce((sum, col) => {
const w = col.width && col.width <= 100 ? col.width : 0;
@ -4653,7 +4696,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
}, 0);
const rightConfigColumnStart = columnsToShow.filter((c: any) => c._isKeyColumn).length;
const canDragRightColumns = isDesignMode && displayColumns.length > 0 && !!onUpdateComponent;
const canDragRightColumns = displayColumns.length > 0;
return (
<div className="flex h-full w-full flex-col">
@ -4670,7 +4713,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<th
key={idx}
className={cn(
"text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em] whitespace-nowrap",
"group/th text-muted-foreground relative px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em] whitespace-nowrap",
isDropTarget && "border-l-[3px] border-l-primary bg-primary/5",
isDraggable && "cursor-grab active:cursor-grabbing",
isDragging && "opacity-50",
@ -4685,6 +4728,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
onDragEnd={handleRightColumnDragEnd}
onDrop={(e) => isDraggable && handleRightColumnDrop(e, configColIndex, "main")}
>
{isDraggable && <GripVertical className="text-muted-foreground/30 group-hover/th:text-muted-foreground/60 absolute top-1/2 left-0.5 h-3 w-3 -translate-y-1/2 transition-opacity" />}
{col.label}
</th>
);
@ -4707,7 +4751,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
const rightDeleteVisible = (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
return (
<tr key={itemId} className={cn("group/action border-b border-border/50 transition-[background] duration-75 hover:bg-accent", idx % 2 === 1 && "bg-muted/50")}>
<tr key={itemId} className={cn("group/action border-b border-border/50 transition-[background] duration-75 hover:bg-accent", idx % 2 === 1 && "bg-muted/20")}>
{columnsToShow.map((col, colIdx) => (
<td
key={colIdx}
@ -4851,7 +4895,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<tr
className={cn(
"group/action cursor-pointer border-b border-border/50 transition-[background] duration-75",
isExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/50 hover:bg-accent" : "hover:bg-accent",
isExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/20 hover:bg-accent" : "hover:bg-accent",
)}
onClick={() => toggleRightItemExpansion(itemId)}
>

View File

@ -110,7 +110,7 @@ export const SingleTableWithSticky: React.FC<SingleTableWithStickyProps> = ({
>
<TableHeader
className={cn("border-b border-border/60", tableConfig?.stickyHeader && "sticky top-0 z-30 shadow-sm")}
style={{ backgroundColor: "hsl(var(--muted) / 0.8)" }}
style={{ backgroundColor: "hsl(var(--muted) / 0.4)" }}
>
<TableRow className="border-b border-border/60">
{actualColumns.map((column, colIndex) => {
@ -136,7 +136,7 @@ export const SingleTableWithSticky: React.FC<SingleTableWithStickyProps> = ({
? "h-9 border-0 px-3 py-1.5 text-center align-middle sm:px-4 sm:py-2"
: "text-muted-foreground hover:text-foreground h-9 cursor-pointer border-0 px-3 py-1.5 text-left align-middle text-[10px] font-bold uppercase tracking-[0.04em] whitespace-nowrap transition-all duration-200 select-none sm:px-4 sm:py-2 sm:text-xs",
`text-${column.align}`,
column.sortable && "hover:bg-muted/70",
column.sortable && "hover:bg-muted/50",
// 고정 컬럼 스타일
column.fixed === "left" && "border-border bg-background sticky z-40 border-r shadow-sm",
column.fixed === "right" && "border-border bg-background sticky z-40 border-l shadow-sm",
@ -151,7 +151,7 @@ export const SingleTableWithSticky: React.FC<SingleTableWithStickyProps> = ({
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap", // 텍스트 줄바꿈 방지
backgroundColor: "hsl(var(--muted) / 0.8)",
backgroundColor: "hsl(var(--muted) / 0.4)",
// sticky 위치 설정
...(column.fixed === "left" && { left: leftFixedWidth }),
...(column.fixed === "right" && { right: rightFixedWidth }),
@ -230,7 +230,7 @@ export const SingleTableWithSticky: React.FC<SingleTableWithStickyProps> = ({
key={`row-${index}`}
className={cn(
"cursor-pointer border-b border-border/50 transition-[background] duration-75",
index % 2 === 0 ? "bg-background" : "bg-muted/70",
index % 2 === 0 ? "bg-background" : "bg-muted/20",
tableConfig.tableStyle?.hoverEffect !== false && "hover:bg-accent",
)}
onClick={(e) => handleRowClick?.(row, index, e)}

View File

@ -5819,8 +5819,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
{/* 🆕 Multi-Level Headers (Column Bands) */}
{columnBandsInfo?.hasBands && (
<tr
className="border-primary/10 bg-muted/70 h-8 border-b sm:h-10"
style={{ backgroundColor: "hsl(var(--muted) / 0.7)" }}
className="border-border/60 bg-muted/40 h-8 border-b sm:h-10"
style={{ backgroundColor: "hsl(var(--muted) / 0.4)" }}
>
{visibleColumns.map((column, colIdx) => {
// 이 컬럼이 속한 band 찾기
@ -5863,7 +5863,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
<tr
className="bg-muted/80 h-10 border-b border-border/60 sm:h-12"
style={{
backgroundColor: "hsl(var(--muted) / 0.8)",
backgroundColor: "hsl(var(--muted) / 0.4)",
}}
>
{visibleColumns.map((column, columnIndex) => {
@ -5895,7 +5895,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
column.columnName === "__checkbox__" ? "px-0 py-1" : "px-3 py-2",
column.sortable !== false &&
column.columnName !== "__checkbox__" &&
"hover:text-foreground hover:bg-muted/70 cursor-pointer transition-colors",
"hover:text-foreground hover:bg-muted/50 cursor-pointer transition-colors",
sortColumn === column.columnName && "!text-primary",
isFrozen && "sticky z-40 shadow-[2px_0_4px_rgba(0,0,0,0.1)]",
// 🆕 Column Reordering 스타일
@ -5916,7 +5916,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
minWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
maxWidth: column.columnName === "__checkbox__" ? "48px" : undefined,
userSelect: "none",
backgroundColor: "hsl(var(--muted) / 0.8)",
backgroundColor: "hsl(var(--muted) / 0.4)",
...(isFrozen && { left: `${leftPosition}px` }),
}}
// 🆕 Column Reordering 이벤트
@ -6167,7 +6167,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
key={index}
className={cn(
"hover:bg-accent cursor-pointer border-b border-border/50 transition-[background] duration-75",
index % 2 === 0 ? "bg-background" : "bg-muted/70",
index % 2 === 0 ? "bg-background" : "bg-muted/20",
)}
onClick={(e) => handleRowClick(row, index, e)}
>
@ -6306,9 +6306,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
key={index}
className={cn(
"hover:bg-accent cursor-pointer border-b border-border/50 transition-[background] duration-75",
index % 2 === 0 ? "bg-background" : "bg-muted/70",
isRowSelected && "!bg-primary/15 hover:!bg-primary/20",
isRowSelected && "[&_td]:!border-b-primary/30",
index % 2 === 0 ? "bg-background" : "bg-muted/20",
isRowSelected && "!bg-primary/10 hover:!bg-primary/15",
isRowFocused && "ring-primary/50 ring-1 ring-inset",
isDragEnabled && "cursor-grab active:cursor-grabbing",
isDragging && "bg-muted opacity-50",
@ -6566,7 +6565,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
: undefined,
...(isFrozen && {
left: `${leftPosition}px`,
backgroundColor: "hsl(var(--muted) / 0.8)",
backgroundColor: "hsl(var(--muted) / 0.4)",
}),
}}
>