import React, { useEffect, useRef } from 'react'; import type { IndicatorConfig } from '../types'; import { getIndicatorChartTitle } from '../utils/indicatorRegistry'; import { formatBbLegendLabel } from '../utils/bollingerConfig'; interface IndicatorContextToolbarProps { indicatorId: string; config: IndicatorConfig | null; chartType?: string; screenX: number; screenY: number; onSettings: () => void; onToggleHidden: () => void; onRemove: () => void; onClose: () => void; /** 툴바 자체에 마우스 진입 시 hide 타이머 취소 */ onMouseEnterToolbar?: () => void; /** 툴바에서 마우스 이탈 시 hide 타이머 재시작 */ onMouseLeaveToolbar?: () => void; } /* SVG Icons */ const IcEye = ({ hidden }: { hidden: boolean }) => hidden ? ( ) : ( ); const IcGear = () => ( ); const IcTrash = () => ( ); const IcMore = () => ( ); /** 인디케이터 파라미터 요약 문자열 (예: "RSI (14)") */ function paramSummary(config: IndicatorConfig): string { if (config.type === 'BollingerBands') { return formatBbLegendLabel(config.params ?? {}); } const name = getIndicatorChartTitle(config.type); const nums = Object.values(config.params) .filter(v => typeof v === 'number') .slice(0, 2) .join(', '); return nums ? `${name} (${nums})` : name; } const IndicatorContextToolbar: React.FC = ({ indicatorId, config, chartType, screenX, screenY, onSettings, onToggleHidden, onRemove, onClose, onMouseEnterToolbar, onMouseLeaveToolbar, }) => { const ref = useRef(null); // hover 모드(onMouseEnterToolbar 존재)에선 hover leave 로만 닫힘 // 클릭 모드에선 외부 클릭 시 닫기 useEffect(() => { if (onMouseEnterToolbar) return; // hover 모드 → 외부 클릭 핸들러 불필요 const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) { onClose(); } }; const tid = setTimeout(() => document.addEventListener('mousedown', handler), 100); return () => { clearTimeout(tid); document.removeEventListener('mousedown', handler); }; }, [onClose, onMouseEnterToolbar]); // pane 좌측 상단 기준 (screenX = pane left, screenY = pane top) const W = 240; const isMain = indicatorId === '__main__'; /** 메인 캔들 pane 상단 tv-legend(OHLCV) 행 아래에 배치 */ const TOP_GAP_MAIN = 38; let left = screenX + 8; let top = screenY + (isMain ? TOP_GAP_MAIN : 8); // 화면 오른쪽 경계 보정 if (left + W > window.innerWidth - 8) left = window.innerWidth - W - 8; const isHidden = config?.hidden === true; const label = isMain ? (chartType === 'candlestick' ? '캔들스틱' : chartType ?? '메인 차트') : (config ? paramSummary(config) : indicatorId); return (
e.stopPropagation()} onMouseEnter={onMouseEnterToolbar} onMouseLeave={onMouseLeaveToolbar} > {/* 이름 */} {label} {/* 가시성 토글 */} {!isMain && ( )} {/* 설정 */} {/* 삭제 */} {!isMain && ( )} {/* 더보기 */}
); }; export default IndicatorContextToolbar;