feat: enhance ResponsiveGridRenderer with row margin calculations

- Added rowMinY and rowMaxBottom properties to ProcessedRow for improved layout calculations.
- Implemented dynamic margin adjustments between rows in the ResponsiveGridRenderer to enhance visual spacing.
- Refactored TabsWidget to streamline the ResponsiveGridRenderer integration, removing unnecessary wrapper divs for cleaner structure.
- Introduced ScaledCustomPanel for better handling of component rendering in split panel layouts.

Made-with: Cursor
This commit is contained in:
kjs
2026-03-12 14:19:48 +09:00
parent 966191786a
commit df47c27b77
7 changed files with 261 additions and 139 deletions

View File

@@ -62,6 +62,7 @@ function SortableColumnRow({
onLabelChange,
onWidthChange,
onFormatChange,
onSuffixChange,
onRemove,
onShowInSummaryChange,
onShowInDetailChange,
@@ -87,6 +88,7 @@ function SortableColumnRow({
onLabelChange: (value: string) => void;
onWidthChange: (value: number) => void;
onFormatChange: (checked: boolean) => void;
onSuffixChange?: (value: string) => void;
onRemove: () => void;
onShowInSummaryChange?: (checked: boolean) => void;
onShowInDetailChange?: (checked: boolean) => void;
@@ -177,15 +179,24 @@ function SortableColumnRow({
className="h-6 w-14 shrink-0 text-xs"
/>
{isNumeric && (
<label className="flex shrink-0 cursor-pointer items-center gap-1 text-[10px]" title="천 단위 구분자 (,)">
<input
type="checkbox"
checked={col.format?.thousandSeparator ?? false}
onChange={(e) => onFormatChange(e.target.checked)}
className="h-3 w-3"
<>
<label className="flex shrink-0 cursor-pointer items-center gap-1 text-[10px]" title="천 단위 구분자 (,)">
<input
type="checkbox"
checked={col.format?.thousandSeparator ?? false}
onChange={(e) => onFormatChange(e.target.checked)}
className="h-3 w-3"
/>
,
</label>
<Input
value={col.format?.suffix || ""}
onChange={(e) => onSuffixChange?.(e.target.value)}
placeholder="단위"
title="값 뒤에 붙는 단위 (예: mm, kg, %)"
className="h-6 w-10 shrink-0 text-[10px]"
/>
,
</label>
</>
)}
{/* 헤더/상세 표시 토글 */}
{onShowInSummaryChange && (
@@ -818,6 +829,18 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
};
updateTab({ columns: newColumns });
}}
onSuffixChange={(value) => {
const newColumns = [...selectedColumns];
newColumns[index] = {
...newColumns[index],
format: {
...newColumns[index].format,
type: "number",
suffix: value || undefined,
},
};
updateTab({ columns: newColumns });
}}
onRemove={() => updateTab({ columns: selectedColumns.filter((_, i) => i !== index) })}
onShowInSummaryChange={(checked) => {
const newColumns = [...selectedColumns];
@@ -2330,6 +2353,18 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
};
updateLeftPanel({ columns: newColumns });
}}
onSuffixChange={(value) => {
const newColumns = [...selectedColumns];
newColumns[index] = {
...newColumns[index],
format: {
...newColumns[index].format,
type: "number",
suffix: value || undefined,
},
};
updateLeftPanel({ columns: newColumns });
}}
onRemove={() =>
updateLeftPanel({ columns: selectedColumns.filter((_, i) => i !== index) })
}
@@ -2988,6 +3023,18 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
};
updateRightPanel({ columns: newColumns });
}}
onSuffixChange={(value) => {
const newColumns = [...selectedColumns];
newColumns[index] = {
...newColumns[index],
format: {
...newColumns[index].format,
type: "number",
suffix: value || undefined,
},
};
updateRightPanel({ columns: newColumns });
}}
onRemove={() =>
updateRightPanel({ columns: selectedColumns.filter((_, i) => i !== index) })
}