Files
invyone/frontend/lib/registry/components/divider/InvDividerConfigPanel.tsx
T
DDD1542 a8ded6455d refactor: ConfigPanel Inv 네이밍 통합 + legacy 패널 분리 + input cp 마이그
11 패널 일괄 Inv* prefix 통일:
- 통합 (lib/registry/components/X/): button / container / divider / search /
  stats / table / title / input → Inv*ConfigPanel
- frontend/components/v2/config-panels/V2FieldConfigPanel → InvFieldConfigPanel
- 옛 v2-* hidden 호환 → InvLegacy{Divider,Text,Button}ConfigPanel

input 통합 컴포넌트 cp 톤 신규 작성 (InvInputConfigPanel):
- 277줄 옛 디자인 → CPVisualGrid 10칸 type 카드 + 타입별 옵션 + FeatureChipGrid

getComponentConfigPanel.tsx 버그 수정 (Codex 검토):
- "stats" key 중복 제거 (옛 StatsCardConfigPanel 이 통합 stats 덮던 silent bug)
- ALIAS 에서 v2-button-primary/v2-divider-line/v2-text-display 제외
  (옵션 B 일관성 — 옛 hidden 컴포넌트는 InvLegacy 패널 사용)
- MAP 의 해당 키를 InvLegacy* 로 직접 매핑

호출처 일괄 갱신:
- 각 통합 컴포넌트의 index.ts 7개 (import / config_panel / re-export)
- v2-input/v2-select/v2-divider-line/v2-text-display/v2-button-primary
  의 index.ts (config_panel 매핑)
- V2PropertiesPanel.tsx 의 require pattern (v2-input/v2-select)

검증: tsc 우리 영역 0건 / V2FieldConfigPanel 잔재 0건 / 기존 path 잔재 0건

다음 세션: useDbTables hook 추출 + 잔여 V2* cp 마이그 + dead code 정리

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 17:57:57 +09:00

195 lines
6.3 KiB
TypeScript

"use client";
/**
* InvDividerConfigPanel — 통합 "구분선" (id: divider) cp 톤 설정 패널
*
* 흐름:
* ① 모양 — 방향 (CPSegment) + 두께 (CPVisualGrid 시각 미리보기) + 선 스타일 (CPVisualGrid 시각 미리보기)
* ② 색 — CPColor
* ③ 텍스트 (가로 전용 조건부)
* ▾ 고급 — 둥근 끝 (FeatureChipGrid)
*
* Reference: notes/gbpark/2026-04-28-cp-panel-standard.md
*/
import React from "react";
import {
CPSection,
CPRow,
CPGroup,
CPText,
CPColor,
CPSegment,
CPVisualGrid,
FeatureChipGrid,
Hint,
} from "@/components/v2/config-panels/_shared/cp";
import type { DividerConfig } from "./types";
export interface InvDividerConfigPanelProps {
config?: DividerConfig;
onChange?: (config: DividerConfig) => void;
onUpdateProperty?: (componentId: string, path: string, value: unknown) => void;
selectedComponent?: { id: string; config?: DividerConfig; [k: string]: any };
}
const DEFAULT_COLOR = "#d1d5db";
export const InvDividerConfigPanel: React.FC<InvDividerConfigPanelProps> = ({
config,
onChange,
onUpdateProperty,
selectedComponent,
}) => {
const current: DividerConfig =
(config as DividerConfig) || (selectedComponent?.config as DividerConfig) || {};
const patch = (p: Partial<DividerConfig>) => {
const next = { ...current, ...p };
onChange?.(next);
if (selectedComponent?.id) {
Object.entries(p).forEach(([key, value]) => {
onUpdateProperty?.(selectedComponent.id, `config.${key}`, value);
});
}
};
const orientation = current.orientation || "horizontal";
const lineColor = current.color || DEFAULT_COLOR;
const thickness = current.thickness || "1px";
const lineStyle = current.lineStyle || "solid";
const isHorizontal = orientation === "horizontal";
return (
<div style={{ fontFamily: "var(--v5-font-sans)", color: "var(--cp-text)", padding: "0 12px" }}>
{/* ── ① 모양 ─────────────────────────── */}
<CPSection title="① 모양" desc="방향 / 두께 / 선 스타일">
<CPRow label="방향">
<CPSegment
value={orientation}
onChange={(v) => patch({ orientation: v as DividerConfig["orientation"] })}
options={[
{ value: "horizontal", label: "가로" },
{ value: "vertical", label: "세로" },
]}
/>
</CPRow>
<div style={{ marginTop: 8 }}>
<CPRow label="두께" />
<CPVisualGrid
cols={3}
cardHeight={44}
value={thickness}
onChange={(v) => patch({ thickness: v })}
options={[
{
value: "1px",
label: "얇게",
preview: <div style={{ width: 36, height: 1, background: lineColor }} />,
},
{
value: "2px",
label: "보통",
preview: <div style={{ width: 36, height: 2, background: lineColor }} />,
},
{
value: "4px",
label: "두껍게",
preview: <div style={{ width: 36, height: 4, background: lineColor }} />,
},
]}
/>
<div style={{ marginTop: 6 }}>
<CPRow label="자유 입력" help="예: 3px / 0.5rem">
<CPText
value={thickness}
onChange={(v) => patch({ thickness: v })}
placeholder="1px"
/>
</CPRow>
</div>
</div>
<div style={{ marginTop: 8 }}>
<CPRow label="선 스타일" />
<CPVisualGrid
cols={3}
cardHeight={44}
value={lineStyle}
onChange={(v) => patch({ lineStyle: v as DividerConfig["lineStyle"] })}
options={[
{
value: "solid",
label: "실선",
preview: (
<div style={{ width: 36, borderTop: `2px solid ${lineColor}` }} />
),
},
{
value: "dashed",
label: "파선",
preview: (
<div style={{ width: 36, borderTop: `2px dashed ${lineColor}` }} />
),
},
{
value: "dotted",
label: "점선",
preview: (
<div style={{ width: 36, borderTop: `2px dotted ${lineColor}` }} />
),
},
]}
/>
</div>
</CPSection>
{/* ── ② 색 ─────────────────────────── */}
<CPSection title="② 색">
<CPRow label="선 색">
<CPColor value={lineColor} onChange={(v) => patch({ color: v })} />
</CPRow>
</CPSection>
{/* ── ③ 텍스트 (가로 전용) ─────────────────────────── */}
{isHorizontal && (
<CPSection title="③ 텍스트" desc="선 가운데 텍스트 (선택)">
<CPRow label="가운데 텍스트" help="비우면 선만 표시">
<CPText
value={current.text || ""}
onChange={(v) => patch({ text: v || undefined })}
placeholder="구분"
/>
</CPRow>
</CPSection>
)}
{!isHorizontal && (
<Hint> .</Hint>
)}
{/* ── ▾ 고급 ─────────────────────────── */}
{isHorizontal && (
<CPGroup title="고급 설정" defaultOpen={false}>
<FeatureChipGrid
items={[
{
key: "rounded",
label: "둥근 끝",
desc: "선의 양쪽 끝을 둥글게(border-radius) 처리합니다.\n두꺼운 선(2px+) 일 때 자연스러워요.\n가로 방향에서만 적용됩니다.",
},
]}
source={current as any}
onToggle={(k, v) => patch({ [k]: v } as Partial<DividerConfig>)}
/>
</CPGroup>
)}
</div>
);
};
InvDividerConfigPanel.displayName = "InvDividerConfigPanel";
export default InvDividerConfigPanel;