/** * LayoutPicker * TradingView 스타일 레이아웃 선택 팝업. */ import React, { useEffect, useRef } from 'react'; import type { LayoutDef, SyncOptions } from '../utils/layoutTypes'; import { LAYOUTS } from '../utils/layoutTypes'; // grid-template-areas 문자열을 파싱해 셀 rect 배열 반환 function parseAreas(def: LayoutDef, bw: number, bh: number, pad: number) { const areaGrid: string[][] = def.areas .split('"') .map(s => s.trim()) .filter(Boolean) .map(row => row.split(/\s+/).filter(Boolean)); if (areaGrid.length === 0) return []; const rowCount = areaGrid.length; const colCount = areaGrid[0]?.length ?? 1; const colW = bw / colCount; const rowH = bh / rowCount; const cellMap = new Map(); for (let ri = 0; ri < areaGrid.length; ri++) { for (let ci = 0; ci < (areaGrid[ri]?.length ?? 0); ci++) { const name = areaGrid[ri][ci]; if (!name || name === '.') continue; const existing = cellMap.get(name); if (!existing) { cellMap.set(name, { c1: ci, r1: ri, c2: ci + 1, r2: ri + 1 }); } else { cellMap.set(name, { c1: Math.min(existing.c1, ci), r1: Math.min(existing.r1, ri), c2: Math.max(existing.c2, ci + 1), r2: Math.max(existing.r2, ri + 1), }); } } } return Array.from(cellMap.values()).map(r => ({ x: pad + r.c1 * colW, y: pad + r.r1 * rowH, w: (r.c2 - r.c1) * colW, h: (r.r2 - r.r1) * rowH, })); } // ── 레이아웃 미니 아이콘 (SVG) ──────────────────────────────────────────────── const LayoutIcon: React.FC<{ def: LayoutDef; size?: number }> = ({ def, size = 34 }) => { const S = size; const PAD = 2; const BW = S - PAD * 2; const BH = S - PAD * 2; const rects = parseAreas(def, BW, BH, PAD); return ( {rects.map((r, i) => ( ))} ); }; // ── 토글 스위치 ────────────────────────────────────────────────────────────── const Toggle: React.FC<{ checked: boolean; onChange: () => void }> = ({ checked, onChange }) => ( ))} ); })}
{/* SYNC IN LAYOUT */}
SYNC IN LAYOUT
{([ ['symbol', 'Symbol'], ['interval', 'Interval'], ['crosshair', 'Crosshair'], ['time', 'Time'], ['dateRange', 'Date range'], ] as [keyof SyncOptions, string][]).map(([key, label]) => (
{label} onSyncChange(key, !syncOptions[key])} />
))}
); }; export default LayoutPicker;