매매 시그널 디테일 팝업 기능 적용
This commit is contained in:
@@ -64,6 +64,7 @@ import { chartHasStaleIndicators, classifyIndicatorChartChange, singleIndParamKe
|
||||
import { sortIndicatorsForPaneLoad } from '../utils/indicatorPaneMerge';
|
||||
import type { ChartPaneSeparatorOptions } from '../types/chartPaneSeparator';
|
||||
import PaneSeparatorOverlay from './PaneSeparatorOverlay';
|
||||
import { centerChartOnSignalBar } from '../utils/tradeSignalChartMarkers';
|
||||
|
||||
interface TradingChartProps {
|
||||
bars: OHLCVBar[];
|
||||
@@ -182,6 +183,12 @@ interface TradingChartProps {
|
||||
resolveInitialDisplayCount?: (plotWidth: number) => number;
|
||||
/** true — reload·layout 복구 타이머의 반복 viewport 재조정 생략 (미니 카드 깜빡임 방지) */
|
||||
skipViewportRecovery?: boolean;
|
||||
/** true — 캔들 숨김, 보조지표 pane 선형 그래프만 표시 (시그널 상세 하단 차트 등) */
|
||||
auxIndicatorOnly?: boolean;
|
||||
/** 지정 시 초기 visible range 대신 시그널 봉 시간축 중앙 정렬 */
|
||||
centerOnSignalTime?: number;
|
||||
/** centerOnSignalTime 사용 시 화면에 보일 봉 수 (미지정 시 전체) */
|
||||
centerVisibleBarCount?: number;
|
||||
}
|
||||
|
||||
const TradingChart: React.FC<TradingChartProps> = ({
|
||||
@@ -237,6 +244,9 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
onOpenCustom1OverlaySettings,
|
||||
resolveInitialDisplayCount,
|
||||
skipViewportRecovery = false,
|
||||
auxIndicatorOnly = false,
|
||||
centerOnSignalTime,
|
||||
centerVisibleBarCount,
|
||||
}) => {
|
||||
const effectiveShowChartRightToolbar = showChartRightToolbar ?? showPaneLegend;
|
||||
const showOverlayControlsOnly = !!(
|
||||
@@ -324,6 +334,9 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
const chartVisibleRef = useRef(chartVisible);
|
||||
const resolveInitialDisplayCountRef = useRef(resolveInitialDisplayCount);
|
||||
const skipViewportRecoveryRef = useRef(skipViewportRecovery);
|
||||
const auxIndicatorOnlyRef = useRef(auxIndicatorOnly);
|
||||
const centerOnSignalTimeRef = useRef(centerOnSignalTime);
|
||||
const centerVisibleBarCountRef = useRef(centerVisibleBarCount);
|
||||
const lastViewportFitRef = useRef<{ count: number; width: number } | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -334,6 +347,27 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
skipViewportRecoveryRef.current = skipViewportRecovery;
|
||||
}, [skipViewportRecovery]);
|
||||
|
||||
useEffect(() => {
|
||||
auxIndicatorOnlyRef.current = auxIndicatorOnly;
|
||||
}, [auxIndicatorOnly]);
|
||||
|
||||
useEffect(() => {
|
||||
centerOnSignalTimeRef.current = centerOnSignalTime;
|
||||
}, [centerOnSignalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
centerVisibleBarCountRef.current = centerVisibleBarCount;
|
||||
}, [centerVisibleBarCount]);
|
||||
|
||||
const applySnapshotViewport = useCallback((mgr: ChartManager) => {
|
||||
const t = centerOnSignalTimeRef.current;
|
||||
if (t != null && Number.isFinite(t)) {
|
||||
centerChartOnSignalBar(mgr, t, centerVisibleBarCountRef.current);
|
||||
} else {
|
||||
mgr.fitContent();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const chartTimeFormat = useChartTimeFormat();
|
||||
const [chartMgr, setChartMgr] = useState<ChartManager | null>(null);
|
||||
/** 초기 reloadAll 완료 전 — pane 구분선·부분 레이아웃 노출 방지 */
|
||||
@@ -523,7 +557,9 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
mgr.applyCandleOnlyLayout(true, wrapperH);
|
||||
required = wrapperH;
|
||||
} else {
|
||||
if (mgr.isCandleOnlyLayout()) {
|
||||
if (auxIndicatorOnlyRef.current) {
|
||||
mgr.applyAuxIndicatorOnlyLayout(true);
|
||||
} else if (mgr.isCandleOnlyLayout()) {
|
||||
mgr.restoreFromCandleFullscreen(wrapperH);
|
||||
}
|
||||
// 사용자 드래그 비율 우선, 없으면 prop 기반 비율
|
||||
@@ -587,9 +623,13 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
applyPaneLayout(mgr);
|
||||
requestAnimationFrame(() => {
|
||||
try { mgr.autoScale(); } catch { /* ok */ }
|
||||
applyInitialVisibleRange(mgr);
|
||||
if (centerOnSignalTimeRef.current != null && Number.isFinite(centerOnSignalTimeRef.current)) {
|
||||
applySnapshotViewport(mgr);
|
||||
} else {
|
||||
applyInitialVisibleRange(mgr);
|
||||
}
|
||||
});
|
||||
}, [applyPaneLayout, applyInitialVisibleRange]);
|
||||
}, [applyPaneLayout, applyInitialVisibleRange, applySnapshotViewport]);
|
||||
|
||||
/** 캔들 확대 보기 → 원복 직후 가격·시간축·pane 비율 정상화 */
|
||||
useEffect(() => {
|
||||
@@ -647,6 +687,8 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
const afterIndicatorPaneMutation = useCallback((mgr: ChartManager) => {
|
||||
if (candleOnlyModeRef.current) {
|
||||
mgr.applyCandleOnlyLayout(true, wrapperRef.current?.clientHeight);
|
||||
} else if (auxIndicatorOnlyRef.current) {
|
||||
mgr.applyAuxIndicatorOnlyLayout(true);
|
||||
} else if (mgr.isCandleOnlyLayout()) {
|
||||
mgr.restoreFromCandleFullscreen(wrapperRef.current?.clientHeight);
|
||||
}
|
||||
@@ -960,6 +1002,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
mgr.setCandleAreaPriceLabelsEnabled(resolvedCandlePriceLabels);
|
||||
mgr.setIndicatorAreaPriceLabelsEnabled(resolvedIndicatorPriceLabels);
|
||||
if (paneSeparatorOptions) mgr.setPaneSeparatorOptions(paneSeparatorOptions);
|
||||
if (auxIndicatorOnlyRef.current) mgr.applyAuxIndicatorOnlyLayout(true);
|
||||
onManagerReady(mgr);
|
||||
|
||||
const unsub = mgr.subscribeCrosshair((p: MouseEventParams<Time>) => {
|
||||
|
||||
Reference in New Issue
Block a user