{"version":3,"file":"index.cjs","sources":["../src/core/DataManager.ts","../src/core/drawing/DrawingSnapManager.ts","../src/core/drawing/DrawingMeasureManager.ts","../src/core/drawing/DrawingObjectManager.ts","../src/core/drawing/DrawingStateManager.ts","../src/core/drawing/DrawingToolHandler.ts","../src/renderers/unified/TextRenderer.ts","../src/components/TextInputModal.ts","../src/core/DrawingManager.ts","../src/core/MarkerManager.ts","../src/core/StopLossManager.ts","../src/core/LineSeriesManager.ts","../src/core/InteractionManager.ts","../src/utils/webgl-utils.ts","../src/core/BufferPool.ts","../src/core/WebGLRenderer.ts","../src/core/ChartPanel.ts","../src/core/UnifiedCoordinateSystem.ts","../src/utils/cursor.ts","../src/panels/chart/ChartEventController.ts","../src/rendering/UnifiedChartRenderer.ts","../src/renderers/GridRenderer.ts","../src/utils/formatters.ts","../src/renderers/LabelRenderer.ts","../src/renderers/CrosshairLabelRenderer.ts","../src/renderers/LineSeriesRenderer.ts","../src/renderers/unified/WebGLLineHelper.ts","../src/renderers/unified/CrosshairRenderer.ts","../src/renderers/unified/DrawingRenderer.ts","../src/renderers/unified/SnapPointRenderer.ts","../src/renderers/unified/MeasureRenderer.ts","../src/renderers/unified/MarkerRenderer.ts","../src/renderers/UnifiedRenderer.ts","../src/panels/chart/ChartRendererManager.ts","../src/panels/chart/ChartUIManager.ts","../src/panels/MainChartPanel.ts","../src/utils/volumeMA.ts","../src/panels/volume/VolumeRendererManager.ts","../src/panels/VolumePanel.ts","../src/ui/AxisRenderer.ts","../src/renderers/XAxisRenderer.ts","../src/core/PanelManager.ts","../src/core/RenderingManager.ts","../src/plugins/IndicatorPlugin.ts","../src/indicators/SMA.ts","../src/plugins/indicators/SMAPlugin.ts","../src/indicators/EMA.ts","../src/plugins/indicators/EMAPlugin.ts","../src/plugins/indicators/index.ts","../src/core/IndicatorManager.ts","../src/core/PluginManager.ts","../src/utils/theme.ts","../src/core/chart/ChartEventHandler.ts","../src/core/chart/ChartLifecycle.ts","../src/core/chart/ChartLineSeriesHelper.ts","../src/core/chart/ChartStopLossHelper.ts","../src/core/chart/ChartStyleHelper.ts","../src/core/chart/ChartViewportHelper.ts","../src/utils/candleResampler.ts","../src/core/chart/ChartDataHelper.ts","../src/core/chart/ChartDrawingHelper.ts","../src/core/chart/ChartMarkerHelper.ts","../src/core/chart/ChartExportHelper.ts","../src/core/chart/ChartThemeHelper.ts","../src/core/chart/ChartUIHelper.ts","../src/utils/timeframeDetector.ts","../src/core/chart/ChartIndicatorHelper.ts","../src/core/Chart.ts","../node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/react-integration/useChart.ts","../src/react-integration/Chart.tsx","../src/index.ts"],"sourcesContent":["import type { Candle, ChartData } from '@/types';\n\nexport class DataManager {\n  private data: ChartData | null = null;\n  \n  constructor() {}\n  \n  /**\n   * 캔들 배열을 TypedArray 기반 ChartData로 변환\n   */\n  setData(candles: Candle[]): void {\n    if (!candles || candles.length === 0) {\n      this.data = null;\n      return;\n    }\n    \n    const length = candles.length;\n    \n    // TypedArray 할당\n    const times = new Float64Array(length);\n    const opens = new Float32Array(length);\n    const highs = new Float32Array(length);\n    const lows = new Float32Array(length);\n    const closes = new Float32Array(length);\n    const volumes = new Float32Array(length);\n    \n    let minPrice = Infinity;\n    let maxPrice = -Infinity;\n    let minTime = Infinity;\n    let maxTime = -Infinity;\n    \n    // 데이터 복사 및 범위 계산\n    for (let i = 0; i < length; i++) {\n      const candle = candles[i];\n      \n      times[i] = candle.time;\n      opens[i] = candle.open;\n      highs[i] = candle.high;\n      lows[i] = candle.low;\n      closes[i] = candle.close;\n      volumes[i] = candle.volume;\n      \n      minPrice = Math.min(minPrice, candle.low);\n      maxPrice = Math.max(maxPrice, candle.high);\n      minTime = Math.min(minTime, candle.time);\n      maxTime = Math.max(maxTime, candle.time);\n    }\n    \n    this.data = {\n      times,\n      opens,\n      highs,\n      lows,\n      closes,\n      volumes,\n      length,\n      timeRange: [minTime, maxTime],\n      priceRange: [minPrice, maxPrice]\n    };\n  }\n  \n  /**\n   * 시간 범위에 해당하는 데이터 인덱스 찾기 (이진 탐색)\n   */\n  findVisibleRange(startTime: number, endTime: number): { start: number; end: number } | null {\n    if (!this.data) return null;\n    \n    const { times, length } = this.data;\n    \n    // 시작 인덱스 찾기\n    let start = 0;\n    let end = length - 1;\n    let startIndex = 0;\n    \n    while (start <= end) {\n      const mid = Math.floor((start + end) / 2);\n      if (times[mid] < startTime) {\n        start = mid + 1;\n      } else {\n        startIndex = mid;\n        end = mid - 1;\n      }\n    }\n    \n    // 끝 인덱스 찾기\n    start = startIndex;\n    end = length - 1;\n    let endIndex = length - 1;\n    \n    while (start <= end) {\n      const mid = Math.floor((start + end) / 2);\n      if (times[mid] <= endTime) {\n        endIndex = mid;\n        start = mid + 1;\n      } else {\n        end = mid - 1;\n      }\n    }\n    \n    // 여유분 추가 (화면 밖 1-2개 캔들)\n    startIndex = Math.max(0, startIndex - 2);\n    endIndex = Math.min(length - 1, endIndex + 2);\n    \n    return { start: startIndex, end: endIndex };\n  }\n  \n  /**\n   * 특정 인덱스의 캔들 데이터 가져오기\n   */\n  getCandle(index: number): Candle | null {\n    if (!this.data || index < 0 || index >= this.data.length) {\n      return null;\n    }\n    \n    return {\n      time: this.data.times[index],\n      open: this.data.opens[index],\n      high: this.data.highs[index],\n      low: this.data.lows[index],\n      close: this.data.closes[index],\n      volume: this.data.volumes[index]\n    };\n  }\n  \n  /**\n   * 가격 범위 계산 (보이는 영역)\n   */\n  getPriceRange(startIndex: number, endIndex: number): [number, number] | null {\n    if (!this.data) return null;\n    \n    let minPrice = Infinity;\n    let maxPrice = -Infinity;\n    \n    for (let i = startIndex; i <= endIndex && i < this.data.length; i++) {\n      minPrice = Math.min(minPrice, this.data.lows[i]);\n      maxPrice = Math.max(maxPrice, this.data.highs[i]);\n    }\n    \n    // 여유분 추가 (위아래 10%)\n    const padding = (maxPrice - minPrice) * 0.1;\n    return [minPrice - padding, maxPrice + padding];\n  }\n  \n  /**\n   * 시간에 해당하는 정확한 캔들 인덱스 찾기\n   */\n  getIndexForTime(time: number): number {\n    if (!this.data || this.data.length === 0) return -1;\n    \n    const { times, length } = this.data;\n    \n    // 이진 탐색으로 정확한 인덱스 찾기\n    let left = 0;\n    let right = length - 1;\n    \n    while (left <= right) {\n      const mid = Math.floor((left + right) / 2);\n      \n      if (times[mid] === time) {\n        return mid;\n      } else if (times[mid] < time) {\n        left = mid + 1;\n      } else {\n        right = mid - 1;\n      }\n    }\n    \n    // 정확히 일치하는 시간이 없으면 가장 가까운 인덱스 반환\n    return this.findNearestIndex(time);\n  }\n  \n  /**\n   * 시간에 가장 가까운 캔들 인덱스 찾기\n   */\n  findNearestIndex(time: number): number {\n    if (!this.data || this.data.length === 0) return -1;\n    \n    const { times, length } = this.data;\n    \n    let left = 0;\n    let right = length - 1;\n    let nearest = 0;\n    let minDiff = Math.abs(times[0] - time);\n    \n    while (left <= right) {\n      const mid = Math.floor((left + right) / 2);\n      const diff = Math.abs(times[mid] - time);\n      \n      if (diff < minDiff) {\n        minDiff = diff;\n        nearest = mid;\n      }\n      \n      if (times[mid] < time) {\n        left = mid + 1;\n      } else if (times[mid] > time) {\n        right = mid - 1;\n      } else {\n        return mid;\n      }\n    }\n    \n    return nearest;\n  }\n  \n  getData(): ChartData | null {\n    return this.data;\n  }\n  \n  isEmpty(): boolean {\n    return !this.data || this.data.length === 0;\n  }\n  \n  getLength(): number {\n    return this.data?.length ?? 0;\n  }\n  \n  /**\n   * 평균 캔들 간격 계산 (초 단위)\n   */\n  getCandleInterval(): number {\n    if (!this.data || this.data.length < 2) return 60; // 기본값 1분\n    \n    // 처음 10개 캔들의 평균 간격 계산\n    const sampleSize = Math.min(10, this.data.length - 1);\n    let totalInterval = 0;\n    \n    for (let i = 1; i <= sampleSize; i++) {\n      totalInterval += this.data.times[i] - this.data.times[i - 1];\n    }\n    \n    return totalInterval / sampleSize;\n  }\n}","import type { Candle } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\nexport interface SnapPoint {\n  x: number;\n  y: number;\n  type: 'high' | 'low' | 'open' | 'close';\n  price: number;\n  time: number;\n  index: number;\n}\n\nexport class DrawingSnapManager {\n  private isMagneticMode: boolean = true; // 기본값 true로 변경\n  private currentSnapPoint: SnapPoint | null = null;\n  private onSnapChange?: (snap: SnapPoint | null) => void;\n\n  setMagneticMode(enabled: boolean): void {\n    this.isMagneticMode = enabled;\n    if (!enabled) {\n      this.updateSnapPoint(null);\n    }\n  }\n\n  getMagneticMode(): boolean {\n    return this.isMagneticMode;\n  }\n\n  setSnapChangeCallback(callback: (snap: SnapPoint | null) => void): void {\n    this.onSnapChange = callback;\n  }\n\n  private updateSnapPoint(point: SnapPoint | null): void {\n    this.currentSnapPoint = point;\n    if (this.onSnapChange) {\n      this.onSnapChange(point);\n    }\n  }\n\n  findSnapPoint(\n    mouseX: number,\n    mouseY: number,\n    candles: Candle[],\n    coordSystem: UnifiedCoordinateSystem,\n    threshold: number = 30\n  ): SnapPoint | null {\n    if (!this.isMagneticMode || !candles || candles.length === 0) return null;\n    \n    // 마우스 X 좌표를 직접 캔들 인덱스로 변환\n    const canvasCoords = coordSystem.cssToCanvas(mouseX, mouseY);\n    const centerIndex = Math.round(coordSystem.canvasXToIndex(canvasCoords.x));\n    \n    \n    // 좌우 2개씩 총 5개 캔들 검사\n    const searchRange = 2;\n    let closestPoint: SnapPoint | null = null;\n    let minDistance = Infinity;\n    \n    for (let i = centerIndex - searchRange; i <= centerIndex + searchRange; i++) {\n      if (i < 0 || i >= candles.length) continue;\n      \n      const candle = candles[i];\n      if (!candle) continue;\n      \n      // OHLC 값들\n      const points = [\n        { price: candle.high, type: 'high' as const },\n        { price: candle.low, type: 'low' as const },\n        { price: candle.open, type: 'open' as const },\n        { price: candle.close, type: 'close' as const }\n      ];\n      \n      for (const point of points) {\n        // 차트 좌표를 CSS 좌표로 변환 - main 패널 지정\n        const cssCoords = coordSystem.chartToCSS(i, point.price, 'main');\n        \n        // 마우스와의 거리 계산\n        const dx = cssCoords.x - mouseX;\n        const dy = cssCoords.y - mouseY;\n        const distance = Math.sqrt(dx * dx + dy * dy);\n        \n        if (distance < minDistance) {\n          minDistance = distance;\n          closestPoint = {\n            x: cssCoords.x,\n            y: cssCoords.y,\n            type: point.type,\n            price: point.price,\n            time: candle.time,\n            index: i\n          };\n        }\n      }\n    }\n    \n    // 임계값 내에 있는 경우만 스냅\n    if (closestPoint && minDistance < threshold) {\n      this.updateSnapPoint(closestPoint);\n      return closestPoint;\n    }\n    \n    this.updateSnapPoint(null);\n    return null;\n  }\n\n  getCurrentSnapPoint(): SnapPoint | null {\n    return this.currentSnapPoint;\n  }\n}","import type { ChartPoint } from '@/types';\n\nexport class DrawingMeasureManager {\n  private measureMode: boolean = false;\n  private measureStartPoint: ChartPoint | null = null;\n  private measureEndPoint: ChartPoint | null = null;\n  private measureFixed: boolean = false;\n  private onMeasureChange?: (start: ChartPoint | null, end: ChartPoint | null, fixed: boolean) => void;\n\n  setMeasureChangeCallback(callback: (start: ChartPoint | null, end: ChartPoint | null, fixed: boolean) => void): void {\n    this.onMeasureChange = callback;\n  }\n\n  startMeasure(point: ChartPoint): void {\n    this.measureMode = true;\n    this.measureStartPoint = point;\n    this.measureEndPoint = null;\n    this.measureFixed = false;\n    \n    if (this.onMeasureChange) {\n      this.onMeasureChange(this.measureStartPoint, null, false);\n    }\n  }\n\n  updateMeasure(endPoint: ChartPoint): void {\n    if (!this.measureMode || !this.measureStartPoint || this.measureFixed) return;\n    \n    this.measureEndPoint = endPoint;\n    if (this.onMeasureChange) {\n      this.onMeasureChange(this.measureStartPoint, this.measureEndPoint, false);\n    }\n  }\n\n  fixMeasure(endPoint: ChartPoint): void {\n    if (!this.measureMode || !this.measureStartPoint) return;\n    \n    this.measureEndPoint = endPoint;\n    this.measureFixed = true;\n    \n    if (this.onMeasureChange) {\n      this.onMeasureChange(this.measureStartPoint, this.measureEndPoint, true);\n    }\n  }\n\n  cancelMeasure(): void {\n    this.measureMode = false;\n    this.measureStartPoint = null;\n    this.measureEndPoint = null;\n    this.measureFixed = false;\n    \n    if (this.onMeasureChange) {\n      this.onMeasureChange(null, null, false);\n    }\n  }\n\n  isMeasureMode(): boolean {\n    return this.measureMode;\n  }\n\n  getMeasurePoints(): { start: ChartPoint | null; end: ChartPoint | null; fixed: boolean } {\n    return {\n      start: this.measureStartPoint,\n      end: this.measureEndPoint,\n      fixed: this.measureFixed\n    };\n  }\n\n  isMeasureFixed(): boolean {\n    return this.measureFixed;\n  }\n}","import type { DrawingObject, ChartPoint, DrawingToolType } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\nexport class DrawingObjectManager {\n  private drawings: DrawingObject[] = [];\n  private selectedDrawing: DrawingObject | null = null;\n  private nextId: number = 1;\n\n  addDrawing(drawing: DrawingObject): void {\n    this.drawings.push(drawing);\n  }\n\n  removeDrawing(id: string): void {\n    this.drawings = this.drawings.filter(d => d.id !== id);\n    if (this.selectedDrawing?.id === id) {\n      this.selectedDrawing = null;\n    }\n  }\n\n  getAllDrawings(): DrawingObject[] {\n    return [...this.drawings];\n  }\n\n  getSelectedDrawing(): DrawingObject | null {\n    return this.selectedDrawing;\n  }\n\n  selectDrawing(drawing: DrawingObject | null): void {\n    // 이전 선택 해제\n    if (this.selectedDrawing) {\n      this.selectedDrawing.selected = false;\n    }\n    \n    this.selectedDrawing = drawing;\n    \n    // 새로운 선택\n    if (drawing) {\n      drawing.selected = true;\n    }\n  }\n\n  selectDrawingAt(x: number, y: number, coordSystem: UnifiedCoordinateSystem, tolerance: number = 10): DrawingObject | null {\n    \n    // 클릭 위치를 차트 좌표로 변환 (CSS 좌표 기준) - main 패널 명시\n    const chartCoords = coordSystem.cssToChart(x, y, 'main');\n    const clickTime = chartCoords.time;\n    const clickPrice = chartCoords.price;\n    \n    // 역순으로 검사 (최근에 그린 것부터)\n    for (let i = this.drawings.length - 1; i >= 0; i--) {\n      const drawing = this.drawings[i];\n      \n      if (this.isPointOnDrawing(drawing, clickTime, clickPrice, coordSystem, tolerance)) {\n        this.selectDrawing(drawing);\n        return drawing;\n      }\n    }\n    \n    this.selectDrawing(null);\n    return null;\n  }\n  \n  checkDrawingAt(x: number, y: number, coordSystem: UnifiedCoordinateSystem, tolerance: number = 10): DrawingObject | null {\n    // 클릭 위치를 차트 좌표로 변환 (CSS 좌표 기준) - main 패널 명시\n    const chartCoords = coordSystem.cssToChart(x, y, 'main');\n    const clickTime = chartCoords.time;\n    const clickPrice = chartCoords.price;\n    \n    // 역순으로 검사 (최근에 그린 것부터)\n    for (let i = this.drawings.length - 1; i >= 0; i--) {\n      const drawing = this.drawings[i];\n      \n      if (this.isPointOnDrawing(drawing, clickTime, clickPrice, coordSystem, tolerance)) {\n        return drawing;\n      }\n    }\n    \n    return null;\n  }\n\n  private isPointOnDrawing(drawing: DrawingObject, time: number, price: number, coordSystem: UnifiedCoordinateSystem, tolerance: number): boolean {\n    switch (drawing.type) {\n      case 'trendline':\n      case 'horizontal':\n        return this.isPointOnLine(drawing, time, price, coordSystem, tolerance);\n      \n      case 'text':\n      case 'marker':\n        return this.isPointOnMarker(drawing, time, price, coordSystem, tolerance);\n      \n      case 'circle':\n        return this.isPointOnCircle(drawing, time, price, coordSystem, tolerance);\n        \n      case 'rectangle':\n        return this.isPointOnRectangle(drawing, time, price, coordSystem, tolerance);\n      \n      default:\n        return false;\n    }\n  }\n\n  private isPointOnLine(drawing: DrawingObject, time: number, price: number, coordSystem: UnifiedCoordinateSystem, tolerance: number): boolean {\n    if (drawing.points.length < 2) return false;\n    \n    const p1 = drawing.points[0];\n    const p2 = drawing.points[1];\n    \n    \n    // 수평선의 경우\n    if (drawing.type === 'horizontal') {\n      const lineCSS = coordSystem.chartToCSS(p1.time, p1.price, 'main');\n      const clickCSS = coordSystem.chartToCSS(time, price, 'main');\n      return Math.abs(lineCSS.y - clickCSS.y) <= tolerance;\n    }\n    \n    // 트렌드라인의 경우 - 점과 선분 사이의 거리 계산\n    const p1CSS = coordSystem.chartToCSS(p1.time, p1.price, 'main');\n    const p2CSS = coordSystem.chartToCSS(p2.time, p2.price, 'main');\n    const clickCSS = coordSystem.chartToCSS(time, price, 'main');\n    \n    const x1 = p1CSS.x;\n    const y1 = p1CSS.y;\n    const x2 = p2CSS.x;\n    const y2 = p2CSS.y;\n    const px = clickCSS.x;\n    const py = clickCSS.y;\n    \n    // 점과 선분 사이의 거리\n    const distance = this.pointToLineDistance(px, py, x1, y1, x2, y2);\n    \n    return distance <= tolerance;\n  }\n\n  private isPointOnMarker(drawing: DrawingObject, time: number, price: number, coordSystem: UnifiedCoordinateSystem, tolerance: number): boolean {\n    if (drawing.points.length === 0) return false;\n    \n    const markerPoint = drawing.points[0];\n    const markerCSS = coordSystem.chartToCSS(markerPoint.time, markerPoint.price, 'main');\n    const clickCSS = coordSystem.chartToCSS(time, price, 'main');\n    const markerX = markerCSS.x;\n    const markerY = markerCSS.y;\n    const clickX = clickCSS.x;\n    const clickY = clickCSS.y;\n    \n    const distance = Math.sqrt(Math.pow(markerX - clickX, 2) + Math.pow(markerY - clickY, 2));\n    \n    // 마커나 텍스트는 좀 더 넓은 영역 허용\n    return distance <= tolerance * 2;\n  }\n\n  private isPointOnCircle(drawing: DrawingObject, time: number, price: number, coordSystem: UnifiedCoordinateSystem, tolerance: number): boolean {\n    if (drawing.points.length === 0 || drawing.radius === undefined) return false;\n    \n    const center = drawing.points[0];\n    const centerCSS = coordSystem.chartToCSS(center.time, center.price, 'main');\n    const clickCSS = coordSystem.chartToCSS(time, price, 'main');\n    const centerX = centerCSS.x;\n    const centerY = centerCSS.y;\n    const clickX = clickCSS.x;\n    const clickY = clickCSS.y;\n    \n    const distance = Math.sqrt(Math.pow(centerX - clickX, 2) + Math.pow(centerY - clickY, 2));\n    \n    \n    // 원의 둘레 근처이거나 내부인지 확인\n    // 1. 원의 둘레에서 tolerance 범위 내\n    // 2. 원의 내부 (distance가 radius보다 작음)\n    return Math.abs(distance - drawing.radius) <= tolerance || distance <= drawing.radius;\n  }\n\n  private isPointOnRectangle(drawing: DrawingObject, time: number, price: number, coordSystem: UnifiedCoordinateSystem, tolerance: number): boolean {\n    if (drawing.points.length < 2) return false;\n    \n    const p1 = drawing.points[0];\n    const p2 = drawing.points[1];\n    \n    const p1CSS = coordSystem.chartToCSS(p1.time, p1.price, 'main');\n    const p2CSS = coordSystem.chartToCSS(p2.time, p2.price, 'main');\n    const x1 = p1CSS.x;\n    const y1 = p1CSS.y;\n    const x2 = p2CSS.x;\n    const y2 = p2CSS.y;\n    const clickCSS = coordSystem.chartToCSS(time, price, 'main');\n    const px = clickCSS.x;\n    const py = clickCSS.y;\n    \n    const minX = Math.min(x1, x2);\n    const maxX = Math.max(x1, x2);\n    const minY = Math.min(y1, y2);\n    const maxY = Math.max(y1, y2);\n    \n    // 사각형 테두리 근처인지 확인\n    const nearLeft = Math.abs(px - minX) <= tolerance && py >= minY - tolerance && py <= maxY + tolerance;\n    const nearRight = Math.abs(px - maxX) <= tolerance && py >= minY - tolerance && py <= maxY + tolerance;\n    const nearTop = Math.abs(py - minY) <= tolerance && px >= minX - tolerance && px <= maxX + tolerance;\n    const nearBottom = Math.abs(py - maxY) <= tolerance && px >= minX - tolerance && px <= maxX + tolerance;\n    \n    return nearLeft || nearRight || nearTop || nearBottom;\n  }\n\n  private pointToLineDistance(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number {\n    const A = px - x1;\n    const B = py - y1;\n    const C = x2 - x1;\n    const D = y2 - y1;\n    \n    const dot = A * C + B * D;\n    const lenSq = C * C + D * D;\n    \n    let param = -1;\n    if (lenSq !== 0) {\n      param = dot / lenSq;\n    }\n    \n    let xx, yy;\n    \n    if (param < 0) {\n      xx = x1;\n      yy = y1;\n    } else if (param > 1) {\n      xx = x2;\n      yy = y2;\n    } else {\n      xx = x1 + param * C;\n      yy = y1 + param * D;\n    }\n    \n    const dx = px - xx;\n    const dy = py - yy;\n    \n    return Math.sqrt(dx * dx + dy * dy);\n  }\n\n  deleteSelectedDrawing(): boolean {\n    if (this.selectedDrawing) {\n      this.removeDrawing(this.selectedDrawing.id);\n      return true;\n    }\n    return false;\n  }\n\n  createDrawing(type: DrawingToolType, points: ChartPoint[], style?: { color?: string; lineWidth?: number; opacity?: number; markerType?: string; markerSize?: number }, extras?: { radius?: number; width?: number; height?: number }): DrawingObject {\n    // 현재 테마에 따라 기본 색상 결정\n    // 배경색을 확인해서 라이트/다크 테마 구분\n    const bgColor = document.body.style.backgroundColor;\n    const isLightTheme = bgColor === 'rgb(255, 255, 255)' || bgColor === '#ffffff';\n    const defaultColor = isLightTheme ? '#000000' : '#FFFFFF';\n    \n    const drawing: DrawingObject = {\n      id: `drawing_${this.nextId++}`,\n      type,\n      points: [...points],\n      style: {\n        color: style?.color || defaultColor,\n        lineWidth: style?.lineWidth || 2,\n        opacity: style?.opacity || 1\n      },\n      selected: false,\n      locked: false,\n      ...extras\n    };\n    \n    // marker 타입인 경우 추가 속성 설정\n    if (type === 'marker') {\n      drawing.markerType = (style?.markerType as any) || 'circle';\n      drawing.markerSize = style?.markerSize || 12;\n    }\n    \n    return drawing;\n  }\n\n  updateDrawing(id: string, updates: Partial<DrawingObject>): void {\n    const drawing = this.drawings.find(d => d.id === id);\n    if (drawing) {\n      Object.assign(drawing, updates);\n    }\n  }\n\n  clear(): void {\n    this.drawings = [];\n    this.selectedDrawing = null;\n  }\n\n  getDrawingsCount(): number {\n    return this.drawings.length;\n  }\n}","import type { DrawingObject } from '@/types';\n\ninterface DrawingState {\n  drawings: DrawingObject[];\n  timestamp: number;\n}\n\nexport class DrawingStateManager {\n  private history: DrawingState[] = [];\n  private currentIndex: number = -1;\n  private maxHistorySize: number = 50;\n\n  saveState(drawings: DrawingObject[]): void {\n    // 현재 인덱스 이후의 히스토리 제거 (새로운 분기 생성)\n    this.history = this.history.slice(0, this.currentIndex + 1);\n    \n    // 새로운 상태 추가\n    const newState: DrawingState = {\n      drawings: this.deepCloneDrawings(drawings),\n      timestamp: Date.now()\n    };\n    \n    this.history.push(newState);\n    this.currentIndex++;\n    \n    // 최대 히스토리 크기 유지\n    if (this.history.length > this.maxHistorySize) {\n      this.history.shift();\n      this.currentIndex--;\n    }\n  }\n\n  canUndo(): boolean {\n    return this.currentIndex > 0;\n  }\n\n  canRedo(): boolean {\n    return this.currentIndex < this.history.length - 1;\n  }\n\n  undo(): DrawingObject[] | null {\n    if (!this.canUndo()) return null;\n    \n    this.currentIndex--;\n    return this.deepCloneDrawings(this.history[this.currentIndex].drawings);\n  }\n\n  redo(): DrawingObject[] | null {\n    if (!this.canRedo()) return null;\n    \n    this.currentIndex++;\n    return this.deepCloneDrawings(this.history[this.currentIndex].drawings);\n  }\n\n  private deepCloneDrawings(drawings: DrawingObject[]): DrawingObject[] {\n    return drawings.map(drawing => ({\n      ...drawing,\n      points: drawing.points.map(point => ({ ...point })),\n      style: { ...drawing.style }\n    }));\n  }\n\n  clear(): void {\n    this.history = [];\n    this.currentIndex = -1;\n  }\n\n  getHistoryInfo(): { current: number; total: number } {\n    return {\n      current: this.currentIndex + 1,\n      total: this.history.length\n    };\n  }\n\n  exportState(): string {\n    const currentState = this.history[this.currentIndex];\n    if (!currentState) return '[]';\n    \n    return JSON.stringify(currentState.drawings);\n  }\n\n  importState(jsonData: string): DrawingObject[] {\n    try {\n      const drawings = JSON.parse(jsonData) as DrawingObject[];\n      // 유효성 검사\n      if (!Array.isArray(drawings)) {\n        throw new Error('Invalid drawing data: not an array');\n      }\n      \n      return drawings;\n    } catch (error) {\n      console.error('Failed to import drawings:', error);\n      throw error;\n    }\n  }\n}","import type { DrawingToolType, ChartPoint, DrawingObject, ICoordinateSystem } from '@/types';\n\nexport class DrawingToolHandler {\n  private currentTool: DrawingToolType | null = null;\n  private isDrawing: boolean = false;\n  private firstPoint: ChartPoint | null = null;\n  private tempDrawing: DrawingObject | null = null;\n  private onTextInput?: (point: ChartPoint, callback: (text: string) => void) => void;\n\n  setCurrentTool(tool: DrawingToolType | null): void {\n    this.currentTool = tool;\n    this.cancelDrawing();\n  }\n\n  getCurrentTool(): DrawingToolType | null {\n    return this.currentTool;\n  }\n\n  isCurrentlyDrawing(): boolean {\n    return this.isDrawing;\n  }\n\n  getFirstPoint(): ChartPoint | null {\n    return this.firstPoint;\n  }\n\n  getTempDrawing(): DrawingObject | null {\n    return this.tempDrawing;\n  }\n\n  setTextInputCallback(callback: (point: ChartPoint, callback: (text: string) => void) => void): void {\n    this.onTextInput = callback;\n  }\n\n  startDrawing(firstPoint: ChartPoint, style: { color: string; lineWidth: number; opacity: number }): DrawingObject | null {\n    if (!this.currentTool) return null;\n    \n    this.isDrawing = true;\n    this.firstPoint = firstPoint;\n    \n    // 도구별 초기 드로잉 객체 생성\n    switch (this.currentTool) {\n      case 'trendline':\n        this.tempDrawing = {\n          id: 'temp',\n          type: 'trendline',\n          points: [firstPoint, firstPoint], // 두 번째 점은 임시\n          style,\n          selected: false,\n          locked: false\n        };\n        break;\n        \n      case 'horizontal':\n        this.tempDrawing = {\n          id: 'temp',\n          type: 'horizontal',\n          points: [firstPoint],\n          style,\n          selected: false,\n          locked: false\n        };\n        break;\n        \n      case 'circle':\n        this.tempDrawing = {\n          id: 'temp',\n          type: 'circle',\n          points: [firstPoint],\n          radius: 0,\n          style,\n          selected: false,\n          locked: false\n        };\n        break;\n        \n      case 'rectangle':\n        this.tempDrawing = {\n          id: 'temp',\n          type: 'rectangle',\n          points: [firstPoint, firstPoint],\n          style,\n          selected: false,\n          locked: false\n        };\n        break;\n        \n      case 'text':\n      case 'marker':\n        // 텍스트와 마커는 즉시 생성\n        this.isDrawing = false;\n        this.firstPoint = null;\n        return null;\n    }\n    \n    return this.tempDrawing;\n  }\n\n  updateDrawing(currentPoint: ChartPoint, coordSystem?: ICoordinateSystem): void {\n    if (!this.isDrawing || !this.tempDrawing || !this.firstPoint) return;\n    \n    switch (this.tempDrawing.type) {\n      case 'trendline':\n        this.tempDrawing.points[1] = currentPoint;\n        break;\n        \n      case 'circle':\n        // 원의 반지름 계산 (픽셀 단위)\n        if (coordSystem && coordSystem.chartToCanvas) {\n          const p1 = coordSystem.chartToCanvas(this.firstPoint.time, this.firstPoint.price);\n          const p2 = coordSystem.chartToCanvas(currentPoint.time, currentPoint.price);\n          const dx = p2.x - p1.x;\n          const dy = p2.y - p1.y;\n          this.tempDrawing.radius = Math.sqrt(dx * dx + dy * dy);\n        } else {\n          // Fallback for legacy code\n          const dx = currentPoint.time - this.firstPoint.time;\n          const dy = currentPoint.price - this.firstPoint.price;\n          this.tempDrawing.radius = Math.sqrt(dx * dx + dy * dy) * 20;\n        }\n        break;\n        \n      case 'rectangle':\n        this.tempDrawing.points[1] = currentPoint;\n        break;\n    }\n  }\n\n  finishDrawing(): DrawingObject | null {\n    if (!this.isDrawing || !this.tempDrawing) return null;\n    \n    const finishedDrawing = { ...this.tempDrawing };\n    \n    this.isDrawing = false;\n    this.firstPoint = null;\n    this.tempDrawing = null;\n    \n    return finishedDrawing;\n  }\n\n  cancelDrawing(): void {\n    this.isDrawing = false;\n    this.firstPoint = null;\n    this.tempDrawing = null;\n  }\n\n  shouldHandleTextInput(tool: DrawingToolType): boolean {\n    return tool === 'text';\n  }\n\n  requestTextInput(point: ChartPoint, callback: (text: string) => void): void {\n    if (this.onTextInput) {\n      this.onTextInput(point, callback);\n    }\n  }\n\n  createImmediateDrawing(type: DrawingToolType, point: ChartPoint, style: { color: string; lineWidth: number; opacity: number; markerType?: any; markerPosition?: any }): DrawingObject | null {\n    switch (type) {\n      case 'horizontal':\n        return {\n          id: `drawing_${Date.now()}`,\n          type: 'horizontal',\n          points: [point],\n          style,\n          selected: false,\n          locked: false\n        };\n        \n      case 'marker':\n        return {\n          id: `drawing_${Date.now()}`,\n          type: 'marker',\n          points: [point],\n          style,\n          selected: false,\n          locked: false,\n          markerType: style.markerType || 'arrowUp',\n          markerPosition: style.markerPosition || 'above'\n        };\n        \n      default:\n        return null;\n    }\n  }\n}","import type { DrawingObject, ChartPoint } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\nexport interface TextStyle {\n  fontSize: number;\n  fontFamily: string;\n  color: string;\n  bold: boolean;\n  italic: boolean;\n  underline: boolean;\n  backgroundColor?: string;\n  borderColor?: string;\n  borderWidth?: number;\n  padding?: number;\n}\n\nexport interface TextObject extends DrawingObject {\n  type: 'text';\n  text: string;\n  textStyle?: TextStyle;\n}\n\nexport class TextRenderer {\n  private container: HTMLElement;\n  private textElements: Map<string, HTMLDivElement> = new Map();\n  private coordSystem: UnifiedCoordinateSystem;\n  private debugLogged: boolean = false;\n  private onStyleEdit?: (id: string, currentStyle: TextStyle) => void;\n  private isEditing: boolean = false;\n  \n  constructor(container: HTMLElement, coordSystem: UnifiedCoordinateSystem) {\n    this.container = container;\n    this.coordSystem = coordSystem;\n    \n    // 텍스트 컨테이너 생성\n    this.createTextContainer();\n  }\n  \n  private createTextContainer(): void {\n    // 기존 컨테이너가 있으면 재사용\n    let textContainer = this.container.querySelector('.chart-text-container') as HTMLDivElement;\n    \n    if (!textContainer) {\n      textContainer = document.createElement('div');\n      textContainer.className = 'chart-text-container';\n      textContainer.style.cssText = `\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100%;\n        height: 100%;\n        pointer-events: none;\n        overflow: visible;\n        z-index: 100;\n      `;\n      this.container.appendChild(textContainer);\n      \n      // placeholder 스타일 추가\n      const style = document.createElement('style');\n      style.textContent = `\n        .chart-text[contenteditable=\"true\"].empty:before {\n          content: attr(data-placeholder);\n          color: #999;\n          font-style: italic;\n        }\n        .chart-text[contenteditable=\"true\"] {\n          min-width: 100px !important;\n          min-height: 20px !important;\n        }\n      `;\n      document.head.appendChild(style);\n    }\n  }\n  \n  /**\n   * 텍스트 객체 렌더링\n   */\n  renderText(textObject: TextObject): void {\n    let element = this.textElements.get(textObject.id);\n    \n    if (!element) {\n      if (!this.debugLogged) {\n        console.log('[TextRenderer] Creating first text element:', textObject);\n        this.debugLogged = true;\n      }\n      element = this.createTextElement(textObject);\n      this.textElements.set(textObject.id, element);\n    }\n    \n    // 위치 업데이트\n    this.updateTextPosition(element, textObject);\n    \n    // 스타일 업데이트\n    this.updateTextStyle(element, textObject);\n    \n    // 텍스트 내용 업데이트\n    if (element.textContent !== textObject.text) {\n      element.textContent = textObject.text;\n    }\n  }\n  \n  /**\n   * 새 텍스트 생성 및 즉시 편집 모드\n   */\n  createAndEditText(point: ChartPoint, style: TextStyle, onComplete: (text: string) => void): void {\n    console.log('[TextRenderer] createAndEditText called with:', { point, style });\n    \n    // 이미 편집 중이면 무시\n    if (this.isEditing) {\n      console.log('[TextRenderer] Already editing, ignoring');\n      return;\n    }\n    \n    this.isEditing = true;\n    \n    const tempId = `temp-${Date.now()}`;\n    const tempObject: TextObject = {\n      id: tempId,\n      type: 'text',\n      points: [point],\n      text: '',\n      textStyle: style,\n      style: { color: style.color, lineWidth: 1, opacity: 1 },\n      selected: false,\n      locked: false\n    };\n    \n    // 임시 요소 생성\n    const element = this.createTextElement(tempObject);\n    this.textElements.set(tempId, element);\n    \n    console.log('[TextRenderer] Created temp element:', element);\n    \n    // 위치 설정\n    this.updateTextPosition(element, tempObject);\n    this.updateTextStyle(element, tempObject);\n    \n    // 편집 모드용 스타일 재설정\n    element.style.transform = 'none'; // translate 제거\n    element.contentEditable = 'true';\n    element.style.cursor = 'text';\n    element.style.userSelect = 'text';\n    element.style.minWidth = '100px';\n    element.style.minHeight = '20px';\n    element.style.outline = '2px solid #2196F3';\n    element.style.padding = '4px';\n    element.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';\n    element.style.color = '#000000';\n    element.style.zIndex = '1000';\n    element.style.pointerEvents = 'auto';\n    \n    // 빈 텍스트를 위한 placeholder\n    element.setAttribute('data-placeholder', 'Type text...');\n    if (!element.textContent) {\n      element.classList.add('empty');\n    }\n    \n    // 포커스 설정을 즉시 실행\n    element.focus();\n    console.log('[TextRenderer] Element focused immediately');\n    \n    const finishEdit = () => {\n      const text = element.textContent || '';\n      \n      // 편집 상태 해제\n      this.isEditing = false;\n      \n      // 임시 요소 제거\n      element.remove();\n      this.textElements.delete(tempId);\n      \n      // 텍스트가 있을 때만 콜백 호출\n      if (text.trim()) {\n        onComplete(text.trim());\n      }\n    };\n    \n    // blur 이벤트로 종료 처리\n    let isFinishing = false;\n    const handleBlur = () => {\n      // 이미 종료 중이면 무시\n      if (isFinishing) return;\n      \n      // 약간의 지연을 주어 클릭 이벤트와 충돌 방지\n      setTimeout(() => {\n        // 포커스가 다시 돌아왔으면 무시\n        if (document.activeElement === element) return;\n        \n        finishEdit();\n      }, 200);\n    };\n    \n    const handleKeydown = (e: KeyboardEvent) => {\n      if (e.key === 'Enter' && !e.shiftKey) {\n        e.preventDefault();\n        isFinishing = true;\n        finishEdit();\n      } else if (e.key === 'Escape') {\n        e.preventDefault();\n        element.textContent = '';\n        isFinishing = true;\n        finishEdit();\n      }\n    };\n    \n    const handleInput = () => {\n      if (element.textContent) {\n        element.classList.remove('empty');\n      } else {\n        element.classList.add('empty');\n      }\n    };\n    \n    // 마우스 이벤트는 정상적으로 처리되도록 함\n    const handleMouseDown = (e: MouseEvent) => {\n      // 텍스트 박스 내부 클릭은 포커스 유지\n      e.stopPropagation();\n    };\n    \n    element.addEventListener('blur', handleBlur);\n    element.addEventListener('keydown', handleKeydown);\n    element.addEventListener('input', handleInput);\n    element.addEventListener('mousedown', handleMouseDown);\n  }\n  \n  /**\n   * 텍스트 요소 생성\n   */\n  private createTextElement(textObject: TextObject): HTMLDivElement {\n    const element = document.createElement('div');\n    element.className = 'chart-text';\n    element.id = `text-${textObject.id}`;\n    \n    // 기본 스타일 설정\n    element.style.cssText = `\n      position: absolute;\n      pointer-events: auto;\n      cursor: move;\n      user-select: none;\n      white-space: nowrap;\n      transform: translate(-50%, -50%);\n    `;\n    \n    // 텍스트 설정\n    element.textContent = textObject.text || '';\n    \n    // 선택 상태 처리\n    if (textObject.selected) {\n      element.classList.add('selected');\n      element.style.outline = '2px solid #2196F3';\n      element.style.outlineOffset = '2px';\n    }\n    \n    // 더블클릭 이벤트 추가\n    element.addEventListener('dblclick', (e) => {\n      e.stopPropagation();\n      this.handleDoubleClick(textObject.id);\n    });\n    \n    // 컨테이너에 추가\n    const textContainer = this.container.querySelector('.chart-text-container');\n    if (textContainer) {\n      textContainer.appendChild(element);\n    }\n    \n    return element;\n  }\n  \n  /**\n   * 텍스트 위치 업데이트\n   */\n  private updateTextPosition(element: HTMLDivElement, textObject: TextObject): void {\n    if (!textObject.points || textObject.points.length === 0) {\n      console.warn('[TextRenderer] No points in text object:', textObject);\n      return;\n    }\n    \n    const point = textObject.points[0];\n    const canvasPoint = this.coordSystem.chartToCanvas(point.time, point.price);\n    \n    // Canvas 픽셀을 CSS 픽셀로 변환\n    const pixelRatio = (this.coordSystem as any).getPixelRatio ? (this.coordSystem as any).getPixelRatio() : 1;\n    const cssPoint = {\n      x: canvasPoint.x / pixelRatio,\n      y: canvasPoint.y / pixelRatio\n    };\n    \n    // 첫 번째 텍스트만 로그\n    if (!this.debugLogged) {\n      console.log('[TextRenderer] Position calculation:', {\n        chartPoint: point,\n        canvasPoint,\n        cssPoint,\n        pixelRatio,\n        containerRect: this.container.getBoundingClientRect()\n      });\n    }\n    \n    // CSS 픽셀 단위로 위치 설정\n    element.style.left = `${cssPoint.x}px`;\n    element.style.top = `${cssPoint.y}px`;\n    \n  }\n  \n  /**\n   * 텍스트 스타일 업데이트\n   */\n  private updateTextStyle(element: HTMLDivElement, textObject: TextObject): void {\n    const defaultStyle: TextStyle = {\n      fontSize: 14,\n      fontFamily: 'Arial, sans-serif',\n      color: '#000000',\n      bold: false,\n      italic: false,\n      underline: false,\n      padding: 4\n    };\n    \n    const style = { ...defaultStyle, ...textObject.textStyle };\n    \n    // 폰트 스타일 적용\n    element.style.fontSize = `${style.fontSize}px`;\n    element.style.fontFamily = style.fontFamily;\n    element.style.color = style.color;\n    element.style.fontWeight = style.bold ? 'bold' : 'normal';\n    element.style.fontStyle = style.italic ? 'italic' : 'normal';\n    element.style.textDecoration = style.underline ? 'underline' : 'none';\n    \n    // 배경 및 테두리\n    if (style.backgroundColor) {\n      element.style.backgroundColor = style.backgroundColor;\n    } else {\n      element.style.backgroundColor = 'transparent';\n    }\n    \n    if (style.borderColor && style.borderWidth) {\n      element.style.border = `${style.borderWidth}px solid ${style.borderColor}`;\n    } else {\n      element.style.border = 'none';\n    }\n    \n    // 패딩\n    element.style.padding = `${style.padding || 4}px`;\n    \n    // 선택 상태\n    if (textObject.selected) {\n      element.style.outline = '2px solid #2196F3';\n      element.style.outlineOffset = '2px';\n    } else {\n      element.style.outline = 'none';\n    }\n  }\n  \n  /**\n   * 모든 텍스트 재렌더링 (줌/패닝 시)\n   */\n  updateAllPositions(textObjects: TextObject[]): void {\n    // 현재 표시된 텍스트 중 더 이상 없는 것 제거\n    const currentIds = new Set(textObjects.map(obj => obj.id));\n    \n    this.textElements.forEach((element, id) => {\n      if (!currentIds.has(id)) {\n        element.remove();\n        this.textElements.delete(id);\n      }\n    });\n    \n    // 모든 텍스트 렌더링\n    textObjects.forEach(textObj => {\n      this.renderText(textObj);\n    });\n  }\n  \n  /**\n   * 텍스트 제거\n   */\n  removeText(id: string): void {\n    const element = this.textElements.get(id);\n    if (element) {\n      element.remove();\n      this.textElements.delete(id);\n    }\n  }\n  \n  /**\n   * 모든 텍스트 제거\n   */\n  clear(): void {\n    this.textElements.forEach(element => element.remove());\n    this.textElements.clear();\n  }\n  \n  /**\n   * 텍스트 선택 상태 업데이트\n   */\n  updateSelection(id: string, selected: boolean): void {\n    const element = this.textElements.get(id);\n    if (element) {\n      if (selected) {\n        element.classList.add('selected');\n        element.style.outline = '2px solid #2196F3';\n        element.style.outlineOffset = '2px';\n        element.style.pointerEvents = 'auto';\n      } else {\n        element.classList.remove('selected');\n        element.style.outline = 'none';\n        element.style.pointerEvents = 'auto';\n      }\n    }\n  }\n  \n  /**\n   * 편집 모드 활성화\n   */\n  enableEdit(id: string, onComplete: (text: string) => void): void {\n    const element = this.textElements.get(id);\n    if (!element) return;\n    \n    // contenteditable로 편집 가능하게\n    element.contentEditable = 'true';\n    element.style.cursor = 'text';\n    element.style.userSelect = 'text';\n    element.style.outline = '2px solid #2196F3';\n    \n    // 포커스 및 전체 선택\n    element.focus();\n    const range = document.createRange();\n    range.selectNodeContents(element);\n    const selection = window.getSelection();\n    if (selection) {\n      selection.removeAllRanges();\n      selection.addRange(range);\n    }\n    \n    // 편집 완료 처리\n    const finishEdit = () => {\n      element.contentEditable = 'false';\n      element.style.cursor = 'move';\n      element.style.userSelect = 'none';\n      \n      const newText = element.textContent || '';\n      onComplete(newText);\n      \n      // 이벤트 리스너 제거\n      element.removeEventListener('blur', handleBlur);\n      element.removeEventListener('keydown', handleKeydown);\n    };\n    \n    const handleBlur = () => finishEdit();\n    const handleKeydown = (e: KeyboardEvent) => {\n      if (e.key === 'Enter' && !e.shiftKey) {\n        e.preventDefault();\n        finishEdit();\n      } else if (e.key === 'Escape') {\n        e.preventDefault();\n        element.blur();\n      }\n    };\n    \n    element.addEventListener('blur', handleBlur);\n    element.addEventListener('keydown', handleKeydown);\n  }\n  \n  /**\n   * 더블클릭 핸들러\n   */\n  private handleDoubleClick(id: string): void {\n    if (this.onStyleEdit) {\n      // DrawingManager에서 설정한 콜백 호출\n      // 실제 스타일은 DrawingManager에서 관리\n      this.onStyleEdit(id, {} as TextStyle);\n    }\n  }\n  \n  /**\n   * 스타일 편집 콜백 설정\n   */\n  setStyleEditCallback(callback: (id: string, currentStyle: TextStyle) => void): void {\n    this.onStyleEdit = callback;\n  }\n  \n  /**\n   * ID로 텍스트 객체 가져오기 (외부 관리자에서 호출)\n   */\n  private getTextObjectById(id: string): TextObject | null {\n    // DrawingManager에서 관리하므로 여기서는 간단히 null 반환\n    // 실제 구현은 DrawingManager에서 처리\n    return null;\n  }\n  \n  /**\n   * 편집 중인지 확인\n   */\n  isTextEditing(): boolean {\n    return this.isEditing;\n  }\n  \n  /**\n   * 컨테이너 정리\n   */\n  dispose(): void {\n    this.clear();\n    const textContainer = this.container.querySelector('.chart-text-container');\n    if (textContainer) {\n      textContainer.remove();\n    }\n  }\n}","import type { TextStyle } from '@/renderers/unified/TextRenderer';\n\nexport interface TextInputOptions {\n  initialText?: string;\n  initialStyle?: TextStyle;\n  position: { x: number; y: number };\n  onConfirm: (text: string, style: TextStyle) => void;\n  onCancel: () => void;\n}\n\nexport class TextInputModal {\n  private container: HTMLElement;\n  private modal: HTMLDivElement | null = null;\n  private options: TextInputOptions | null = null;\n  \n  constructor(container: HTMLElement) {\n    this.container = container;\n  }\n  \n  show(options: TextInputOptions): void {\n    this.options = options;\n    this.createModal();\n  }\n  \n  private createModal(): void {\n    // 모달 배경\n    const backdrop = document.createElement('div');\n    backdrop.className = 'text-input-backdrop';\n    backdrop.style.cssText = `\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: rgba(0, 0, 0, 0.5);\n      z-index: 100;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    `;\n    \n    // 모달 컨테이너\n    this.modal = document.createElement('div');\n    this.modal.className = 'text-input-modal';\n    this.modal.style.cssText = `\n      background: white;\n      color: #333333;\n      border-radius: 8px;\n      padding: 20px;\n      min-width: 400px;\n      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n    `;\n    \n    // 기본 스타일\n    const defaultStyle: TextStyle = {\n      fontSize: 14,\n      fontFamily: 'Arial, sans-serif',\n      color: '#000000',\n      bold: false,\n      italic: false,\n      underline: false\n    };\n    \n    const style = { ...defaultStyle, ...this.options?.initialStyle };\n    \n    // 모달 내용\n    this.modal.innerHTML = `\n      <div style=\"margin-bottom: 16px;\">\n        <h3 style=\"margin: 0 0 16px 0; font-size: 18px; color: #333;\">텍스트 입력</h3>\n        \n        <textarea \n          id=\"text-input\" \n          style=\"\n            width: 100%;\n            min-height: 60px;\n            padding: 8px;\n            border: 1px solid #ddd;\n            border-radius: 4px;\n            font-size: 14px;\n            color: #333;\n            background: white;\n            resize: vertical;\n          \"\n          placeholder=\"텍스트를 입력하세요...\"\n        >${this.options?.initialText || ''}</textarea>\n      </div>\n      \n      <div style=\"margin-bottom: 16px;\">\n        <h4 style=\"margin: 0 0 8px 0; font-size: 14px; color: #333;\">텍스트 스타일</h4>\n        \n        <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 12px;\">\n          <div>\n            <label style=\"display: block; margin-bottom: 4px; font-size: 12px; color: #666;\">폰트 크기</label>\n            <input \n              type=\"number\" \n              id=\"font-size\" \n              value=\"${style.fontSize}\"\n              min=\"8\" \n              max=\"72\"\n              style=\"width: 100%; padding: 4px; border: 1px solid #ddd; border-radius: 4px; color: #333; background: white;\"\n            >\n          </div>\n          \n          <div>\n            <label style=\"display: block; margin-bottom: 4px; font-size: 12px; color: #666;\">폰트</label>\n            <select \n              id=\"font-family\"\n              style=\"width: 100%; padding: 4px; border: 1px solid #ddd; border-radius: 4px; color: #333; background: white;\"\n            >\n              <option value=\"Arial, sans-serif\" ${style.fontFamily === 'Arial, sans-serif' ? 'selected' : ''}>Arial</option>\n              <option value=\"'Times New Roman', serif\" ${style.fontFamily === \"'Times New Roman', serif\" ? 'selected' : ''}>Times New Roman</option>\n              <option value=\"'Courier New', monospace\" ${style.fontFamily === \"'Courier New', monospace\" ? 'selected' : ''}>Courier New</option>\n              <option value=\"Georgia, serif\" ${style.fontFamily === 'Georgia, serif' ? 'selected' : ''}>Georgia</option>\n              <option value=\"Verdana, sans-serif\" ${style.fontFamily === 'Verdana, sans-serif' ? 'selected' : ''}>Verdana</option>\n              <option value=\"'Trebuchet MS', sans-serif\" ${style.fontFamily === \"'Trebuchet MS', sans-serif\" ? 'selected' : ''}>Trebuchet MS</option>\n            </select>\n          </div>\n          \n          <div>\n            <label style=\"display: block; margin-bottom: 4px; font-size: 12px; color: #666;\">텍스트 색상</label>\n            <input \n              type=\"color\" \n              id=\"text-color\" \n              value=\"${style.color}\"\n              style=\"width: 100%; height: 32px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;\"\n            >\n          </div>\n          \n          <div>\n            <label style=\"display: block; margin-bottom: 4px; font-size: 12px; color: #666;\">배경 색상</label>\n            <div style=\"display: flex; gap: 4px;\">\n              <input \n                type=\"checkbox\" \n                id=\"use-background\"\n                ${style.backgroundColor ? 'checked' : ''}\n                style=\"margin-top: 8px;\"\n              >\n              <input \n                type=\"color\" \n                id=\"background-color\" \n                value=\"${style.backgroundColor || '#ffffff'}\"\n                ${!style.backgroundColor ? 'disabled' : ''}\n                style=\"flex: 1; height: 32px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;\"\n              >\n            </div>\n          </div>\n        </div>\n        \n        <div style=\"margin-top: 12px; display: flex; gap: 12px;\">\n          <label style=\"display: flex; align-items: center; gap: 4px; cursor: pointer; color: #333;\">\n            <input type=\"checkbox\" id=\"text-bold\" ${style.bold ? 'checked' : ''}>\n            <span style=\"font-weight: bold;\">굵게</span>\n          </label>\n          \n          <label style=\"display: flex; align-items: center; gap: 4px; cursor: pointer; color: #333;\">\n            <input type=\"checkbox\" id=\"text-italic\" ${style.italic ? 'checked' : ''}>\n            <span style=\"font-style: italic;\">기울임</span>\n          </label>\n          \n          <label style=\"display: flex; align-items: center; gap: 4px; cursor: pointer; color: #333;\">\n            <input type=\"checkbox\" id=\"text-underline\" ${style.underline ? 'checked' : ''}>\n            <span style=\"text-decoration: underline;\">밑줄</span>\n          </label>\n        </div>\n      </div>\n      \n      <div style=\"display: flex; justify-content: flex-end; gap: 8px;\">\n        <button \n          id=\"cancel-btn\"\n          style=\"\n            padding: 8px 16px;\n            border: 1px solid #ddd;\n            border-radius: 4px;\n            background: white;\n            cursor: pointer;\n          \"\n        >취소</button>\n        \n        <button \n          id=\"confirm-btn\"\n          style=\"\n            padding: 8px 16px;\n            border: none;\n            border-radius: 4px;\n            background: #2196F3;\n            color: white;\n            cursor: pointer;\n          \"\n        >확인</button>\n      </div>\n    `;\n    \n    backdrop.appendChild(this.modal);\n    this.container.appendChild(backdrop);\n    \n    // 이벤트 핸들러 설정\n    this.setupEventHandlers(backdrop);\n    \n    // 텍스트 입력 필드에 포커스\n    const textInput = this.modal.querySelector('#text-input') as HTMLTextAreaElement;\n    if (textInput) {\n      textInput.focus();\n      textInput.select();\n    }\n  }\n  \n  private setupEventHandlers(backdrop: HTMLDivElement): void {\n    if (!this.modal) return;\n    \n    // 배경 색상 체크박스\n    const useBackground = this.modal.querySelector('#use-background') as HTMLInputElement;\n    const backgroundColor = this.modal.querySelector('#background-color') as HTMLInputElement;\n    \n    useBackground?.addEventListener('change', () => {\n      backgroundColor.disabled = !useBackground.checked;\n    });\n    \n    // 취소 버튼\n    const cancelBtn = this.modal.querySelector('#cancel-btn');\n    cancelBtn?.addEventListener('click', () => {\n      this.close(backdrop);\n      this.options?.onCancel();\n    });\n    \n    // 확인 버튼\n    const confirmBtn = this.modal.querySelector('#confirm-btn');\n    confirmBtn?.addEventListener('click', () => {\n      this.handleConfirm(backdrop);\n    });\n    \n    // Enter 키로 확인\n    const textInput = this.modal.querySelector('#text-input') as HTMLTextAreaElement;\n    textInput?.addEventListener('keydown', (e) => {\n      if (e.key === 'Enter' && e.ctrlKey) {\n        e.preventDefault();\n        this.handleConfirm(backdrop);\n      }\n    });\n    \n    // ESC 키로 취소\n    backdrop.addEventListener('keydown', (e) => {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        this.close(backdrop);\n        this.options?.onCancel();\n      }\n    });\n    \n    // 배경 클릭으로 취소\n    backdrop.addEventListener('click', (e) => {\n      if (e.target === backdrop) {\n        this.close(backdrop);\n        this.options?.onCancel();\n      }\n    });\n  }\n  \n  private handleConfirm(backdrop: HTMLDivElement): void {\n    if (!this.modal) return;\n    \n    const textInput = this.modal.querySelector('#text-input') as HTMLTextAreaElement;\n    const text = textInput?.value || '';\n    \n    if (!text.trim()) {\n      alert('텍스트를 입력해주세요.');\n      return;\n    }\n    \n    // 스타일 수집\n    const style: TextStyle = {\n      fontSize: parseInt((this.modal.querySelector('#font-size') as HTMLInputElement)?.value || '14'),\n      fontFamily: (this.modal.querySelector('#font-family') as HTMLSelectElement)?.value || 'Arial, sans-serif',\n      color: (this.modal.querySelector('#text-color') as HTMLInputElement)?.value || '#000000',\n      bold: (this.modal.querySelector('#text-bold') as HTMLInputElement)?.checked || false,\n      italic: (this.modal.querySelector('#text-italic') as HTMLInputElement)?.checked || false,\n      underline: (this.modal.querySelector('#text-underline') as HTMLInputElement)?.checked || false\n    };\n    \n    // 배경색 처리\n    const useBackground = (this.modal.querySelector('#use-background') as HTMLInputElement)?.checked;\n    if (useBackground) {\n      style.backgroundColor = (this.modal.querySelector('#background-color') as HTMLInputElement)?.value;\n    }\n    \n    this.close(backdrop);\n    this.options?.onConfirm(text, style);\n  }\n  \n  private close(backdrop: HTMLDivElement): void {\n    backdrop.remove();\n    this.modal = null;\n  }\n}","import type { DrawingObject, DrawingToolType, ChartPoint, Candle, Theme, DrawingUpdateOptions } from '@/types';\nimport type { ICoordinateSystem } from '@/types/viewport';\nimport type { UnifiedCoordinateSystem } from './UnifiedCoordinateSystem';\nimport { DrawingSnapManager, type SnapPoint } from './drawing/DrawingSnapManager';\nimport { DrawingMeasureManager } from './drawing/DrawingMeasureManager';\nimport { DrawingObjectManager } from './drawing/DrawingObjectManager';\nimport { DrawingStateManager } from './drawing/DrawingStateManager';\nimport { DrawingToolHandler } from './drawing/DrawingToolHandler';\nimport { TextRenderer, type TextObject, type TextStyle } from '@/renderers/unified/TextRenderer';\nimport { TextInputModal } from '@/components/TextInputModal';\n\nexport class DrawingManager {\n  private snapManager: DrawingSnapManager;\n  private measureManager: DrawingMeasureManager;\n  private objectManager: DrawingObjectManager;\n  private stateManager: DrawingStateManager;\n  private toolHandler: DrawingToolHandler;\n  private theme: Theme | null = null;\n  private defaultStyle: { \n    color?: string; \n    lineWidth?: number; \n    opacity?: number;\n    markerType?: string;\n    markerSize?: number;\n  } = {};\n  private currentTool: DrawingToolType | null = null;\n  private textRenderer: TextRenderer | null = null;\n  private textInputModal: TextInputModal | null = null;\n  private container: HTMLElement | null = null;\n  private coordSystem: UnifiedCoordinateSystem | null = null;\n  private textDefaults: TextStyle | null = null;\n  private textDebugLogged: boolean = false;\n  private chart: any = null; // Chart 타입을 사용하면 순환 참조가 발생하므로 any 사용\n  \n  constructor() {\n    this.snapManager = new DrawingSnapManager();\n    this.measureManager = new DrawingMeasureManager();\n    this.objectManager = new DrawingObjectManager();\n    this.stateManager = new DrawingStateManager();\n    this.toolHandler = new DrawingToolHandler();\n    \n    // 초기 상태 저장\n    this.saveState();\n  }\n  \n  // 컨테이너와 좌표계 설정\n  setContainerAndCoordSystem(container: HTMLElement, coordSystem: UnifiedCoordinateSystem): void {\n    this.container = container;\n    this.coordSystem = coordSystem;\n    \n    // 텍스트 렌더러 초기화\n    this.textRenderer = new TextRenderer(container, coordSystem);\n    this.textInputModal = new TextInputModal(container);\n    \n    // 텍스트 더블클릭 시 스타일 편집\n    this.textRenderer.setStyleEditCallback((id: string, currentStyle: TextStyle) => {\n      const textObject = this.objectManager.getAllDrawings().find(d => d.id === id) as TextObject;\n      if (!textObject || !this.textInputModal || !this.coordSystem) return;\n      \n      const point = textObject.points[0];\n      const canvasPoint = this.coordSystem.chartToCanvas(point.time, point.price);\n      \n      this.textInputModal.show({\n        position: { x: canvasPoint.x, y: canvasPoint.y },\n        initialText: textObject.text,\n        initialStyle: textObject.textStyle || currentStyle,\n        onConfirm: (newText: string, newStyle: TextStyle) => {\n          // 텍스트와 스타일 업데이트\n          textObject.text = newText;\n          textObject.textStyle = newStyle;\n          \n          // 색상도 업데이트\n          if (textObject.style) {\n            textObject.style.color = newStyle.color;\n          }\n          \n          this.saveState();\n          \n          // 텍스트 렌더러로 다시 렌더링\n          if (this.textRenderer) {\n            this.textRenderer.renderText(textObject);\n          }\n        },\n        onCancel: () => {\n          // 취소 시 아무것도 하지 않음\n        }\n      });\n    });\n    \n    // 텍스트 입력 콜백 설정\n    this.toolHandler.setTextInputCallback((point: ChartPoint, callback: (text: string) => void) => {\n      \n      if (!this.textInputModal || !this.coordSystem) {\n        console.error('[DrawingManager] Missing textInputModal or coordSystem:', {\n          textInputModal: !!this.textInputModal,\n          coordSystem: !!this.coordSystem\n        });\n        return;\n      }\n      \n      // 차트 좌표를 캔버스 좌표로 변환\n      const canvasPoint = this.coordSystem.chartToCanvas(point.time, point.price);\n      \n      // 기본 스타일 설정\n      const defaultStyle: TextStyle = this.textDefaults || {\n        fontSize: 14,\n        fontFamily: 'Arial, sans-serif',\n        color: this.getDrawingColor(),\n        bold: false,\n        italic: false,\n        underline: false,\n        padding: 4\n      };\n      \n      // 텍스트 입력 모달 표시\n      this.textInputModal.show({\n        position: { x: canvasPoint.x, y: canvasPoint.y },\n        initialText: '',\n        initialStyle: defaultStyle,\n        onConfirm: (text: string, style: TextStyle) => {\n          // 텍스트 객체 생성\n          const textDrawing = this.objectManager.createDrawing('text', [point], {\n            color: style.color,\n            lineWidth: 1,\n            opacity: 1\n          }) as TextObject;\n          \n          textDrawing.text = text;\n          textDrawing.textStyle = style;\n          \n          \n          this.objectManager.addDrawing(textDrawing);\n          this.saveState();\n          \n          // 텍스트 렌더러로 렌더링\n          if (this.textRenderer) {\n            this.textRenderer.renderText(textDrawing);\n          }\n          \n          callback(text);\n        },\n        onCancel: () => {\n          // 취소 시 아무것도 하지 않음\n        }\n      });\n    });\n  }\n  \n  // ===== 테마 설정 =====\n  setTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n  \n  setChart(chart: any): void {\n    this.chart = chart;\n  }\n\n  // 기본 드로잉 스타일 설정 (Trading Journal 통합용)\n  setDefaultStyle(style: { \n    color?: string; \n    lineWidth?: number; \n    opacity?: number;\n    markerType?: string;\n    markerSize?: number;\n    markerColor?: string;  // markerColor 속성도 지원\n  }): void {\n    // markerColor를 color로 매핑\n    if (style.markerColor && !style.color) {\n      style.color = style.markerColor;\n    }\n    this.defaultStyle = { ...this.defaultStyle, ...style };\n  }\n  \n  // 텍스트 기본 스타일 설정\n  setTextDefaults(textDefaults: TextStyle): void {\n    this.textDefaults = textDefaults;\n  }\n\n  private getDrawingColor(): string {\n    // 1. defaultStyle이 설정된 경우 우선 사용\n    if (this.defaultStyle.color) {\n      return this.defaultStyle.color;\n    }\n    \n    // 2. 테마가 설정된 경우 테마 기반 색상 사용\n    if (this.theme) {\n      return this.theme.background === '#ffffff' || this.theme.background?.includes('255, 255, 255') \n        ? '#000000'  // 라이트 테마: 검은색\n        : '#FFFFFF'; // 다크 테마: 흰색\n    }\n    \n    // 3. 폴백: 기존 방식\n    const bgColor = document.body.style.backgroundColor;\n    const isLightTheme = bgColor === 'rgb(255, 255, 255)' || bgColor === '#ffffff';\n    return isLightTheme ? '#000000' : '#FFFFFF';\n  }\n\n  private getMarkerColor(): string {\n    // 1. defaultStyle이 설정된 경우 우선 사용\n    if (this.defaultStyle.color) {\n      return this.defaultStyle.color;\n    }\n    \n    // 2. 테마가 설정된 경우 테마 기반 색상 사용\n    if (this.theme) {\n      return this.theme.background === '#ffffff' || this.theme.background?.includes('255, 255, 255') \n        ? '#FFA500'  // 라이트 테마: 오렌지색\n        : '#FFFF00'; // 다크 테마: 노란색\n    }\n    \n    // 3. 폴백: 기존 방식\n    const bgColor = document.body.style.backgroundColor;\n    const isLightTheme = bgColor === 'rgb(255, 255, 255)' || bgColor === '#ffffff';\n    return isLightTheme ? '#FFA500' : '#FFFF00';\n  }\n  \n  // ===== 콜백 설정 =====\n  setSnapChangeCallback(callback: (snap: SnapPoint | null) => void): void {\n    this.snapManager.setSnapChangeCallback(callback);\n  }\n  \n  setMeasureChangeCallback(callback: (start: ChartPoint | null, end: ChartPoint | null, fixed: boolean) => void): void {\n    this.measureManager.setMeasureChangeCallback(callback);\n  }\n  \n  setTextInputCallback(callback: (point: ChartPoint, callback: (text: string) => void) => void): void {\n    this.toolHandler.setTextInputCallback(callback);\n  }\n  \n  // ===== 도구 관리 =====\n  setCurrentTool(tool: DrawingToolType | null): void {\n    this.currentTool = tool;\n    this.toolHandler.setCurrentTool(tool);\n    if (this.measureManager.isMeasureMode()) {\n      this.measureManager.cancelMeasure();\n    }\n  }\n  \n  getCurrentTool(): DrawingToolType | null {\n    return this.toolHandler.getCurrentTool();\n  }\n  \n  // ===== 마그네틱 모드 =====\n  setMagneticMode(enabled: boolean): void {\n    this.snapManager.setMagneticMode(enabled);\n  }\n  \n  getMagneticMode(): boolean {\n    return this.snapManager.getMagneticMode();\n  }\n  \n  // ===== 스냅 포인트 =====\n  findSnapPoint(\n    mouseX: number,\n    mouseY: number,\n    candles: Candle[],\n    coordSystem: UnifiedCoordinateSystem,\n    threshold: number = 20\n  ): SnapPoint | null {\n    return this.snapManager.findSnapPoint(mouseX, mouseY, candles, coordSystem, threshold);\n  }\n  \n  // ===== 마우스 이벤트 처리 =====\n  handleMouseMove(\n    mouseX: number,\n    mouseY: number,\n    candles: Candle[],\n    coordSystem: UnifiedCoordinateSystem,\n    getChartPoint: (x: number, y: number) => ChartPoint\n  ): void {\n    // 마그네틱 모드에서 스냅 포인트 찾기\n    if (this.snapManager.getMagneticMode()) {\n      this.findSnapPoint(mouseX, mouseY, candles, coordSystem);\n    }\n    \n    // 측정 모드 업데이트\n    if (this.measureManager.isMeasureMode() && !this.measureManager.isMeasureFixed()) {\n      const measurePoints = this.measureManager.getMeasurePoints();\n      if (measurePoints.start) {\n        // 스냅된 위치가 있으면 사용, 없으면 마우스 위치 사용\n        const snapPoint = this.snapManager.getCurrentSnapPoint();\n        const currentPoint = snapPoint\n          ? { time: snapPoint.time, price: snapPoint.price }\n          : getChartPoint(mouseX, mouseY);\n        this.measureManager.updateMeasure(currentPoint);\n      }\n    }\n    \n    // 드로잉 업데이트\n    if (this.toolHandler.isCurrentlyDrawing()) {\n      // 스냅된 위치가 있으면 사용, 없으면 마우스 위치 사용\n      const snapPoint = this.snapManager.getCurrentSnapPoint();\n      const currentPoint = snapPoint\n        ? { time: snapPoint.time, price: snapPoint.price }\n        : getChartPoint(mouseX, mouseY);\n      this.toolHandler.updateDrawing(currentPoint, coordSystem);\n    }\n  }\n  \n  handleClick(\n    x: number,\n    y: number,\n    getChartPoint: (x: number, y: number) => ChartPoint,\n    coordSystem: ICoordinateSystem\n  ): void {\n    // 스냅된 위치가 있으면 사용, 없으면 마우스 위치 사용\n    const snapPoint = this.snapManager.getCurrentSnapPoint();\n    const chartPoint = snapPoint \n      ? { time: snapPoint.time, price: snapPoint.price }\n      : getChartPoint(x, y);\n    \n    // 도구가 없으면 선택 모드\n    if (!this.toolHandler.getCurrentTool()) {\n      // 측정 모드 처리\n      if (this.measureManager.isMeasureMode()) {\n        const measurePoints = this.measureManager.getMeasurePoints();\n        if (!measurePoints.start) {\n          this.measureManager.startMeasure(chartPoint);\n        } else if (!measurePoints.fixed) {\n          this.measureManager.fixMeasure(chartPoint);\n        } else {\n          this.measureManager.cancelMeasure();\n        }\n        return;\n      }\n      \n      // 드로잉 선택\n      // TODO: ICoordinateSystem을 UnifiedCoordinateSystem으로 변환하거나 타입 수정 필요\n      this.objectManager.selectDrawingAt(x, y, coordSystem as any);\n      return;\n    }\n    \n    const currentTool = this.toolHandler.getCurrentTool()!;\n    \n    // 도구별 처리\n    if (currentTool === 'trendline' || currentTool === 'circle' || currentTool === 'rectangle') {\n      if (!this.toolHandler.getFirstPoint()) {\n        // 첫 번째 점\n        const drawing = this.toolHandler.startDrawing(chartPoint, {\n          color: this.getDrawingColor(),\n          lineWidth: this.defaultStyle.lineWidth || 2,\n          opacity: this.defaultStyle.opacity || 1\n        });\n        \n        if (drawing && currentTool === 'circle') {\n          drawing.radius = 0;\n        }\n      } else {\n        // 두 번째 점 - 드로잉 완성\n        const finishedDrawing = this.toolHandler.finishDrawing();\n        if (finishedDrawing) {\n          // 임시 ID를 실제 ID로 변경\n          const newDrawing = this.objectManager.createDrawing(\n            finishedDrawing.type,\n            finishedDrawing.points,\n            finishedDrawing.style,\n            finishedDrawing.type === 'circle' ? { radius: finishedDrawing.radius } : undefined\n          );\n          \n          this.objectManager.addDrawing(newDrawing);\n          this.saveState();\n          \n          // 트렌드라인 모드는 계속 유지 (ESC나 우클릭으로만 취소)\n          // this.setCurrentTool(null);\n        }\n      }\n    } else if (currentTool === 'horizontal') {\n      // 수평선은 즉시 생성\n      this.createHorizontalLineImmediate(chartPoint);\n      // 수평선 모드 계속 유지\n      // this.setCurrentTool(null);\n    } else if (currentTool === 'marker') {\n      // 마커 즉시 생성\n      const markerColor = this.getMarkerColor();\n      \n      const marker = this.objectManager.createDrawing('marker', [chartPoint], {\n        color: markerColor,\n        lineWidth: 2,\n        opacity: 1,\n        markerType: this.defaultStyle.markerType,\n        markerSize: this.defaultStyle.markerSize\n      }, {\n      });\n      \n      this.objectManager.addDrawing(marker);\n      this.saveState();\n      // 마커 모드 계속 유지\n      // this.setCurrentTool(null);\n    } else if (currentTool === 'text') {\n      // 텍스트 입력 요청 - 콜백은 이미 설정됨\n      this.toolHandler.requestTextInput(chartPoint, (text: string) => {\n        // 콜백은 setContainerAndCoordSystem에서 이미 처리됨\n      });\n      // 텍스트 모드 계속 유지\n      // this.setCurrentTool(null);\n    }\n  }\n  \n  // ===== 드로잉 작업 =====\n  cancelDrawing(): void {\n    this.toolHandler.cancelDrawing();\n    if (this.measureManager.isMeasureMode()) {\n      this.measureManager.cancelMeasure();\n    }\n  }\n  \n  createHorizontalLineImmediate(point: ChartPoint): void {\n    const line = this.objectManager.createDrawing('horizontal', [point], {\n      color: this.getDrawingColor(),\n      lineWidth: 2,\n      opacity: 1\n    });\n    \n    this.objectManager.addDrawing(line);\n    this.saveState();\n  }\n  \n  // ===== 측정 도구 =====\n  startMeasure(point: ChartPoint): void {\n    if (this.toolHandler.getCurrentTool() || this.toolHandler.isCurrentlyDrawing()) {\n      this.cancelDrawing();\n    }\n    this.measureManager.startMeasure(point);\n  }\n  \n  cancelMeasure(): void {\n    this.measureManager.cancelMeasure();\n  }\n  \n  fixMeasure(endPoint: ChartPoint): void {\n    this.measureManager.fixMeasure(endPoint);\n  }\n  \n  isMeasureMode(): boolean {\n    return this.measureManager.isMeasureMode();\n  }\n  \n  // ===== 드로잉 객체 관리 =====\n  getAllDrawings(): DrawingObject[] {\n    const drawings = this.objectManager.getAllDrawings();\n    const tempDrawing = this.toolHandler.getTempDrawing();\n    \n    if (tempDrawing) {\n      return [...drawings, tempDrawing];\n    }\n    return drawings;\n  }\n  \n  deleteSelectedDrawing(): boolean {\n    if (this.objectManager.deleteSelectedDrawing()) {\n      this.saveState();\n      return true;\n    }\n    return false;\n  }\n  \n  getSelectedDrawing(): DrawingObject | null {\n    return this.objectManager.getSelectedDrawing();\n  }\n  \n  selectDrawingAt(x: number, y: number): DrawingObject | null {\n    \n    // 좌표계 컨텍스트 사용\n    if (!this.coordSystem) {\n      console.error('DrawingManager: coordSystem not initialized');\n      return null;\n    }\n    \n    const selectedDrawing = this.objectManager.selectDrawingAt(x, y, this.coordSystem);\n    \n    // 선택이 변경되었으면 다시 그리기 요청\n    if (this.chart && this.chart.setDirty) {\n      this.chart.setDirty(true);\n    }\n    \n    return selectedDrawing;\n  }\n  \n  checkDrawingHover(x: number, y: number): DrawingObject | null {\n    // 좌표계 컨텍스트 사용\n    if (!this.coordSystem) {\n      return null;\n    }\n    \n    // 호버는 선택하지 않고 체크만 함\n    return this.objectManager.checkDrawingAt(x, y, this.coordSystem);\n  }\n  \n  moveSelectedDrawing(timeDiff: number, priceDiff: number): void {\n    const selectedDrawing = this.objectManager.getSelectedDrawing();\n    if (!selectedDrawing) return;\n    \n    // 모든 포인트를 이동\n    selectedDrawing.points = selectedDrawing.points.map(point => ({\n      time: point.time + timeDiff,\n      price: point.price + priceDiff\n    }));\n    \n    // 상태 저장 및 다시 그리기\n    this.saveState();\n    if (this.chart && this.chart.setDirty) {\n      this.chart.setDirty(true);\n    }\n  }\n  \n  clear(): void {\n    this.objectManager.clear();\n    this.stateManager.clear();\n    this.saveState();\n    \n    // 텍스트 렌더러도 클리어\n    if (this.textRenderer) {\n      this.textRenderer.clear();\n    }\n  }\n\n  // ===== InteractionManager 호환 메서드들 =====\n  addDrawing(drawing: DrawingObject): void {\n    this.objectManager.addDrawing(drawing);\n    this.saveState();\n  }\n\n  removeDrawing(id: string): void {\n    this.deleteDrawing(id);\n  }\n\n  clearDrawings(): void {\n    this.clear();\n  }\n\n  getDrawingById(id: string): DrawingObject | undefined {\n    return this.objectManager.getAllDrawings().find(d => d.id === id);\n  }\n\n  updateDrawingById(id: string, updates: Partial<DrawingObject>): void {\n    this.updateDrawing(id, updates as any);\n  }\n\n  // 드로잉 프로세스 메서드들\n  private currentDrawingProcess: {\n    startPoint?: ChartPoint;\n    tool?: DrawingToolType;\n  } = {};\n\n  startDrawing(x: number, y: number, time: number, price: number): void {\n    if (!this.currentTool) return;\n    \n    const point: ChartPoint = { time, price };\n    // handleClick needs x, y, getChartPoint, coordSystem\n    // Since we already have the point, we'll create a mock getChartPoint\n    const getChartPoint = (_x: number, _y: number) => point;\n    this.handleClick(x, y, getChartPoint, null as any);\n    this.currentDrawingProcess = {\n      startPoint: point,\n      tool: this.currentTool\n    };\n  }\n\n  updateDrawingPosition(x: number, y: number, time: number, price: number): void {\n    if (!this.currentDrawingProcess.startPoint) return;\n    \n    const point: ChartPoint = { time, price };\n    // handleMouseMove needs x, y, candles, coordSystem, getChartPoint\n    const getChartPoint = (_x: number, _y: number) => point;\n    this.handleMouseMove(x, y, [], null as any, getChartPoint);\n  }\n\n  endDrawing(): DrawingObject | null {\n    const drawings = this.objectManager.getAllDrawings();\n    const lastDrawing = drawings[drawings.length - 1];\n    \n    this.currentDrawingProcess = {};\n    return lastDrawing || null;\n  }\n\n  isDrawing(): boolean {\n    return this.toolHandler.getTempDrawing() !== null;\n  }\n  \n  // ===== 실행 취소/다시 실행 =====\n  private saveState(): void {\n    this.stateManager.saveState(this.objectManager.getAllDrawings());\n  }\n  \n  undo(): boolean {\n    const drawings = this.stateManager.undo();\n    if (drawings) {\n      this.objectManager.clear();\n      drawings.forEach(drawing => this.objectManager.addDrawing(drawing));\n      return true;\n    }\n    return false;\n  }\n  \n  redo(): boolean {\n    const drawings = this.stateManager.redo();\n    if (drawings) {\n      this.objectManager.clear();\n      drawings.forEach(drawing => this.objectManager.addDrawing(drawing));\n      return true;\n    }\n    return false;\n  }\n  \n  canUndo(): boolean {\n    return this.stateManager.canUndo();\n  }\n  \n  canRedo(): boolean {\n    return this.stateManager.canRedo();\n  }\n  \n  // ===== 텍스트 렌더링 =====\n  updateTextRendering(): void {\n    if (!this.textRenderer) return;\n    \n    // 모든 텍스트 드로잉 가져오기\n    const textDrawings = this.objectManager.getAllDrawings()\n      .filter(d => d.type === 'text') as TextObject[];\n    \n    // 텍스트 렌더러로 업데이트\n    this.textRenderer.updateAllPositions(textDrawings);\n  }\n  \n  // 텍스트 선택 상태 업데이트\n  updateTextSelection(id: string, selected: boolean): void {\n    if (!this.textRenderer) return;\n    this.textRenderer.updateSelection(id, selected);\n  }\n  \n  // 텍스트 편집 모드 활성화\n  enableTextEdit(id: string): void {\n    if (!this.textRenderer) return;\n    \n    const drawing = this.objectManager.getAllDrawings().find(d => d.id === id) as TextObject;\n    if (!drawing || drawing.type !== 'text') return;\n    \n    this.textRenderer.enableEdit(id, (newText: string) => {\n      // 텍스트 업데이트\n      drawing.text = newText;\n      this.saveState();\n    });\n  }\n  \n  // 렌더러 정리\n  dispose(): void {\n    if (this.textRenderer) {\n      this.textRenderer.dispose();\n      this.textRenderer = null;\n    }\n  }\n  \n  updateDrawing(id: string, updates: DrawingUpdateOptions): void {\n    this.objectManager.updateDrawing(id, updates);\n    this.saveState();\n  }\n  \n  deleteDrawing(id: string): void {\n    this.objectManager.removeDrawing(id);\n    this.saveState();\n  }\n  \n  // ===== 내보내기/가져오기 =====\n  exportDrawings(): string {\n    return this.stateManager.exportState();\n  }\n  \n  importDrawings(jsonData: string): void {\n    try {\n      const drawings = this.stateManager.importState(jsonData);\n      this.objectManager.clear();\n      drawings.forEach(drawing => this.objectManager.addDrawing(drawing));\n      this.saveState();\n    } catch (error) {\n      console.error('Failed to import drawings:', error);\n      throw error;\n    }\n  }\n}","import type { Marker, MarkerStyle } from '@/types/marker';\nimport type { Candle } from '@/types';\n\nexport class MarkerManager {\n  private markers: Map<string, Marker> = new Map();\n  private markerIdCounter = 0;\n  private defaultStyle: MarkerStyle = {\n    color: '#FF0000',\n    size: 10,\n    strokeWidth: 1,\n    textColor: '#FFFFFF',\n    fontSize: 12\n  };\n\n  /**\n   * 마커 추가\n   */\n  addMarker(marker: Marker): string {\n    const id = marker.id || `marker_${this.markerIdCounter++}`;\n    this.markers.set(id, { ...marker, id });\n    return id;\n  }\n\n  /**\n   * 여러 마커 설정 (기존 마커 모두 제거)\n   */\n  setMarkers(markers: Marker[]): void {\n    this.clear();\n    markers.forEach(marker => this.addMarker(marker));\n  }\n\n  /**\n   * 마커 제거\n   */\n  removeMarker(id: string): void {\n    this.markers.delete(id);\n  }\n\n  /**\n   * 모든 마커 제거\n   */\n  clear(): void {\n    this.markers.clear();\n  }\n\n  /**\n   * 모든 마커 가져오기\n   */\n  getMarkers(): Marker[] {\n    return Array.from(this.markers.values());\n  }\n\n  /**\n   * 특정 시간 범위의 마커 가져오기\n   */\n  getMarkersInRange(startTime: number, endTime: number): Marker[] {\n    return Array.from(this.markers.values()).filter(\n      marker => marker.time >= startTime && marker.time <= endTime\n    );\n  }\n\n  /**\n   * 마커 업데이트\n   */\n  updateMarker(id: string, updates: Partial<Marker>): void {\n    const marker = this.markers.get(id);\n    if (marker) {\n      this.markers.set(id, { ...marker, ...updates });\n    }\n  }\n\n  /**\n   * 캔들에 해당하는 마커 찾기\n   */\n  findMarkersForCandle(candle: Candle): Marker[] {\n    return Array.from(this.markers.values()).filter(\n      marker => marker.time >= candle.time && marker.time < candle.time + (candle.interval || 0)\n    );\n  }\n\n  /**\n   * 마커 스타일 가져오기\n   */\n  getMarkerStyle(marker: Marker): MarkerStyle {\n    return {\n      ...this.defaultStyle,\n      color: marker.color || this.defaultStyle.color,\n      size: marker.size || this.defaultStyle.size\n    };\n  }\n  \n  /**\n   * ID로 마커 가져오기\n   */\n  getMarkerById(id: string): Marker | undefined {\n    return this.markers.get(id);\n  }\n}","import type { StopLossLine, StopLossOptions } from '@/types/stopLoss';\r\n\r\nexport class StopLossManager {\r\n  private stopLossLines: Map<string, StopLossLine> = new Map();\r\n  private options: StopLossOptions;\r\n  private nextId: number = 1;\r\n  \r\n  constructor(options?: StopLossOptions) {\r\n    this.options = {\r\n      defaultColor: '#ef5350',\r\n      defaultLineWidth: 2,\r\n      defaultOpacity: 0.8,\r\n      showLabel: true,\r\n      labelPosition: 'right',\r\n      labelBackground: 'rgba(239, 83, 80, 0.9)',\r\n      labelTextColor: '#ffffff',\r\n      fontSize: 11,\r\n      fontFamily: 'Arial',\r\n      ...options\r\n    };\r\n  }\r\n  \r\n  /**\r\n   * Add a stop loss line\r\n   */\r\n  addStopLossLine(price: number, options?: Partial<StopLossLine>): string {\r\n    const id = options?.id || `stop-loss-${this.nextId++}`;\r\n    \r\n    const stopLossLine: StopLossLine = {\r\n      id,\r\n      price,\r\n      label: options?.label || `SL: ${price.toFixed(2)}`,\r\n      color: options?.color || this.options.defaultColor,\r\n      lineWidth: options?.lineWidth || this.options.defaultLineWidth,\r\n      opacity: options?.opacity || this.options.defaultOpacity,\r\n      dashed: options?.dashed ?? true,\r\n      dashLength: options?.dashLength || 5,\r\n      gapLength: options?.gapLength || 3\r\n    };\r\n    \r\n    this.stopLossLines.set(id, stopLossLine);\r\n    return id;\r\n  }\r\n  \r\n  /**\r\n   * Remove a stop loss line\r\n   */\r\n  removeStopLossLine(id: string): boolean {\r\n    return this.stopLossLines.delete(id);\r\n  }\r\n  \r\n  /**\r\n   * Clear all stop loss lines\r\n   */\r\n  clearStopLossLines(): void {\r\n    this.stopLossLines.clear();\r\n  }\r\n  \r\n  /**\r\n   * Get all stop loss lines\r\n   */\r\n  getStopLossLines(): StopLossLine[] {\r\n    return Array.from(this.stopLossLines.values());\r\n  }\r\n  \r\n  /**\r\n   * Get a specific stop loss line\r\n   */\r\n  getStopLossLine(id: string): StopLossLine | undefined {\r\n    return this.stopLossLines.get(id);\r\n  }\r\n  \r\n  /**\r\n   * Update a stop loss line\r\n   */\r\n  updateStopLossLine(id: string, updates: Partial<StopLossLine>): boolean {\r\n    const line = this.stopLossLines.get(id);\r\n    if (!line) return false;\r\n    \r\n    Object.assign(line, updates);\r\n    return true;\r\n  }\r\n  \r\n  /**\r\n   * Get options\r\n   */\r\n  getOptions(): StopLossOptions {\r\n    return { ...this.options };\r\n  }\r\n  \r\n  /**\r\n   * Update options\r\n   */\r\n  updateOptions(options: Partial<StopLossOptions>): void {\r\n    Object.assign(this.options, options);\r\n  }\r\n}","\nexport interface LineSeriesOptions {\n  id?: string;\n  name: string;\n  data: Array<{ time: number; value: number }>;\n  color?: string;\n  lineWidth?: number;\n  visible?: boolean;\n  yAxisPosition?: 'left' | 'right';\n  showInLegend?: boolean;\n}\n\nexport interface LineSeries {\n  id: string;\n  name: string;\n  values: Float32Array;\n  times: Float64Array;\n  color: string;\n  lineWidth: number;\n  visible: boolean;\n  yAxisPosition: 'left' | 'right';\n  showInLegend: boolean;\n  priceRange: [number, number];\n}\n\nexport class LineSeriesManager {\n  private series: Map<string, LineSeries> = new Map();\n  private nextId: number = 1;\n\n  /**\n   * 라인 시리즈 추가\n   */\n  addLineSeries(options: LineSeriesOptions): string {\n    const id = options.id || `line-series-${this.nextId++}`;\n    \n    // 데이터 정렬\n    const sortedData = [...options.data].sort((a, b) => a.time - b.time);\n    \n    // TypedArray로 변환\n    const times = new Float64Array(sortedData.map(d => d.time));\n    const values = new Float32Array(sortedData.map(d => d.value));\n    \n    // 가격 범위 계산\n    let min = Infinity;\n    let max = -Infinity;\n    for (const value of values) {\n      if (value < min) min = value;\n      if (value > max) max = value;\n    }\n    \n    const series: LineSeries = {\n      id,\n      name: options.name,\n      times,\n      values,\n      color: options.color || '#2196f3',\n      lineWidth: options.lineWidth || 2,\n      visible: options.visible !== false,\n      yAxisPosition: options.yAxisPosition || 'right',\n      showInLegend: options.showInLegend !== false,\n      priceRange: [min, max]\n    };\n    \n    this.series.set(id, series);\n    return id;\n  }\n\n  /**\n   * 라인 시리즈 업데이트\n   */\n  updateLineSeries(id: string, data: Array<{ time: number; value: number }>): void {\n    const series = this.series.get(id);\n    if (!series) return;\n    \n    const sortedData = [...data].sort((a, b) => a.time - b.time);\n    series.times = new Float64Array(sortedData.map(d => d.time));\n    series.values = new Float32Array(sortedData.map(d => d.value));\n    \n    // 가격 범위 재계산\n    let min = Infinity;\n    let max = -Infinity;\n    for (const value of series.values) {\n      if (value < min) min = value;\n      if (value > max) max = value;\n    }\n    series.priceRange = [min, max];\n  }\n\n  /**\n   * 라인 시리즈 제거\n   */\n  removeLineSeries(id: string): void {\n    this.series.delete(id);\n  }\n\n  /**\n   * 라인 시리즈 가시성 토글\n   */\n  toggleVisibility(id: string): void {\n    const series = this.series.get(id);\n    if (series) {\n      series.visible = !series.visible;\n    }\n  }\n\n  /**\n   * 라인 시리즈 스타일 업데이트\n   */\n  updateStyle(id: string, style: Partial<Pick<LineSeries, 'color' | 'lineWidth'>>): void {\n    const series = this.series.get(id);\n    if (series) {\n      if (style.color !== undefined) series.color = style.color;\n      if (style.lineWidth !== undefined) series.lineWidth = style.lineWidth;\n    }\n  }\n\n  /**\n   * 라인 시리즈 표시/숨김 설정\n   */\n  setSeriesVisibility(id: string, visible: boolean): void {\n    const series = this.series.get(id);\n    if (series) {\n      series.visible = visible;\n    }\n  }\n\n  /**\n   * 모든 라인 시리즈 가져오기\n   */\n  getAllSeries(): LineSeries[] {\n    return Array.from(this.series.values());\n  }\n\n  /**\n   * 가시적인 라인 시리즈만 가져오기\n   */\n  getVisibleSeries(): LineSeries[] {\n    return Array.from(this.series.values()).filter(s => s.visible);\n  }\n\n  /**\n   * 특정 라인 시리즈 가져오기\n   */\n  getSeries(id: string): LineSeries | undefined {\n    return this.series.get(id);\n  }\n\n  /**\n   * 전체 가격 범위 계산\n   */\n  getTotalPriceRange(): [number, number] {\n    const visibleSeries = this.getVisibleSeries();\n    if (visibleSeries.length === 0) return [0, 100];\n    \n    let min = Infinity;\n    let max = -Infinity;\n    \n    for (const series of visibleSeries) {\n      if (series.priceRange[0] < min) min = series.priceRange[0];\n      if (series.priceRange[1] > max) max = series.priceRange[1];\n    }\n    \n    return [min, max];\n  }\n\n  /**\n   * 특정 시간 범위의 데이터 포인트 가져오기\n   */\n  getDataInTimeRange(timeRange: [number, number]): Map<string, { times: Float64Array; values: Float32Array }> {\n    const result = new Map();\n    \n    for (const series of this.getVisibleSeries()) {\n      const startIdx = this.binarySearchTime(series.times, timeRange[0], 'left');\n      const endIdx = this.binarySearchTime(series.times, timeRange[1], 'right');\n      \n      if (startIdx < endIdx) {\n        result.set(series.id, {\n          times: series.times.slice(startIdx, endIdx),\n          values: series.values.slice(startIdx, endIdx)\n        });\n      }\n    }\n    \n    return result;\n  }\n\n  /**\n   * 이진 탐색으로 시간 인덱스 찾기\n   */\n  private binarySearchTime(times: Float64Array, target: number, side: 'left' | 'right'): number {\n    let left = 0;\n    let right = times.length - 1;\n    let result = side === 'left' ? 0 : times.length;\n    \n    while (left <= right) {\n      const mid = Math.floor((left + right) / 2);\n      \n      if (times[mid] < target) {\n        left = mid + 1;\n        if (side === 'right') result = mid + 1;\n      } else if (times[mid] > target) {\n        right = mid - 1;\n        if (side === 'left') result = mid;\n      } else {\n        return side === 'left' ? mid : mid + 1;\n      }\n    }\n    \n    return result;\n  }\n\n  /**\n   * 모든 라인 시리즈 제거\n   */\n  clear(): void {\n    this.series.clear();\n  }\n}","import type { DrawingObject, DrawingToolType, ChartPoint } from '@/types/drawing';\nimport type { Marker } from '@/types/marker';\nimport type { StopLossLine, StopLossOptions } from '@/types/stopLoss';\nimport type { LineSeriesData } from '@/types/lineSeries';\nimport { DrawingManager } from './DrawingManager';\nimport { MarkerManager } from './MarkerManager';\nimport { StopLossManager } from './StopLossManager';\nimport { LineSeriesManager } from './LineSeriesManager';\n\n/**\n * 사용자 인터랙션 관련 기능을 통합 관리하는 매니저\n * - 드로잉 도구\n * - 마커\n * - 스톱로스 라인\n * - 라인 시리즈\n */\nexport class InteractionManager {\n  public drawingManager: DrawingManager;\n  public markerManager: MarkerManager;\n  public stopLossManager: StopLossManager;\n  public lineSeriesManager: LineSeriesManager;\n\n  constructor() {\n    this.drawingManager = new DrawingManager();\n    this.markerManager = new MarkerManager();\n    this.stopLossManager = new StopLossManager();\n    this.lineSeriesManager = new LineSeriesManager();\n  }\n\n  // Drawing 관련 메서드들\n  setActiveTool(tool: DrawingToolType | null): void {\n    this.drawingManager.setCurrentTool(tool);\n  }\n\n  getActiveTool(): DrawingToolType | null {\n    return this.drawingManager.getCurrentTool();\n  }\n\n  addDrawing(drawing: DrawingObject): void {\n    this.drawingManager.addDrawing(drawing);\n  }\n\n  removeDrawing(id: string): void {\n    this.drawingManager.removeDrawing(id);\n  }\n\n  getAllDrawings(): DrawingObject[] {\n    return this.drawingManager.getAllDrawings();\n  }\n\n  clearDrawings(): void {\n    this.drawingManager.clearDrawings();\n  }\n\n  startDrawing(x: number, y: number, time: number, price: number): void {\n    this.drawingManager.startDrawing(x, y, time, price);\n  }\n\n  updateDrawing(x: number, y: number, time: number, price: number): void {\n    this.drawingManager.updateDrawingPosition(x, y, time, price);\n  }\n\n  endDrawing(): DrawingObject | null {\n    return this.drawingManager.endDrawing();\n  }\n\n  isDrawing(): boolean {\n    return this.drawingManager.isDrawing();\n  }\n\n  getDrawingById(id: string): DrawingObject | undefined {\n    return this.drawingManager.getDrawingById(id);\n  }\n\n  updateDrawingById(id: string, updates: Partial<DrawingObject>): void {\n    this.drawingManager.updateDrawingById(id, updates);\n  }\n\n  setMagneticMode(enabled: boolean): void {\n    this.drawingManager.setMagneticMode(enabled);\n  }\n\n  getMagneticMode(): boolean {\n    return this.drawingManager.getMagneticMode();\n  }\n\n  exportDrawings(): string {\n    return this.drawingManager.exportDrawings();\n  }\n\n  importDrawings(jsonData: string): void {\n    this.drawingManager.importDrawings(jsonData);\n  }\n\n  setDefaultDrawingStyle(style: { color?: string; lineWidth?: number; opacity?: number; markerType?: string; markerSize?: number; markerColor?: string }): void {\n    this.drawingManager.setDefaultStyle(style);\n  }\n  \n  setTextDefaults(textDefaults: any): void {\n    this.drawingManager.setTextDefaults(textDefaults);\n  }\n\n  // Marker 관련 메서드들\n  addMarker(marker: Marker): string {\n    return this.markerManager.addMarker(marker);\n  }\n\n  setMarkers(markers: Marker[]): void {\n    this.markerManager.setMarkers(markers);\n  }\n\n  removeMarker(id: string): void {\n    this.markerManager.removeMarker(id);\n  }\n\n  getMarkers(): Marker[] {\n    return this.markerManager.getMarkers();\n  }\n\n  getMarkerById(id: string): Marker | undefined {\n    return this.markerManager.getMarkerById(id);\n  }\n\n  clearMarkers(): void {\n    this.markerManager.clear();\n  }\n\n  // StopLoss 관련 메서드들\n  addStopLossLine(price: number, options?: StopLossOptions): string {\n    return this.stopLossManager.addStopLossLine(price, options);\n  }\n\n  removeStopLossLine(id: string): boolean {\n    return this.stopLossManager.removeStopLossLine(id);\n  }\n\n  updateStopLossLine(id: string, updates: Partial<StopLossOptions & { price?: number }>): boolean {\n    return this.stopLossManager.updateStopLossLine(id, updates);\n  }\n\n  getStopLossLines(): StopLossLine[] {\n    return this.stopLossManager.getStopLossLines();\n  }\n\n  clearStopLossLines(): void {\n    this.stopLossManager.clearStopLossLines();\n  }\n\n  // LineSeries 관련 메서드들\n  addLineSeries(options: any): string {\n    return this.lineSeriesManager.addLineSeries(options);\n  }\n\n  removeLineSeries(id: string): void {\n    this.lineSeriesManager.removeLineSeries(id);\n  }\n\n  updateLineSeries(id: string, data: Array<{ time: number; value: number }>): void {\n    this.lineSeriesManager.updateLineSeries(id, data);\n  }\n\n  toggleLineSeriesVisibility(id: string): void {\n    this.lineSeriesManager.toggleVisibility(id);\n  }\n\n  updateLineSeriesStyle(id: string, style: { color?: string; lineWidth?: number }): void {\n    this.lineSeriesManager.updateStyle(id, style);\n  }\n\n  getLineSeries(id: string): LineSeriesData | undefined {\n    return this.lineSeriesManager.getSeries(id) as any;\n  }\n\n  getAllLineSeries(): LineSeriesData[] {\n    return this.lineSeriesManager.getAllSeries() as any;\n  }\n\n  getVisibleSeries(): LineSeriesData[] {\n    return this.lineSeriesManager.getVisibleSeries() as any;\n  }\n\n  setSeriesVisibility(id: string, visible: boolean): void {\n    this.lineSeriesManager.setSeriesVisibility(id, visible);\n  }\n\n  clearLineSeries(): void {\n    this.lineSeriesManager.clear();\n  }\n\n  // DrawingManager 특수 메서드들\n  setDataManager(_dataManager: any): void {\n    // DrawingManager에 setDataManager가 없으므로 주석 처리\n    // 필요한 경우 나중에 추가\n    // this.drawingManager.setDataManager(dataManager);\n  }\n\n  setSnapManager(_snapManager: any): void {\n    // DrawingManager에 setSnapManager가 없으므로 주석 처리\n    // this.drawingManager.setSnapManager(snapManager);\n  }\n\n  setSnapChangeCallback(callback: ((snapPoint: any) => void) | null): void {\n    if (callback) {\n      this.drawingManager.setSnapChangeCallback(callback);\n    }\n  }\n\n  setMeasureChangeCallback(callback: ((start: any, end: any, fixed: boolean) => void) | null): void {\n    if (callback) {\n      this.drawingManager.setMeasureChangeCallback(callback);\n    }\n  }\n\n  cancelMeasure(): void {\n    this.drawingManager.cancelMeasure();\n  }\n\n  isMeasureMode(): boolean {\n    return this.drawingManager.isMeasureMode();\n  }\n\n  cancelDrawing(): void {\n    this.drawingManager.cancelDrawing();\n  }\n\n  createHorizontalLineImmediate(point: ChartPoint): void {\n    this.drawingManager.createHorizontalLineImmediate(point);\n  }\n\n  undo(): boolean {\n    return this.drawingManager.undo();\n  }\n\n  redo(): boolean {\n    return this.drawingManager.redo();\n  }\n\n  deleteSelectedDrawing(): boolean {\n    return this.drawingManager.deleteSelectedDrawing();\n  }\n\n  dispose(): void {\n    // 각 매니저의 dispose 호출 (있다면)\n    if ('dispose' in this.drawingManager) {\n      (this.drawingManager as any).dispose();\n    }\n    if ('dispose' in this.markerManager) {\n      (this.markerManager as any).dispose();\n    }\n    if ('dispose' in this.stopLossManager) {\n      (this.stopLossManager as any).dispose();\n    }\n    if ('dispose' in this.lineSeriesManager) {\n      (this.lineSeriesManager as any).dispose();\n    }\n  }\n}","/**\n * WebGL 유틸리티 함수들\n */\n\nexport function createShader(\n  gl: WebGLRenderingContext,\n  type: number,\n  source: string\n): WebGLShader | null {\n  const shader = gl.createShader(type);\n  if (!shader) {\n    console.error('Failed to create shader');\n    return null;\n  }\n\n  gl.shaderSource(shader, source);\n  gl.compileShader(shader);\n\n  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n    console.error('Shader compilation error:', gl.getShaderInfoLog(shader));\n    gl.deleteShader(shader);\n    return null;\n  }\n\n  return shader;\n}\n\nexport function createProgram(\n  gl: WebGLRenderingContext,\n  vertexShader: WebGLShader,\n  fragmentShader: WebGLShader\n): WebGLProgram | null {\n  const program = gl.createProgram();\n  if (!program) {\n    console.error('Failed to create program');\n    return null;\n  }\n\n  gl.attachShader(program, vertexShader);\n  gl.attachShader(program, fragmentShader);\n  gl.linkProgram(program);\n\n  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n    console.error('Program linking error:', gl.getProgramInfoLog(program));\n    gl.deleteProgram(program);\n    return null;\n  }\n\n  return program;\n}\n\nexport function createBuffer(\n  gl: WebGLRenderingContext,\n  data: Float32Array | Uint16Array,\n  target: number = gl.ARRAY_BUFFER\n): WebGLBuffer | null {\n  const buffer = gl.createBuffer();\n  if (!buffer) {\n    console.error('Failed to create buffer');\n    return null;\n  }\n\n  gl.bindBuffer(target, buffer);\n  gl.bufferData(target, data, gl.STATIC_DRAW);\n\n  return buffer;\n}\n\nexport function resizeCanvasToDisplaySize(\n  canvas: HTMLCanvasElement,\n  pixelRatio: number = window.devicePixelRatio\n): boolean {\n  const width = Math.floor(canvas.clientWidth * pixelRatio);\n  const height = Math.floor(canvas.clientHeight * pixelRatio);\n  \n  if (canvas.width !== width || canvas.height !== height) {\n    canvas.width = width;\n    canvas.height = height;\n    return true;\n  }\n  \n  return false;\n}\n\nexport function createTexture(\n  gl: WebGLRenderingContext,\n  width: number,\n  height: number,\n  data?: Uint8Array\n): WebGLTexture | null {\n  const texture = gl.createTexture();\n  if (!texture) {\n    console.error('Failed to create texture');\n    return null;\n  }\n\n  gl.bindTexture(gl.TEXTURE_2D, texture);\n  \n  // 텍스처 파라미터 설정\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n  \n  // 텍스처 데이터 설정\n  gl.texImage2D(\n    gl.TEXTURE_2D,\n    0,\n    gl.RGBA,\n    width,\n    height,\n    0,\n    gl.RGBA,\n    gl.UNSIGNED_BYTE,\n    data || null\n  );\n\n  return texture;\n}\n\n// 색상 변환 함수\nexport function hexToRGBA(hex: string, alpha: number = 1): [number, number, number, number] {\n  const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n  if (!result) {\n    return [0, 0, 0, alpha];\n  }\n  \n  return [\n    parseInt(result[1], 16) / 255,\n    parseInt(result[2], 16) / 255,\n    parseInt(result[3], 16) / 255,\n    alpha\n  ];\n}\n\n// 행렬 함수들\nexport function createOrthoMatrix(\n  left: number,\n  right: number,\n  bottom: number,\n  top: number,\n  near: number = -1,\n  far: number = 1\n): Float32Array {\n  const lr = 1 / (left - right);\n  const bt = 1 / (bottom - top);\n  const nf = 1 / (near - far);\n  \n  const matrix = new Float32Array(16);\n  \n  matrix[0] = -2 * lr;\n  matrix[5] = -2 * bt;\n  matrix[10] = 2 * nf;\n  matrix[12] = (left + right) * lr;\n  matrix[13] = (top + bottom) * bt;\n  matrix[14] = (far + near) * nf;\n  matrix[15] = 1;\n  \n  return matrix;\n}\n\n// 성능 모니터링\nexport class PerformanceMonitor {\n  private lastTime: number = 0;\n  private frames: number = 0;\n  private fps: number = 0;\n  \n  update(): number {\n    this.frames++;\n    const currentTime = performance.now();\n    \n    if (currentTime >= this.lastTime + 1000) {\n      this.fps = (this.frames * 1000) / (currentTime - this.lastTime);\n      this.frames = 0;\n      this.lastTime = currentTime;\n    }\n    \n    return this.fps;\n  }\n  \n  getFPS(): number {\n    return Math.round(this.fps);\n  }\n}","/**\n * WebGL 버퍼 풀링 시스템\n * 버퍼를 재사용하여 가비지 컬렉션 압력을 줄이고 성능을 향상시킵니다.\n */\nexport class BufferPool {\n  private gl: WebGLRenderingContext;\n  private availableBuffers: WebGLBuffer[] = [];\n  private activeBuffers: Set<WebGLBuffer> = new Set();\n  private maxPoolSize: number = 50;\n  \n  constructor(gl: WebGLRenderingContext, maxPoolSize: number = 50) {\n    this.gl = gl;\n    this.maxPoolSize = maxPoolSize;\n  }\n  \n  /**\n   * 버퍼를 가져옵니다. 풀에 사용 가능한 버퍼가 있으면 재사용하고,\n   * 없으면 새로 생성합니다.\n   */\n  acquire(): WebGLBuffer {\n    let buffer: WebGLBuffer | null;\n    \n    if (this.availableBuffers.length > 0) {\n      buffer = this.availableBuffers.pop()!;\n    } else {\n      buffer = this.gl.createBuffer();\n      if (!buffer) {\n        throw new Error('Failed to create WebGL buffer');\n      }\n    }\n    \n    this.activeBuffers.add(buffer);\n    return buffer;\n  }\n  \n  /**\n   * 버퍼를 풀에 반환합니다.\n   */\n  release(buffer: WebGLBuffer): void {\n    if (!this.activeBuffers.has(buffer)) {\n      console.warn('Attempting to release buffer that was not acquired from this pool');\n      return;\n    }\n    \n    this.activeBuffers.delete(buffer);\n    \n    // 풀 크기 제한\n    if (this.availableBuffers.length < this.maxPoolSize) {\n      this.availableBuffers.push(buffer);\n    } else {\n      // 풀이 가득 찬 경우 버퍼 삭제\n      this.gl.deleteBuffer(buffer);\n    }\n  }\n  \n  /**\n   * 모든 활성 버퍼를 풀로 반환합니다.\n   */\n  releaseAll(): void {\n    const buffers = Array.from(this.activeBuffers);\n    buffers.forEach(buffer => this.release(buffer));\n  }\n  \n  /**\n   * 풀의 모든 버퍼를 삭제하고 정리합니다.\n   */\n  dispose(): void {\n    // 활성 버퍼 삭제\n    this.activeBuffers.forEach(buffer => {\n      this.gl.deleteBuffer(buffer);\n    });\n    this.activeBuffers.clear();\n    \n    // 풀의 버퍼 삭제\n    this.availableBuffers.forEach(buffer => {\n      this.gl.deleteBuffer(buffer);\n    });\n    this.availableBuffers = [];\n  }\n  \n  /**\n   * 풀 상태 정보를 반환합니다.\n   */\n  getStats(): { active: number; available: number; total: number } {\n    return {\n      active: this.activeBuffers.size,\n      available: this.availableBuffers.length,\n      total: this.activeBuffers.size + this.availableBuffers.length\n    };\n  }\n}","import {\n  createShader,\n  createProgram,\n  resizeCanvasToDisplaySize,\n  hexToRGBA,\n  createOrthoMatrix\n} from '@/utils/webgl-utils';\nimport { BufferPool } from './BufferPool';\n\ninterface ShaderProgram {\n  program: WebGLProgram;\n  attributes: Record<string, number>;\n  uniforms: Record<string, WebGLUniformLocation | null>;\n}\n\nexport class WebGLRenderer {\n  private canvas: HTMLCanvasElement;\n  private gl: WebGLRenderingContext;\n  private programs: Map<string, ShaderProgram> = new Map();\n  private width: number = 0;\n  private height: number = 0;\n  private pixelRatio: number = window.devicePixelRatio;\n  private bufferPool: BufferPool;\n  \n  constructor(canvas: HTMLCanvasElement) {\n    this.canvas = canvas;\n    \n    const gl = canvas.getContext('webgl', {\n      alpha: false,\n      antialias: true,\n      premultipliedAlpha: false,\n      preserveDrawingBuffer: true  // 차트 캡쳐를 위해 true로 설정\n    });\n    \n    if (!gl) {\n      throw new Error('WebGL not supported');\n    }\n    \n    this.gl = gl;\n    this.bufferPool = new BufferPool(gl);\n    this.setupContextLossHandling();\n    this.init();\n  }\n  \n  private setupContextLossHandling(): void {\n    this.canvas.addEventListener('webglcontextlost', (e) => {\n      e.preventDefault();\n      console.warn('[WebGLRenderer] WebGL context lost');\n      // 프로그램과 버퍼 정리\n      this.programs.clear();\n    });\n    \n    this.canvas.addEventListener('webglcontextrestored', () => {\n      console.log('[WebGLRenderer] WebGL context restored');\n      // 컨텍스트 복구 시 재초기화\n      this.init();\n    });\n  }\n  \n  init(): void {\n    const gl = this.gl;\n    \n    // 블렌딩 설정\n    gl.enable(gl.BLEND);\n    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n    \n    // 뷰포트 설정\n    this.resize();\n  }\n  \n  /**\n   * 셰이더 프로그램 로드\n   */\n  async loadShaderProgram(\n    name: string,\n    vertexSource: string,\n    fragmentSource: string,\n    attributes: string[],\n    uniforms: string[]\n  ): Promise<void> {\n    const gl = this.gl;\n    \n    // 셰이더 생성\n    const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);\n    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n    \n    if (!vertexShader || !fragmentShader) {\n      throw new Error(`Failed to create shaders for ${name}`);\n    }\n    \n    // 프로그램 생성\n    const program = createProgram(gl, vertexShader, fragmentShader);\n    if (!program) {\n      throw new Error(`Failed to create program for ${name}`);\n    }\n    \n    // 속성 위치 가져오기\n    const attributeLocations: Record<string, number> = {};\n    for (const attr of attributes) {\n      const location = gl.getAttribLocation(program, attr);\n      if (location === -1) {\n        console.warn(`Attribute ${attr} not found in shader ${name}`);\n      }\n      attributeLocations[attr] = location;\n    }\n    \n    // 유니폼 위치 가져오기\n    const uniformLocations: Record<string, WebGLUniformLocation | null> = {};\n    for (const uniform of uniforms) {\n      uniformLocations[uniform] = gl.getUniformLocation(program, uniform);\n      if (!uniformLocations[uniform]) {\n        console.warn(`Uniform ${uniform} not found in shader ${name}`);\n      }\n    }\n    \n    this.programs.set(name, {\n      program,\n      attributes: attributeLocations,\n      uniforms: uniformLocations\n    });\n  }\n  \n  /**\n   * 화면 크기 조정\n   */\n  resize(): void {\n    const resized = resizeCanvasToDisplaySize(this.canvas, this.pixelRatio);\n    \n    if (resized) {\n      this.width = this.canvas.width;\n      this.height = this.canvas.height;\n      this.gl.viewport(0, 0, this.width, this.height);\n    }\n  }\n  \n  /**\n   * 화면 지우기\n   */\n  clear(color: string = '#000000'): void {\n    const gl = this.gl;\n    const [r, g, b, a] = hexToRGBA(color, 1);\n    \n    gl.clearColor(r, g, b, a);\n    gl.clear(gl.COLOR_BUFFER_BIT);\n  }\n  \n  /**\n   * 직교 투영 행렬 생성\n   */\n  createProjectionMatrix(\n    left: number,\n    right: number,\n    bottom: number,\n    top: number\n  ): Float32Array {\n    return createOrthoMatrix(left, right, bottom, top);\n  }\n  \n  /**\n   * 프로그램 사용\n   */\n  useProgram(name: string): ShaderProgram | null {\n    const program = this.programs.get(name);\n    if (!program) {\n      console.error(`Program ${name} not found`);\n      return null;\n    }\n    \n    this.gl.useProgram(program.program);\n    return program;\n  }\n  \n  /**\n   * 버퍼 생성 헬퍼 (BufferPool 사용)\n   */\n  createBuffer(data: Float32Array | Uint16Array, target?: number): WebGLBuffer | null {\n    const gl = this.gl;\n    const buffer = this.bufferPool.acquire();\n    const bufferTarget = target || gl.ARRAY_BUFFER;\n    \n    gl.bindBuffer(bufferTarget, buffer);\n    gl.bufferData(bufferTarget, data, gl.STATIC_DRAW);\n    \n    return buffer;\n  }\n  \n  /**\n   * 속성 설정\n   */\n  setupAttribute(\n    location: number,\n    buffer: WebGLBuffer,\n    size: number,\n    type: number = this.gl.FLOAT,\n    normalized: boolean = false,\n    stride: number = 0,\n    offset: number = 0\n  ): void {\n    const gl = this.gl;\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n    gl.enableVertexAttribArray(location);\n    gl.vertexAttribPointer(location, size, type, normalized, stride, offset);\n  }\n  \n  /**\n   * 유니폼 설정 헬퍼 함수들\n   */\n  setUniform1f(location: WebGLUniformLocation | null, value: number): void {\n    if (location) {\n      this.gl.uniform1f(location, value);\n    }\n  }\n  \n  setUniform2f(location: WebGLUniformLocation | null, x: number, y: number): void {\n    if (location) {\n      this.gl.uniform2f(location, x, y);\n    }\n  }\n  \n  setUniform4f(location: WebGLUniformLocation | null, x: number, y: number, z: number, w: number): void {\n    if (location) {\n      this.gl.uniform4f(location, x, y, z, w);\n    }\n  }\n  \n  setUniformMatrix4fv(location: WebGLUniformLocation | null, matrix: Float32Array): void {\n    if (location) {\n      this.gl.uniformMatrix4fv(location, false, matrix);\n    }\n  }\n  \n  getUniformLocation(programName: string, uniformName: string): WebGLUniformLocation | null {\n    const program = this.programs.get(programName);\n    if (!program) return null;\n    \n    return program.uniforms[uniformName] || null;\n  }\n  \n  /**\n   * 그리기 함수들\n   */\n  drawArrays(mode: number, first: number, count: number): void {\n    this.gl.drawArrays(mode, first, count);\n  }\n  \n  drawElements(mode: number, count: number, type: number, offset: number): void {\n    this.gl.drawElements(mode, count, type, offset);\n  }\n  \n  /**\n   * 리소스 정리\n   */\n  dispose(): void {\n    // 버퍼 풀 정리\n    this.bufferPool.dispose();\n    \n    // 프로그램 정리\n    for (const [_, program] of this.programs) {\n      this.gl.deleteProgram(program.program);\n    }\n    this.programs.clear();\n    \n    // 컨텍스트 손실 처리\n    const loseContext = this.gl.getExtension('WEBGL_lose_context');\n    if (loseContext) {\n      loseContext.loseContext();\n    }\n  }\n  \n  getGL(): WebGLRenderingContext {\n    return this.gl;\n  }\n  \n  getBufferPool(): BufferPool {\n    return this.bufferPool;\n  }\n  \n  getCanvas(): HTMLCanvasElement {\n    return this.canvas;\n  }\n  \n  getWidth(): number {\n    return this.width;\n  }\n  \n  getHeight(): number {\n    return this.height;\n  }\n  \n  getPixelRatio(): number {\n    return this.pixelRatio;\n  }\n}","import { WebGLRenderer } from '@/core/WebGLRenderer';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport type { ChartData, Theme } from '@/types';\n\nexport interface PanelOptions {\n  height: number; // 패널 높이 (픽셀 또는 비율)\n  minHeight?: number; // 최소 높이\n  maxHeight?: number; // 최대 높이\n  showYAxis?: boolean; // Y축 표시 여부\n  showGrid?: boolean; // 그리드 표시 여부\n}\n\nexport abstract class ChartPanel {\n  protected container: HTMLElement;\n  protected canvas: HTMLCanvasElement;\n  protected renderer: WebGLRenderer;\n  protected coordSystem: UnifiedCoordinateSystem;\n  protected height: number;\n  protected minHeight: number;\n  protected maxHeight: number;\n  protected showYAxis: boolean;\n  protected showGrid: boolean;\n  \n  constructor(container: HTMLElement, options: PanelOptions) {\n    this.container = container;\n    this.height = options.height;\n    this.minHeight = options.minHeight || 50;\n    this.maxHeight = options.maxHeight || Number.MAX_SAFE_INTEGER;\n    this.showYAxis = options.showYAxis !== false;\n    this.showGrid = options.showGrid !== false;\n    \n    // Canvas 생성\n    this.canvas = document.createElement('canvas');\n    // Y축 레이블 영역(80px)을 고려하여 캔버스 너비 조정\n    this.canvas.style.cssText = `\n      position: absolute;\n      left: 0;\n      top: 0;\n      width: calc(100% - 80px);\n      height: 100%;\n      box-sizing: border-box;\n      display: block;\n    `;\n    this.container.appendChild(this.canvas);\n    \n    // WebGL 렌더러 생성\n    this.renderer = new WebGLRenderer(this.canvas);\n    \n    // UnifiedCoordinateSystem은 하위 클래스에서 설정됨\n    this.coordSystem = null as any; // 초기화는 하위 클래스에서\n  }\n  \n  abstract render(data: ChartData): void;\n  \n  resize(width?: number, height?: number): void {\n    // 크기가 제공되지 않으면 컨테이너에서 가져옴\n    const rect = this.container.getBoundingClientRect();\n    const actualWidth = width || rect.width;\n    const actualHeight = height || rect.height;\n    \n    this.height = Math.max(this.minHeight, Math.min(actualHeight, this.maxHeight));\n    const pixelRatio = window.devicePixelRatio || 1;\n    \n    if (this.coordSystem) {\n      this.coordSystem.resize(actualWidth * pixelRatio, this.height * pixelRatio);\n    }\n    this.renderer.resize();\n  }\n  \n  getHeight(): number {\n    return this.height;\n  }\n  \n  setHeight(height: number): void {\n    this.height = Math.max(this.minHeight, Math.min(height, this.maxHeight));\n    this.resize(this.coordSystem?.getCanvasWidth(), this.height);\n  }\n  \n  getViewport(): UnifiedCoordinateSystem {\n    return this.coordSystem;\n  }\n  \n  async init(): Promise<void> {\n    // 실제 크기로 coordSystem 업데이트\n    const rect = this.container.getBoundingClientRect();\n    const pixelRatio = window.devicePixelRatio || 1;\n    const width = Math.max(rect.width || 800, 100) * pixelRatio;\n    const height = Math.max(rect.height || 600, 100) * pixelRatio;\n    if (this.coordSystem) {\n      this.coordSystem.resize(width, height);\n    }\n    this.renderer.resize();\n  }\n  \n  updateTheme(_theme: Theme): void {\n    // 하위 클래스에서 구현\n  }\n  \n  requestRender(): void {\n    // 렌더링 요청 - 하위 클래스에서 필요시 구현\n  }\n  \n  dispose(): void {\n    this.renderer.dispose();\n    this.canvas.remove();\n  }\n}","/**\n * 통합 좌표 시스템\n * Viewport와 CoordinateSystem의 기능을 하나로 통합\n * \n * 좌표계 정의:\n * - CSS 픽셀: 브라우저 이벤트 좌표 (clientX, clientY)\n * - Canvas 픽셀: WebGL이 사용하는 실제 픽셀 (CSS * devicePixelRatio)\n * - Chart 좌표: 차트 데이터 좌표 (캔들 인덱스, 가격)\n * \n * 모든 내부 계산은 Canvas 픽셀 기준으로 통일\n */\n\nimport type { ViewportState, ChartPoint, ICoordinateSystem } from '@/types';\nimport type { DataManager } from './DataManager';\n\nexport interface Point {\n  x: number;\n  y: number;\n}\n\n\nexport interface Range {\n  start: number;\n  end: number;\n}\n\nexport interface PriceRange {\n  min: number;\n  max: number;\n}\n\nexport class UnifiedCoordinateSystem implements ICoordinateSystem {\n  // Canvas 크기 (물리적 픽셀)\n  private canvasWidth: number = 0;\n  private canvasHeight: number = 0;\n  private pixelRatio: number;\n  private _rangeLogged: boolean = false;\n  \n  // Y축 너비 (CSS 픽셀)\n  private _yAxisWidth: number = 80;\n  \n  // 뷰포트 상태\n  private pixelOffset: number = 0;  // 단일 진실의 소스\n  private candleWidth: number = 10;\n  private readonly MIN_CANDLE_WIDTH = 1;\n  private readonly MAX_CANDLE_WIDTH = 50;\n  \n  // 가격 범위\n  private minPrice: number = 0;\n  private maxPrice: number = 100;\n  private priceMarginTop: number = 0.1;  // 10% 여백\n  private priceMarginBottom: number = 0.1;  // 10% 여백\n  \n  // 오른쪽 여백 (캔들 개수로 정의)\n  private rightMarginCandles: number = 0;  // 기본값: 여백 없음\n  \n  // 패널별 Y축 범위 관리\n  private panelPriceRanges: Map<string, { min: number, max: number, marginTop: number, marginBottom: number }> = new Map();\n  private currentPanelId: string = 'main';  // 기본 패널 ID\n  \n  // 패널별 높이 관리\n  private panelHeights: Map<string, number> = new Map();\n  // 패널별 Y 오프셋 관리 (화면에서의 시작 위치)\n  private panelYOffsets: Map<string, number> = new Map();\n  \n  // 데이터 정보\n  private totalCandles: number = 0;\n  private dataTimeRange: [number, number] = [0, 0];\n  \n  // 패닝 관성\n  private velocity: number = 0;\n  private readonly FRICTION = 0.92;\n  \n  // Y축 설정\n  private autoScale: boolean = true;\n  private logScale: boolean = true; // 로그스케일 기본값으로 설정\n  private fixedPriceRange: [number, number] | null = null;\n  \n  // DataManager 참조 (타임스탬프 변환용)\n  private dataManager: DataManager | null = null;\n  \n  constructor(width: number, height: number, pixelRatio: number = window.devicePixelRatio, yAxisWidth: number = 80) {\n    // WebGLRenderer에서 전달받은 width는 이미 Y축이 제외된 실제 차트 영역의 Canvas 픽셀 크기\n    this.canvasWidth = width;\n    this.canvasHeight = height;\n    this.pixelRatio = pixelRatio;\n    this._yAxisWidth = yAxisWidth;\n  }\n  \n  // ========== 크기 관리 ==========\n  \n  /**\n   * Canvas 크기 업데이트\n   * @param width 전체 컨테이너 너빔 (Canvas 픽셀)\n   * @param height 전체 컨테이너 높이 (Canvas 픽셀)\n   */\n  resize(width: number, height: number): void {\n    // 실제 차트 영역은 Y축을 제외한 너비\n    this.canvasWidth = width;\n    this.canvasHeight = height;\n  }\n  \n  /**\n   * Y축 너비 설정\n   */\n  setYAxisWidth(width: number): void {\n    this._yAxisWidth = width;\n  }\n  \n  /**\n   * Y축 너비 반환\n   */\n  getYAxisWidth(): number {\n    return this._yAxisWidth;\n  }\n  \n  /**\n   * 총 캔들 수 반환\n   */\n  getTotalCandles(): number {\n    return this.totalCandles;\n  }\n  \n  /**\n   * 현재 픽셀 오프셋 반환\n   */\n  getPixelOffset(): number {\n    return this.pixelOffset;\n  }\n  \n  /**\n   * 현재 패널 ID 반환\n   */\n  getCurrentPanel(): string {\n    return this.currentPanelId;\n  }\n  \n  /**\n   * 실제 차트 영역 너비 반환\n   */\n  getChartAreaWidth(): number {\n    // canvasWidth가 이미 Y축이 제외된 실제 차트 영역의 너비\n    return this.canvasWidth;\n  }\n  \n  /**\n   * 패널별 높이 설정\n   * @param panelId 패널 ID\n   * @param height 패널 높이 (Canvas 픽셀 단위)\n   */\n  setPanelHeight(panelId: string, height: number): void {\n    this.panelHeights.set(panelId, height);\n  }\n  \n  /**\n   * 패널별 Y 오프셋 설정\n   * @param panelId 패널 ID\n   * @param yOffset Y 오프셋 (Canvas 픽셀 단위)\n   */\n  setPanelYOffset(panelId: string, yOffset: number): void {\n    this.panelYOffsets.set(panelId, yOffset);\n  }\n  \n  /**\n   * 패널의 실제 높이 가져오기\n   * @param panelId 패널 ID\n   * @returns 패널 높이 (Canvas 픽셀 단위)\n   */\n  private getPanelHeight(panelId?: string): number {\n    const id = panelId || this.currentPanelId;\n    return this.panelHeights.get(id) || this.canvasHeight;\n  }\n  \n  /**\n   * DataManager 설정 (타임스탬프 변환용)\n   */\n  setDataManager(dataManager: DataManager): void {\n    this.dataManager = dataManager;\n  }\n\n  /**\n   * DataManager 가져오기\n   */\n  getDataManager(): DataManager | null {\n    return this.dataManager;\n  }\n  \n  /**\n   * 데이터 정보 설정\n   */\n  setDataInfo(totalCandles: number, timeRange: [number, number]): void {\n    this.totalCandles = totalCandles;\n    this.dataTimeRange = timeRange;\n    \n    // 실제 차트 영역 너비 사용\n    const chartAreaWidth = this.getChartAreaWidth();\n    \n    // chartAreaWidth가 0이더라도 totalCandles는 저장해야 함\n    if (chartAreaWidth === 0) {\n      // console.log('[setDataInfo] Chart area width is 0, setting default candle width');\n      this.candleWidth = 10;\n      return;  // pixelOffset은 나중에 scrollToEnd에서 설정\n    }\n    \n    // 캔들 너비만 설정하고, 오프셋은 applyInitialView에서 처리\n    const visibleCandles = Math.min(100, totalCandles);\n    this.candleWidth = chartAreaWidth / visibleCandles;\n    this.candleWidth = Math.max(\n      this.MIN_CANDLE_WIDTH,\n      Math.min(this.MAX_CANDLE_WIDTH, this.candleWidth)\n    );\n    \n    // pixelOffset 설정을 제거 - scrollToEnd에서 처리하도록 함\n  }\n  \n  // ========== 좌표 변환 (핵심 기능) ==========\n  \n  /**\n   * CSS 픽셀을 Canvas 픽셀로 변환\n   */\n  cssToCanvas(cssX: number, cssY: number): Point {\n    return {\n      x: cssX * this.pixelRatio,\n      y: cssY * this.pixelRatio\n    };\n  }\n  \n  /**\n   * Canvas 픽셀을 CSS 픽셀로 변환\n   */\n  canvasToCSS(canvasX: number, canvasY: number): Point {\n    return {\n      x: canvasX / this.pixelRatio,\n      y: canvasY / this.pixelRatio\n    };\n  }\n  \n  /**\n   * Chart 좌표를 Canvas 픽셀로 변환\n   * @param indexOrTime - 캔들 인덱스 또는 타임스탬프\n   * @param price - 가격\n   * @param panelId - 패널 ID (optional, Y축 변환용)\n   */\n  chartToCanvas(indexOrTime: number, price: number, panelId?: string): Point {\n    // 드로잉에서는 일관성을 위해 인덱스를 직접 사용\n    let index = indexOrTime;\n    \n    // 큰 숫자는 타임스탬프로 간주하여 변환\n    if (indexOrTime > 1000000000) { // Unix timestamp (초 단위)\n      index = this.timeToIndex(indexOrTime);\n    }\n    \n    return {\n      x: this.indexToCanvasX(index),\n      y: this.priceToCanvasY(price, panelId)\n    };\n  }\n  \n  /**\n   * Canvas 픽셀을 Chart 좌표로 변환\n   * @param canvasX Canvas X 좌표\n   * @param canvasY Canvas Y 좌표\n   * @param panelId 패널 ID (optional, Y축 변환용)\n   */\n  canvasToChart(canvasX: number, canvasY: number, panelId?: string): ChartPoint {\n    const index = this.canvasXToIndex(canvasX);\n    \n    // 캔들 없는 영역에서는 인덱스를 시간으로 직접 사용\n    // (드로잉에서는 정확한 타임스탬프보다 일관된 좌표가 중요)\n    let time = index;\n    \n    // 데이터가 있는 경우에만 실제 타임스탬프로 변환\n    if (this.dataManager && this.dataManager.getData()) {\n      const data = this.dataManager.getData();\n      const times = data!.times;  // 위에서 체크했으므로 null이 아님\n      \n      // 데이터 범위 내에서만 실제 타임스탬프 사용\n      if (index >= 0 && index < times.length) {\n        const clampedIndex = Math.max(0, Math.min(times.length - 1, Math.round(index)));\n        time = times[clampedIndex];\n      }\n      // 데이터 범위 밖에서는 인덱스를 그대로 사용 (일관성 유지)\n    }\n    \n    return {\n      time: time,\n      price: this.canvasYToPrice(canvasY, panelId)\n    };\n  }\n  \n  /**\n   * CSS 픽셀을 Chart 좌표로 변환 (편의 메서드)\n   */\n  cssToChart(cssX: number, cssY: number, panelId?: string): ChartPoint {\n    const canvas = this.cssToCanvas(cssX, cssY);\n    return this.canvasToChart(canvas.x, canvas.y, panelId);\n  }\n  \n  /**\n   * Chart 좌표를 CSS 픽셀로 변환 (편의 메서드)\n   */\n  chartToCSS(index: number, price: number, panelId?: string): Point {\n    const canvas = this.chartToCanvas(index, price, panelId);\n    return this.canvasToCSS(canvas.x, canvas.y);\n  }\n  \n  // ========== 내부 변환 헬퍼 ==========\n  \n  /**\n   * 타임스탬프를 캔들 인덱스로 변환 (캔들 없는 영역도 허용)\n   */\n  private timeToIndex(timestamp: number): number {\n    // dataManager가 있고 시간 데이터가 있는 경우\n    if (this.dataManager && this.dataManager.getData()) {\n      const data = this.dataManager.getData();\n      const times = data!.times;  // 위에서 체크했으므로 null이 아님\n      \n      if (times.length === 0) return 0;\n      if (times.length === 1) return 0;\n      \n      const timeInterval = times[1] - times[0];\n      \n      // 데이터 범위를 벗어나는 경우 외삽\n      if (timestamp < times[0]) {\n        // 왼쪽 확장\n        return (timestamp - times[0]) / timeInterval;\n      } else if (timestamp > times[times.length - 1]) {\n        // 오른쪽 확장\n        return times.length - 1 + (timestamp - times[times.length - 1]) / timeInterval;\n      }\n      \n      // 이진 검색으로 가장 가까운 인덱스 찾기\n      let left = 0;\n      let right = times.length - 1;\n      \n      while (left <= right) {\n        const mid = Math.floor((left + right) / 2);\n        if (times[mid] === timestamp) {\n          return mid;\n        } else if (times[mid] < timestamp) {\n          left = mid + 1;\n        } else {\n          right = mid - 1;\n        }\n      }\n      \n      // 정확한 매치가 없으면 가장 가까운 인덱스 반환\n      if (left >= times.length) return times.length - 1;\n      if (right < 0) return 0;\n      \n      // 더 가까운 쪽 선택\n      const leftDiff = Math.abs(times[left] - timestamp);\n      const rightDiff = Math.abs(times[right] - timestamp);\n      return leftDiff < rightDiff ? left : right;\n    }\n    \n    // dataManager가 없으면 그대로 반환 (인덱스로 가정)\n    return timestamp;\n  }\n  \n  /**\n   * 캔들 인덱스를 Canvas X 좌표로 변환 (캔들 중앙)\n   */\n  indexToCanvasX(index: number): number {\n    // 드로잉에서는 정확한 좌표가 필요 (반올림 제거)\n    return (index + 0.5) * this.candleWidth + this.pixelOffset;\n  }\n  \n  /**\n   * Canvas X 좌표를 캔들 인덱스로 변환\n   */\n  canvasXToIndex(canvasX: number): number {\n    // 드로잉에서는 정확한 소수점 인덱스가 필요 (반올림 제거)\n    return (canvasX - this.pixelOffset) / this.candleWidth - 0.5;\n  }\n  \n  // 레거시 호환성 (CoordinateSystem)\n  canvasXToCandleIndex(x: number): number {\n    return this.canvasXToIndex(x);\n  }\n  \n  /**\n   * 가격을 Canvas Y 좌표로 변환\n   * @param price 가격\n   * @param panelId 패널 ID (optional, 기본값은 현재 패널)\n   */\n  priceToCanvasY(price: number, panelId?: string): number {\n    const id = panelId || this.currentPanelId;\n    const panelRange = this.panelPriceRanges.get(id);\n    const minPrice = panelRange?.min ?? this.minPrice;\n    const maxPrice = panelRange?.max ?? this.maxPrice;\n    \n    // 패널별 높이 사용\n    const panelHeight = this.getPanelHeight(id);\n    \n    const priceRange = maxPrice - minPrice;\n    if (priceRange === 0) return panelHeight / 2;\n    \n    if (this.logScale && price > 0 && minPrice > 0) {\n      // 로그 스케일\n      const logPrice = Math.log(price);\n      const logMin = Math.log(minPrice);\n      const logMax = Math.log(maxPrice);\n      const logRange = logMax - logMin;\n      return ((logMax - logPrice) / logRange) * panelHeight;\n    } else {\n      // 선형 스케일\n      const normalized = (price - minPrice) / priceRange;\n      return panelHeight * (1 - normalized);\n    }\n  }\n  \n  /**\n   * Canvas Y 좌표를 가격으로 변환\n   * @param canvasY Canvas Y 좌표\n   * @param panelId 패널 ID (optional, 기본값은 현재 패널)\n   */\n  canvasYToPrice(canvasY: number, panelId?: string): number {\n    const id = panelId || this.currentPanelId;\n    const panelRange = this.panelPriceRanges.get(id);\n    const minPrice = panelRange?.min ?? this.minPrice;\n    const maxPrice = panelRange?.max ?? this.maxPrice;\n    \n    // 패널별 높이 사용\n    const panelHeight = this.getPanelHeight(id);\n    \n    if (this.logScale && minPrice > 0) {\n      // 로그 스케일\n      const logMin = Math.log(minPrice);\n      const logMax = Math.log(maxPrice);\n      const logRange = logMax - logMin;\n      const logPrice = logMax - (canvasY / panelHeight) * logRange;\n      return Math.exp(logPrice);\n    } else {\n      // 선형 스케일\n      const normalized = 1 - (canvasY / panelHeight);\n      return minPrice + normalized * (maxPrice - minPrice);\n    }\n  }\n  \n  /**\n   * Canvas 좌표를 WebGL NDC로 변환\n   */\n  canvasToNDC(canvasX: number, canvasY: number): Point {\n    return {\n      x: (canvasX / this.canvasWidth) * 2 - 1,\n      y: 1 - (canvasY / this.canvasHeight) * 2\n    };\n  }\n  \n  \n  // ========== 뷰포트 조작 ==========\n  \n  /**\n   * 패닝\n   */\n  pan(deltaX: number): void {\n    this.pixelOffset += deltaX;\n    this.velocity = deltaX;\n  }\n  \n  /**\n   * 줌 (마우스/터치 위치 중심)\n   */\n  zoom(factor: number, centerX: number): void {\n    const newCandleWidth = this.candleWidth * factor;\n    \n    if (newCandleWidth < this.MIN_CANDLE_WIDTH || newCandleWidth > this.MAX_CANDLE_WIDTH) {\n      return;\n    }\n    \n    // 줌 중심점의 캔들 인덱스 계산\n    const candleAtMouse = (centerX - this.pixelOffset) / this.candleWidth;\n    \n    // 새로운 캔들 너비 적용\n    this.candleWidth = newCandleWidth;\n    \n    // 줌 중심점이 같은 위치에 있도록 오프셋 조정\n    this.pixelOffset = centerX - candleAtMouse * this.candleWidth;\n  }\n  \n  /**\n   * 관성 업데이트\n   */\n  updateInertia(): boolean {\n    if (Math.abs(this.velocity) < 0.5) {\n      this.velocity = 0;\n      return false;\n    }\n    \n    this.pan(this.velocity);\n    this.velocity *= this.FRICTION;\n    return true;\n  }\n  \n  /**\n   * 컨텐츠에 맞춰 조정\n   */\n  fitContent(): void {\n    if (this.totalCandles === 0) return;\n    \n    // console.log('[fitContent] Called - this should NOT happen after scrollToEnd!');\n    \n    const chartAreaWidth = this.getChartAreaWidth();\n    this.candleWidth = chartAreaWidth / this.totalCandles;\n    this.candleWidth = Math.max(\n      this.MIN_CANDLE_WIDTH,\n      Math.min(this.MAX_CANDLE_WIDTH, this.candleWidth)\n    );\n    \n    const totalWidth = this.totalCandles * this.candleWidth;\n    this.pixelOffset = (chartAreaWidth - totalWidth) / 2;\n    // console.log('[fitContent] Setting pixelOffset to:', this.pixelOffset);\n  }\n  \n  // ========== 가격 범위 관리 ==========\n  \n  /**\n   * 가격 범위 설정\n   * @param minPrice 최소 가격\n   * @param maxPrice 최대 가격\n   * @param panelId 패널 ID (optional, 기본값은 현재 패널)\n   */\n  setPriceRange(minPrice: number, maxPrice: number, panelId?: string): void {\n    const id = panelId || this.currentPanelId;\n    \n    if (this.autoScale && !this.fixedPriceRange) {\n      const range = maxPrice - minPrice;\n      const marginTop = this.panelPriceRanges.get(id)?.marginTop ?? this.priceMarginTop;\n      const marginBottom = this.panelPriceRanges.get(id)?.marginBottom ?? this.priceMarginBottom;\n      const paddingTop = range * marginTop;\n      const paddingBottom = range * marginBottom;\n      \n      const adjustedMin = minPrice - paddingBottom;\n      const adjustedMax = maxPrice + paddingTop;\n      \n      // 패널별로 저장\n      this.panelPriceRanges.set(id, {\n        min: adjustedMin,\n        max: adjustedMax,\n        marginTop,\n        marginBottom\n      });\n      \n      // 현재 패널이면 기본값도 업데이트\n      if (id === this.currentPanelId) {\n        this.minPrice = adjustedMin;\n        this.maxPrice = adjustedMax;\n      }\n    } else if (this.fixedPriceRange) {\n      this.minPrice = this.fixedPriceRange[0];\n      this.maxPrice = this.fixedPriceRange[1];\n    }\n  }\n  \n  /**\n   * 가격 여백 설정\n   * @param top 위쪽 여백 비율\n   * @param bottom 아래쪽 여백 비율\n   * @param panelId 패널 ID (optional, 기본값은 현재 패널)\n   */\n  setPriceMargin(top: number, bottom: number, panelId?: string): void {\n    const id = panelId || this.currentPanelId;\n    const clampedTop = Math.max(0, Math.min(0.5, top));\n    const clampedBottom = Math.max(0, Math.min(0.5, bottom));\n    \n    \n    // 현재 패널의 기본값 업데이트\n    if (id === this.currentPanelId) {\n      this.priceMarginTop = clampedTop;\n      this.priceMarginBottom = clampedBottom;\n    }\n    \n    // 패널별 여백 저장\n    const currentRange = this.panelPriceRanges.get(id);\n    if (currentRange) {\n      currentRange.marginTop = clampedTop;\n      currentRange.marginBottom = clampedBottom;\n    }\n  }\n  \n  /**\n   * 고정 가격 범위 설정\n   */\n  setFixedPriceRange(range: [number, number] | null): void {\n    this.fixedPriceRange = range;\n    if (range && !this.autoScale) {\n      this.minPrice = range[0];\n      this.maxPrice = range[1];\n    }\n  }\n  \n  /**\n   * 오토 스케일 설정\n   */\n  setAutoScale(enabled: boolean): void {\n    this.autoScale = enabled;\n    if (!enabled && this.fixedPriceRange) {\n      this.minPrice = this.fixedPriceRange[0];\n      this.maxPrice = this.fixedPriceRange[1];\n    }\n  }\n  \n  /**\n   * 로그 스케일 설정\n   */\n  setLogScale(enabled: boolean): void {\n    this.logScale = enabled;\n  }\n  \n  /**\n   * 오른쪽 여백 설정 (캔들 개수로 지정)\n   * @param candles 오른쪽 여백에 표시할 빈 캔들 개수\n   */\n  setRightMargin(candles: number): void {\n    this.rightMarginCandles = Math.max(0, Math.min(50, candles)); // 0-50 캔들 제한\n    this._rangeLogged = false; // 로그 플래그 리셋\n  }\n  \n  // ========== 상태 조회 ==========\n  \n  /**\n   * 보이는 캔들 범위 계산\n   */\n  getVisibleRange(): Range {\n    const chartAreaWidth = this.getChartAreaWidth();\n    \n    if (chartAreaWidth === 0 || this.candleWidth === 0) {\n      return { start: 0, end: 100 };\n    }\n    \n    const startCandle = Math.floor(-this.pixelOffset / this.candleWidth);\n    const endCandle = startCandle + Math.ceil(chartAreaWidth / this.candleWidth) + 1;\n    \n    // rightMargin은 캔들을 숨기지 않고, 화면에 빈 공간을 만듬\n    // 데이터는 모두 표시하되, 스크롤 제한을 조정\n    const range = {\n      start: Math.max(0, startCandle - 1),\n      end: Math.min(this.totalCandles - 1, endCandle + 1)\n    };\n    \n    \n    return range;\n  }\n  \n  // Getter 메서드들\n  getCanvasWidth(): number { return this.canvasWidth; }\n  getCanvasHeight(): number { return this.canvasHeight; }\n  getPixelRatio(): number { return this.pixelRatio; }\n  getCandleWidth(): number { return this.candleWidth; }\n  /**\n   * 가격 범위 가져오기\n   * @param panelId 패널 ID (optional, 기본값은 현재 패널)\n   */\n  getPriceRange(panelId?: string): [number, number] {\n    const id = panelId || this.currentPanelId;\n    const panelRange = this.panelPriceRanges.get(id);\n    if (panelRange) {\n      return [panelRange.min, panelRange.max];\n    }\n    return [this.minPrice, this.maxPrice];\n  }\n  isAutoScale(): boolean { return this.autoScale; }\n  isLogScale(): boolean { return this.logScale; }\n  \n  /**\n   * 레거시 ViewportState 호환성\n   */\n  getState(): ViewportState {\n    const visible = this.getVisibleRange();\n    const [startTime, endTime] = this.dataTimeRange;\n    const timePerCandle = (endTime - startTime) / (this.totalCandles - 1);\n    \n    return {\n      startTime: startTime + visible.start * timePerCandle,\n      endTime: startTime + visible.end * timePerCandle,\n      minPrice: this.minPrice,\n      maxPrice: this.maxPrice,\n      candleWidth: this.candleWidth,\n      pixelRatio: this.pixelRatio\n    };\n  }\n  \n  /**\n   * 레거시 메서드 (Viewport 호환성)\n   */\n  getWidth(): number { return this.canvasWidth / this.pixelRatio; }\n  getHeight(): number { return this.canvasHeight / this.pixelRatio; }\n  \n  // ICoordinateSystem 인터페이스 구현\n  xToTime(x: number): number {\n    const index = this.canvasXToIndex(x);\n    return this.indexToTime(index);\n  }\n  \n  indexToTime(index: number): number {\n    if (!this.dataManager || !this.dataManager.getData()) return 0;\n    const data = this.dataManager.getData();\n    if (!data || !data.times || index < 0 || index >= data.times.length) return 0;\n    return data.times[index];\n  }\n  \n  timeToX(time: number): number {\n    const index = this.timeToIndex(time);\n    return this.indexToCanvasX(index);\n  }\n  \n  yToPrice(y: number): number {\n    return this.canvasYToPrice(y);\n  }\n  \n  priceToY(price: number): number {\n    return this.priceToCanvasY(price);\n  }\n  \n  getViewport(): ViewportState {\n    return this.getState();\n  }\n  \n  candleIndexToPixelX(index: number): number {\n    // Canvas 픽셀 좌표로 변환 (pixelOffset 포함)\n    return Math.round((index + 0.5) * this.candleWidth + this.pixelOffset);\n  }\n  \n  pixelXToCandleIndex(x: number): number {\n    return this.canvasXToIndex(x);\n  }\n  \n  priceToPixelY(price: number, panelId?: string): number {\n    // Canvas Y 좌표를 반환 (이미 물리적 픽셀 단위)\n    return this.priceToCanvasY(price, panelId);\n  }\n  \n  pixelYToPrice(y: number, panelId?: string): number {\n    return this.canvasYToPrice(y, panelId);\n  }\n  \n  /**\n   * 가격 스케일 정보 가져오기\n   * @param panelId 패널 ID (optional, 기본값은 현재 패널)\n   */\n  getPriceScale(panelId?: string): { min: number; max: number; range: number } {\n    const [min, max] = this.getPriceRange(panelId);\n    return {\n      min,\n      max,\n      range: max - min\n    };\n  }\n  \n  /**\n   * 현재 패널 설정\n   * @param panelId 패널 ID\n   */\n  setCurrentPanel(panelId: string): void {\n    this.currentPanelId = panelId;\n    const panelRange = this.panelPriceRanges.get(panelId);\n    if (panelRange) {\n      this.minPrice = panelRange.min;\n      this.maxPrice = panelRange.max;\n    }\n  }\n  \n  /**\n   * 시간을 Canvas X 좌표로 변환\n   */\n  timeToCanvasX(time: number): number {\n    if (!this.dataManager) {\n      return 0;\n    }\n    const index = this.dataManager.getIndexForTime(time);\n    return this.indexToCanvasX(index);\n  }\n  \n  /**\n   * 시간을 픽셀 X 좌표로 변환 (Canvas X와 동일)\n   */\n  timeToPixelX(time: number): number {\n    return this.timeToCanvasX(time);\n  }\n\n  /**\n   * 최신 데이터로 스크롤\n   */\n  scrollToEnd(): void {\n    if (this.totalCandles === 0) {\n      // console.log('[scrollToEnd] No candles to display');\n      return;\n    }\n    \n    const chartAreaWidth = this.getChartAreaWidth();\n    \n    // chartAreaWidth가 0이면 나중에 다시 시도\n    if (chartAreaWidth === 0) {\n      // console.log('[scrollToEnd] Chart area width is 0, cannot scroll yet');\n      return;\n    }\n    \n    // candleWidth가 0이면 기본값 설정\n    if (this.candleWidth === 0) {\n      // console.log('[scrollToEnd] Candle width is 0, setting default');\n      const visibleCandles = Math.min(100, this.totalCandles);\n      this.candleWidth = Math.max(\n        this.MIN_CANDLE_WIDTH,\n        Math.min(this.MAX_CANDLE_WIDTH, chartAreaWidth / visibleCandles)\n      );\n    }\n    \n    // 최신 데이터가 오른쪽 끝에 보이도록 오프셋 계산\n    const totalWidth = this.totalCandles * this.candleWidth;\n    const yAxisOffset = this._yAxisWidth * this.pixelRatio;\n    \n    // 전체 데이터가 화면보다 클 경우\n    if (totalWidth > chartAreaWidth) {\n      // 마지막 캔들이 화면 오른쪽 끝에서 Y축 레이블 영역(80px) 만큼 떨어지도록\n      // rightMargin이 있으면 추가로 왼쪽으로 이동 (빈 공간 생성)\n      const rightMarginPixels = this.rightMarginCandles * this.candleWidth;\n      this.pixelOffset = -(totalWidth - chartAreaWidth) - yAxisOffset - rightMarginPixels;\n    } else {\n      // 전체 데이터가 화면보다 작으면 중앙 정렬\n      this.pixelOffset = (chartAreaWidth - totalWidth) / 2;\n    }\n    \n  }\n\n  /**\n   * 특정 시간으로 스크롤\n   */\n  scrollToTime(targetTime: number): void {\n    if (this.totalCandles === 0 || !this.dataTimeRange || this.dataTimeRange[1] === 0) return;\n    \n    const timeRange = this.dataTimeRange[1] - this.dataTimeRange[0];\n    const timeRatio = (targetTime - this.dataTimeRange[0]) / timeRange;\n    const targetCandle = Math.floor(this.totalCandles * timeRatio);\n    \n    // 중앙에 위치시키기\n    const chartAreaWidth = this.getChartAreaWidth();\n    const centerOffset = chartAreaWidth / 2;\n    this.pixelOffset = -(targetCandle * this.candleWidth) + centerOffset;\n  }\n\n\n  /**\n   * 보이는 캔들 수 설정\n   */\n  setVisibleCandles(count: number): void {\n    const chartAreaWidth = this.getChartAreaWidth();\n    if (count <= 0 || chartAreaWidth === 0) return;\n    \n    const targetCandleWidth = chartAreaWidth / count;\n    this.candleWidth = Math.max(\n      this.MIN_CANDLE_WIDTH,\n      Math.min(this.MAX_CANDLE_WIDTH, targetCandleWidth)\n    );\n  }\n\n  /**\n   * 시간 범위 설정 (차트 표시용)\n   */\n  setTimeRange(startTime: number, endTime: number): void {\n    if (this.totalCandles === 0 || !this.dataTimeRange || this.dataTimeRange[1] === 0) return;\n    \n    const totalTimeRange = this.dataTimeRange[1] - this.dataTimeRange[0];\n    const startRatio = (startTime - this.dataTimeRange[0]) / totalTimeRange;\n    const endRatio = (endTime - this.dataTimeRange[0]) / totalTimeRange;\n    \n    const startCandle = Math.floor(this.totalCandles * startRatio);\n    const endCandle = Math.ceil(this.totalCandles * endRatio);\n    const candleRange = endCandle - startCandle;\n    \n    if (candleRange <= 0) return;\n    \n    this.setVisibleCandles(candleRange);\n    this.pixelOffset = -(startCandle * this.candleWidth);\n  }\n}","// 커서 타입 정의\nexport type CursorType = 'default' | 'crosshair' | 'dot';\n\n// 점 커서를 위한 SVG 데이터\nconst DOT_CURSOR_SVG = `\n<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n  <circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"#000000\" stroke=\"#FFFFFF\" stroke-width=\"1\"/>\n</svg>`;\n\n// SVG를 base64로 인코딩\nconst encodeSVG = (svg: string): string => {\n  return `data:image/svg+xml;base64,${btoa(svg.trim())}`;\n};\n\n// 커서 타입에 따른 CSS 값 반환\nexport const getCursorStyle = (type: CursorType): string => {\n  switch (type) {\n    case 'default':\n      return 'default';\n    case 'crosshair':\n      return 'crosshair';\n    case 'dot':\n      // 12 12는 커서의 핫스팟(클릭 지점) 좌표\n      return `url('${encodeSVG(DOT_CURSOR_SVG)}') 12 12, crosshair`;\n    default:\n      return 'crosshair';\n  }\n};\n\n// 드로잉 호버시 커서 (pointer는 항상 동일)\nexport const HOVER_CURSOR = 'pointer';","import type { DrawingManager } from '@/core/DrawingManager';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport type { DataManager } from '@/core/DataManager';\nimport type { UnifiedRenderer } from '@/renderers/UnifiedRenderer';\nimport type { LabelRenderer } from '@/renderers/LabelRenderer';\nimport type { Candle } from '@/types';\nimport { getCursorStyle, HOVER_CURSOR, type CursorType } from '@/utils/cursor';\n\nexport interface EventCallbacks {\n  onMouseMove?: (x: number, y: number, chartCoords: { time: number; price: number }) => void;\n  onMouseClick?: (x: number, y: number, chartCoords: { time: number; price: number }) => void;\n  onMouseDown?: (x: number, y: number) => void;\n  onMouseUp?: (x: number, y: number) => void;\n  onMouseLeave?: () => void;\n  onContextMenu?: (e: MouseEvent) => void;\n  onDoubleClick?: (e: MouseEvent) => void;\n}\n\nexport class ChartEventController {\n  private canvas: HTMLCanvasElement;\n  private lastMouseX: number = -1;\n  private lastMouseY: number = -1;\n  private isDraggingDrawing: boolean = false;\n  private dragStartChartCoords: { time: number; price: number } | null = null;\n  private cursorType: CursorType = 'crosshair';\n  \n  // 이벤트 핸들러를 바인딩된 메서드로 저장\n  private boundHandlers: {\n    mousemove?: (e: MouseEvent) => void;\n    mousedown?: (e: MouseEvent) => void;\n    mouseup?: (e: MouseEvent) => void;\n    click?: (e: MouseEvent) => void;\n    dblclick?: (e: MouseEvent) => void;\n    mouseleave?: (e: MouseEvent) => void;\n    contextmenu?: (e: MouseEvent) => void;\n  } = {};\n  \n  constructor(\n    canvas: HTMLCanvasElement,\n    private coordSystem: UnifiedCoordinateSystem,\n    private drawingManager: DrawingManager,\n    private dataManager: DataManager | null,\n    private unifiedRenderer: UnifiedRenderer,\n    private labelRenderer: LabelRenderer,\n    private callbacks: EventCallbacks = {}\n  ) {\n    this.canvas = canvas;\n    this.setupEventListeners();\n  }\n  \n  private handleContextMenu = (e: MouseEvent) => {\n    e.preventDefault();\n    \n    // 가격 비교 모드 취소\n    if (this.drawingManager.isMeasureMode()) {\n      this.drawingManager.cancelMeasure();\n      return;\n    }\n    \n    // 드로잉 모드 취소\n    if (this.drawingManager.getCurrentTool()) {\n      this.drawingManager.setCurrentTool(null);\n      this.drawingManager.cancelDrawing();\n    }\n    \n    if (this.callbacks.onContextMenu) {\n      this.callbacks.onContextMenu(e);\n    }\n  };\n\n  private setupEventListeners(): void {\n    // 마우스 이동\n    this.canvas.addEventListener('mousemove', (e) => {\n      const rect = this.canvas.getBoundingClientRect();\n      const cssX = e.clientX - rect.left;\n      const cssY = e.clientY - rect.top;\n      \n      this.lastMouseX = cssX;\n      this.lastMouseY = cssY;\n      \n      // 통합 렌더러에 마우스 위치 전달\n      this.unifiedRenderer.setMousePosition(cssX, cssY);\n      \n      // 차트 좌표로 변환 - main 패널 지정\n      const chartCoords = this.coordSystem.cssToChart(cssX, cssY, 'main');\n      \n      // 콜백 호출\n      if (this.callbacks.onMouseMove) {\n        this.callbacks.onMouseMove(cssX, cssY, chartCoords);\n      }\n      \n      // 드로잉 드래그 중인 경우\n      if (this.isDraggingDrawing && this.dragStartChartCoords) {\n        const currentChartCoords = this.coordSystem.cssToChart(cssX, cssY, 'main');\n        const timeDiff = currentChartCoords.time - this.dragStartChartCoords.time;\n        const priceDiff = currentChartCoords.price - this.dragStartChartCoords.price;\n        \n        this.drawingManager.moveSelectedDrawing(timeDiff, priceDiff);\n        this.dragStartChartCoords = currentChartCoords;\n        return;\n      }\n      \n      // 드로잉 모드가 아닐 때 호버 체크\n      if (!this.drawingManager.getCurrentTool() && !this.isDraggingDrawing) {\n        const hoveredDrawing = this.drawingManager.checkDrawingHover(cssX, cssY);\n        this.canvas.style.cursor = hoveredDrawing ? HOVER_CURSOR : getCursorStyle(this.cursorType);\n      }\n      \n      // 드로잉 매니저에 마우스 이동 전달 (드래그 중이 아닐 때만)\n      if (this.dataManager && !this.isDraggingDrawing) {\n        const candles: Candle[] = [];\n        const candleCount = this.dataManager.getLength();\n        for (let i = 0; i < candleCount; i++) {\n          const candle = this.dataManager.getCandle(i);\n          if (candle) {\n            candles.push(candle);\n          }\n        }\n        \n        this.drawingManager.handleMouseMove(\n          cssX,  // CSS 좌표 그대로 전달\n          cssY,\n          candles,\n          this.coordSystem,  // UnifiedCoordinateSystem 직접 전달\n          (x: number, y: number) => {\n            // CSS 좌표를 차트 좌표로 변환 - main 패널 지정\n            const chartCoords = this.coordSystem.cssToChart(x, y, 'main');\n            return { time: chartCoords.time, price: chartCoords.price };\n          }\n        );\n      }\n      \n      // 가격 비교 중이면 툴팁 위치 업데이트\n      const measureManager = this.drawingManager as any;\n      if (measureManager.measureManager && measureManager.measureManager.getMeasurePoints) {\n        const measurePoints = measureManager.measureManager.getMeasurePoints();\n        if (measurePoints.start && !measurePoints.fixed) {\n          this.labelRenderer.showMeasureTooltip(\n            measurePoints.start.price,\n            chartCoords.price,\n            cssX,\n            cssY\n          );\n        }\n      }\n    });\n    \n    // 마우스 다운\n    this.canvas.addEventListener('mousedown', (e) => {\n      const rect = this.canvas.getBoundingClientRect();\n      const cssX = e.clientX - rect.left;\n      const cssY = e.clientY - rect.top;\n      \n      // 드로잉 모드가 아닐 때 드로잉 선택 및 드래그 시작\n      if (!this.drawingManager.getCurrentTool()) {\n        const clickedDrawing = this.drawingManager.selectDrawingAt(cssX, cssY);\n        if (clickedDrawing) {\n          // 드로잉을 선택하면 바로 드래그 시작\n          this.isDraggingDrawing = true;\n          this.dragStartChartCoords = this.coordSystem.cssToChart(cssX, cssY, 'main');\n          e.preventDefault();\n          return;\n        }\n      }\n      \n      this.drawingManager.handleClick(\n        cssX,  // CSS 좌표 그대로 전달\n        cssY,\n        (x: number, y: number) => {\n          // CSS 좌표를 차트 좌표로 변환 - main 패널 지정\n          const chartCoords = this.coordSystem.cssToChart(x, y, 'main');\n          return { time: chartCoords.time, price: chartCoords.price };\n        },\n        this.coordSystem  // UnifiedCoordinateSystem 직접 전달\n      );\n      \n      if (this.callbacks.onMouseDown) {\n        this.callbacks.onMouseDown(cssX, cssY);\n      }\n    });\n    \n    // 마우스 클릭\n    this.canvas.addEventListener('click', (e) => {\n      const rect = this.canvas.getBoundingClientRect();\n      const cssX = e.clientX - rect.left;\n      const cssY = e.clientY - rect.top;\n      \n      const chartCoords = this.coordSystem.cssToChart(cssX, cssY, 'main');\n      \n      // Shift+클릭으로 가격 비교 시작 (드로잉 모드가 아닐 때만)\n      if (e.shiftKey && !this.drawingManager.getCurrentTool()) {\n        this.drawingManager.startMeasure({ time: chartCoords.time, price: chartCoords.price });\n        e.preventDefault();\n        return;\n      }\n      \n      // 드로잉 모드가 아닐 때 드로잉 선택 (mousedown에서 이미 처리했으므로 여기서는 스킵)\n      if (!this.drawingManager.getCurrentTool() && !e.shiftKey) {\n        // mousedown에서 이미 선택 처리했으므로 click에서는 처리하지 않음\n        e.preventDefault();\n        return;\n      }\n      \n      if (this.callbacks.onMouseClick) {\n        this.callbacks.onMouseClick(cssX, cssY, chartCoords);\n      }\n    });\n    \n    // 마우스 업\n    this.canvas.addEventListener('mouseup', (e) => {\n      this.isDraggingDrawing = false;\n      this.dragStartChartCoords = null;\n      \n      if (this.callbacks.onMouseUp) {\n        const rect = this.canvas.getBoundingClientRect();\n        const cssX = e.clientX - rect.left;\n        const cssY = e.clientY - rect.top;\n        this.callbacks.onMouseUp(cssX, cssY);\n      }\n    });\n    \n    // 우클릭으로 취소\n    this.boundHandlers.contextmenu = this.handleContextMenu;\n    this.canvas.addEventListener('contextmenu', this.boundHandlers.contextmenu);\n    \n    // 마우스 나가기\n    this.canvas.addEventListener('mouseleave', () => {\n      this.lastMouseX = -1;\n      this.lastMouseY = -1;\n      this.unifiedRenderer.setMousePosition(-1, -1);\n      \n      if (this.callbacks.onMouseLeave) {\n        this.callbacks.onMouseLeave();\n      }\n    });\n    \n    // 더블클릭\n    this.canvas.addEventListener('dblclick', (e) => {\n      if (this.callbacks.onDoubleClick) {\n        this.callbacks.onDoubleClick(e);\n      }\n    });\n  }\n  \n  getLastMousePosition(): { x: number; y: number } {\n    return { x: this.lastMouseX, y: this.lastMouseY };\n  }\n  \n  setCursorType(type: CursorType): void {\n    this.cursorType = type;\n    // 현재 커서 상태 즉시 업데이트\n    if (!this.drawingManager.getCurrentTool() && !this.isDraggingDrawing) {\n      this.canvas.style.cursor = getCursorStyle(this.cursorType);\n    }\n  }\n  \n  dispose(): void {\n    // 바인딩된 이벤트 리스너 제거\n    if (this.boundHandlers.contextmenu) {\n      this.canvas.removeEventListener('contextmenu', this.boundHandlers.contextmenu);\n    }\n    // 나머지 이벤트는 canvas가 제거될 때 자동으로 처리됨\n  }\n}","import { BufferPool } from '@/core/BufferPool';\nimport { ChartData, Theme, ChartOptions, IndicatorConfig } from '@/types';\nimport { StopLossLine } from '@/types/stopLoss';\nimport { Marker } from '@/types/marker';\nimport { createShader, createProgram, hexToRGBA } from '@/utils/webgl-utils';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\n// 셰이더 소스\nconst candleVertexShader = `\nattribute vec2 a_position;\nattribute vec4 a_color;\n\nuniform vec2 u_resolution;\nuniform float u_pixelOffset;\nuniform vec2 u_priceRange;\n\nvarying vec4 v_color;\n\nvoid main() {\n  // pixelOffset은 이미 a_position.x에 포함되어 있음\n  vec2 normalized = vec2(\n    (a_position.x / u_resolution.x) * 2.0 - 1.0,\n    1.0 - (a_position.y / u_resolution.y) * 2.0\n  );\n  \n  gl_Position = vec4(normalized, 0.0, 1.0);\n  v_color = a_color;\n}\n`;\n\nconst candleFragmentShader = `\nprecision mediump float;\n\nvarying vec4 v_color;\n\nvoid main() {\n  gl_FragColor = v_color;\n}\n`;\n\nconst lineVertexShader = candleVertexShader; // 동일한 셰이더 사용\nconst lineFragmentShader = candleFragmentShader; // 동일한 셰이더 사용\n\nexport interface RenderLayer {\n  visible: boolean;\n  data: any;\n  zIndex?: number;\n}\n\nexport interface RenderData {\n  grid?: RenderLayer;\n  candles?: RenderLayer & { data: ChartData };\n  volume?: RenderLayer & { data: ChartData; options?: any };\n  volumeMA?: RenderLayer & { data: Float32Array; period: number; color?: string };\n  indicators?: RenderLayer & { data: IndicatorConfig[] };\n  lineSeries?: RenderLayer;\n  stopLoss?: RenderLayer & { data: StopLossLine[] };\n  drawings?: RenderLayer;\n  markers?: RenderLayer & { data: Marker[] };\n  crosshair?: RenderLayer & { x: number; y: number; verticalOnly?: boolean };\n  labels?: RenderLayer;\n}\n\nexport class UnifiedChartRenderer {\n  private gl: WebGLRenderingContext;\n  private bufferPool: BufferPool;\n  private programs: Map<string, WebGLProgram> = new Map();\n  private theme: Theme;\n  private options: ChartOptions;\n  private canvas: HTMLCanvasElement;\n  private width: number = 0;\n  private height: number = 0;\n  \n  // 렌더링 레이어 순서 (z-index)\n  private readonly layerOrder = [\n    'grid',       // 0: 가장 뒤\n    'candles',    // 1: 캔들\n    'volume',     // 2: 볼륨\n    'volumeMA',   // 3: 볼륨 MA\n    'indicators', // 4: 인디케이터\n    'lineSeries', // 5: 라인 시리즈\n    'stopLoss',   // 6: 스톱로스\n    'drawings',   // 7: 드로잉\n    'markers',    // 8: 마커\n    'crosshair',  // 9: 크로스헤어\n    'labels'      // 10: 라벨 (가장 앞)\n  ];\n  \n  constructor(\n    canvas: HTMLCanvasElement,\n    theme: Theme,\n    options: ChartOptions\n  ) {\n    this.canvas = canvas;\n    this.theme = theme;\n    this.options = options;\n    \n    // WebGL 컨텍스트 초기화\n    const gl = canvas.getContext('webgl', {\n      alpha: false,\n      antialias: false,\n      depth: false,\n      preserveDrawingBuffer: false,\n      stencil: false\n    });\n    \n    if (!gl) {\n      throw new Error('WebGL not supported');\n    }\n    \n    this.gl = gl;\n    this.bufferPool = new BufferPool(gl);\n    this.width = canvas.width;\n    this.height = canvas.height;\n    \n    // 프로그램 초기화\n    this.initializePrograms();\n    \n    // WebGL 기본 설정\n    this.setupWebGL();\n  }\n  \n  private initializePrograms(): void {\n    const gl = this.gl;\n    \n    // 캔들 셰이더 컴파일\n    const candleVS = createShader(gl, gl.VERTEX_SHADER, candleVertexShader);\n    const candleFS = createShader(gl, gl.FRAGMENT_SHADER, candleFragmentShader);\n    \n    if (candleVS && candleFS) {\n      const candleProgram = createProgram(gl, candleVS, candleFS);\n      if (candleProgram) {\n        this.programs.set('candles', candleProgram);\n      }\n    }\n    \n    // 라인 셰이더 컴파일 (볼륨, 인디케이터, 스톱로스 등에 사용)\n    const lineVS = createShader(gl, gl.VERTEX_SHADER, lineVertexShader);\n    const lineFS = createShader(gl, gl.FRAGMENT_SHADER, lineFragmentShader);\n    \n    if (lineVS && lineFS) {\n      const lineProgram = createProgram(gl, lineVS, lineFS);\n      if (lineProgram) {\n        this.programs.set('lines', lineProgram);\n      }\n    }\n  }\n  \n  private setupWebGL(): void {\n    const gl = this.gl;\n    \n    // 블렌딩 설정\n    gl.enable(gl.BLEND);\n    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n    \n    // 뷰포트 설정\n    gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n    \n    // 배경색 설정\n    const bgColor = hexToRGBA(this.theme.background || this.theme.backgroundColor);\n    gl.clearColor(bgColor[0], bgColor[1], bgColor[2], 1.0);\n  }\n  \n  public render(data: RenderData, viewport: UnifiedCoordinateSystem): void {\n    const gl = this.gl;\n    \n    // 캔버스 클리어\n    gl.clear(gl.COLOR_BUFFER_BIT);\n    \n    // 각 레이어를 순서대로 렌더링\n    for (const layerName of this.layerOrder) {\n      const layer = data[layerName as keyof RenderData];\n      \n      if (layer?.visible) {\n        this.renderLayer(layerName, layer, viewport);\n      }\n    }\n  }\n  \n  private renderLayer(layerName: string, layer: RenderLayer, viewport: UnifiedCoordinateSystem): void {\n    switch (layerName) {\n      case 'grid':\n        this.renderGrid(layer, viewport);\n        break;\n      case 'candles':\n        this.renderCandles(layer as RenderLayer & { data: ChartData }, viewport);\n        break;\n      case 'volume':\n        this.renderVolume(layer as RenderLayer & { data: ChartData }, viewport);\n        break;\n      case 'volumeMA':\n        this.renderVolumeMA(layer as RenderLayer & { data: Float32Array; period: number; color?: string }, viewport);\n        break;\n      case 'indicators':\n        this.renderIndicators(layer as RenderLayer & { data: IndicatorConfig[] }, viewport);\n        break;\n      case 'stopLoss':\n        this.renderStopLoss(layer as RenderLayer & { data: StopLossLine[] }, viewport);\n        break;\n      case 'markers':\n        this.renderMarkers(layer as RenderLayer & { data: Marker[] }, viewport);\n        break;\n      case 'crosshair':\n        this.renderCrosshair(layer as RenderLayer & { x: number; y: number; verticalOnly?: boolean }, viewport);\n        break;\n      // TODO: 나머지 레이어들\n    }\n  }\n  \n  // 각 렌더링 메서드는 기존 렌더러들의 로직을 통합\n  private renderGrid(_layer: RenderLayer, _viewport: UnifiedCoordinateSystem): void {\n    // TODO: GridRenderer 로직 통합\n  }\n  \n  private renderCandles(layer: RenderLayer & { data: ChartData }, viewport: UnifiedCoordinateSystem): void {\n    const program = this.programs.get('candles');\n    if (!program) return;\n    \n    const gl = this.gl;\n    gl.useProgram(program);\n    \n    const data = layer.data;\n    const visibleRange = viewport.getVisibleRange();\n    \n    if (visibleRange.start >= visibleRange.end) {\n      return;\n    }\n    \n    // 버텍스 데이터\n    const positions: number[] = [];\n    const colors: number[] = [];\n    \n    // 캔들 너비와 간격\n    const candleWidth = viewport.getCandleWidth();\n    const bodyWidth = Math.max(1, candleWidth * 0.8);\n    const halfBodyWidth = bodyWidth / 2;\n    \n    // 색상 준비\n    const upColor = hexToRGBA(this.theme.candleUp || this.theme.candle?.upColor || '#00ff00');\n    const downColor = hexToRGBA(this.theme.candleDown || this.theme.candle?.downColor || '#ff0000');\n    const upWickColor = hexToRGBA(this.theme.candleUpWick || this.theme.candleUp || this.theme.candle?.wickUpColor || '#00ff00');\n    const downWickColor = hexToRGBA(this.theme.candleDownWick || this.theme.candleDown || this.theme.candle?.wickDownColor || '#ff0000');\n    \n    // 차트 타입 가져오기\n    const chartType = this.options.chartType || 'candle';\n    \n    // 각 캔들에 대해 버텍스 생성\n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      const x = viewport.indexToCanvasX(i);\n      \n      const open = data.opens[i];\n      const high = data.highs[i];\n      const low = data.lows[i];\n      const close = data.closes[i];\n      \n      const yOpen = viewport.priceToPixelY(open);\n      const yHigh = viewport.priceToPixelY(high);\n      const yLow = viewport.priceToPixelY(low);\n      const yClose = viewport.priceToPixelY(close);\n      \n      const isUp = close >= open;\n      const bodyColor = isUp ? upColor : downColor;\n      const wickColor = isUp ? upWickColor : downWickColor;\n      \n      // 차트 타입에 따른 렌더링\n      if (chartType === 'bar') {\n        // Bar 차트 스타일\n        // 세로선 (High-Low)\n        this.addLine(positions, x, yHigh, x, yLow, 1);\n        for (let j = 0; j < 6; j++) {\n          colors.push(...wickColor);\n        }\n        \n        // 왼쪽 틱 (Open)\n        const tickWidth = halfBodyWidth;\n        this.addLine(positions, x - tickWidth, yOpen, x, yOpen, 1);\n        for (let j = 0; j < 6; j++) {\n          colors.push(...bodyColor);\n        }\n        \n        // 오른쪽 틱 (Close)\n        this.addLine(positions, x, yClose, x + tickWidth, yClose, 1);\n        for (let j = 0; j < 6; j++) {\n          colors.push(...bodyColor);\n        }\n      } else if (chartType === 'hollow') {\n        // Hollow Candle 스타일\n        const bodyTop = Math.min(yOpen, yClose);\n        const bodyBottom = Math.max(yOpen, yClose);\n        const bodyHeight = Math.max(1, bodyBottom - bodyTop);\n        \n        // 속이 빈 캔들 (테두리만)\n        const borderWidth = 1;\n        \n        // 상단 테두리\n        this.addRectangle(positions, x - halfBodyWidth, bodyTop, x + halfBodyWidth, bodyTop + borderWidth);\n        for (let j = 0; j < 6; j++) colors.push(...bodyColor);\n        \n        // 하단 테두리\n        this.addRectangle(positions, x - halfBodyWidth, bodyBottom - borderWidth, x + halfBodyWidth, bodyBottom);\n        for (let j = 0; j < 6; j++) colors.push(...bodyColor);\n        \n        // 왼쪽 테두리\n        this.addRectangle(positions, x - halfBodyWidth, bodyTop, x - halfBodyWidth + borderWidth, bodyBottom);\n        for (let j = 0; j < 6; j++) colors.push(...bodyColor);\n        \n        // 오른쪽 테두리\n        this.addRectangle(positions, x + halfBodyWidth - borderWidth, bodyTop, x + halfBodyWidth, bodyBottom);\n        for (let j = 0; j < 6; j++) colors.push(...bodyColor);\n        \n        // 하락일 때만 속 채우기 (할로우 캔들은 양봉이 비어있고 음봉이 차있음)\n        if (!isUp) {\n          // 음봉 채우기는 다운 색상 사용\n          const fillColor = [...downColor.slice(0, 3), 0.8]; // 음봉 색상으로 채우기\n          this.addRectangle(positions, x - halfBodyWidth + borderWidth, bodyTop + borderWidth, \n                          x + halfBodyWidth - borderWidth, bodyBottom - borderWidth);\n          for (let j = 0; j < 6; j++) colors.push(...fillColor);\n        }\n        \n        // 위쪽 심지\n        if (yHigh < bodyTop) {\n          this.addLine(positions, x, yHigh, x, bodyTop, 1);\n          for (let j = 0; j < 6; j++) colors.push(...wickColor);\n        }\n        \n        // 아래쪽 심지\n        if (yLow > bodyBottom) {\n          this.addLine(positions, x, bodyBottom, x, yLow, 1);\n          for (let j = 0; j < 6; j++) colors.push(...wickColor);\n        }\n      } else {\n        // 기본 캔들 스타일\n        const bodyTop = Math.min(yOpen, yClose);\n        const bodyBottom = Math.max(yOpen, yClose);\n        const bodyHeight = Math.max(1, bodyBottom - bodyTop);\n        \n        // 바디 렌더링 (사각형)\n        this.addRectangle(\n          positions,\n          x - halfBodyWidth, bodyTop,\n          x + halfBodyWidth, bodyTop + bodyHeight\n        );\n        \n        // 바디 색상 추가 (6개 버텍스)\n        for (let j = 0; j < 6; j++) {\n          colors.push(...bodyColor);\n        }\n        \n        // 위쪽 심지\n        if (yHigh < bodyTop) {\n          this.addLine(positions, x, yHigh, x, bodyTop, 1);\n          // 심지 색상 추가 (6개 버텍스)\n          for (let j = 0; j < 6; j++) {\n            colors.push(...wickColor);\n          }\n        }\n        \n        // 아래쪽 심지\n        if (yLow > bodyBottom) {\n          this.addLine(positions, x, bodyBottom, x, yLow, 1);\n          // 심지 색상 추가 (6개 버텍스)\n          for (let j = 0; j < 6; j++) {\n            colors.push(...wickColor);\n          }\n        }\n      }\n    }\n    \n    if (positions.length === 0) {\n      return;\n    }\n    \n    // 버퍼 풀에서 버퍼 가져오기\n    const positionBuffer = this.bufferPool.acquire();\n    const colorBuffer = this.bufferPool.acquire();\n    \n    // 버퍼에 데이터 업로드\n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n    \n    // 속성 위치 가져오기\n    const positionLocation = gl.getAttribLocation(program, 'a_position');\n    const colorLocation = gl.getAttribLocation(program, 'a_color');\n    \n    // Position 속성 설정\n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.enableVertexAttribArray(positionLocation);\n    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n    \n    // Color 속성 설정\n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.enableVertexAttribArray(colorLocation);\n    gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n    \n    // 유니폼 설정\n    const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n    const pixelOffsetLocation = gl.getUniformLocation(program, 'u_pixelOffset');\n    \n    gl.uniform2f(resolutionLocation, this.canvas.width, this.canvas.height);\n    gl.uniform1f(pixelOffsetLocation, viewport.getPixelOffset());\n    \n    // 렌더링\n    gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);\n    \n    // 속성 비활성화\n    gl.disableVertexAttribArray(positionLocation);\n    gl.disableVertexAttribArray(colorLocation);\n    \n    // 버퍼 반환\n    this.bufferPool.release(positionBuffer);\n    this.bufferPool.release(colorBuffer);\n  }\n  \n  private addRectangle(\n    positions: number[],\n    x1: number, y1: number,\n    x2: number, y2: number\n  ): void {\n    // First triangle\n    positions.push(x1, y1);\n    positions.push(x2, y1);\n    positions.push(x1, y2);\n    \n    // Second triangle\n    positions.push(x2, y1);\n    positions.push(x2, y2);\n    positions.push(x1, y2);\n  }\n  \n  private addLine(\n    positions: number[],\n    x1: number, y1: number,\n    x2: number, y2: number,\n    thickness: number\n  ): void {\n    const halfThickness = thickness / 2;\n    \n    // 수직선인 경우\n    if (Math.abs(x2 - x1) < 0.001) {\n      this.addRectangle(\n        positions,\n        x1 - halfThickness, y1,\n        x1 + halfThickness, y2\n      );\n    }\n    // 수평선인 경우\n    else if (Math.abs(y2 - y1) < 0.001) {\n      this.addRectangle(\n        positions,\n        x1, y1 - halfThickness,\n        x2, y1 + halfThickness\n      );\n    }\n    // 대각선인 경우 (현재는 사용하지 않음)\n    else {\n      // 간단히 사각형으로 근사\n      this.addRectangle(positions, x1, y1, x2, y2);\n    }\n  }\n  \n  private renderVolume(layer: RenderLayer & { data: ChartData }, viewport: UnifiedCoordinateSystem): void {\n    const program = this.programs.get('lines'); // 볼륨도 같은 셰이더 사용\n    if (!program) return;\n    \n    const gl = this.gl;\n    gl.useProgram(program);\n    \n    const data = layer.data;\n    const visibleRange = viewport.getVisibleRange();\n    \n    if (visibleRange.start >= visibleRange.end) return;\n    \n    // 볼륨 범위 계산\n    let maxVolume = 0;\n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      if (data.volumes[i] > maxVolume) {\n        maxVolume = data.volumes[i];\n      }\n    }\n    \n    if (maxVolume === 0) return;\n    \n    // 색상 준비 (옵션 적용)\n    const volumeOptions = (layer as any).options || this.options.panels?.volume;\n    const upColor = hexToRGBA(\n      volumeOptions?.colors?.up || this.theme.volume?.upColor || this.theme.candleUp || this.theme.candle?.upColor || '#00ff00'\n    );\n    const downColor = hexToRGBA(\n      volumeOptions?.colors?.down || this.theme.volume?.downColor || this.theme.candleDown || this.theme.candle?.downColor || '#ff0000'\n    );\n    const opacity = volumeOptions?.opacity ?? 1.0;\n    \n    // 버텍스 데이터\n    const positions: number[] = [];\n    const colors: number[] = [];\n    \n    // 캔들 너비와 간격\n    const candleWidth = viewport.getCandleWidth();\n    const barWidth = Math.max(1, candleWidth * 0.8);\n    const halfBarWidth = barWidth / 2;\n    \n    // 각 볼륨 바에 대해 버텍스 생성\n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      const x = viewport.indexToCanvasX(i);\n      const volume = data.volumes[i];\n      \n      // 볼륨을 픽셀 높이로 변환\n      const yBottom = viewport.priceToPixelY(0, 'volume');\n      const yTop = viewport.priceToPixelY(volume, 'volume');\n      \n      const isUp = data.closes[i] >= data.opens[i];\n      const color = isUp ? upColor : downColor;\n      \n      // 사각형 추가\n      this.addRectangle(\n        positions,\n        x - halfBarWidth, yTop,\n        x + halfBarWidth, yBottom\n      );\n      \n      // 색상 추가 (6개 버텍스, 투명도 적용)\n      for (let j = 0; j < 6; j++) {\n        colors.push(color[0], color[1], color[2], opacity);\n      }\n    }\n    \n    if (positions.length === 0) return;\n    \n    // 버퍼 풀에서 버퍼 가져오기\n    const positionBuffer = this.bufferPool.acquire();\n    const colorBuffer = this.bufferPool.acquire();\n    \n    // 버퍼에 데이터 업로드\n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n    \n    // 속성 위치 가져오기\n    const positionLocation = gl.getAttribLocation(program, 'a_position');\n    const colorLocation = gl.getAttribLocation(program, 'a_color');\n    \n    // Position 속성 설정\n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.enableVertexAttribArray(positionLocation);\n    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n    \n    // Color 속성 설정\n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.enableVertexAttribArray(colorLocation);\n    gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n    \n    // 유니폼 설정\n    const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n    const pixelOffsetLocation = gl.getUniformLocation(program, 'u_pixelOffset');\n    \n    gl.uniform2f(resolutionLocation, this.canvas.width, this.canvas.height);\n    gl.uniform1f(pixelOffsetLocation, viewport.getPixelOffset());\n    \n    // 렌더링\n    gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);\n    \n    // 속성 비활성화\n    gl.disableVertexAttribArray(positionLocation);\n    gl.disableVertexAttribArray(colorLocation);\n    \n    // 버퍼 반환\n    this.bufferPool.release(positionBuffer);\n    this.bufferPool.release(colorBuffer);\n  }\n  \n  private renderIndicators(layer: RenderLayer & { data: IndicatorConfig[] }, viewport: UnifiedCoordinateSystem): void {\n    const program = this.programs.get('lines'); // 인디케이터도 라인 셰이더 사용\n    if (!program) return;\n    \n    const gl = this.gl;\n    const indicators = layer.data.filter((ind: any) => ind.visible && ind.values && ind.values.length > 0);\n    \n    if (indicators.length === 0) return;\n    \n    const visibleRange = viewport.getVisibleRange();\n    \n    // 각 인디케이터별로 렌더링\n    indicators.forEach((indicator: any) => {\n      gl.useProgram(program);\n      \n      const positions: number[] = [];\n      const colors: number[] = [];\n      \n      // 라인을 위한 포인트 수집\n      const points: { x: number; y: number }[] = [];\n      \n      // values가 Float32Array인지 {time, value}[] 형식인지 확인\n      const isFloat32Array = indicator.values instanceof Float32Array;\n      \n      for (let i = visibleRange.start; i <= visibleRange.end && i < indicator.values.length; i++) {\n        let value: number;\n        \n        if (isFloat32Array) {\n          value = indicator.values[i];\n        } else {\n          // {time, value}[] 형식인 경우\n          value = indicator.values[i].value;\n        }\n        \n        if (!isNaN(value)) {\n          const x = viewport.indexToCanvasX(i);\n          const y = viewport.priceToPixelY(value, 'main');\n          points.push({ x, y });\n        }\n      }\n      \n      // 연속된 점들을 선분으로 변환\n      // indicator가 IndicatorData 타입인지 확인\n      const style = indicator.config?.style || indicator.style || { color: '#2196f3', lineWidth: 2 };\n      const color = hexToRGBA(style.color);\n      const lineWidth = style.lineWidth || 2;\n      \n      for (let i = 1; i < points.length; i++) {\n        const p1 = points[i - 1];\n        const p2 = points[i];\n        \n        // 선분을 두꺼운 사각형으로 렌더링\n        const dx = p2.x - p1.x;\n        const dy = p2.y - p1.y;\n        const len = Math.sqrt(dx * dx + dy * dy);\n        \n        if (len > 0) {\n          // 법선 벡터 계산\n          const nx = -dy / len * lineWidth / 2;\n          const ny = dx / len * lineWidth / 2;\n          \n          // 사각형의 네 모서리\n          const x1 = p1.x + nx;\n          const y1 = p1.y + ny;\n          const x2 = p1.x - nx;\n          const y2 = p1.y - ny;\n          const x3 = p2.x - nx;\n          const y3 = p2.y - ny;\n          const x4 = p2.x + nx;\n          const y4 = p2.y + ny;\n          \n          // 두 개의 삼각형으로 사각형 구성\n          positions.push(x1, y1, x2, y2, x3, y3);\n          positions.push(x1, y1, x3, y3, x4, y4);\n          \n          // 색상 추가 (6개 버텍스)\n          const opacity = style.opacity || 1.0;\n          for (let j = 0; j < 6; j++) {\n            colors.push(color[0], color[1], color[2], opacity);\n          }\n        }\n      }\n      \n      if (positions.length === 0) return;\n      \n      // 버퍼 생성 및 렌더링\n      const positionBuffer = this.bufferPool.acquire();\n      const colorBuffer = this.bufferPool.acquire();\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n      \n      // 속성 설정\n      const positionLocation = gl.getAttribLocation(program, 'a_position');\n      const colorLocation = gl.getAttribLocation(program, 'a_color');\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n      gl.enableVertexAttribArray(positionLocation);\n      gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n      gl.enableVertexAttribArray(colorLocation);\n      gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n      \n      // 유니폼 설정\n      const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n      const pixelOffsetLocation = gl.getUniformLocation(program, 'u_pixelOffset');\n      \n      gl.uniform2f(resolutionLocation, this.canvas.width, this.canvas.height);\n      gl.uniform1f(pixelOffsetLocation, viewport.getPixelOffset());\n      \n      // 렌더링\n      gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);\n      \n      // 정리\n      gl.disableVertexAttribArray(positionLocation);\n      gl.disableVertexAttribArray(colorLocation);\n      \n      this.bufferPool.release(positionBuffer);\n      this.bufferPool.release(colorBuffer);\n    });\n  }\n  \n  private renderVolumeMA(layer: RenderLayer & { data: Float32Array; period: number; color?: string }, viewport: UnifiedCoordinateSystem): void {\n    const program = this.programs.get('lines'); // 라인 셰이더 사용\n    if (!program) return;\n    \n    const gl = this.gl;\n    gl.useProgram(program);\n    \n    const volumeMAData = layer.data;\n    const visibleRange = viewport.getVisibleRange();\n    \n    if (visibleRange.start >= visibleRange.end) return;\n    \n    // 라인을 위한 포인트 수집\n    const points: { x: number; y: number }[] = [];\n    \n    for (let i = visibleRange.start; i <= visibleRange.end && i < volumeMAData.length; i++) {\n      const value = volumeMAData[i];\n      \n      if (value > 0) {\n        const x = viewport.indexToCanvasX(i);\n        const y = viewport.priceToPixelY(value, 'volume');\n        points.push({ x, y });\n      }\n    }\n    \n    if (points.length < 2) return;\n    \n    // 버텍스 데이터\n    const positions: number[] = [];\n    const colors: number[] = [];\n    \n    // 색상 설정\n    const defaultColor = this.options.panels?.volume?.maColor || '#FFD700';\n    const color = hexToRGBA(layer.color || defaultColor);\n    const lineWidth = 2;\n    \n    // 연속된 점들을 선분으로 변환\n    for (let i = 1; i < points.length; i++) {\n      const p1 = points[i - 1];\n      const p2 = points[i];\n      \n      // 선분을 두꺼운 사각형으로 렌더링\n      const dx = p2.x - p1.x;\n      const dy = p2.y - p1.y;\n      const len = Math.sqrt(dx * dx + dy * dy);\n      \n      if (len > 0) {\n        // 법선 벡터 계산\n        const nx = -dy / len * lineWidth / 2;\n        const ny = dx / len * lineWidth / 2;\n        \n        // 사각형의 네 모서리\n        const x1 = p1.x + nx;\n        const y1 = p1.y + ny;\n        const x2 = p1.x - nx;\n        const y2 = p1.y - ny;\n        const x3 = p2.x - nx;\n        const y3 = p2.y - ny;\n        const x4 = p2.x + nx;\n        const y4 = p2.y + ny;\n        \n        // 두 개의 삼각형으로 사각형 구성\n        positions.push(x1, y1, x2, y2, x3, y3);\n        positions.push(x1, y1, x3, y3, x4, y4);\n        \n        // 색상 추가 (6개 버텍스)\n        for (let j = 0; j < 6; j++) {\n          colors.push(color[0], color[1], color[2], 1.0);\n        }\n      }\n    }\n    \n    if (positions.length === 0) return;\n    \n    // 버퍼 생성 및 렌더링\n    const positionBuffer = this.bufferPool.acquire();\n    const colorBuffer = this.bufferPool.acquire();\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n    \n    // 속성 설정\n    const positionLocation = gl.getAttribLocation(program, 'a_position');\n    const colorLocation = gl.getAttribLocation(program, 'a_color');\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.enableVertexAttribArray(positionLocation);\n    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.enableVertexAttribArray(colorLocation);\n    gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n    \n    // 유니폼 설정\n    const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n    const pixelOffsetLocation = gl.getUniformLocation(program, 'u_pixelOffset');\n    \n    gl.uniform2f(resolutionLocation, this.canvas.width, this.canvas.height);\n    gl.uniform1f(pixelOffsetLocation, viewport.getPixelOffset());\n    \n    // 렌더링\n    gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);\n    \n    // 정리\n    gl.disableVertexAttribArray(positionLocation);\n    gl.disableVertexAttribArray(colorLocation);\n    \n    this.bufferPool.release(positionBuffer);\n    this.bufferPool.release(colorBuffer);\n  }\n  \n  private renderStopLoss(layer: RenderLayer & { data: StopLossLine[] }, viewport: UnifiedCoordinateSystem): void {\n    const program = this.programs.get('lines');\n    if (!program) return;\n    \n    const gl = this.gl;\n    const stopLossLines = layer.data;\n    \n    if (stopLossLines.length === 0) return;\n    \n    // 각 스톱로스 라인 렌더링\n    stopLossLines.forEach((line: any) => {\n      gl.useProgram(program);\n      \n      const positions: number[] = [];\n      const colors: number[] = [];\n      \n      // 라인 색상\n      const color = hexToRGBA(line.color || '#ff0000');\n      const opacity = line.opacity || 0.8;\n      \n      // Y 좌표 계산\n      const y = viewport.priceToPixelY(line.price, 'main');\n      const lineWidth = line.lineWidth || 2;\n      \n      if (line.dashed) {\n        // 점선 렌더링\n        const dashLength = line.dashLength || 10;\n        const gapLength = line.gapLength || 5;\n        const totalLength = dashLength + gapLength;\n        \n        for (let x = 0; x < this.canvas.width; x += totalLength) {\n          const dashEnd = Math.min(x + dashLength, this.canvas.width);\n          this.addLine(positions, x, y, dashEnd, y, lineWidth);\n          \n          // 색상 추가 (6개 버텍스)\n          for (let j = 0; j < 6; j++) {\n            colors.push(color[0], color[1], color[2], opacity);\n          }\n        }\n      } else {\n        // 실선 렌더링\n        this.addLine(positions, 0, y, this.canvas.width, y, lineWidth);\n        \n        // 색상 추가 (6개 버텍스)\n        for (let j = 0; j < 6; j++) {\n          colors.push(color[0], color[1], color[2], opacity);\n        }\n      }\n      \n      if (positions.length === 0) return;\n      \n      // 버퍼 생성 및 렌더링\n      const positionBuffer = this.bufferPool.acquire();\n      const colorBuffer = this.bufferPool.acquire();\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n      \n      // 속성 설정\n      const positionLocation = gl.getAttribLocation(program, 'a_position');\n      const colorLocation = gl.getAttribLocation(program, 'a_color');\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n      gl.enableVertexAttribArray(positionLocation);\n      gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n      \n      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n      gl.enableVertexAttribArray(colorLocation);\n      gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n      \n      // 유니폼 설정\n      const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n      const pixelOffsetLocation = gl.getUniformLocation(program, 'u_pixelOffset');\n      \n      gl.uniform2f(resolutionLocation, this.canvas.width, this.canvas.height);\n      gl.uniform1f(pixelOffsetLocation, 0);\n      \n      // 렌더링\n      gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);\n      \n      // 정리\n      gl.disableVertexAttribArray(positionLocation);\n      gl.disableVertexAttribArray(colorLocation);\n      \n      this.bufferPool.release(positionBuffer);\n      this.bufferPool.release(colorBuffer);\n    });\n  }\n  \n  private renderMarkers(layer: RenderLayer & { data: Marker[] }, viewport: UnifiedCoordinateSystem): void {\n    if (!layer.visible || !layer.data || layer.data.length === 0) return;\n    \n    \n    const program = this.programs.get('lines'); // 라인 셰이더 사용\n    if (!program) return;\n    \n    const gl = this.gl;\n    const markers = layer.data;\n    \n    // viewport는 coordSystem이므로 dataManager에서 데이터를 가져와야 함\n    const dataManager = viewport.getDataManager ? viewport.getDataManager() : null;\n    const data = dataManager ? dataManager.getData() : null;\n    \n    if (!data) return;\n    \n    // 각 마커별로 렌더링\n    markers.forEach((marker: any) => {\n      // 시간에 해당하는 캔들 인덱스 찾기\n      const times = data.times;\n      let candleIndex = -1;\n      \n      for (let i = 0; i < times.length; i++) {\n        if (times[i] >= marker.time) {\n          candleIndex = i;\n          break;\n        }\n      }\n      \n      if (candleIndex < 0) return;\n      \n      // 좌표 계산\n      const chartCoords = viewport.chartToCanvas(candleIndex, marker.price || data.closes[candleIndex]);\n      let x = chartCoords.x;\n      let y = chartCoords.y;\n      \n      // 위치 조정\n      if (!marker.price && marker.position) {\n        const high = data.highs[candleIndex];\n        const low = data.lows[candleIndex];\n        \n        switch (marker.position) {\n          case 'aboveBar':\n            y = viewport.chartToCanvas(candleIndex, high).y - 20;\n            break;\n          case 'belowBar':\n            y = viewport.chartToCanvas(candleIndex, low).y + 20;\n            break;\n          case 'inBar':\n          default:\n            y = viewport.chartToCanvas(candleIndex, (high + low) / 2).y;\n            break;\n        }\n      }\n      \n      // 화면 영역 체크\n      if (x < 0 || x > gl.canvas.width || y < 0 || y > gl.canvas.height) return;\n      \n      const color = hexToRGBA(marker.color || '#FF0000');\n      const size = marker.size || 10;\n      \n      // WebGL로 마커 그리기\n      gl.useProgram(program);\n      \n      const positions: number[] = [];\n      const colors: number[] = [];\n      \n      // 마커 도형 생성\n      switch (marker.shape) {\n        case 'circle':\n          // 원을 삼각형들로 근사\n          const segments = 16;\n          for (let i = 0; i < segments; i++) {\n            const angle1 = (i / segments) * Math.PI * 2;\n            const angle2 = ((i + 1) / segments) * Math.PI * 2;\n            \n            // 중심점\n            positions.push(x, y);\n            // 첫 번째 점\n            positions.push(x + Math.cos(angle1) * size/2, y + Math.sin(angle1) * size/2);\n            // 두 번째 점\n            positions.push(x + Math.cos(angle2) * size/2, y + Math.sin(angle2) * size/2);\n            \n            // 색상 (각 정점마다)\n            colors.push(...color, ...color, ...color);\n          }\n          break;\n          \n        case 'square':\n          // 사각형 (두 개의 삼각형)\n          this.addRectangle(positions, x - size/2, y - size/2, x + size/2, y + size/2);\n          for (let i = 0; i < 6; i++) {\n            colors.push(...color);\n          }\n          break;\n          \n        case 'arrowUp':\n          // 위쪽 화살표\n          positions.push(x, y - size/2);  // 상단\n          positions.push(x - size/2, y + size/2);  // 좌하단\n          positions.push(x + size/2, y + size/2);  // 우하단\n          colors.push(...color, ...color, ...color);\n          break;\n          \n        case 'arrowDown':\n          // 아래쪽 화살표\n          positions.push(x, y + size/2);  // 하단\n          positions.push(x - size/2, y - size/2);  // 좌상단\n          positions.push(x + size/2, y - size/2);  // 우상단\n          colors.push(...color, ...color, ...color);\n          break;\n          \n        default:\n          // 기본값: 원\n          const defaultSegments = 16;\n          for (let i = 0; i < defaultSegments; i++) {\n            const angle1 = (i / defaultSegments) * Math.PI * 2;\n            const angle2 = ((i + 1) / defaultSegments) * Math.PI * 2;\n            \n            positions.push(x, y);\n            positions.push(x + Math.cos(angle1) * size/2, y + Math.sin(angle1) * size/2);\n            positions.push(x + Math.cos(angle2) * size/2, y + Math.sin(angle2) * size/2);\n            \n            colors.push(...color, ...color, ...color);\n          }\n          break;\n      }\n      \n      // 버퍼 생성 및 렌더링\n      if (positions.length > 0) {\n        const positionBuffer = this.bufferPool.acquire();\n        const colorBuffer = this.bufferPool.acquire();\n        \n        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n        \n        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n        \n        // 속성 설정\n        const positionLocation = gl.getAttribLocation(program, 'a_position');\n        const colorLocation = gl.getAttribLocation(program, 'a_color');\n        \n        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n        gl.enableVertexAttribArray(positionLocation);\n        gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n        \n        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n        gl.enableVertexAttribArray(colorLocation);\n        gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n        \n        // 유니폼 설정\n        const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n        gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);\n        \n        // 렌더링\n        gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);\n        \n        // 정리\n        gl.disableVertexAttribArray(positionLocation);\n        gl.disableVertexAttribArray(colorLocation);\n        \n        this.bufferPool.release(positionBuffer);\n        this.bufferPool.release(colorBuffer);\n      }\n    });\n  }\n  \n  private renderCrosshair(layer: RenderLayer & { x: number; y: number; verticalOnly?: boolean }, viewport: UnifiedCoordinateSystem): void {\n    const program = this.programs.get('lines');\n    if (!program) return;\n    \n    const gl = this.gl;\n    gl.useProgram(program);\n    \n    const positions: number[] = [];\n    const colors: number[] = [];\n    \n    // 색상 설정\n    const color = hexToRGBA(this.theme.crosshair?.color || '#888888');\n    const opacity = 0.5;\n    \n    // CSS 좌표를 캔버스 좌표로 변환\n    const pixelRatio = viewport.getPixelRatio ? viewport.getPixelRatio() : window.devicePixelRatio;\n    const canvasX = layer.x * pixelRatio;\n    const canvasY = layer.y * pixelRatio;\n    \n    // 수직선 (항상 그림)\n    positions.push(canvasX, 0, canvasX, this.canvas.height);\n    colors.push(color[0], color[1], color[2], opacity, color[0], color[1], color[2], opacity);\n    \n    // 수평선 (verticalOnly가 false일 때만)\n    if (!layer.verticalOnly && canvasY >= 0) {\n      positions.push(0, canvasY, this.canvas.width, canvasY);\n      colors.push(color[0], color[1], color[2], opacity, color[0], color[1], color[2], opacity);\n    }\n    \n    if (positions.length === 0) return;\n    \n    // 버퍼 생성 및 렌더링\n    const positionBuffer = this.bufferPool.acquire();\n    const colorBuffer = this.bufferPool.acquire();\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);\n    \n    // 속성 설정\n    const positionLocation = gl.getAttribLocation(program, 'a_position');\n    const colorLocation = gl.getAttribLocation(program, 'a_color');\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.enableVertexAttribArray(positionLocation);\n    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n    \n    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);\n    gl.enableVertexAttribArray(colorLocation);\n    gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);\n    \n    // 유니폼 설정\n    const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');\n    const pixelOffsetLocation = gl.getUniformLocation(program, 'u_pixelOffset');\n    \n    gl.uniform2f(resolutionLocation, this.canvas.width, this.canvas.height);\n    gl.uniform1f(pixelOffsetLocation, 0);\n    \n    // 점선 효과를 위해 여러 개의 짧은 선분으로 그리기\n    // const dashLength = 5;  // 사용하지 않음\n    // const gapLength = 5;  // 사용하지 않음\n    // const segmentLength = dashLength + gapLength; // 사용하지 않음\n    \n    // 실제로는 GL_LINES로 점선을 그리기 어려우므로\n    // 나중에 개선 필요 - 일단은 실선으로\n    gl.lineWidth(1.0);\n    gl.drawArrays(gl.LINES, 0, positions.length / 2);\n    \n    // 정리\n    gl.disableVertexAttribArray(positionLocation);\n    gl.disableVertexAttribArray(colorLocation);\n    \n    this.bufferPool.release(positionBuffer);\n    this.bufferPool.release(colorBuffer);\n  }\n  \n  public resize(width: number, height: number): void {\n    this.canvas.width = width;\n    this.canvas.height = height;\n    this.gl.viewport(0, 0, width, height);\n  }\n  \n  public updateTheme(theme: Theme): void {\n    this.theme = theme;\n    this.setupWebGL(); // 배경색 업데이트\n  }\n  \n  public setChartType(type: any): void {\n    this.options.chartType = type;\n  }\n  \n  public dispose(): void {\n    // 프로그램 정리\n    for (const program of this.programs.values()) {\n      this.gl.deleteProgram(program);\n    }\n    this.programs.clear();\n    \n    // 버퍼 풀 정리\n    this.bufferPool.dispose();\n  }\n}","import type { ChartData, Theme } from '@/types';\nimport { WebGLRenderer } from '@/core/WebGLRenderer';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { hexToRGBA } from '@/utils/webgl-utils';\n\nconst LINE_VERTEX_SHADER = `\nattribute vec2 a_position;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n  gl_Position = u_matrix * vec4(a_position, 0.0, 1.0);\n}\n`;\n\nconst LINE_FRAGMENT_SHADER = `\nprecision mediump float;\n\nuniform vec4 u_color;\n\nvoid main() {\n  gl_FragColor = u_color;\n}\n`;\n\nexport class GridRenderer {\n  private renderer: WebGLRenderer;\n  private theme: Theme;\n  private buffer: WebGLBuffer | null = null;\n  private initialized: boolean = false;\n  private showGrid: boolean = true;\n  \n  constructor(renderer: WebGLRenderer, theme: Theme) {\n    this.renderer = renderer;\n    this.theme = theme;\n  }\n  \n  async init(): Promise<void> {\n    await this.renderer.loadShaderProgram(\n      'grid',\n      LINE_VERTEX_SHADER,\n      LINE_FRAGMENT_SHADER,\n      ['a_position'],\n      ['u_matrix', 'u_color']\n    );\n    \n    const gl = this.renderer.getGL();\n    this.buffer = gl.createBuffer();\n    \n    this.initialized = true;\n  }\n  \n  render(_data: ChartData, coordSystem: UnifiedCoordinateSystem): void {\n    if (!this.initialized || !this.buffer || !this.showGrid) return;\n    \n    const program = this.renderer.useProgram('grid');\n    if (!program) return;\n    \n    const gl = this.renderer.getGL();\n    const width = coordSystem.getCanvasWidth();\n    const height = coordSystem.getCanvasHeight();\n    \n    const vertices: number[] = [];\n    \n    // 가격 그리드 라인 계산\n    const [minPrice, maxPrice] = coordSystem.getPriceRange();\n    const priceRange = maxPrice - minPrice;\n    const priceStep = this.calculatePriceStep(priceRange);\n    const startPrice = Math.floor(minPrice / priceStep) * priceStep;\n    \n    for (let price = startPrice; price <= maxPrice; price += priceStep) {\n      const y = coordSystem.priceToPixelY(price);\n      if (y >= 0 && y <= height) {\n        vertices.push(0, y, width, y);\n      }\n    }\n    \n    // 시간 그리드 라인 계산\n    const candleWidth = coordSystem.getCandleWidth();\n    const pixelOffset = coordSystem.getPixelOffset();\n    const visibleRange = coordSystem.getVisibleRange();\n    const timeStep = Math.max(1, Math.floor((visibleRange.end - visibleRange.start) / 10));\n    \n    for (let i = visibleRange.start; i <= visibleRange.end; i += timeStep) {\n      const x = (i + 0.5) * candleWidth + pixelOffset;\n      if (x >= 0 && x <= width) {\n        vertices.push(x, 0, x, height);\n      }\n    }\n    \n    if (vertices.length === 0) return;\n    \n    // 버퍼에 데이터 설정\n    gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.DYNAMIC_DRAW);\n    \n    // 속성 설정\n    gl.enableVertexAttribArray(program.attributes.a_position);\n    gl.vertexAttribPointer(program.attributes.a_position, 2, gl.FLOAT, false, 0, 0);\n    \n    // 투영 행렬 설정\n    const matrix = this.renderer.createProjectionMatrix(0, width, height, 0);\n    this.renderer.setUniformMatrix4fv(program.uniforms.u_matrix, matrix);\n    \n    // 색상 설정\n    const gridColor = this.theme.grid || this.theme.gridColor || '#333333';\n    const color = hexToRGBA(gridColor, 0.3);\n    this.renderer.setUniform4f(program.uniforms.u_color, ...color);\n    \n    // 그리기\n    gl.drawArrays(gl.LINES, 0, vertices.length / 2);\n    \n    // 속성 비활성화\n    gl.disableVertexAttribArray(program.attributes.a_position);\n  }\n  \n  private calculatePriceStep(range: number): number {\n    const targetLines = 8;\n    const roughStep = range / targetLines;\n    \n    // 적절한 단위로 반올림\n    const magnitude = Math.pow(10, Math.floor(Math.log10(roughStep)));\n    const normalized = roughStep / magnitude;\n    \n    let step: number;\n    if (normalized < 2) step = 1;\n    else if (normalized < 5) step = 2;\n    else step = 5;\n    \n    return step * magnitude;\n  }\n  \n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n  \n  setShowGrid(show: boolean): void {\n    this.showGrid = show;\n  }\n  \n  updateOptions(options: { grid?: any }): void {\n    if (options.grid !== undefined) {\n      if (typeof options.grid === 'boolean') {\n        this.showGrid = options.grid;\n      } else if (options.grid && typeof options.grid === 'object') {\n        this.showGrid = options.grid.show !== false;\n      }\n    }\n  }\n  \n  dispose(): void {\n    const gl = this.renderer.getGL();\n    if (this.buffer) gl.deleteBuffer(this.buffer);\n  }\n}","export interface YAxisFormatOptions {\n  format?: 'number' | 'percent' | 'currency';\n  decimals?: number;\n  thousandsSeparator?: string;\n  currencySymbol?: string;\n  percentMultiply?: boolean;\n}\n\nexport class YAxisFormatter {\n  private options: Required<YAxisFormatOptions>;\n\n  constructor(options: YAxisFormatOptions = {}) {\n    this.options = {\n      format: options.format || 'number',\n      decimals: options.decimals ?? 2,\n      thousandsSeparator: options.thousandsSeparator || ',',\n      currencySymbol: options.currencySymbol || '$',\n      percentMultiply: options.percentMultiply ?? true\n    };\n  }\n\n  format(value: number): string {\n    switch (this.options.format) {\n      case 'percent':\n        return this.formatPercent(value);\n      case 'currency':\n        return this.formatCurrency(value);\n      default:\n        return this.formatNumber(value);\n    }\n  }\n\n  private formatNumber(value: number): string {\n    const fixed = value.toFixed(this.options.decimals);\n    if (this.options.thousandsSeparator) {\n      return this.addThousandsSeparator(fixed);\n    }\n    return fixed;\n  }\n\n  private formatPercent(value: number): string {\n    const percentValue = this.options.percentMultiply ? value * 100 : value;\n    const fixed = percentValue.toFixed(this.options.decimals);\n    const formatted = this.options.thousandsSeparator \n      ? this.addThousandsSeparator(fixed) \n      : fixed;\n    return `${formatted}%`;\n  }\n\n  private formatCurrency(value: number): string {\n    const fixed = value.toFixed(this.options.decimals);\n    const formatted = this.options.thousandsSeparator \n      ? this.addThousandsSeparator(fixed) \n      : fixed;\n    return `${this.options.currencySymbol}${formatted}`;\n  }\n\n  private addThousandsSeparator(value: string): string {\n    const parts = value.split('.');\n    const integerPart = parts[0];\n    const decimalPart = parts[1];\n    \n    // 정수 부분에 천 단위 구분자 추가\n    const formattedInteger = integerPart.replace(\n      /\\B(?=(\\d{3})+(?!\\d))/g, \n      this.options.thousandsSeparator\n    );\n    \n    return decimalPart !== undefined \n      ? `${formattedInteger}.${decimalPart}`\n      : formattedInteger;\n  }\n\n  updateOptions(options: YAxisFormatOptions): void {\n    this.options = {\n      format: options.format || this.options.format,\n      decimals: options.decimals ?? this.options.decimals,\n      thousandsSeparator: options.thousandsSeparator ?? this.options.thousandsSeparator,\n      currencySymbol: options.currencySymbol || this.options.currencySymbol,\n      percentMultiply: options.percentMultiply ?? this.options.percentMultiply\n    };\n  }\n\n  getOptions(): Required<YAxisFormatOptions> {\n    return { ...this.options };\n  }\n}\n\n// X축 날짜 포맷터\nexport class XAxisFormatter {\n  private locale: string;\n  private format: string;\n\n  constructor(locale: string = 'en-US', format: string = 'short') {\n    this.locale = locale;\n    this.format = format;\n  }\n\n  formatTime(timestamp: number): string {\n    // timestamp가 초 단위인지 밀리초 단위인지 자동 감지\n    const timestampMs = timestamp < 10000000000 ? timestamp * 1000 : timestamp;\n    const date = new Date(timestampMs);\n    \n    // 날짜가 유효한지 확인\n    if (isNaN(date.getTime())) {\n      console.warn('Invalid timestamp:', timestamp);\n      return 'Invalid Date';\n    }\n    \n    switch (this.format) {\n      case 'time':\n        return date.toLocaleTimeString(this.locale, {\n          hour: '2-digit',\n          minute: '2-digit'\n        });\n      case 'date':\n        return date.toLocaleDateString(this.locale, {\n          month: '2-digit',\n          day: '2-digit'\n        });\n      case 'short':\n        return date.toLocaleDateString(this.locale, {\n          month: 'short',\n          day: 'numeric'\n        });\n      case 'full':\n        return date.toLocaleDateString(this.locale, {\n          year: 'numeric',\n          month: 'short',\n          day: 'numeric'\n        });\n      default:\n        return date.toLocaleString(this.locale);\n    }\n  }\n\n  formatTimeRange(timestamp: number, range: number): string {\n    // timestamp가 초 단위인지 밀리초 단위인지 자동 감지\n    // Unix timestamp는 1970년 이후 초 단위로 표현되므로, \n    // 10자리 숫자면 초 단위, 13자리면 밀리초 단위\n    const timestampMs = timestamp < 10000000000 ? timestamp * 1000 : timestamp;\n    const rangeMs = range < 10000000000 ? range * 1000 : range;\n    \n    // range에 따라 적절한 포맷 선택\n    const hour = 3600000; // 1시간 in ms\n    const day = 86400000; // 1일 in ms\n    const month = day * 30; // 대략 1달\n    \n    const date = new Date(timestampMs);\n    \n    // 날짜가 유효한지 확인\n    if (isNaN(date.getTime())) {\n      console.warn('Invalid timestamp:', timestamp);\n      return 'Invalid Date';\n    }\n    \n    if (rangeMs < hour * 24) {\n      // 24시간 미만: 시간 표시\n      return date.toLocaleTimeString(this.locale, {\n        hour: '2-digit',\n        minute: '2-digit'\n      });\n    } else if (rangeMs < day * 7) {\n      // 1주일 미만: 날짜 표시\n      return date.toLocaleDateString(this.locale, {\n        month: 'short',\n        day: 'numeric'\n      });\n    } else if (rangeMs < month * 3) {\n      // 3개월 미만: 월/일 표시\n      return date.toLocaleDateString(this.locale, {\n        month: 'short',\n        day: 'numeric'\n      });\n    } else {\n      // 3개월 이상: 년/월 표시\n      return date.toLocaleDateString(this.locale, {\n        year: '2-digit',\n        month: 'short'\n      });\n    }\n  }\n\n  updateFormat(format: string): void {\n    this.format = format;\n  }\n\n  updateLocale(locale: string): void {\n    this.locale = locale;\n  }\n}","import type { Theme, ChartData, Candle, ChartOptions } from '@/types';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { YAxisFormatter } from '@/utils/formatters';\n\nexport class LabelRenderer {\n  private container: HTMLElement;\n  private canvas: HTMLCanvasElement;\n  private ctx: CanvasRenderingContext2D;\n  private theme: Theme;\n  private options: Partial<ChartOptions>;\n  private measureTooltip: HTMLElement | null = null;\n  private yAxisFormatter: YAxisFormatter;\n  \n  constructor(container: HTMLElement, theme: Theme, options?: ChartOptions) {\n    this.container = container;\n    this.theme = theme;\n    this.options = options || {};\n    this.yAxisFormatter = new YAxisFormatter(options?.axis?.y);\n    \n    // 라벨용 캔버스 생성\n    this.canvas = document.createElement('canvas');\n    this.canvas.style.cssText = `\n      position: absolute;\n      top: 0;\n      right: 0;\n      width: 80px;\n      height: 100%;\n      pointer-events: none;\n      z-index: 10;\n    `;\n    container.appendChild(this.canvas);\n    \n    const ctx = this.canvas.getContext('2d');\n    if (!ctx) throw new Error('Failed to get 2D context');\n    this.ctx = ctx;\n    \n    // 초기 크기 설정\n    this.resize();\n  }\n  \n  private resize(): void {\n    const rect = this.container.getBoundingClientRect();\n    const pixelRatio = window.devicePixelRatio || 1;\n    \n    this.canvas.width = 80 * pixelRatio;\n    this.canvas.height = rect.height * pixelRatio;\n    this.canvas.style.height = rect.height + 'px';\n  }\n  \n  render(\n    _data: ChartData,\n    viewport: UnifiedCoordinateSystem,\n    currentPrice: number,\n    _currentTime: number,\n    _currentCandle: Candle | null\n  ): void {\n    // Y축 설정 확인\n    if (this.options.axis?.y?.show === false) return;\n    \n    // 매 렌더링마다 크기 확인\n    this.resize();\n    \n    const width = this.canvas.width;\n    const height = this.canvas.height;\n    // const pixelRatio = window.devicePixelRatio || 1;\n    \n    // Clear canvas\n    this.ctx.clearRect(0, 0, width, height);\n    \n    // 가격 축 렌더링\n    this.renderPriceAxis(viewport);\n    \n    // 현재 가격 라벨 렌더링\n    if (currentPrice >= 0) {\n      this.renderCurrentPriceLabel(currentPrice, viewport);\n    }\n  }\n  \n  private renderPriceAxis(viewport: UnifiedCoordinateSystem): void {\n    const pixelRatio = window.devicePixelRatio || 1;\n    const [minPrice, maxPrice] = viewport.getPriceRange();\n    const height = this.canvas.height / pixelRatio;\n    \n    // 디버그 로그 제거\n    \n    // 스타일 설정\n    this.ctx.save();\n    this.ctx.scale(pixelRatio, pixelRatio);\n    \n    // Y축 폰트 설정 적용\n    const fontOptions = this.options.axis?.y?.font;\n    \n    this.ctx.fillStyle = fontOptions?.color || this.theme.axis?.textColor || this.theme.axis?.unifiedColor || this.theme.text || this.theme.textColor;\n    const fontSize = fontOptions?.size || 11;\n    const fontFamily = fontOptions?.family || 'Arial';\n    this.ctx.font = `${fontSize}px ${fontFamily}`;\n    this.ctx.textAlign = 'left';\n    \n    // 가격 눈금 계산\n    const priceStep = this.calculatePriceStep(minPrice, maxPrice);\n    const startPrice = Math.ceil(minPrice / priceStep) * priceStep;\n    \n    let renderedCount = 0;\n    \n    for (let price = startPrice; price <= maxPrice; price += priceStep) {\n      // priceToPixelY는 전체 좌표계 높이 기준이므로, MainChartPanel의 실제 Y 좌표로 변환\n      const normalizedY = viewport.priceToPixelY(price) / viewport.getCanvasHeight();\n      const y = normalizedY * height;\n      \n      if (y >= 0 && y <= height) {\n        // 가격 텍스트\n        const priceText = this.yAxisFormatter.format(price);\n        this.ctx.fillText(priceText, 8, y + 3);\n        renderedCount++;\n      }\n    }\n    \n    // 디버그 로그 제거\n    \n    this.ctx.restore();\n  }\n  \n  private renderCurrentPriceLabel(price: number, viewport: UnifiedCoordinateSystem): void {\n    const pixelRatio = window.devicePixelRatio || 1;\n    const y = viewport.priceToPixelY(price) / pixelRatio;\n    \n    this.ctx.save();\n    this.ctx.scale(pixelRatio, pixelRatio);\n    \n    // 배경\n    this.ctx.fillStyle = this.theme.crosshair.labelBackground || '#2962ff';\n    this.ctx.fillRect(0, y - 10, 80, 20);\n    \n    // 텍스트\n    this.ctx.fillStyle = '#ffffff';\n    this.ctx.font = 'bold 11px Arial';\n    this.ctx.textAlign = 'center';\n    this.ctx.fillText(this.yAxisFormatter.format(price), 40, y + 3);\n    \n    this.ctx.restore();\n  }\n  \n  private calculatePriceStep(minPrice: number, maxPrice: number): number {\n    const range = maxPrice - minPrice;\n    const targetSteps = 10; // 목표 눈금 개수\n    \n    const roughStep = range / targetSteps;\n    const magnitude = Math.pow(10, Math.floor(Math.log10(roughStep)));\n    \n    const normalizedStep = roughStep / magnitude;\n    let step: number;\n    \n    if (normalizedStep < 1.5) step = 1;\n    else if (normalizedStep < 3) step = 2;\n    else if (normalizedStep < 7) step = 5;\n    else step = 10;\n    \n    return step * magnitude;\n  }\n  \n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n  \n  updateOptions(options: ChartOptions): void {\n    if (options.axis?.y) {\n      this.yAxisFormatter.updateOptions(options.axis?.y);\n    }\n  }\n  \n  /**\n   * 가격 비교 툴팁 표시\n   */\n  showMeasureTooltip(\n    startPrice: number,\n    endPrice: number,\n    x: number,\n    y: number\n  ): void {\n    if (!this.measureTooltip) {\n      this.measureTooltip = document.createElement('div');\n      this.measureTooltip.style.cssText = `\n        position: absolute;\n        background: rgba(30, 30, 30, 0.95);\n        border: 1px solid #333;\n        border-radius: 4px;\n        padding: 8px 12px;\n        font-family: Arial, sans-serif;\n        font-size: 12px;\n        color: #ccc;\n        pointer-events: none;\n        z-index: 10000;\n        box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n        white-space: nowrap;\n      `;\n      this.container.appendChild(this.measureTooltip);\n    }\n    \n    const priceDiff = endPrice - startPrice;\n    const pricePercent = (priceDiff / startPrice) * 100;\n    const isPositive = priceDiff >= 0;\n    \n    const diffColor = isPositive ? '#4caf50' : '#f44336';\n    const arrow = isPositive ? '▲' : '▼';\n    \n    this.measureTooltip.innerHTML = `\n      <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n        <div style=\"display: flex; align-items: center; gap: 8px;\">\n          <span style=\"color: ${diffColor}; font-size: 16px;\">${arrow}</span>\n          <span style=\"font-size: 14px; font-weight: bold; color: ${diffColor};\">\n            ${isPositive ? '+' : ''}${pricePercent.toFixed(2)}%\n          </span>\n        </div>\n        <div style=\"font-size: 11px; color: #999;\">\n          ${this.yAxisFormatter.format(startPrice)} → ${this.yAxisFormatter.format(endPrice)}\n        </div>\n        <div style=\"font-size: 11px; color: #999;\">\n          차이: ${isPositive ? '+' : ''}${this.yAxisFormatter.format(priceDiff)}\n        </div>\n      </div>\n    `;\n    \n    // 위치 조정 (화면 밖으로 나가지 않도록)\n    const rect = this.measureTooltip.getBoundingClientRect();\n    const containerRect = this.container.getBoundingClientRect();\n    \n    let left = x + 10;\n    let top = y - rect.height / 2;\n    \n    // 오른쪽 경계 체크\n    if (left + rect.width > containerRect.width) {\n      left = x - rect.width - 10;\n    }\n    \n    // 상하 경계 체크\n    if (top < 0) {\n      top = 0;\n    } else if (top + rect.height > containerRect.height) {\n      top = containerRect.height - rect.height;\n    }\n    \n    this.measureTooltip.style.left = `${left}px`;\n    this.measureTooltip.style.top = `${top}px`;\n    this.measureTooltip.style.display = 'block';\n  }\n  \n  /**\n   * 가격 비교 툴팁 숨기기\n   */\n  hideMeasureTooltip(): void {\n    if (this.measureTooltip) {\n      this.measureTooltip.style.display = 'none';\n    }\n  }\n  \n  dispose(): void {\n    this.canvas.remove();\n    if (this.measureTooltip) {\n      this.measureTooltip.remove();\n    }\n  }\n}","import type { Theme, ChartData } from '@/types';\r\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\r\nimport { YAxisFormatter, XAxisFormatter } from '@/utils/formatters';\r\n\r\nexport class CrosshairLabelRenderer {\r\n  private theme: Theme;\r\n  private coordSystem: UnifiedCoordinateSystem;\r\n  private yAxisFormatter: YAxisFormatter;\r\n  private xAxisFormatter: XAxisFormatter;\r\n  \r\n  private priceLabel: HTMLElement;\r\n  private timeLabel: HTMLElement;\r\n  \r\n  constructor(container: HTMLElement, theme: Theme, coordSystem: UnifiedCoordinateSystem) {\r\n    this.theme = theme;\r\n    this.coordSystem = coordSystem;\r\n    this.yAxisFormatter = new YAxisFormatter();\r\n    this.xAxisFormatter = new XAxisFormatter();\r\n    \r\n    // Create price label\r\n    this.priceLabel = document.createElement('div');\r\n    this.priceLabel.style.cssText = `\r\n      position: absolute;\r\n      right: 0;\r\n      padding: 4px 8px;\r\n      background: ${this.theme.crosshair.labelBackground || '#2962ff'};\r\n      color: ${this.theme.crosshair.labelTextColor || '#ffffff'};\r\n      font-size: 11px;\r\n      font-family: Arial, sans-serif;\r\n      border-radius: 3px;\r\n      transform: translateY(-50%);\r\n      pointer-events: none;\r\n      z-index: 20;\r\n      display: none;\r\n    `;\r\n    container.appendChild(this.priceLabel);\r\n    \r\n    // Create time label - 주석 처리하여 시간 라벨 제거\r\n    this.timeLabel = document.createElement('div');\r\n    this.timeLabel.style.cssText = `\r\n      position: absolute;\r\n      bottom: 0;\r\n      padding: 4px 8px;\r\n      background: ${this.theme.crosshair.labelBackground || '#2962ff'};\r\n      color: ${this.theme.crosshair.labelTextColor || '#ffffff'};\r\n      font-size: 11px;\r\n      font-family: Arial, sans-serif;\r\n      border-radius: 3px;\r\n      transform: translateX(-50%);\r\n      pointer-events: none;\r\n      z-index: 20;\r\n      display: none;\r\n    `;\r\n    // container.appendChild(this.timeLabel); // 시간 라벨을 DOM에 추가하지 않음\r\n  }\r\n  \r\n  /**\r\n   * Render crosshair labels\r\n   */\r\n  render(mouseX: number, mouseY: number, data: ChartData): void {\r\n    if (mouseX < 0 || mouseY < 0) {\r\n      this.hide();\r\n      return;\r\n    }\r\n    \r\n    // Update price label\r\n    // Convert CSS coordinates to canvas coordinates first\r\n    const canvasY = mouseY * this.coordSystem.getPixelRatio();\r\n    const price = this.coordSystem.canvasYToPrice(canvasY);\r\n    this.priceLabel.textContent = this.yAxisFormatter.format(price);\r\n    this.priceLabel.style.top = `${mouseY}px`;\r\n    this.priceLabel.style.display = 'block';\r\n    \r\n    // Update time label\r\n    // Convert CSS coordinates to canvas coordinates first\r\n    const canvasX = mouseX * this.coordSystem.getPixelRatio();\r\n    const candleIndex = this.coordSystem.canvasXToCandleIndex(canvasX);\r\n    const roundedIndex = Math.round(candleIndex);\r\n    \r\n    if (roundedIndex >= 0 && roundedIndex < data.length) {\r\n      const time = data.times[roundedIndex];\r\n      this.timeLabel.textContent = this.xAxisFormatter.formatTime(time);\r\n      this.timeLabel.style.left = `${mouseX}px`;\r\n      this.timeLabel.style.display = 'block';\r\n    } else {\r\n      this.timeLabel.style.display = 'none';\r\n    }\r\n  }\r\n  \r\n  /**\r\n   * Hide labels\r\n   */\r\n  hide(): void {\r\n    this.priceLabel.style.display = 'none';\r\n    this.timeLabel.style.display = 'none';\r\n  }\r\n  \r\n  /**\r\n   * Update theme\r\n   */\r\n  updateTheme(theme: Theme): void {\r\n    this.theme = theme;\r\n    this.priceLabel.style.background = theme.crosshair.labelBackground || '#2962ff';\r\n    this.priceLabel.style.color = theme.crosshair.labelTextColor || '#ffffff';\r\n    this.timeLabel.style.background = theme.crosshair.labelBackground || '#2962ff';\r\n    this.timeLabel.style.color = theme.crosshair.labelTextColor || '#ffffff';\r\n  }\r\n  \r\n  /**\r\n   * Dispose\r\n   */\r\n  dispose(): void {\r\n    this.priceLabel.remove();\r\n    this.timeLabel.remove();\r\n  }\r\n}","import type { ChartData, Theme, ChartOptions } from '@/types';\nimport type { LineSeries } from '@/core/LineSeriesManager';\n\ninterface ViewportInfo {\n  visibleRange: { startTime: number; endTime: number };\n  priceScale: { min: number; max: number };\n  timeToX: (time: number, width: number) => number;\n  priceToY: (price: number, height: number) => number;\n}\n\nexport class LineSeriesRenderer {\n  private ctx: CanvasRenderingContext2D;\n  private theme: Theme;\n\n  constructor(ctx: CanvasRenderingContext2D, theme: Theme, _options: ChartOptions) {\n    this.ctx = ctx;\n    this.theme = theme;\n  }\n\n  /**\n   * 여러 라인 시리즈 렌더링\n   */\n  render(\n    series: LineSeries[],\n    chartData: ChartData,\n    viewport: ViewportInfo,\n    width: number,\n    height: number\n  ): void {\n    if (series.length === 0) return;\n\n    const { visibleRange } = viewport;\n    \n    // 시간 범위 내의 인덱스 찾기\n    const startIdx = this.findTimeIndex(chartData.times, visibleRange.startTime, 'left');\n    const endIdx = this.findTimeIndex(chartData.times, visibleRange.endTime, 'right');\n    \n    if (startIdx >= endIdx) return;\n\n    // 각 라인 시리즈 렌더링\n    for (const lineSeries of series) {\n      if (!lineSeries.visible) continue;\n      \n      this.renderSingleLine(\n        lineSeries,\n        chartData,\n        viewport,\n        width,\n        height,\n        startIdx,\n        endIdx\n      );\n    }\n  }\n\n  /**\n   * 단일 라인 시리즈 렌더링\n   */\n  private renderSingleLine(\n    series: LineSeries,\n    chartData: ChartData,\n    viewport: ViewportInfo,\n    width: number,\n    height: number,\n    startIdx: number,\n    endIdx: number\n  ): void {\n    \n    this.ctx.save();\n    this.ctx.strokeStyle = series.color;\n    this.ctx.lineWidth = series.lineWidth;\n    this.ctx.lineJoin = 'round';\n    this.ctx.lineCap = 'round';\n    \n    // 안티앨리어싱을 위한 설정\n    this.ctx.imageSmoothingEnabled = true;\n    this.ctx.imageSmoothingQuality = 'high';\n    \n    this.ctx.beginPath();\n    \n    let firstPoint = true;\n    let prevX = 0;\n    \n    // 라인 시리즈 데이터와 차트 데이터의 시간을 매칭\n    for (let i = startIdx; i < endIdx; i++) {\n      const time = chartData.times[i];\n      const valueIdx = this.findTimeIndex(series.times, time, 'exact');\n      \n      if (valueIdx === -1) continue;\n      \n      const value = series.values[valueIdx];\n      const x = viewport.timeToX(time, width);\n      const y = viewport.priceToY(value, height);\n      \n      // 화면 밖의 포인트는 스킵 (최적화)\n      if (x < -10 || x > width + 10) {\n        if (!firstPoint) {\n          this.ctx.lineTo(x, y);\n        }\n        prevX = x;\n        continue;\n      }\n      \n      if (firstPoint) {\n        this.ctx.moveTo(x, y);\n        firstPoint = false;\n      } else {\n        // 부드러운 선을 위한 보간\n        if (Math.abs(x - prevX) > 1) {\n          this.ctx.lineTo(x, y);\n        }\n      }\n      \n      prevX = x;\n    }\n    \n    this.ctx.stroke();\n    this.ctx.restore();\n  }\n\n  /**\n   * 라인 시리즈 전용 렌더링 (차트 데이터 없이)\n   */\n  renderLineSeries(\n    series: LineSeries[],\n    viewport: ViewportInfo,\n    width: number,\n    height: number\n  ): void {\n    if (series.length === 0) return;\n\n    \n    for (const lineSeries of series) {\n      if (!lineSeries.visible) continue;\n      \n      // 시간 범위 내의 인덱스 찾기\n      const { visibleRange } = viewport;\n      const startIdx = this.findTimeIndex(lineSeries.times, visibleRange.startTime, 'left');\n      const endIdx = this.findTimeIndex(lineSeries.times, visibleRange.endTime, 'right');\n      \n      if (startIdx >= endIdx) continue;\n      \n      this.ctx.save();\n      this.ctx.strokeStyle = lineSeries.color;\n      this.ctx.lineWidth = lineSeries.lineWidth;\n      this.ctx.lineJoin = 'round';\n      this.ctx.lineCap = 'round';\n      \n      this.ctx.beginPath();\n      \n      let firstPoint = true;\n      \n      for (let i = startIdx; i < endIdx; i++) {\n        const time = lineSeries.times[i];\n        const value = lineSeries.values[i];\n        \n        const x = viewport.timeToX(time, width);\n        const y = viewport.priceToY(value, height);\n        \n        if (firstPoint) {\n          this.ctx.moveTo(x, y);\n          firstPoint = false;\n        } else {\n          this.ctx.lineTo(x, y);\n        }\n      }\n      \n      this.ctx.stroke();\n      this.ctx.restore();\n    }\n  }\n\n  /**\n   * 호버 포인트 렌더링\n   */\n  renderHoverPoints(\n    series: LineSeries[],\n    hoverTime: number,\n    viewport: ViewportInfo,\n    width: number,\n    height: number\n  ): void {\n    for (const lineSeries of series) {\n      if (!lineSeries.visible) continue;\n      \n      const valueIdx = this.findTimeIndex(lineSeries.times, hoverTime, 'exact');\n      if (valueIdx === -1) continue;\n      \n      const value = lineSeries.values[valueIdx];\n      const x = viewport.timeToX(hoverTime, width);\n      const y = viewport.priceToY(value, height);\n      \n      // 호버 포인트 그리기\n      this.ctx.save();\n      this.ctx.fillStyle = lineSeries.color;\n      this.ctx.strokeStyle = this.theme.background || this.theme.backgroundColor;\n      this.ctx.lineWidth = 2;\n      \n      this.ctx.beginPath();\n      this.ctx.arc(x, y, 4, 0, Math.PI * 2);\n      this.ctx.fill();\n      this.ctx.stroke();\n      \n      this.ctx.restore();\n    }\n  }\n\n  /**\n   * 범례 렌더링\n   */\n  renderLegend(series: LineSeries[], x: number, y: number): void {\n    const visibleSeries = series.filter(s => s.visible && s.showInLegend);\n    if (visibleSeries.length === 0) return;\n    \n    this.ctx.save();\n    this.ctx.font = '12px sans-serif';\n    \n    let offsetY = 0;\n    const lineHeight = 20;\n    const padding = 8;\n    \n    // 배경 그리기\n    const maxWidth = Math.max(...visibleSeries.map(s => \n      this.ctx.measureText(s.name).width + 30\n    ));\n    \n    this.ctx.fillStyle = this.theme.background + 'ee';\n    this.ctx.fillRect(x, y, maxWidth + padding * 2, visibleSeries.length * lineHeight + padding * 2);\n    \n    this.ctx.strokeStyle = this.theme.grid || this.theme.gridColor;\n    this.ctx.strokeRect(x, y, maxWidth + padding * 2, visibleSeries.length * lineHeight + padding * 2);\n    \n    // 각 시리즈 렌더링\n    for (const lineSeries of visibleSeries) {\n      const legendY = y + padding + offsetY + lineHeight / 2;\n      \n      // 라인 샘플\n      this.ctx.strokeStyle = lineSeries.color;\n      this.ctx.lineWidth = lineSeries.lineWidth;\n      this.ctx.beginPath();\n      this.ctx.moveTo(x + padding, legendY);\n      this.ctx.lineTo(x + padding + 20, legendY);\n      this.ctx.stroke();\n      \n      // 텍스트\n      this.ctx.fillStyle = this.theme.text || this.theme.textColor;\n      this.ctx.fillText(lineSeries.name, x + padding + 25, legendY + 4);\n      \n      offsetY += lineHeight;\n    }\n    \n    this.ctx.restore();\n  }\n\n  /**\n   * 이진 탐색으로 시간 인덱스 찾기\n   */\n  private findTimeIndex(times: Float64Array, target: number, mode: 'left' | 'right' | 'exact'): number {\n    let left = 0;\n    let right = times.length - 1;\n    \n    if (mode === 'exact') {\n      while (left <= right) {\n        const mid = Math.floor((left + right) / 2);\n        if (times[mid] === target) return mid;\n        if (times[mid] < target) left = mid + 1;\n        else right = mid - 1;\n      }\n      return -1;\n    }\n    \n    let result = mode === 'left' ? 0 : times.length;\n    \n    while (left <= right) {\n      const mid = Math.floor((left + right) / 2);\n      \n      if (times[mid] < target) {\n        left = mid + 1;\n        if (mode === 'right') result = mid + 1;\n      } else if (times[mid] > target) {\n        right = mid - 1;\n        if (mode === 'left') result = mid;\n      } else {\n        return mode === 'left' ? mid : mid + 1;\n      }\n    }\n    \n    return result;\n  }\n\n  /**\n   * 테마 업데이트\n   */\n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n}","import { WebGLRenderer } from '@/core/WebGLRenderer';\nimport { hexToRGBA } from '@/utils/webgl-utils';\n\nexport interface LineStyle {\n  color: string;\n  width: number;\n  opacity?: number;\n  dashed?: boolean;\n  dashLength?: number;\n  gapLength?: number;\n}\n\nexport class WebGLLineHelper {\n  private renderer: WebGLRenderer;\n  private vertices: number[] = [];\n  \n  constructor(renderer: WebGLRenderer) {\n    this.renderer = renderer;\n  }\n  \n  /**\n   * Get the WebGL renderer\n   */\n  getRenderer(): WebGLRenderer {\n    return this.renderer;\n  }\n  \n  /**\n   * Draw a line between two points\n   */\n  drawLine(x1: number, y1: number, x2: number, y2: number, style: LineStyle): void {\n    if (style.dashed) {\n      this.drawDashedLine(x1, y1, x2, y2, style);\n    } else {\n      this.drawSolidLine(x1, y1, x2, y2, style);\n    }\n  }\n  \n  /**\n   * Draw a solid line\n   */\n  private drawSolidLine(x1: number, y1: number, x2: number, y2: number, style: LineStyle): void {\n    this.vertices = [];\n    \n    if (style.width <= 1) {\n      // Simple line for 1px width\n      this.vertices.push(x1, y1, x2, y2);\n    } else {\n      // Thick line using triangles\n      const angle = Math.atan2(y2 - y1, x2 - x1);\n      const perpAngle = angle + Math.PI / 2;\n      const halfWidth = style.width / 2;\n      \n      const offsetX = Math.cos(perpAngle) * halfWidth;\n      const offsetY = Math.sin(perpAngle) * halfWidth;\n      \n      // Create rectangle using two triangles\n      this.vertices.push(\n        x1 - offsetX, y1 - offsetY,\n        x1 + offsetX, y1 + offsetY,\n        x2 - offsetX, y2 - offsetY,\n        \n        x1 + offsetX, y1 + offsetY,\n        x2 + offsetX, y2 + offsetY,\n        x2 - offsetX, y2 - offsetY\n      );\n    }\n    \n    this.render(style);\n  }\n  \n  /**\n   * Draw a dashed line\n   */\n  private drawDashedLine(x1: number, y1: number, x2: number, y2: number, style: LineStyle): void {\n    this.vertices = [];\n    \n    const dashLength = style.dashLength || 5;\n    const gapLength = style.gapLength || 5;\n    const totalLength = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);\n    const segmentLength = dashLength + gapLength;\n    const segments = Math.floor(totalLength / segmentLength);\n    \n    const dx = (x2 - x1) / totalLength;\n    const dy = (y2 - y1) / totalLength;\n    \n    for (let i = 0; i < segments; i++) {\n      const startX = x1 + dx * (i * segmentLength);\n      const startY = y1 + dy * (i * segmentLength);\n      const endX = x1 + dx * (i * segmentLength + dashLength);\n      const endY = y1 + dy * (i * segmentLength + dashLength);\n      \n      if (style.width <= 1) {\n        this.vertices.push(startX, startY, endX, endY);\n      } else {\n        // Thick dashed line\n        const angle = Math.atan2(dy, dx);\n        const perpAngle = angle + Math.PI / 2;\n        const halfWidth = style.width / 2;\n        \n        const offsetX = Math.cos(perpAngle) * halfWidth;\n        const offsetY = Math.sin(perpAngle) * halfWidth;\n        \n        this.vertices.push(\n          startX - offsetX, startY - offsetY,\n          startX + offsetX, startY + offsetY,\n          endX - offsetX, endY - offsetY,\n          \n          startX + offsetX, startY + offsetY,\n          endX + offsetX, endY + offsetY,\n          endX - offsetX, endY - offsetY\n        );\n      }\n    }\n    \n    // Draw remaining segment\n    const remainingLength = totalLength - segments * segmentLength;\n    if (remainingLength > 0) {\n      const startX = x1 + dx * (segments * segmentLength);\n      const startY = y1 + dy * (segments * segmentLength);\n      const finalLength = Math.min(remainingLength, dashLength);\n      const endX = startX + dx * finalLength;\n      const endY = startY + dy * finalLength;\n      \n      if (style.width <= 1) {\n        this.vertices.push(startX, startY, endX, endY);\n      } else {\n        const angle = Math.atan2(dy, dx);\n        const perpAngle = angle + Math.PI / 2;\n        const halfWidth = style.width / 2;\n        \n        const offsetX = Math.cos(perpAngle) * halfWidth;\n        const offsetY = Math.sin(perpAngle) * halfWidth;\n        \n        this.vertices.push(\n          startX - offsetX, startY - offsetY,\n          startX + offsetX, startY + offsetY,\n          endX - offsetX, endY - offsetY,\n          \n          startX + offsetX, startY + offsetY,\n          endX + offsetX, endY + offsetY,\n          endX - offsetX, endY - offsetY\n        );\n      }\n    }\n    \n    this.render(style);\n  }\n  \n  /**\n   * Draw a rectangle\n   */\n  drawRect(x: number, y: number, width: number, height: number, style: LineStyle): void {\n    this.drawLine(x, y, x + width, y, style);\n    this.drawLine(x + width, y, x + width, y + height, style);\n    this.drawLine(x + width, y + height, x, y + height, style);\n    this.drawLine(x, y + height, x, y, style);\n  }\n  \n  /**\n   * Draw a circle (approximated with line segments)\n   */\n  drawCircle(centerX: number, centerY: number, radius: number, style: LineStyle, segments: number = 32): void {\n    this.vertices = [];\n    \n    const angleStep = (Math.PI * 2) / segments;\n    \n    for (let i = 0; i < segments; i++) {\n      const angle1 = i * angleStep;\n      const angle2 = (i + 1) * angleStep;\n      \n      const x1 = centerX + Math.cos(angle1) * radius;\n      const y1 = centerY + Math.sin(angle1) * radius;\n      const x2 = centerX + Math.cos(angle2) * radius;\n      const y2 = centerY + Math.sin(angle2) * radius;\n      \n      if (style.width <= 1) {\n        this.vertices.push(x1, y1, x2, y2);\n      } else {\n        // Thick circle outline\n        const innerRadius = radius - style.width / 2;\n        const outerRadius = radius + style.width / 2;\n        \n        const ix1 = centerX + Math.cos(angle1) * innerRadius;\n        const iy1 = centerY + Math.sin(angle1) * innerRadius;\n        const ix2 = centerX + Math.cos(angle2) * innerRadius;\n        const iy2 = centerY + Math.sin(angle2) * innerRadius;\n        \n        const ox1 = centerX + Math.cos(angle1) * outerRadius;\n        const oy1 = centerY + Math.sin(angle1) * outerRadius;\n        const ox2 = centerX + Math.cos(angle2) * outerRadius;\n        const oy2 = centerY + Math.sin(angle2) * outerRadius;\n        \n        this.vertices.push(\n          ix1, iy1, ox1, oy1, ix2, iy2,\n          ox1, oy1, ox2, oy2, ix2, iy2\n        );\n      }\n    }\n    \n    this.render(style);\n  }\n  \n  /**\n   * Render the accumulated vertices\n   */\n  private render(style: LineStyle): void {\n    if (this.vertices.length === 0) return;\n    \n    const gl = this.renderer.getGL();\n    \n    this.renderer.useProgram('unified');\n    \n    // Set uniforms\n    const rgba = hexToRGBA(style.color, style.opacity || 1);\n    const colorLocation = this.renderer.getUniformLocation('unified', 'u_color');\n    const resolutionLocation = this.renderer.getUniformLocation('unified', 'u_resolution');\n    \n    if (colorLocation) {\n      gl.uniform4f(colorLocation, rgba[0], rgba[1], rgba[2], rgba[3]);\n    }\n    if (resolutionLocation) {\n      gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);\n    }\n    \n    // Create and bind buffer\n    const positionBuffer = gl.createBuffer();\n    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.vertices), gl.STATIC_DRAW);\n    \n    // Set attributes\n    const program = gl.getParameter(gl.CURRENT_PROGRAM);\n    if (program) {\n      const positionLocation = gl.getAttribLocation(program, 'a_position');\n      gl.enableVertexAttribArray(positionLocation);\n      gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n    }\n    \n    // Draw\n    const drawMode = style.width <= 1 ? gl.LINES : gl.TRIANGLES;\n    const vertexCount = style.width <= 1 ? this.vertices.length / 2 : this.vertices.length / 2;\n    gl.drawArrays(drawMode, 0, vertexCount);\n    \n    // Cleanup\n    gl.deleteBuffer(positionBuffer);\n  }\n}","import type { Theme, ChartData } from '@/types';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { WebGLLineHelper, type LineStyle } from './WebGLLineHelper';\n\nexport class CrosshairRenderer {\n  private theme: Theme;\n  private coordSystem: UnifiedCoordinateSystem;\n  private lineHelper: WebGLLineHelper;\n  \n  constructor(theme: Theme, coordSystem: UnifiedCoordinateSystem, lineHelper: WebGLLineHelper) {\n    this.theme = theme;\n    this.coordSystem = coordSystem;\n    this.lineHelper = lineHelper;\n  }\n  \n  /**\n   * Render crosshair at given position\n   * @param mouseX - CSS X coordinate\n   * @param mouseY - CSS Y coordinate\n   * @param data - Chart data\n   * @param verticalOnly - If true, only render vertical line (for volume panel)\n   */\n  render(mouseX: number, mouseY: number, data: ChartData, verticalOnly: boolean = false): void {\n    if (mouseX < 0 || mouseY < 0) return;\n    \n    // Convert CSS coordinates to canvas coordinates\n    const canvasX = mouseX * this.coordSystem.getPixelRatio();\n    const canvasY = mouseY * this.coordSystem.getPixelRatio();\n    \n    const style: LineStyle = {\n      color: this.theme.crosshair.color,\n      width: 1,\n      opacity: 0.7,\n      dashed: true,\n      dashLength: 5,\n      gapLength: 5\n    };\n    \n    // Get canvas dimensions from WebGL renderer (actual canvas size)\n    const renderer = this.lineHelper.getRenderer();\n    const width = renderer.getWidth();\n    const height = renderer.getHeight();\n    \n    // Draw vertical line\n    this.lineHelper.drawLine(canvasX, 0, canvasX, height, style);\n    \n    // Draw horizontal line only if not in verticalOnly mode\n    if (!verticalOnly) {\n      this.lineHelper.drawLine(0, canvasY, width, canvasY, style);\n    }\n    \n    // Draw price and time highlight boxes only if not in verticalOnly mode\n    if (!verticalOnly) {\n      this.drawPriceBox(canvasX, canvasY, data);\n      this.drawTimeBox(canvasX, canvasY, data);\n    }\n  }\n  \n  /**\n   * Draw price highlight box on y-axis\n   */\n  private drawPriceBox(_canvasX: number, _canvasY: number, _data: ChartData): void {\n    // 가격 박스 완전 제거 - 사각형이 보이는 문제 해결\n    // const price = this.coordSystem.canvasYToPrice(canvasY);\n    // const priceText = price.toFixed(2); // For future text rendering\n    // const boxWidth = 80;\n    // const boxHeight = 20;\n    // const rightEdge = this.coordSystem.getCanvasWidth();\n    \n    // 배경 라인도 제거 - 이것이 사각형으로 보이는 원인\n    // const boxStyle: LineStyle = {\n    //   color: this.theme.crosshair.labelBackground || '#1e222d',\n    //   width: boxHeight,\n    //   opacity: 0.9\n    // };\n    \n    // this.lineHelper.drawLine(\n    //   rightEdge - boxWidth,\n    //   canvasY,\n    //   rightEdge,\n    //   canvasY,\n    //   boxStyle\n    // );\n  }\n  \n  /**\n   * Draw time highlight box on x-axis\n   */\n  private drawTimeBox(_canvasX: number, _canvasY: number, _data: ChartData): void {\n    // 시간 박스 완전 제거 - 사각형이 보이는 문제 해결\n    // const candleIndex = this.coordSystem.canvasXToCandleIndex(canvasX);\n    // const roundedIndex = Math.round(candleIndex);\n    \n    // if (roundedIndex < 0 || roundedIndex >= data.length) return;\n    \n    // const time = data.times[roundedIndex];\n    // const timeText = new Date(time).toLocaleTimeString(); // For future text rendering\n    // const boxWidth = 100;\n    // const boxHeight = 20;\n    // const bottomEdge = this.coordSystem.getCanvasHeight();\n    \n    // 배경 라인도 제거 - 이것이 사각형으로 보이는 원인\n    // const boxStyle: LineStyle = {\n    //   color: this.theme.crosshair.labelBackground || '#1e222d',\n    //   width: boxHeight,\n    //   opacity: 0.9\n    // };\n    \n    // this.lineHelper.drawLine(\n    //   canvasX - boxWidth / 2,\n    //   bottomEdge - boxHeight,\n    //   canvasX + boxWidth / 2,\n    //   bottomEdge - boxHeight,\n    //   boxStyle\n    // );\n  }\n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n}","import type { Theme, DrawingObject } from '@/types';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { WebGLLineHelper, type LineStyle } from './WebGLLineHelper';\n\nexport class DrawingRenderer {\n  private theme: Theme;\n  private coordSystem: UnifiedCoordinateSystem;\n  private lineHelper: WebGLLineHelper;\n  \n  constructor(theme: Theme, coordSystem: UnifiedCoordinateSystem, lineHelper: WebGLLineHelper) {\n    this.theme = theme;\n    this.coordSystem = coordSystem;\n    this.lineHelper = lineHelper;\n  }\n  \n  /**\n   * Render all drawing objects\n   */\n  render(drawings: DrawingObject[]): void {\n    drawings.forEach(drawing => {\n      // if (!drawing.visible) return; // visible property not in DrawingObject type\n      \n      switch (drawing.type) {\n        case 'trendline':\n          this.renderTrendline(drawing);\n          break;\n        case 'horizontal':\n          this.renderHorizontalLine(drawing);\n          break;\n        case 'rectangle':\n          this.renderRectangle(drawing);\n          break;\n        case 'circle':\n          this.renderCircle(drawing);\n          break;\n        case 'text':\n          this.renderText(drawing);\n          break;\n        case 'marker':\n          this.renderMarker(drawing);\n          break;\n      }\n      \n      // Draw selection indicators if selected\n      if (drawing.selected) {\n        this.renderSelectionHandles(drawing);\n      }\n    });\n  }\n  \n  /**\n   * Render trendline\n   */\n  private renderTrendline(drawing: DrawingObject): void {\n    if (drawing.points.length < 2) return;\n    \n    const p1 = drawing.points[0];\n    const p2 = drawing.points[1];\n    \n    const start = this.coordSystem.chartToCanvas(p1.time, p1.price);\n    const end = this.coordSystem.chartToCanvas(p2.time, p2.price);\n    \n    // Alt+T 트렌드라인 모드에서는 두 점 사이에만 그리기\n    // 전체 화면으로 확장하지 않음\n    // const extended = this.extendLineToEdges(start, end);\n    \n    const style: LineStyle = {\n      color: drawing.style.color,\n      width: drawing.style.lineWidth,\n      opacity: drawing.style.opacity,\n      dashed: false, // drawing.style.lineDash === 'dashed',\n      dashLength: 5,\n      gapLength: 5\n    };\n    \n    // 두 점 사이에만 라인 그리기\n    this.lineHelper.drawLine(start.x, start.y, end.x, end.y, style);\n  }\n  \n  /**\n   * Render horizontal line\n   */\n  private renderHorizontalLine(drawing: DrawingObject): void {\n    if (drawing.points.length === 0) return;\n    \n    const price = drawing.points[0].price;\n    const y = this.coordSystem.priceToCanvasY(price);\n    const width = this.coordSystem.getCanvasWidth();\n    \n    const style: LineStyle = {\n      color: drawing.style.color,\n      width: drawing.style.lineWidth,\n      opacity: drawing.style.opacity,\n      dashed: false, // drawing.style.lineDash === 'dashed',\n      dashLength: 10,\n      gapLength: 5\n    };\n    \n    this.lineHelper.drawLine(0, y, width, y, style);\n    \n    // Draw price label - 주석 처리 (오른쪽 사각형 제거)\n    // this.drawPriceLabel(width - 80, y, price, drawing.style.color);\n  }\n  \n  /**\n   * Render rectangle\n   */\n  private renderRectangle(drawing: DrawingObject): void {\n    if (drawing.points.length < 2) return;\n    \n    const p1 = drawing.points[0];\n    const p2 = drawing.points[1];\n    \n    const topLeft = this.coordSystem.chartToCanvas(\n      Math.min(p1.time, p2.time),\n      Math.max(p1.price, p2.price)\n    );\n    \n    const bottomRight = this.coordSystem.chartToCanvas(\n      Math.max(p1.time, p2.time),\n      Math.min(p1.price, p2.price)\n    );\n    \n    const width = bottomRight.x - topLeft.x;\n    const height = bottomRight.y - topLeft.y;\n    \n    // Draw filled rectangle if configured\n    // TODO: Add fillColor support to DrawingObject style\n    // if (drawing.style.fillColor) {\n    //   const fillStyle: LineStyle = {\n    //     color: drawing.style.fillColor,\n    //     width: height,\n    //     opacity: drawing.style.fillOpacity || 0.2\n    //   };\n    //   \n    //   this.lineHelper.drawLine(\n    //     topLeft.x,\n    //     topLeft.y + height / 2,\n    //     topLeft.x + width,\n    //     topLeft.y + height / 2,\n    //     fillStyle\n    //   );\n    // }\n    \n    // Draw border\n    const borderStyle: LineStyle = {\n      color: drawing.style.color,\n      width: drawing.style.lineWidth,\n      opacity: drawing.style.opacity\n    };\n    \n    this.lineHelper.drawRect(topLeft.x, topLeft.y, width, height, borderStyle);\n  }\n  \n  /**\n   * Render circle\n   */\n  private renderCircle(drawing: DrawingObject): void {\n    if (drawing.points.length === 0 || drawing.radius === undefined) return;\n    \n    const center = this.coordSystem.chartToCanvas(drawing.points[0].time, drawing.points[0].price);\n    \n    const style: LineStyle = {\n      color: drawing.style.color,\n      width: drawing.style.lineWidth,\n      opacity: drawing.style.opacity\n    };\n    \n    this.lineHelper.drawCircle(center.x, center.y, drawing.radius, style);\n  }\n  \n  /**\n   * Render text\n   */\n  private renderText(drawing: DrawingObject): void {\n    if (drawing.points.length === 0 || !drawing.text) return;\n    \n    const pos = this.coordSystem.chartToCanvas(drawing.points[0].time, drawing.points[0].price);\n    \n    // Draw text background\n    const textWidth = drawing.text.length * 8; // Approximate\n    const textHeight = 16;\n    \n    const bgStyle: LineStyle = {\n      color: this.theme.background || '#131722',\n      width: textHeight,\n      opacity: 0.8\n    };\n    \n    this.lineHelper.drawLine(\n      pos.x,\n      pos.y,\n      pos.x + textWidth,\n      pos.y,\n      bgStyle\n    );\n    \n    // Draw text border\n    const borderStyle: LineStyle = {\n      color: drawing.style.color,\n      width: 1,\n      opacity: drawing.style.opacity\n    };\n    \n    this.lineHelper.drawRect(\n      pos.x - 4,\n      pos.y - textHeight / 2 - 4,\n      textWidth + 8,\n      textHeight + 8,\n      borderStyle\n    );\n  }\n  \n  /**\n   * Render marker\n   */\n  private renderMarker(drawing: DrawingObject): void {\n    if (drawing.points.length === 0) return;\n    \n    const pos = this.coordSystem.chartToCanvas(drawing.points[0].time, drawing.points[0].price);\n    const markerType = drawing.markerType || 'circle';\n    const size = drawing.markerSize || 12;\n    \n    const style: LineStyle = {\n      color: drawing.style.color,\n      width: drawing.style.lineWidth,\n      opacity: drawing.style.opacity\n    };\n    \n    switch (markerType) {\n      case 'circle':\n        this.drawCircleMarker(pos.x, pos.y, size, style);\n        break;\n      case 'square':\n        this.drawSquareMarker(pos.x, pos.y, size, style);\n        break;\n      case 'arrowUp':\n        this.drawArrowUp(pos.x, pos.y, size, style);\n        break;\n      case 'arrowDown':\n        this.drawArrowDown(pos.x, pos.y, size, style);\n        break;\n      case 'triangleUp':\n        this.drawTriangleUp(pos.x, pos.y, size, style);\n        break;\n      case 'triangleDown':\n        this.drawTriangleDown(pos.x, pos.y, size, style);\n        break;\n      default:\n        // 기본값으로 circle 그리기\n        this.drawCircleMarker(pos.x, pos.y, size, style);\n        break;\n    }\n  }\n  \n  /**\n   * Draw selection handles for selected drawing\n   */\n  private renderSelectionHandles(drawing: DrawingObject): void {\n    const handleSize = 6;\n    const handleStyle: LineStyle = {\n      color: '#2962ff',\n      width: 2,\n      opacity: 1\n    };\n    \n    drawing.points.forEach(point => {\n      const pos = this.coordSystem.chartToCanvas(point.time, point.price);\n      \n      // Draw handle square\n      this.lineHelper.drawRect(\n        pos.x - handleSize / 2,\n        pos.y - handleSize / 2,\n        handleSize,\n        handleSize,\n        handleStyle\n      );\n    });\n  }\n  \n  /**\n   * Helper methods for drawing shapes\n   */\n  private drawArrowUp(x: number, y: number, size: number, style: LineStyle): void {\n    this.lineHelper.drawLine(x, y - size, x - size/2, y, style);\n    this.lineHelper.drawLine(x, y - size, x + size/2, y, style);\n    this.lineHelper.drawLine(x - size/2, y, x + size/2, y, style);\n  }\n  \n  private drawArrowDown(x: number, y: number, size: number, style: LineStyle): void {\n    this.lineHelper.drawLine(x, y + size, x - size/2, y, style);\n    this.lineHelper.drawLine(x, y + size, x + size/2, y, style);\n    this.lineHelper.drawLine(x - size/2, y, x + size/2, y, style);\n  }\n  \n  private drawTriangleUp(x: number, y: number, size: number, style: LineStyle): void {\n    this.lineHelper.drawLine(x, y - size, x - size/2, y + size/2, style);\n    this.lineHelper.drawLine(x - size/2, y + size/2, x + size/2, y + size/2, style);\n    this.lineHelper.drawLine(x + size/2, y + size/2, x, y - size, style);\n  }\n  \n  private drawTriangleDown(x: number, y: number, size: number, style: LineStyle): void {\n    this.lineHelper.drawLine(x, y + size, x - size/2, y - size/2, style);\n    this.lineHelper.drawLine(x - size/2, y - size/2, x + size/2, y - size/2, style);\n    this.lineHelper.drawLine(x + size/2, y - size/2, x, y + size, style);\n  }\n  \n  private drawCircleMarker(x: number, y: number, size: number, style: LineStyle): void {\n    // WebGL 라인으로 원을 그리기 (8각형으로 근사)\n    const segments = 8;\n    const angleStep = (Math.PI * 2) / segments;\n    const radius = size / 2;\n    \n    for (let i = 0; i < segments; i++) {\n      const angle1 = i * angleStep;\n      const angle2 = (i + 1) * angleStep;\n      \n      const x1 = x + Math.cos(angle1) * radius;\n      const y1 = y + Math.sin(angle1) * radius;\n      const x2 = x + Math.cos(angle2) * radius;\n      const y2 = y + Math.sin(angle2) * radius;\n      \n      this.lineHelper.drawLine(x1, y1, x2, y2, style);\n    }\n  }\n  \n  private drawSquareMarker(x: number, y: number, size: number, style: LineStyle): void {\n    const halfSize = size / 2;\n    this.lineHelper.drawRect(\n      x - halfSize,\n      y - halfSize,\n      size,\n      size,\n      style\n    );\n  }\n  \n  \n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n}","import type { Theme } from '@/types';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { WebGLLineHelper, type LineStyle } from './WebGLLineHelper';\n\nexport interface SnapPoint {\n  index: number;\n  price: number;\n  type: 'open' | 'high' | 'low' | 'close';\n}\n\nexport class SnapPointRenderer {\n  private theme: Theme;\n  private coordSystem: UnifiedCoordinateSystem;\n  private lineHelper: WebGLLineHelper;\n  \n  constructor(theme: Theme, coordSystem: UnifiedCoordinateSystem, lineHelper: WebGLLineHelper) {\n    this.theme = theme;\n    this.coordSystem = coordSystem;\n    this.lineHelper = lineHelper;\n  }\n  \n  /**\n   * Render snap point indicator\n   */\n  render(snapPoint: SnapPoint | null): void {\n    if (!snapPoint) return;\n    \n    // Convert chart coordinates to canvas coordinates\n    const canvasPos = this.coordSystem.chartToCanvas(snapPoint.index, snapPoint.price);\n    \n    // Determine snap point color based on type\n    const color = this.getSnapPointColor(snapPoint.type);\n    \n    // Draw outer circle\n    const outerStyle: LineStyle = {\n      color: color,\n      width: 2,\n      opacity: 0.8\n    };\n    \n    this.lineHelper.drawCircle(canvasPos.x, canvasPos.y, 8, outerStyle);\n    \n    // Draw inner circle (filled effect)\n    const innerStyle: LineStyle = {\n      color: color,\n      width: 4,\n      opacity: 0.5\n    };\n    \n    this.lineHelper.drawCircle(canvasPos.x, canvasPos.y, 4, innerStyle);\n    \n    // Draw crosshair from snap point\n    this.drawSnapCrosshair(canvasPos.x, canvasPos.y, color);\n    \n    // Draw snap type label\n    this.drawSnapLabel(canvasPos.x, canvasPos.y, snapPoint.type);\n  }\n  \n  /**\n   * Get color for snap point based on type\n   */\n  private getSnapPointColor(type: string): string {\n    switch (type) {\n      case 'high':\n        return this.theme.candleUp || '#26a69a';\n      case 'low':\n        return this.theme.candleDown || '#ef5350';\n      case 'open':\n      case 'close':\n      default:\n        return this.theme.text || '#d1d4dc';\n    }\n  }\n  \n  /**\n   * Draw crosshair lines from snap point\n   */\n  private drawSnapCrosshair(x: number, y: number, color: string): void {\n    const style: LineStyle = {\n      color: color,\n      width: 1,\n      opacity: 0.5,\n      dashed: true,\n      dashLength: 3,\n      gapLength: 3\n    };\n    \n    const width = this.coordSystem.getWidth();\n    const height = this.coordSystem.getHeight();\n    \n    // Vertical line\n    this.lineHelper.drawLine(x, 0, x, height, style);\n    \n    // Horizontal line\n    this.lineHelper.drawLine(0, y, width, y, style);\n  }\n  \n  /**\n   * Draw snap point type label\n   */\n  private drawSnapLabel(x: number, y: number, type: string): void {\n    // Label background\n    const labelWidth = 40;\n    const labelHeight = 16;\n    const labelX = x + 12;\n    const labelY = y - 8;\n    \n    const bgStyle: LineStyle = {\n      color: this.theme.background || '#131722',\n      width: labelHeight,\n      opacity: 0.9\n    };\n    \n    this.lineHelper.drawLine(\n      labelX,\n      labelY + labelHeight / 2,\n      labelX + labelWidth,\n      labelY + labelHeight / 2,\n      bgStyle\n    );\n    \n    // Label border\n    const borderStyle: LineStyle = {\n      color: this.getSnapPointColor(type),\n      width: 1,\n      opacity: 1\n    };\n    \n    this.lineHelper.drawRect(labelX, labelY, labelWidth, labelHeight, borderStyle);\n    \n    // Note: Text rendering would require a separate text rendering system\n    // For now, we just draw the background and border\n  }\n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n}","import type { Theme } from '@/types';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { WebGLLineHelper, type LineStyle } from './WebGLLineHelper';\n\nexport interface MeasurePoint {\n  index: number;\n  price: number;\n}\n\nexport class MeasureRenderer {\n  private theme: Theme;\n  private coordSystem: UnifiedCoordinateSystem;\n  private lineHelper: WebGLLineHelper;\n  \n  constructor(theme: Theme, coordSystem: UnifiedCoordinateSystem, lineHelper: WebGLLineHelper) {\n    this.theme = theme;\n    this.coordSystem = coordSystem;\n    this.lineHelper = lineHelper;\n  }\n  \n  /**\n   * Render price measurement tool\n   */\n  render(start: MeasurePoint | null, end: MeasurePoint | null, fixed: boolean): void {\n    if (!start) return;\n    \n    const startCanvas = this.coordSystem.chartToCanvas(start.index, start.price);\n    \n    if (!end) {\n      // Just draw the starting point\n      this.drawMeasurePoint(startCanvas.x, startCanvas.y, true);\n      return;\n    }\n    \n    const endCanvas = this.coordSystem.chartToCanvas(end.index, end.price);\n    \n    // Draw the measurement line\n    this.drawMeasureLine(startCanvas, endCanvas, fixed);\n    \n    // Draw start and end points\n    this.drawMeasurePoint(startCanvas.x, startCanvas.y, true);\n    this.drawMeasurePoint(endCanvas.x, endCanvas.y, false);\n    \n    // Draw measurement info\n    this.drawMeasurementInfo(start, end, startCanvas, endCanvas);\n  }\n  \n  /**\n   * Draw measurement line between two points\n   */\n  private drawMeasureLine(\n    start: { x: number; y: number },\n    end: { x: number; y: number },\n    fixed: boolean\n  ): void {\n    const color = fixed ? '#2962ff' : '#ff6c00';\n    \n    // Main line\n    const lineStyle: LineStyle = {\n      color: color,\n      width: 2,\n      opacity: fixed ? 1 : 0.8\n    };\n    \n    this.lineHelper.drawLine(start.x, start.y, end.x, end.y, lineStyle);\n    \n    // Draw parallel lines for range visualization\n    const rangeStyle: LineStyle = {\n      color: color,\n      width: 1,\n      opacity: 0.3,\n      dashed: true,\n      dashLength: 5,\n      gapLength: 5\n    };\n    \n    // Horizontal lines at start and end price\n    const width = this.coordSystem.getWidth();\n    this.lineHelper.drawLine(0, start.y, width, start.y, rangeStyle);\n    this.lineHelper.drawLine(0, end.y, width, end.y, rangeStyle);\n    \n    // Vertical lines at start and end time\n    const height = this.coordSystem.getHeight();\n    this.lineHelper.drawLine(start.x, 0, start.x, height, rangeStyle);\n    this.lineHelper.drawLine(end.x, 0, end.x, height, rangeStyle);\n  }\n  \n  /**\n   * Draw measurement point indicator\n   */\n  private drawMeasurePoint(x: number, y: number, isStart: boolean): void {\n    const color = isStart ? '#2962ff' : '#ff6c00';\n    \n    // Outer circle\n    const outerStyle: LineStyle = {\n      color: color,\n      width: 2,\n      opacity: 1\n    };\n    \n    this.lineHelper.drawCircle(x, y, 6, outerStyle);\n    \n    // Inner filled circle\n    const innerStyle: LineStyle = {\n      color: color,\n      width: 3,\n      opacity: 0.5\n    };\n    \n    this.lineHelper.drawCircle(x, y, 3, innerStyle);\n  }\n  \n  /**\n   * Draw measurement information (price difference, percentage, etc.)\n   */\n  private drawMeasurementInfo(\n    start: MeasurePoint,\n    end: MeasurePoint,\n    startCanvas: { x: number; y: number },\n    endCanvas: { x: number; y: number }\n  ): void {\n    // Calculate measurement data\n    const priceDiff = end.price - start.price;\n    // const pricePercent = (priceDiff / start.price) * 100; // For future display\n    // const timeDiff = end.index - start.index; // For future display\n    \n    // Draw info box at midpoint\n    const midX = (startCanvas.x + endCanvas.x) / 2;\n    const midY = (startCanvas.y + endCanvas.y) / 2;\n    \n    // Info box dimensions\n    const boxWidth = 120;\n    const boxHeight = 40;\n    const boxX = midX - boxWidth / 2;\n    const boxY = midY - boxHeight / 2;\n    \n    // Draw box background\n    const bgStyle: LineStyle = {\n      color: this.theme.background || '#131722',\n      width: boxHeight,\n      opacity: 0.9\n    };\n    \n    this.lineHelper.drawLine(\n      boxX,\n      midY,\n      boxX + boxWidth,\n      midY,\n      bgStyle\n    );\n    \n    // Draw box border\n    const borderStyle: LineStyle = {\n      color: priceDiff >= 0 ? (this.theme.candleUp || this.theme.candle?.upColor || '#00ff00') : (this.theme.candleDown || this.theme.candle?.downColor || '#ff0000'),\n      width: 2,\n      opacity: 1\n    };\n    \n    this.lineHelper.drawRect(boxX, boxY, boxWidth, boxHeight, borderStyle);\n    \n    // Draw directional arrow\n    if (Math.abs(priceDiff) > 0.001) {\n      this.drawArrow(midX, midY, priceDiff > 0);\n    }\n  }\n  \n  /**\n   * Draw directional arrow\n   */\n  private drawArrow(x: number, y: number, isUp: boolean): void {\n    const arrowSize = 8;\n    const color = isUp ? (this.theme.candleUp || this.theme.candle?.upColor || '#00ff00') : (this.theme.candleDown || this.theme.candle?.downColor || '#ff0000');\n    \n    const style: LineStyle = {\n      color: color || '#ffffff',\n      width: 2,\n      opacity: 1\n    };\n    \n    if (isUp) {\n      // Up arrow\n      this.lineHelper.drawLine(x, y - arrowSize, x - arrowSize/2, y, style);\n      this.lineHelper.drawLine(x, y - arrowSize, x + arrowSize/2, y, style);\n    } else {\n      // Down arrow\n      this.lineHelper.drawLine(x, y + arrowSize, x - arrowSize/2, y, style);\n      this.lineHelper.drawLine(x, y + arrowSize, x + arrowSize/2, y, style);\n    }\n  }\n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n}","import type { Marker } from '@/types/marker';\nimport type { ChartData, Theme } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport type { WebGLLineHelper } from './WebGLLineHelper';\n\nexport class MarkerRenderer {\n  private coordSystem: UnifiedCoordinateSystem;\n  private theme: Theme;\n  \n  constructor(\n    coordSystem: UnifiedCoordinateSystem,\n    _lineHelper: WebGLLineHelper,  // 현재 사용하지 않지만 인터페이스 유지\n    theme: Theme\n  ) {\n    this.coordSystem = coordSystem;\n    this.theme = theme;\n  }\n  \n  /**\n   * Render all markers\n   */\n  render(\n    ctx: CanvasRenderingContext2D,\n    markers: Marker[],\n    data: ChartData | null,\n    chartWidth: number,\n    chartHeight: number\n  ): void {\n    if (!data || markers.length === 0) return;\n    \n    \n    ctx.save();\n    \n    markers.forEach(marker => {\n      this.renderMarker(ctx, marker, data, chartWidth, chartHeight);\n    });\n    \n    ctx.restore();\n  }\n  \n  /**\n   * Render a single marker\n   */\n  private renderMarker(\n    ctx: CanvasRenderingContext2D,\n    marker: Marker,\n    data: ChartData,\n    chartWidth: number,\n    chartHeight: number\n  ): void {\n    // ChartData는 TypedArray 기반이므로 times 배열에서 찾기\n    const times = data.times;\n    let candleIndex = -1;\n    \n    \n    for (let i = 0; i < times.length; i++) {\n      if (times[i] >= marker.time) {\n        candleIndex = i;\n        break;\n      }\n    }\n    \n    if (candleIndex < 0) return;\n    \n    // 캔들 데이터 구성\n    const candle = {\n      time: times[candleIndex],\n      high: data.highs[candleIndex],\n      low: data.lows[candleIndex],\n      open: data.opens[candleIndex],\n      close: data.closes[candleIndex]\n    };\n    \n    // time을 캔들 인덱스로 변환하여 X 좌표 계산\n    const x = this.coordSystem.candleIndexToPixelX(candleIndex);\n    \n    // Determine Y position\n    let y: number;\n    if (marker.price !== undefined) {\n      y = this.coordSystem.priceToCanvasY(marker.price);\n    } else {\n      // Position relative to candle\n      switch (marker.position) {\n        case 'aboveBar':\n          y = this.coordSystem.priceToCanvasY(candle.high) - 20;\n          break;\n        case 'belowBar':\n          y = this.coordSystem.priceToCanvasY(candle.low) + 20;\n          break;\n        case 'inBar':\n        default:\n          y = this.coordSystem.priceToCanvasY((candle.high + candle.low) / 2);\n          break;\n      }\n    }\n    \n    // Ensure marker is within bounds\n    if (x < 0 || x > chartWidth || y < 0 || y > chartHeight) return;\n    \n    const color = marker.color || '#FF0000';  // 기본 빨간색\n    const size = marker.size || 10;\n    \n    // Draw marker shape\n    ctx.fillStyle = color;\n    ctx.strokeStyle = color;\n    ctx.lineWidth = 1;\n    \n    switch (marker.shape) {\n      case 'circle':\n        ctx.beginPath();\n        ctx.arc(x, y, size / 2, 0, Math.PI * 2);\n        ctx.fill();\n        break;\n        \n      case 'square':\n        ctx.fillRect(x - size / 2, y - size / 2, size, size);\n        break;\n        \n      case 'arrowUp':\n        ctx.beginPath();\n        ctx.moveTo(x, y - size / 2);\n        ctx.lineTo(x - size / 2, y + size / 2);\n        ctx.lineTo(x + size / 2, y + size / 2);\n        ctx.closePath();\n        ctx.fill();\n        break;\n        \n      case 'arrowDown':\n        ctx.beginPath();\n        ctx.moveTo(x, y + size / 2);\n        ctx.lineTo(x - size / 2, y - size / 2);\n        ctx.lineTo(x + size / 2, y - size / 2);\n        ctx.closePath();\n        ctx.fill();\n        break;\n        \n      default:\n        // Default to circle\n        ctx.beginPath();\n        ctx.arc(x, y, size / 2, 0, Math.PI * 2);\n        ctx.fill();\n        break;\n    }\n    \n    // Draw text if provided\n    if (marker.text) {\n      ctx.fillStyle = marker.color || this.theme.text || '#FFFFFF';\n      ctx.font = '12px Arial, sans-serif';\n      ctx.textAlign = 'center';\n      ctx.textBaseline = marker.position === 'aboveBar' ? 'bottom' : 'top';\n      \n      const textY = marker.position === 'aboveBar' ? y - size / 2 - 5 : y + size / 2 + 5;\n      ctx.fillText(marker.text, x, textY);\n    }\n  }\n  \n  /**\n   * Update theme\n   */\n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n}","import type { Theme, DrawingObject, ChartData, ViewportState } from '@/types';\nimport type { Marker } from '@/types/marker';\nimport { WebGLRenderer } from '@/core/WebGLRenderer';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { WebGLLineHelper } from './unified/WebGLLineHelper';\nimport { CrosshairRenderer } from './unified/CrosshairRenderer';\nimport { DrawingRenderer } from './unified/DrawingRenderer';\nimport { SnapPointRenderer, type SnapPoint } from './unified/SnapPointRenderer';\nimport { MeasureRenderer } from './unified/MeasureRenderer';\nimport { MarkerRenderer } from './unified/MarkerRenderer';\n\n// Unified shader for all line rendering\nconst VERTEX_SHADER = `\nattribute vec2 a_position;\nuniform vec2 u_resolution;\n\nvoid main() {\n  // UnifiedRenderer receives Canvas pixel coordinates\n  vec2 normalized = vec2(\n    (a_position.x / u_resolution.x) * 2.0 - 1.0,\n    1.0 - (a_position.y / u_resolution.y) * 2.0\n  );\n  \n  gl_Position = vec4(normalized, 0.0, 1.0);\n}\n`;\n\nconst FRAGMENT_SHADER = `\nprecision mediump float;\nuniform vec4 u_color;\n\nvoid main() {\n  gl_FragColor = u_color;\n}\n`;\n\n/**\n * Unified renderer for crosshair, drawings, snap points, and measurements\n */\nexport class UnifiedRenderer {\n  private renderer: WebGLRenderer;\n  private theme: Theme;\n  private coordSystem: UnifiedCoordinateSystem;\n  private initialized: boolean = false;\n  \n  // Sub-renderers\n  private lineHelper!: WebGLLineHelper;\n  private crosshairRenderer!: CrosshairRenderer;\n  private drawingRenderer!: DrawingRenderer;\n  private snapPointRenderer!: SnapPointRenderer;\n  private measureRenderer!: MeasureRenderer;\n  private markerRenderer!: MarkerRenderer;\n  \n  // State\n  private mouseX: number = -1;\n  private mouseY: number = -1;\n  private snapPoint: SnapPoint | null = null;\n  private measureStart: { index: number; price: number } | null = null;\n  private measureEnd: { index: number; price: number } | null = null;\n  private measureFixed: boolean = false;\n  \n  constructor(renderer: WebGLRenderer, theme: Theme, coordSystem: UnifiedCoordinateSystem) {\n    this.renderer = renderer;\n    this.theme = theme;\n    this.coordSystem = coordSystem;\n  }\n  \n  async init(): Promise<void> {\n    // Load unified shader program\n    await this.renderer.loadShaderProgram(\n      'unified',\n      VERTEX_SHADER,\n      FRAGMENT_SHADER,\n      ['a_position'],\n      ['u_resolution', 'u_color']\n    );\n    \n    // Initialize sub-renderers\n    this.lineHelper = new WebGLLineHelper(this.renderer);\n    this.crosshairRenderer = new CrosshairRenderer(this.theme, this.coordSystem, this.lineHelper);\n    this.drawingRenderer = new DrawingRenderer(this.theme, this.coordSystem, this.lineHelper);\n    this.snapPointRenderer = new SnapPointRenderer(this.theme, this.coordSystem, this.lineHelper);\n    this.measureRenderer = new MeasureRenderer(this.theme, this.coordSystem, this.lineHelper);\n    this.markerRenderer = new MarkerRenderer(this.coordSystem, this.lineHelper, this.theme);\n    \n    this.initialized = true;\n  }\n  \n  /**\n   * Set mouse position (CSS coordinates)\n   */\n  setMousePosition(cssX: number, cssY: number): void {\n    this.mouseX = cssX;\n    this.mouseY = cssY;\n  }\n  \n  /**\n   * Set snap point\n   */\n  setSnapPoint(snap: SnapPoint | null): void {\n    this.snapPoint = snap;\n  }\n  \n  /**\n   * Set measurement points\n   */\n  setMeasure(\n    start: { index: number; price: number } | null,\n    end: { index: number; price: number } | null,\n    fixed: boolean\n  ): void {\n    this.measureStart = start;\n    this.measureEnd = end;\n    this.measureFixed = fixed;\n  }\n  \n  /**\n   * Main render method\n   */\n  render(drawings: DrawingObject[], data: ChartData, markers?: Marker[], _viewport?: ViewportState | UnifiedCoordinateSystem, verticalOnly: boolean = false): void {\n    if (!this.initialized) return;\n    \n    const gl = this.renderer.getGL();\n    \n    // Enable blending for transparency\n    gl.enable(gl.BLEND);\n    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n    \n    // Render in order of visual priority\n    \n    // 1. Drawings (bottom layer)\n    this.drawingRenderer.render(drawings);\n    \n    // 2. Measurement tool\n    if (this.measureStart) {\n      this.measureRenderer.render(this.measureStart, this.measureEnd, this.measureFixed);\n    }\n    \n    // 3. Crosshair with snap support\n    if (this.mouseX >= 0 && this.mouseY >= 0) {\n      // 스냅 포인트가 있으면 크로스헤어를 스냅 위치로 이동\n      if (this.snapPoint) {\n        // DrawingSnapManager가 이미 계산한 x, y 좌표를 직접 사용\n        const snapPoint = this.snapPoint as any;\n        if (snapPoint.x !== undefined && snapPoint.y !== undefined) {\n          // DrawingSnapManager에서 계산한 좌표를 직접 사용 (이미 CSS 좌표)\n          // crosshairRenderer는 CSS 좌표를 기대함\n          this.crosshairRenderer.render(snapPoint.x, snapPoint.y, data, verticalOnly);\n        } else {\n          // 폴백: index와 price로 계산하여 CSS 좌표로 변환\n          const candleWidth = this.coordSystem.getCandleWidth();\n          const pixelOffset = this.coordSystem.getPixelOffset();\n          const canvasX = (this.snapPoint.index + 0.5) * candleWidth + pixelOffset;\n          const canvasY = this.coordSystem.priceToCanvasY(this.snapPoint.price);\n          // Canvas 좌표를 CSS 좌표로 변환\n          const pixelRatio = this.coordSystem.getPixelRatio();\n          this.crosshairRenderer.render(canvasX / pixelRatio, canvasY / pixelRatio, data, verticalOnly);\n        }\n        // 스냅 포인트 시각적 표시 제거 - 크로스헤어만 이동\n      } else {\n        // 스냅이 없으면 마우스 위치 사용 (이미 CSS 좌표)\n        this.crosshairRenderer.render(this.mouseX, this.mouseY, data, verticalOnly);\n      }\n    }\n    \n    // Disable blending\n    gl.disable(gl.BLEND);\n    \n    // 4. Markers (Canvas 2D로 렌더링)\n    if (markers && markers.length > 0) {\n      const canvas = this.renderer.getCanvas();\n      const ctx = canvas.getContext('2d');\n      if (ctx) {\n        ctx.save();\n        // Canvas 좌표계로 스케일 조정\n        const pixelRatio = this.coordSystem.getPixelRatio();\n        ctx.scale(pixelRatio, pixelRatio);\n        \n        this.markerRenderer.render(\n          ctx,\n          markers,\n          data,\n          canvas.width / pixelRatio,\n          canvas.height / pixelRatio\n        );\n        \n        ctx.restore();\n      }\n    }\n  }\n  \n  /**\n   * Get line helper for external use\n   */\n  getLineHelper(): WebGLLineHelper {\n    return this.lineHelper;\n  }\n  \n  /**\n   * Update theme\n   */\n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n    \n    if (this.crosshairRenderer) {\n      this.crosshairRenderer.updateTheme(theme);\n    }\n    if (this.drawingRenderer) {\n      this.drawingRenderer.updateTheme(theme);\n    }\n    if (this.snapPointRenderer) {\n      this.snapPointRenderer.updateTheme(theme);\n    }\n    if (this.measureRenderer) {\n      this.measureRenderer.updateTheme(theme);\n    }\n    if (this.markerRenderer) {\n      this.markerRenderer.updateTheme(theme);\n    }\n  }\n  \n  /**\n   * Dispose resources\n   */\n  dispose(): void {\n    // Cleanup if needed\n    this.initialized = false;\n  }\n}","import type { Theme, ChartType, ChartOptions, ChartData, IndicatorConfig } from '@/types';\nimport type { WebGLRenderer } from '@/core/WebGLRenderer';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport type { LineSeries } from '@/core/LineSeriesManager';\nimport type { StopLossManager } from '@/core/StopLossManager';\nimport { UnifiedChartRenderer } from '@/rendering/UnifiedChartRenderer';\nimport { GridRenderer } from '@/renderers/GridRenderer';\nimport { LabelRenderer } from '@/renderers/LabelRenderer';\nimport { CrosshairLabelRenderer } from '@/renderers/CrosshairLabelRenderer';\nimport { LineSeriesRenderer } from '@/renderers/LineSeriesRenderer';\nimport { UnifiedRenderer } from '@/renderers/UnifiedRenderer';\n\nexport class ChartRendererManager {\n  private unifiedChartRenderer!: UnifiedChartRenderer;\n  private gridRenderer!: GridRenderer;\n  private labelRenderer!: LabelRenderer;\n  private lineSeriesRenderer!: LineSeriesRenderer;\n  private crosshairLabelRenderer!: CrosshairLabelRenderer;\n  private unifiedRenderer!: UnifiedRenderer;\n  private _chartType: ChartType = 'candle';  // setChartType에서 사용\n  \n  constructor(\n    private renderer: WebGLRenderer,\n    private container: HTMLElement,\n    private theme: Theme,\n    private coordSystem: UnifiedCoordinateSystem,\n    private options: Partial<ChartOptions> = {}\n  ) {}\n  \n  async init(): Promise<void> {\n    // WebGL 캔버스 가져오기\n    const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    \n    // UnifiedChartRenderer 생성\n    this.unifiedChartRenderer = new UnifiedChartRenderer(canvas, this.theme, this.options as ChartOptions);\n    \n    // 그리드 렌더러 (아직 통합되지 않음)\n    this.gridRenderer = new GridRenderer(this.renderer, this.theme);\n    await this.gridRenderer.init();\n    \n    // 라벨 렌더러 (DOM 기반이므로 유지)\n    this.labelRenderer = new LabelRenderer(this.container, this.theme, this.options as ChartOptions);\n    \n    // UnifiedRenderer 초기화 (드로잉, 크로스헤어 등을 위해 임시 유지)\n    this.unifiedRenderer = new UnifiedRenderer(this.renderer, this.theme, this.coordSystem);\n    await this.unifiedRenderer.init();\n    \n    // 라인 시리즈 렌더러 (Canvas 2D 기반이므로 유지)\n    const overlayCanvas = document.createElement('canvas');\n    overlayCanvas.width = canvas.width;\n    overlayCanvas.height = canvas.height;\n    overlayCanvas.style.position = 'absolute';\n    overlayCanvas.style.left = '0';\n    overlayCanvas.style.top = '0';\n    overlayCanvas.style.pointerEvents = 'none';\n    this.container.appendChild(overlayCanvas);\n    \n    const ctx = overlayCanvas.getContext('2d');\n    if (!ctx) throw new Error('Failed to get 2D context');\n    \n    this.lineSeriesRenderer = new LineSeriesRenderer(ctx, this.theme, this.options as ChartOptions);\n    \n    // 크로스헤어 라벨 렌더러\n    this.crosshairLabelRenderer = new CrosshairLabelRenderer(\n      this.container,\n      this.theme,\n      this.coordSystem\n    );\n    \n    // Grid show 옵션 적용\n    if (this.options.grid?.show !== undefined) {\n      this.gridRenderer.setShowGrid(this.options.grid.show);\n    }\n  }\n  \n  // 통합 렌더링 메서드\n  renderMain(\n    data: ChartData,\n    indicators: Map<string, any>,  // IndicatorData로 변경\n    stopLossLines: Array<{ id: string; price: number; options?: any }>,\n    markers: any[]\n  ): void {\n    // 렌더 데이터 준비\n    const renderData = {\n      candles: {\n        visible: true,\n        data: data\n      },\n      indicators: {\n        visible: indicators.size > 0,\n        data: Array.from(indicators.values())\n      },\n      stopLoss: {\n        visible: stopLossLines.length > 0,\n        data: stopLossLines\n      },\n      markers: {\n        visible: markers.length > 0,\n        data: markers\n      }\n    };\n    \n    // 통합 렌더러로 렌더링\n    this.unifiedChartRenderer.render(renderData, this.coordSystem);\n  }\n  \n  // 기존 호환성을 위한 메서드들\n  getCandleRenderer(): any {\n    // 호환성을 위한 더미 객체 반환\n    return {\n      setChartType: (type: ChartType) => { this.setChartType(type); },\n      render: () => { /* UnifiedChartRenderer에서 처리 */ },\n      updateTheme: (theme: Theme) => { this.unifiedChartRenderer.updateTheme(theme); }\n    };\n  }\n  \n  setChartType(type: ChartType): void {\n    this._chartType = type;\n    // UnifiedChartRenderer에 차트 타입 변경 전달\n    if (this.unifiedChartRenderer) {\n      this.unifiedChartRenderer.setChartType(type);\n    }\n  }\n  \n  getGridRenderer(): GridRenderer {\n    return this.gridRenderer;\n  }\n  \n  getUnifiedRenderer(): UnifiedRenderer {\n    return this.unifiedRenderer;\n  }\n  \n  getIndicatorRenderer(): any {\n    // 호환성을 위한 더미 객체 반환\n    return {\n      render: () => { /* UnifiedChartRenderer에서 처리 */ },\n      updateTheme: () => { /* UnifiedChartRenderer에서 처리 */ }\n    };\n  }\n  \n  getLabelRenderer(): LabelRenderer {\n    return this.labelRenderer;\n  }\n  \n  getLineSeriesRenderer(): LineSeriesRenderer {\n    return this.lineSeriesRenderer;\n  }\n  \n  getStopLossRenderer(): any {\n    // 호환성을 위한 더미 객체 반환\n    return {\n      render: () => { /* UnifiedChartRenderer에서 처리 */ },\n      updateTheme: () => { /* UnifiedChartRenderer에서 처리 */ }\n    };\n  }\n  \n  getCrosshairLabelRenderer(): CrosshairLabelRenderer {\n    return this.crosshairLabelRenderer;\n  }\n  \n  updateOptions(options: Partial<ChartOptions>): void {\n    this.options = { ...this.options, ...options };\n    \n    // 그리드 설정 업데이트\n    if (options.grid !== undefined) {\n      this.gridRenderer.updateOptions({ grid: options.grid });\n    }\n    \n    // UnifiedChartRenderer 옵션 업데이트\n    if (this.unifiedChartRenderer) {\n      // 차트 타입 업데이트\n      if (options.chartType) {\n        this.unifiedChartRenderer.setChartType(options.chartType);\n      }\n    }\n  }\n  \n  setStopLossManager(_manager: StopLossManager | null): void {\n    // No-op\n  }\n  \n  renderLineSeries(series: LineSeries[], coordSystem: UnifiedCoordinateSystem): void {\n    const viewportState = coordSystem.getState();\n    const viewport = {\n      visibleRange: {\n        startTime: viewportState.startTime,\n        endTime: viewportState.endTime\n      },\n      priceScale: coordSystem.getPriceScale(),\n      timeToX: (time: number, _width: number) => {\n        const canvasX = coordSystem.timeToCanvasX(time);\n        return canvasX / coordSystem.getPixelRatio();\n      },\n      priceToY: (price: number, _height: number) => {\n        const canvasY = coordSystem.priceToCanvasY(price);\n        return canvasY / coordSystem.getPixelRatio();\n      }\n    };\n    \n    const width = this.renderer.getWidth() / coordSystem.getPixelRatio();\n    const height = this.renderer.getHeight() / coordSystem.getPixelRatio();\n    \n    const canvas = this.lineSeriesRenderer['ctx'].canvas;\n    const pixelRatio = coordSystem.getPixelRatio();\n    \n    if (canvas.width !== width * pixelRatio || canvas.height !== height * pixelRatio) {\n      canvas.width = width * pixelRatio;\n      canvas.height = height * pixelRatio;\n      canvas.style.width = `${width}px`;\n      canvas.style.height = `${height}px`;\n      this.lineSeriesRenderer['ctx'].scale(pixelRatio, pixelRatio);\n    }\n    \n    // @ts-ignore - LineSeriesRenderer.render 시그니처 불일치 문제\n    this.lineSeriesRenderer.render(series, viewport, width, height);\n  }\n  \n  updateCandleColors(theme: Theme): void {\n    this.unifiedChartRenderer.updateTheme(theme);\n  }\n  \n  updateTheme(theme: Theme, _options?: Partial<ChartOptions>): void {\n    this.theme = theme;\n    this.unifiedChartRenderer.updateTheme(theme);\n    this.gridRenderer.updateTheme(theme);\n    this.labelRenderer.updateTheme(theme);\n    this.lineSeriesRenderer.updateTheme(theme);\n    this.unifiedRenderer.updateTheme(theme);\n    this.crosshairLabelRenderer.updateTheme(theme);\n  }\n  \n  resize(): void {\n    const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    this.unifiedChartRenderer.resize(canvas.width, canvas.height);\n  }\n  \n  dispose(): void {\n    this.unifiedChartRenderer.dispose();\n  }\n}","import type { ChartPoint, DrawingObject, DrawingUpdateOptions, MarkerType } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\nexport class ChartUIManager {\n  private canvas: HTMLCanvasElement;\n  \n  constructor(\n    canvas: HTMLCanvasElement,\n    private coordSystem: UnifiedCoordinateSystem\n  ) {\n    this.canvas = canvas;\n  }\n  \n  showTextInput(point: ChartPoint, callback: (text: string) => void): void {\n    // 텍스트 입력 패널\n    const existingPanel = document.getElementById('text-input-panel');\n    if (existingPanel) {\n      existingPanel.remove();\n    }\n    \n    const canvasPos = this.coordSystem.chartToCanvas(point.time, point.price);\n    const cssPos = this.coordSystem.canvasToCSS(canvasPos.x, canvasPos.y);\n    const rect = this.canvas.getBoundingClientRect();\n    \n    const panel = document.createElement('div');\n    panel.id = 'text-input-panel';\n    panel.style.cssText = `\n      position: fixed;\n      left: ${rect.left + cssPos.x}px;\n      top: ${rect.top + cssPos.y}px;\n      background: #1e1e1e;\n      border: 1px solid #333;\n      border-radius: 4px;\n      padding: 8px;\n      z-index: 10000;\n      font-family: Arial, sans-serif;\n      font-size: 14px;\n      color: #ccc;\n      box-shadow: 0 4px 8px rgba(0,0,0,0.3);\n    `;\n    \n    panel.innerHTML = `\n      <input id=\"text-input\" type=\"text\" placeholder=\"텍스트 입력...\" style=\"width: 200px; padding: 6px; background: #2a2a2a; color: #ccc; border: 1px solid #333; border-radius: 2px;\">\n    `;\n    \n    document.body.appendChild(panel);\n    \n    const input = panel.querySelector('#text-input') as HTMLInputElement;\n    \n    const save = () => {\n      const text = input.value.trim();\n      if (text) {\n        callback(text);\n      }\n      panel.remove();\n    };\n    \n    const cancel = () => {\n      panel.remove();\n    };\n    \n    input.addEventListener('keydown', (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        save();\n      } else if (e.key === 'Escape') {\n        e.preventDefault();\n        cancel();\n      }\n    });\n    \n    input.addEventListener('blur', () => {\n      // 포커스를 잃으면 잠시 후 저장\n      setTimeout(save, 200);\n    });\n    \n    input.focus();\n  }\n  \n  showTextEdit(drawing: DrawingObject, x: number, y: number, onUpdate: (text: string) => void): void {\n    const existingPanel = document.getElementById('text-edit-panel');\n    if (existingPanel) {\n      existingPanel.remove();\n    }\n    \n    const panel = document.createElement('div');\n    panel.id = 'text-edit-panel';\n    panel.style.cssText = `\n      position: fixed;\n      left: ${x}px;\n      top: ${y}px;\n      background: #1e1e1e;\n      border: 1px solid #333;\n      border-radius: 4px;\n      padding: 8px;\n      z-index: 10000;\n    `;\n    \n    const input = document.createElement('input');\n    input.type = 'text';\n    input.value = drawing.text || '';\n    input.style.cssText = `\n      width: 200px;\n      padding: 6px;\n      background: #2a2a2a;\n      color: #ccc;\n      border: 1px solid #333;\n      border-radius: 2px;\n    `;\n    \n    const save = () => {\n      onUpdate(input.value);\n      panel.remove();\n    };\n    \n    const cancel = () => {\n      panel.remove();\n    };\n    \n    input.addEventListener('keydown', (e) => {\n      if (e.key === 'Enter') save();\n      else if (e.key === 'Escape') cancel();\n    });\n    \n    input.addEventListener('blur', () => {\n      setTimeout(save, 200);\n    });\n    \n    panel.appendChild(input);\n    document.body.appendChild(panel);\n    input.focus();\n    input.select();\n  }\n  \n  showMarkerConfig(drawing: DrawingObject, x: number, y: number, onUpdate: (updates: DrawingUpdateOptions) => void): void {\n    // 임시 설정 패널 (나중에 전용 UI 컴포넌트로 대체)\n    const existingPanel = document.getElementById('marker-config-panel');\n    if (existingPanel) {\n      existingPanel.remove();\n    }\n    \n    const panel = document.createElement('div');\n    panel.id = 'marker-config-panel';\n    panel.style.cssText = `\n      position: fixed;\n      left: ${x}px;\n      top: ${y}px;\n      background: #1e1e1e;\n      border: 1px solid #333;\n      border-radius: 4px;\n      padding: 12px;\n      z-index: 10000;\n      font-family: Arial, sans-serif;\n      font-size: 14px;\n      color: #ccc;\n      box-shadow: 0 4px 8px rgba(0,0,0,0.3);\n    `;\n    \n    panel.innerHTML = `\n      <div style=\"margin-bottom: 8px;\">\n        <label style=\"display: block; margin-bottom: 4px;\">형태:</label>\n        <select id=\"marker-type\" style=\"width: 150px; padding: 4px; background: #2a2a2a; color: #ccc; border: 1px solid #333; border-radius: 2px;\">\n          <option value=\"arrowUp\" ${drawing.markerType === 'arrowUp' ? 'selected' : ''}>위쪽 화살표</option>\n          <option value=\"arrowDown\" ${drawing.markerType === 'arrowDown' ? 'selected' : ''}>아래쪽 화살표</option>\n          <option value=\"triangleUp\" ${drawing.markerType === 'triangleUp' ? 'selected' : ''}>위쪽 삼각형</option>\n          <option value=\"triangleDown\" ${drawing.markerType === 'triangleDown' ? 'selected' : ''}>아래쪽 삼각형</option>\n        </select>\n      </div>\n      <div style=\"margin-bottom: 8px;\">\n        <label style=\"display: block; margin-bottom: 4px;\">텍스트:</label>\n        <input id=\"marker-text\" type=\"text\" value=\"${drawing.text || ''}\" style=\"width: 150px; padding: 4px; background: #2a2a2a; color: #ccc; border: 1px solid #333; border-radius: 2px;\">\n      </div>\n      <div style=\"display: flex; gap: 8px; margin-top: 12px;\">\n        <button id=\"marker-save\" style=\"padding: 4px 12px; background: #2962ff; color: white; border: none; border-radius: 2px; cursor: pointer;\">저장</button>\n        <button id=\"marker-cancel\" style=\"padding: 4px 12px; background: #444; color: white; border: none; border-radius: 2px; cursor: pointer;\">취소</button>\n      </div>\n    `;\n    \n    document.body.appendChild(panel);\n    \n    // 이벤트 핸들러\n    const saveBtn = panel.querySelector('#marker-save') as HTMLButtonElement;\n    const cancelBtn = panel.querySelector('#marker-cancel') as HTMLButtonElement;\n    const typeSelect = panel.querySelector('#marker-type') as HTMLSelectElement;\n    const textInput = panel.querySelector('#marker-text') as HTMLInputElement;\n    \n    const save = () => {\n      onUpdate({\n        markerType: typeSelect.value as MarkerType,\n        text: textInput.value\n      });\n      panel.remove();\n    };\n    \n    const cancel = () => {\n      panel.remove();\n    };\n    \n    saveBtn.addEventListener('click', save);\n    cancelBtn.addEventListener('click', cancel);\n    \n    // Enter로 저장, ESC로 취소\n    textInput.addEventListener('keydown', (e) => {\n      if (e.key === 'Enter') save();\n      else if (e.key === 'Escape') cancel();\n    });\n    \n    textInput.focus();\n  }\n  \n  showDrawingConfig(drawing: DrawingObject, x: number, y: number, onUpdate: (updates: DrawingUpdateOptions) => void, onDelete: () => void): void {\n    const existingPanel = document.getElementById('drawing-config-panel');\n    if (existingPanel) {\n      existingPanel.remove();\n    }\n    \n    const panel = document.createElement('div');\n    panel.id = 'drawing-config-panel';\n    panel.style.cssText = `\n      position: fixed;\n      left: ${x}px;\n      top: ${y}px;\n      background: #1e1e1e;\n      border: 1px solid #333;\n      border-radius: 4px;\n      padding: 12px;\n      z-index: 10000;\n      font-family: Arial, sans-serif;\n      font-size: 14px;\n      color: #ccc;\n      box-shadow: 0 4px 8px rgba(0,0,0,0.3);\n    `;\n    \n    panel.innerHTML = `\n      <div style=\"margin-bottom: 12px; font-weight: bold;\">${drawing.type.charAt(0).toUpperCase() + drawing.type.slice(1)} 설정</div>\n      <div style=\"margin-bottom: 8px;\">\n        <label style=\"display: block; margin-bottom: 4px;\">색상:</label>\n        <input id=\"drawing-color\" type=\"color\" value=\"${drawing.style.color}\" style=\"width: 100%; height: 30px; background: #2a2a2a; border: 1px solid #333; border-radius: 2px; cursor: pointer;\">\n      </div>\n      <div style=\"margin-bottom: 8px;\">\n        <label style=\"display: block; margin-bottom: 4px;\">선 굵기:</label>\n        <input id=\"drawing-width\" type=\"range\" min=\"1\" max=\"10\" value=\"${drawing.style.lineWidth}\" style=\"width: 100%;\">\n        <span id=\"width-value\" style=\"font-size: 12px; color: #999;\">${drawing.style.lineWidth}px</span>\n      </div>\n      <div style=\"margin-bottom: 8px;\">\n        <label style=\"display: block; margin-bottom: 4px;\">투명도:</label>\n        <input id=\"drawing-opacity\" type=\"range\" min=\"0\" max=\"100\" value=\"${drawing.style.opacity * 100}\" style=\"width: 100%;\">\n        <span id=\"opacity-value\" style=\"font-size: 12px; color: #999;\">${Math.round(drawing.style.opacity * 100)}%</span>\n      </div>\n      <div style=\"display: flex; gap: 8px; margin-top: 12px;\">\n        <button id=\"drawing-save\" style=\"padding: 4px 12px; background: #2962ff; color: white; border: none; border-radius: 2px; cursor: pointer;\">저장</button>\n        <button id=\"drawing-delete\" style=\"padding: 4px 12px; background: #f44336; color: white; border: none; border-radius: 2px; cursor: pointer;\">삭제</button>\n        <button id=\"drawing-cancel\" style=\"padding: 4px 12px; background: #444; color: white; border: none; border-radius: 2px; cursor: pointer;\">취소</button>\n      </div>\n    `;\n    \n    document.body.appendChild(panel);\n    \n    // 이벤트 핸들러\n    const colorInput = panel.querySelector('#drawing-color') as HTMLInputElement;\n    const widthInput = panel.querySelector('#drawing-width') as HTMLInputElement;\n    const widthValue = panel.querySelector('#width-value') as HTMLElement;\n    const opacityInput = panel.querySelector('#drawing-opacity') as HTMLInputElement;\n    const opacityValue = panel.querySelector('#opacity-value') as HTMLElement;\n    const saveBtn = panel.querySelector('#drawing-save') as HTMLButtonElement;\n    const deleteBtn = panel.querySelector('#drawing-delete') as HTMLButtonElement;\n    const cancelBtn = panel.querySelector('#drawing-cancel') as HTMLButtonElement;\n    \n    widthInput.addEventListener('input', () => {\n      widthValue.textContent = `${widthInput.value}px`;\n    });\n    \n    opacityInput.addEventListener('input', () => {\n      opacityValue.textContent = `${opacityInput.value}%`;\n    });\n    \n    const save = () => {\n      onUpdate({\n        style: {\n          color: colorInput.value,\n          lineWidth: parseInt(widthInput.value),\n          opacity: parseInt(opacityInput.value) / 100\n        }\n      });\n      panel.remove();\n    };\n    \n    const deleteDrawing = () => {\n      onDelete();\n      panel.remove();\n    };\n    \n    const cancel = () => {\n      panel.remove();\n    };\n    \n    saveBtn.addEventListener('click', save);\n    deleteBtn.addEventListener('click', deleteDrawing);\n    cancelBtn.addEventListener('click', cancel);\n  }\n  \n  dispose(): void {\n    // 모든 열린 패널 제거\n    const panels = ['text-input-panel', 'text-edit-panel', 'marker-config-panel', 'drawing-config-panel'];\n    panels.forEach(id => {\n      const panel = document.getElementById(id);\n      if (panel) {\n        panel.remove();\n      }\n    });\n  }\n}","import type { ChartData, Theme, ChartType, ChartOptions } from '@/types';\nimport { ChartPanel } from '@/core/ChartPanel';\nimport { WebGLRenderer } from '@/core/WebGLRenderer';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { DrawingManager } from '@/core/DrawingManager';\nimport { DataManager } from '@/core/DataManager';\nimport { MarkerManager } from '@/core/MarkerManager';\nimport { LineSeriesManager } from '@/core/LineSeriesManager';\nimport { StopLossManager } from '@/core/StopLossManager';\nimport { ChartEventController } from './chart/ChartEventController';\nimport { ChartRendererManager } from './chart/ChartRendererManager';\nimport { ChartUIManager } from './chart/ChartUIManager';\n// import { ChartInteractionHandler } from './chart/ChartInteractionHandler';  // 필요시 활성화\n\nexport class MainChartPanel extends ChartPanel {\n  protected coordSystem: UnifiedCoordinateSystem;\n  private drawingManager: DrawingManager;\n  private dataManager: DataManager;\n  private markerManager: MarkerManager | null;\n  private lineSeriesManager: LineSeriesManager | null;\n  private stopLossManager: StopLossManager | null;\n  private theme: Theme;\n  private options: Partial<ChartOptions> = {};\n  \n  // 마우스 X 위치 콜백\n  private onMouseXChange?: (x: number) => void;\n  \n  // 컴포넌트들\n  private eventController!: ChartEventController;\n  private rendererManager!: ChartRendererManager;\n  private uiManager!: ChartUIManager;\n  // private _interactionHandler!: ChartInteractionHandler; // 확장성을 위해 보관\n  \n  private chartType: ChartType = 'candle';\n  \n  constructor(\n    container: HTMLElement,\n    theme: Theme,\n    _renderer: WebGLRenderer | null,\n    coordSystem: UnifiedCoordinateSystem | null,\n    drawingManager: DrawingManager,\n    dataManager: DataManager,\n    markerManager: MarkerManager | null,\n    lineSeriesManager: LineSeriesManager | null,\n    stopLossManager: StopLossManager | null,\n    options?: Partial<ChartOptions>\n  ) {\n    super(container, { height: container.clientHeight });\n    \n    this.theme = theme;\n    this.options = options || {};\n    this.drawingManager = drawingManager;\n    this.dataManager = dataManager;\n    this.markerManager = markerManager;\n    this.lineSeriesManager = lineSeriesManager;\n    this.stopLossManager = stopLossManager;\n    \n    // 전달받은 좌표계 사용, 없으면 새로 생성\n    if (coordSystem) {\n      // console.log('[MainChartPanel] Using shared coordinate system:', coordSystem);\n      this.coordSystem = coordSystem;\n    } else {\n      // console.log('[MainChartPanel] Creating new coordinate system');\n      this.coordSystem = new UnifiedCoordinateSystem(\n        this.renderer.getWidth(),\n        this.renderer.getHeight(),\n        this.renderer.getPixelRatio()\n      );\n      // DataManager 설정 (타임스탬프 변환용)\n      this.coordSystem.setDataManager(this.dataManager);\n    }\n    \n    // 메인 패널로 설정\n    this.coordSystem.setCurrentPanel('main');\n    \n    // 패널 높이 설정 (WebGLRenderer의 실제 높이 사용)\n    // init() 후에 설정되므로 일단 임시값 설정\n    const pixelRatio = this.renderer.getPixelRatio();\n    this.coordSystem.setPanelHeight('main', container.clientHeight * pixelRatio);\n  }\n  \n  async init(): Promise<void> {\n    await super.init();\n    \n    // WebGLRenderer 초기화 후 실제 높이로 업데이트\n    this.coordSystem.setPanelHeight('main', this.renderer.getHeight());\n    \n    // 컴포넌트 초기화\n    this.rendererManager = new ChartRendererManager(\n      this.renderer,\n      this.container,\n      this.theme,\n      this.coordSystem,\n      this.options\n    );\n    \n    await this.rendererManager.init();\n    \n    const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    this.uiManager = new ChartUIManager(canvas, this.coordSystem);\n    // this._interactionHandler = new ChartInteractionHandler(\n    //   this.drawingManager,\n    //   this.uiManager\n    // );\n    \n    // DrawingManager에 컨테이너와 좌표계 설정 (텍스트 렌더러용)\n    this.drawingManager.setContainerAndCoordSystem(this.container, this.coordSystem);\n    \n    // 이벤트 컨트롤러 초기화\n    this.eventController = new ChartEventController(\n      canvas,\n      this.coordSystem,\n      this.drawingManager,\n      this.dataManager,\n      this.rendererManager.getUnifiedRenderer(),\n      this.rendererManager.getLabelRenderer(),\n      {\n        onMouseMove: this.handleMouseMove.bind(this),\n        onMouseLeave: this.handleMouseLeave.bind(this)\n      }\n    );\n    \n    // 옵션에 cursorType이 있다면 설정\n    if (this.options.cursorType) {\n      this.eventController.setCursorType(this.options.cursorType);\n    }\n    \n    // 드로잉 매니저 콜백 설정\n    this.setupDrawingCallbacks();\n  }\n  \n  private setupDrawingCallbacks(): void {\n    // 스냅 변경 콜백\n    this.drawingManager.setSnapChangeCallback((snap) => {\n      if (snap) {\n        // DrawingSnapManager의 SnapPoint를 SnapPointRenderer의 형식으로 변환\n        // x, y 좌표도 함께 전달\n        this.rendererManager.getUnifiedRenderer()?.setSnapPoint({\n          index: snap.index,\n          price: snap.price,\n          type: snap.type,\n          x: snap.x,\n          y: snap.y\n        } as any);\n      } else {\n        this.rendererManager.getUnifiedRenderer()?.setSnapPoint(null);\n      }\n    });\n    \n    // 가격 비교 변경 콜백\n    this.drawingManager.setMeasureChangeCallback((start, end, fixed) => {\n      const measureStart = start ? { index: start.time, price: start.price } : null;\n      const measureEnd = end ? { index: end.time, price: end.price } : null;\n      \n      this.rendererManager.getUnifiedRenderer()?.setMeasure(\n        measureStart,\n        measureEnd,\n        fixed\n      );\n      \n      // 툴팁 표시/숨기기\n      if (measureStart && measureEnd) {\n        const endCanvas = this.coordSystem.chartToCanvas(measureEnd.index, measureEnd.price);\n        const endCSS = this.coordSystem.canvasToCSS(endCanvas.x, endCanvas.y);\n        this.rendererManager.getLabelRenderer().showMeasureTooltip(\n          measureStart.price,\n          measureEnd.price,\n          endCSS.x,\n          endCSS.y\n        );\n      } else {\n        this.rendererManager.getLabelRenderer().hideMeasureTooltip();\n      }\n    });\n  }\n  \n  private handleMouseMove(x: number, _y: number, _chartCoords: { time: number; price: number }): void {\n    // 마우스 X 위치를 다른 패널로 전파\n    if (this.onMouseXChange) {\n      this.onMouseXChange(x);\n    }\n  }\n  \n  private handleMouseLeave(): void {\n    // 마우스가 나갔을 때 다른 패널로도 전파\n    if (this.onMouseXChange) {\n      this.onMouseXChange(-1);\n    }\n  }\n  \n  /**\n   * 마우스 X 위치 변경 콜백 설정\n   */\n  setMouseXChangeCallback(callback: (x: number) => void): void {\n    this.onMouseXChange = callback;\n  }\n  \n  // UI 메서드들은 ChartUIManager로 이동됨\n  \n  render(data: ChartData, indicators?: Map<string, any>): void {\n    // 메인 패널로 전환\n    this.coordSystem.setCurrentPanel('main');\n    \n    const visibleRange = this.coordSystem.getVisibleRange();\n    \n    // 보이는 범위의 실제 가격 범위 계산\n    let minPrice = Infinity;\n    let maxPrice = -Infinity;\n    \n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      const high = data.highs[i];\n      const low = data.lows[i];\n      if (high > maxPrice) maxPrice = high;\n      if (low < minPrice) minPrice = low;\n    }\n    \n    // 인디케이터 값도 가격 범위에 포함\n    if (indicators) {\n      indicators.forEach((indicator) => {\n        if (indicator.values && indicator.visible) {\n          for (let i = visibleRange.start; i <= visibleRange.end && i < indicator.values.length; i++) {\n            const value = indicator.values[i];\n            if (!isNaN(value)) {\n              if (value > maxPrice) maxPrice = value;\n              if (value < minPrice) minPrice = value;\n            }\n          }\n        }\n      });\n    }\n    \n    // 가격 범위가 유효한 경우만 업데이트 (main 패널의 범위로)\n    if (minPrice < Infinity && maxPrice > -Infinity) {\n      this.coordSystem.setPriceRange(minPrice, maxPrice, 'main');\n    }\n    \n    // 화면 지우기\n    this.renderer.clear(this.theme.background);\n    \n    // 그리드는 아직 통합 안 됨\n    this.rendererManager.getGridRenderer().render(data, this.coordSystem);\n    \n    // 통합 렌더러로 캔들, 인디케이터, 스톱로스, 마커 렌더링\n    const stopLossLines = this.stopLossManager ? this.stopLossManager.getStopLossLines() : [];\n    const markers = this.markerManager ? this.markerManager.getMarkers() : [];\n    \n    this.rendererManager.renderMain(\n      data,\n      indicators || new Map(),\n      stopLossLines,\n      markers\n    );\n    \n    // 라인 시리즈 렌더링 (Canvas 2D 기반이므로 별도)\n    if (this.lineSeriesManager) {\n      const lineSeries = this.lineSeriesManager.getVisibleSeries();\n      if (lineSeries.length > 0) {\n        this.rendererManager.renderLineSeries(lineSeries, this.coordSystem);\n      }\n    }\n    \n    // 통합 렌더러로 크로스헤어, 드로잉, 스냅 렌더링\n    this.rendererManager.getUnifiedRenderer().render(this.drawingManager.getAllDrawings(), data, [], this.coordSystem);\n    \n    // 텍스트 렌더링 업데이트 (DOM 기반)\n    this.drawingManager.updateTextRendering();\n    \n    // 마우스 위치 가져오기\n    const mousePos = this.eventController.getLastMousePosition();\n    \n    // 크로스헤어 라벨 렌더링\n    if (mousePos.x >= 0 && mousePos.y >= 0) {\n      this.rendererManager.getCrosshairLabelRenderer().render(mousePos.x, mousePos.y, data);\n    }\n    \n    // 레이블 렌더링\n    const labelData = {\n      price: mousePos.y >= 0 ? this.coordSystem.canvasYToPrice(mousePos.y * this.coordSystem.getPixelRatio(), 'main') : -1,\n      time: mousePos.x >= 0 ? this.coordSystem.canvasXToCandleIndex(mousePos.x * this.coordSystem.getPixelRatio()) : -1,\n      candle: null as any\n    };\n    \n    if (labelData.time >= 0 && labelData.time < data.length) {\n      labelData.candle = {\n        time: data.times[Math.round(labelData.time)],\n        open: data.opens[Math.round(labelData.time)],\n        high: data.highs[Math.round(labelData.time)],\n        low: data.lows[Math.round(labelData.time)],\n        close: data.closes[Math.round(labelData.time)],\n        volume: data.volumes[Math.round(labelData.time)]\n      };\n    }\n    \n    this.rendererManager.getLabelRenderer().render(\n      data,\n      this.coordSystem,\n      labelData.price,\n      labelData.time,\n      labelData.candle\n    );\n  }\n  \n  setChartType(type: ChartType): void {\n    this.chartType = type;\n    this.rendererManager.setChartType(type);\n  }\n  \n  getChartType(): ChartType {\n    return this.chartType;\n  }\n  \n  resize(width?: number, height?: number): void {\n    super.resize(width, height);\n    \n    // WebGLRenderer의 실제 높이로 업데이트\n    this.coordSystem.setPanelHeight('main', this.renderer.getHeight());\n  }\n  \n  updateTheme(theme: Theme, options?: Partial<ChartOptions>): void {\n    super.updateTheme(theme);\n    this.theme = theme;\n    if (options) {\n      this.options = options;\n    }\n    this.rendererManager.updateTheme(theme, options);\n  }\n  \n  /**\n   * 캔들 색상 업데이트\n   */\n  updateCandleColors(theme: Theme): void {\n    this.theme = theme;\n    this.rendererManager.updateCandleColors(theme);\n  }\n  \n  updateOptions(options: Partial<ChartOptions>): void {\n    this.options = { ...this.options, ...options };\n    \n    // 그리드 설정 업데이트\n    if (options.grid !== undefined) {\n      this.rendererManager.getGridRenderer().updateOptions({ grid: options.grid });\n    }\n    \n    // 렌더러 매니저에 옵션 전달\n    if (this.rendererManager && 'updateOptions' in this.rendererManager) {\n      this.rendererManager.updateOptions(options);\n    }\n    \n    // 다시 렌더링 요청\n    this.requestRender();\n  }\n  \n  \n  getViewport(): UnifiedCoordinateSystem {\n    // UnifiedCoordinateSystem을 viewport로 반환\n    return this.coordSystem;\n  }\n\n  dispose(): void {\n    this.eventController.dispose();\n    this.rendererManager.dispose();\n    this.uiManager.dispose();\n    this.drawingManager.dispose(); // 텍스트 렌더러 정리\n    super.dispose();\n  }\n}","import type { ChartData } from '@/types';\r\n\r\n/**\r\n * 볼륨 이동평균 계산\r\n * @param data 차트 데이터\r\n * @param period 이동평균 기간\r\n * @returns 볼륨 이동평균 배열\r\n */\r\nexport function calculateVolumeMA(data: ChartData, period: number): Float32Array {\r\n  const result = new Float32Array(data.length);\r\n  \r\n  for (let i = 0; i < data.length; i++) {\r\n    if (i < period - 1) {\r\n      // 기간이 부족한 경우 0으로 설정\r\n      result[i] = 0;\r\n    } else {\r\n      // 이동평균 계산\r\n      let sum = 0;\r\n      for (let j = 0; j < period; j++) {\r\n        sum += data.volumes[i - j];\r\n      }\r\n      result[i] = sum / period;\r\n    }\r\n  }\r\n  \r\n  return result;\r\n}","import type { Theme, ChartOptions, ChartData } from '@/types';\nimport type { RenderLayer } from '@/rendering/UnifiedChartRenderer';\nimport type { WebGLRenderer } from '@/core/WebGLRenderer';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { UnifiedChartRenderer } from '@/rendering/UnifiedChartRenderer';\nimport { GridRenderer } from '@/renderers/GridRenderer';\nimport { UnifiedRenderer } from '@/renderers/UnifiedRenderer';\nimport { calculateVolumeMA } from '@/utils/volumeMA';\n\nexport class VolumeRendererManager {\n  private unifiedChartRenderer!: UnifiedChartRenderer;\n  private gridRenderer!: GridRenderer;\n  private unifiedRenderer!: UnifiedRenderer;\n  \n  constructor(\n    private renderer: WebGLRenderer,\n    private _container: HTMLElement,  // 나중에 UI 확장 시 사용\n    private theme: Theme,\n    private coordSystem: UnifiedCoordinateSystem,\n    private options: Partial<ChartOptions> = {}\n  ) {}\n  \n  async init(): Promise<void> {\n    // WebGL 캔버스 가져오기\n    const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    \n    // UnifiedChartRenderer 생성\n    this.unifiedChartRenderer = new UnifiedChartRenderer(canvas, this.theme, this.options as ChartOptions);\n    \n    // 그리드 렌더러 (아직 통합되지 않음)\n    this.gridRenderer = new GridRenderer(this.renderer, this.theme);\n    await this.gridRenderer.init();\n    \n    // UnifiedRenderer 초기화 (크로스헤어를 위해 임시 유지)\n    this.unifiedRenderer = new UnifiedRenderer(this.renderer, this.theme, this.coordSystem);\n    await this.unifiedRenderer.init();\n    \n    // Grid show 옵션 적용\n    const grid = this.options.panels?.volume?.grid;\n    if (grid === false || (typeof grid === 'object' && grid?.show === false)) {\n      this.gridRenderer.setShowGrid(false);\n    }\n  }\n  \n  // 통합 렌더링 메서드\n  renderVolume(\n    data: ChartData,\n    _visibleRange: { start: number; end: number },\n    _mouseX: number,\n    _mouseY: number\n  ): void {\n    // 볼륨 MA 계산\n    let volumeMAData: Float32Array | null = null;\n    const volumeOptions = this.options.panels?.volume;\n    \n    if (volumeOptions?.showMA && volumeOptions?.maLength) {\n      volumeMAData = calculateVolumeMA(data, volumeOptions.maLength);\n    }\n    \n    // 렌더 데이터 준비\n    const renderData = {\n      volume: {\n        visible: true,\n        data: data,\n        options: volumeOptions\n      },\n      volumeMA: volumeOptions?.showMA && volumeMAData ? {\n        visible: true,\n        data: volumeMAData,\n        period: volumeOptions.maLength || 0,\n        color: volumeOptions.maColor || '#ffffff'\n      } : undefined,\n      crosshair: _mouseX >= 0 ? {\n        visible: true,\n        data: {},  // RenderLayer에 필요한 data 필드\n        x: _mouseX,\n        y: -1,  // 수직선만\n        verticalOnly: true\n      } as RenderLayer & { x: number; y: number; verticalOnly?: boolean } : undefined\n    };\n    \n    // 통합 렌더러로 볼륨 렌더링 (크로스헤어 포함)\n    this.unifiedChartRenderer.render(renderData, this.coordSystem);\n  }\n  \n  getGridRenderer(): GridRenderer {\n    return this.gridRenderer;\n  }\n  \n  getUnifiedRenderer(): UnifiedRenderer {\n    return this.unifiedRenderer;\n  }\n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n    this.unifiedChartRenderer.updateTheme(theme);\n    this.gridRenderer.updateTheme(theme);\n    this.unifiedRenderer.updateTheme(theme);\n  }\n  \n  updateColors(colors: {\n    up?: string;\n    down?: string;\n    maColor?: string;\n  }): void {\n    console.log('[VolumeRendererManager] updateColors called with:', colors);\n    \n    // 테마를 복사하여 볼륨 색상만 업데이트\n    if (colors.up || colors.down) {\n      // 테마 복사 (깊은 복사)\n      const newTheme = JSON.parse(JSON.stringify(this.theme));\n      \n      if (!newTheme.volume) {\n        newTheme.volume = {\n          upColor: this.theme.candle?.upColor || '#26a69a',\n          downColor: this.theme.candle?.downColor || '#ef5350'\n        };\n      }\n      \n      if (colors.up) newTheme.volume.upColor = colors.up;\n      if (colors.down) newTheme.volume.downColor = colors.down;\n      \n      console.log('[VolumeRendererManager] Updated theme.volume:', newTheme.volume);\n      \n      // 로컬 테마 업데이트\n      this.theme = newTheme;\n      \n      // 볼륨 전용 UnifiedChartRenderer에만 업데이트\n      this.unifiedChartRenderer.updateTheme(newTheme);\n    }\n    \n    // MA 색상 업데이트\n    if (colors.maColor && this.options.panels?.volume) {\n      this.options.panels.volume.maColor = colors.maColor;\n    }\n  }\n  \n  updateOptions(options: ChartOptions): void {\n    this.options = { ...this.options, ...options };\n    \n    // 볼륨 패널 그리드 설정 업데이트\n    const grid = options.panels?.volume?.grid;\n    if (grid !== undefined) {\n      if (typeof grid === 'boolean') {\n        this.gridRenderer.setShowGrid(grid);\n      } else if (grid?.show !== undefined) {\n        this.gridRenderer.setShowGrid(grid.show);\n      }\n    }\n  }\n  \n  resize(): void {\n    const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    this.unifiedChartRenderer.resize(canvas.width, canvas.height);\n  }\n  \n  dispose(): void {\n    this.unifiedChartRenderer.dispose();\n    this.gridRenderer.dispose();\n    this.unifiedRenderer.dispose();\n  }\n}","import { ChartPanel } from '@/core/ChartPanel';\nimport type { ChartData, Theme, ChartOptions } from '@/types';\nimport { WebGLRenderer } from '@/core/WebGLRenderer';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { VolumeRendererManager } from './volume/VolumeRendererManager';\nimport { calculateVolumeMA } from '@/utils/volumeMA';\n\nexport class VolumePanel extends ChartPanel {\n  private theme: Theme;\n  private rendererManager!: VolumeRendererManager;\n  protected coordSystem: UnifiedCoordinateSystem;\n  private options: ChartOptions;\n  private mouseX: number = -1;\n  private mouseY: number = -1;\n  private currentData: ChartData | null = null;\n  \n  // 이벤트 핸들러를 인스턴스 속성으로 저장\n  // private boundHandleMouseMove: (e: MouseEvent) => void;  // 사용하지 않음\n  // private boundHandleMouseLeave: (e: MouseEvent) => void;  // 사용하지 않음\n  \n  constructor(\n    container: HTMLElement,\n    theme: Theme,\n    _renderer: WebGLRenderer | null,\n    coordSystem: UnifiedCoordinateSystem | null,\n    options?: ChartOptions\n  ) {\n    super(container, { height: container.clientHeight });\n    this.theme = theme;\n    this.options = options || {} as ChartOptions;\n    \n    // 전달받은 좌표계 사용, 없으면 새로 생성\n    if (coordSystem) {\n      // console.log('[VolumePanel] Using shared coordinate system:', coordSystem);\n      this.coordSystem = coordSystem;\n    } else {\n      // console.log('[VolumePanel] Creating new coordinate system');\n      this.coordSystem = new UnifiedCoordinateSystem(\n        this.renderer.getWidth(),\n        this.renderer.getHeight(),\n        this.renderer.getPixelRatio()\n      );\n    }\n    \n    // 볼륨 패널로 설정\n    this.coordSystem.setCurrentPanel('volume');\n    \n    // 패널 높이 설정 (픽셀 단위로 변환)\n    const pixelRatio = this.renderer.getPixelRatio();\n    this.coordSystem.setPanelHeight('volume', container.clientHeight * pixelRatio);\n    \n    // 이벤트 핸들러 바인딩\n    // this.boundHandleMouseMove = this.handleMouseMove.bind(this);  // 사용하지 않음\n    // this.boundHandleMouseLeave = this.handleMouseLeave.bind(this);  // 사용하지 않음\n  }\n  \n  async init(): Promise<void> {\n    await super.init();\n    \n    // WebGLRenderer 초기화 후 실제 높이로 업데이트\n    this.coordSystem.setPanelHeight('volume', this.renderer.getHeight());\n    \n    // 렌더러 매니저 생성 및 초기화\n    this.rendererManager = new VolumeRendererManager(\n      this.renderer,\n      this.container,\n      this.theme,\n      this.coordSystem,\n      this.options\n    );\n    \n    await this.rendererManager.init();\n    \n    // 마우스 이벤트 리스너 추가 - 일단 비활성화\n    // const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    // canvas.addEventListener('mousemove', this.boundHandleMouseMove);\n    // canvas.addEventListener('mouseleave', this.boundHandleMouseLeave);\n  }\n  \n  render(data: ChartData): void {\n    // 데이터 저장\n    this.currentData = data;\n    \n    // Clear\n    this.renderer.clear(this.theme.background);\n    \n    // 볼륨 패널로 전환\n    this.coordSystem.setCurrentPanel('volume');\n    \n    // 거래량 데이터 계산\n    const visibleRange = this.coordSystem.getVisibleRange();\n    if (visibleRange.start >= visibleRange.end) return;\n    \n    // 거래량 범위 계산\n    let minVolume = Infinity;\n    let maxVolume = -Infinity;\n    \n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      minVolume = Math.min(minVolume, data.volumes[i]);\n      maxVolume = Math.max(maxVolume, data.volumes[i]);\n    }\n    \n    // 볼륨 MA도 범위에 포함 (옵션에 따라)\n    const volumeOptions = this.options.panels?.volume;\n    if (volumeOptions?.showMA && volumeOptions?.maLength) {\n      const volumeMAData = calculateVolumeMA(data, volumeOptions.maLength);\n      \n      for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n        if (volumeMAData[i] > 0) {\n          maxVolume = Math.max(maxVolume, volumeMAData[i]);\n        }\n      }\n    }\n    \n    // 여유분 추가 (상단만)\n    const padding = (maxVolume - minVolume) * 0.1;\n    this.coordSystem.setPriceRange(0, maxVolume + padding, 'volume');\n    \n    // 볼륨 패널은 하단 마진을 0으로 설정\n    this.coordSystem.setPriceMargin(0.1, 0, 'volume');\n    \n    // 그리드 렌더링\n    const grid = this.options.panels?.volume?.grid;\n    const showGrid = grid === true || (typeof grid === 'object' && grid?.show !== false);\n    if (showGrid) {\n      this.rendererManager.getGridRenderer().render(data, this.coordSystem as any);\n    }\n    \n    // 통합 렌더러로 볼륨 렌더링\n    this.rendererManager.renderVolume(data, visibleRange, this.mouseX, this.mouseY);\n    \n    // 디버깅: 마우스 위치 확인\n    // console.log('[VolumePanel] render - mouseX:', this.mouseX, 'mouseY:', this.mouseY);\n  }\n  \n  // 사용하지 않는 메서드 - 나중에 필요하면 구현\n  private _handleMouseMove(_event: MouseEvent): void {\n    // const rect = (event.target as HTMLElement).getBoundingClientRect();\n    // const x = event.clientX - rect.left;\n    // const y = event.clientY - rect.top;\n    // \n    // // 볼륨 패널 내에서 마우스가 움직일 때는 자체 좌표 사용\n    // this.mouseX = x;\n    // this.mouseY = y;\n    // \n    // // 크로스헤어 업데이트를 위해 렌더링 요청\n    // this.requestRender();\n  }\n  \n  // 사용하지 않는 메서드 - 나중에 필요하면 구현\n  private _handleMouseLeave(): void {\n    // // 볼륨 패널에서 마우스가 나갔을 때\n    // // 메인 차트의 크로스헤어는 유지하고 자체 마우스만 리셋\n    // // setMouseX로 전달받은 값은 유지됨\n    // \n    // // 크로스헤어 제거를 위해 렌더링 요청\n    // this.requestRender();\n  }\n  \n  \n  updateTheme(theme: Theme, options?: ChartOptions): void {\n    super.updateTheme(theme);\n    this.theme = theme;\n    if (this.rendererManager) {\n      this.rendererManager.updateTheme(theme);\n    }\n    \n    // 옵션이 전달된 경우 업데이트\n    if (options) {\n      this.updateOptions(options);\n    }\n  }\n  \n  /**\n   * 볼륨 색상 업데이트\n   */\n  updateColors(colors: {\n    up?: string;\n    down?: string;\n    maColor?: string;\n  }): void {\n    // 옵션 업데이트\n    if (this.options.panels?.volume) {\n      if (colors.up || colors.down) {\n        if (!this.options.panels.volume.colors) {\n          this.options.panels.volume.colors = {};\n        }\n        if (colors.up) this.options.panels.volume.colors.up = colors.up;\n        if (colors.down) this.options.panels.volume.colors.down = colors.down;\n      }\n      if (colors.maColor) {\n        this.options.panels.volume.maColor = colors.maColor;\n      }\n    }\n    \n    // 렌더러 매니저에 색상 전달\n    if (this.rendererManager) {\n      this.rendererManager.updateColors(colors);\n    }\n    \n    // 렌더링 요청\n    this.requestRender();\n  }\n  \n  resize(width?: number, height?: number): void {\n    super.resize(width, height);\n    \n    // WebGLRenderer의 실제 높이로 업데이트\n    this.coordSystem.setPanelHeight('volume', this.renderer.getHeight());\n    \n    // 렌더러 매니저 리사이즈\n    if (this.rendererManager) {\n      this.rendererManager.resize();\n    }\n  }\n  \n  getViewport(): UnifiedCoordinateSystem {\n    // UnifiedCoordinateSystem을 viewport로 반환\n    return this.coordSystem;\n  }\n  \n  updateOptions(options: ChartOptions | Partial<ChartOptions>): void {\n    this.options = { ...this.options, ...options } as ChartOptions;\n    \n    // 그리드 설정 업데이트\n    if (options.grid !== undefined) {\n      const showGrid = typeof options.grid === 'boolean' ? options.grid : options.grid?.show !== false;\n      this.rendererManager.getGridRenderer().setShowGrid(showGrid);\n    }\n    \n    // 렌더러 매니저에 옵션 업데이트 전달\n    if (this.rendererManager) {\n      this.rendererManager.updateOptions(this.options);\n    }\n    \n    // 다시 렌더링 요청\n    this.requestRender();\n  }\n  \n  requestRender(): void {\n    // 저장된 데이터로 다시 렌더링\n    if (this.currentData) {\n      this.render(this.currentData);\n    }\n  }\n  \n  /**\n   * 메인 차트에서 마우스 X 위치 전달받기\n   */\n  setMouseX(x: number): void {\n    this.mouseX = x;\n    // Y는 -1로 설정 (수직선만 표시)\n    this.mouseY = -1;\n    this.requestRender();\n  }\n\n  dispose(): void {\n    if (this.rendererManager) {\n      this.rendererManager.dispose();\n    }\n    \n    // 이벤트 리스너 제거 - 현재 비활성화 상태\n    // const canvas = this.renderer.getGL().canvas as HTMLCanvasElement;\n    // if (this.boundHandleMouseMove) {\n    //   canvas.removeEventListener('mousemove', this.boundHandleMouseMove);\n    // }\n    // if (this.boundHandleMouseLeave) {\n    //   canvas.removeEventListener('mouseleave', this.boundHandleMouseLeave);\n    // }\n    \n    super.dispose();\n  }\n}","import type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport type { ChartData, Theme } from '@/types';\n\nexport class AxisRenderer {\n  private theme: Theme;\n  private width: number = 80; // Y축 너비\n  private height: number = 30; // X축 높이\n  \n  constructor(theme: Theme) {\n    this.theme = theme;\n  }\n  \n  renderYAxis(\n    container: HTMLElement,\n    viewport: UnifiedCoordinateSystem,\n    type: 'price' | 'volume',\n    data?: ChartData\n  ): void {\n    // Y축 컨테이너 찾기 또는 생성\n    let yAxisContainer = container.querySelector('.y-axis') as HTMLElement;\n    if (!yAxisContainer) {\n      yAxisContainer = document.createElement('div');\n      yAxisContainer.className = 'y-axis';\n      // 패널 타입별로 고유한 data 속성 추가\n      yAxisContainer.setAttribute('data-panel-type', type);\n      yAxisContainer.style.cssText = `\n        position: absolute;\n        right: 0;\n        top: 0;\n        width: ${this.width}px;\n        height: 100%;\n        background: ${this.theme.background || this.theme.backgroundColor};\n        border-left: 1px solid ${this.theme.axis?.dividerColor || this.theme.axis?.unifiedColor || this.theme.grid || this.theme.gridColor};\n        overflow: hidden;\n        z-index: 10;\n      `;\n      container.appendChild(yAxisContainer);\n    }\n    \n    // 캔버스 찾기 또는 생성\n    let canvas = yAxisContainer.querySelector('canvas') as HTMLCanvasElement;\n    if (!canvas) {\n      canvas = document.createElement('canvas');\n      canvas.style.cssText = `\n        position: absolute;\n        left: 0;\n        top: 0;\n        width: 100%;\n        height: 100%;\n      `;\n      yAxisContainer.appendChild(canvas);\n    }\n    \n    // 캔버스 크기 설정\n    const rect = yAxisContainer.getBoundingClientRect();\n    const pixelRatio = window.devicePixelRatio || 1;\n    canvas.width = rect.width * pixelRatio;\n    canvas.height = rect.height * pixelRatio;\n    canvas.style.width = `${rect.width}px`;\n    canvas.style.height = `${rect.height}px`;\n    \n    const ctx = canvas.getContext('2d');\n    if (!ctx) return;\n    \n    // 클리어\n    ctx.clearRect(0, 0, canvas.width, canvas.height);\n    ctx.save();\n    ctx.scale(pixelRatio, pixelRatio);\n    \n    // 스타일 설정\n    ctx.fillStyle = this.theme.axis?.textColor || this.theme.axis?.unifiedColor || this.theme.axis?.text || this.theme.text || this.theme.textColor;\n    ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n    ctx.textAlign = 'right';\n    ctx.textBaseline = 'middle';\n    \n    \n    if (type === 'price') {\n      this.renderPriceScale(ctx, viewport, rect);\n    } else if (type === 'volume' && data) {\n      this.renderVolumeScale(ctx, viewport, rect, data);\n    }\n    \n    ctx.restore();\n  }\n  \n  private renderPriceScale(ctx: CanvasRenderingContext2D, viewport: UnifiedCoordinateSystem, rect: DOMRect): void {\n    const [minPrice, maxPrice] = viewport.getPriceRange();\n    const priceRange = maxPrice - minPrice;\n    \n    // 적절한 가격 간격 계산\n    const tickCount = Math.floor(rect.height / 40); // 40px당 하나의 눈금\n    const rawInterval = priceRange / tickCount;\n    const magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval)));\n    const normalizedInterval = rawInterval / magnitude;\n    \n    let interval: number;\n    if (normalizedInterval <= 1) interval = magnitude;\n    else if (normalizedInterval <= 2) interval = 2 * magnitude;\n    else if (normalizedInterval <= 5) interval = 5 * magnitude;\n    else interval = 10 * magnitude;\n    \n    // 첫 번째 눈금 찾기\n    const firstTick = Math.ceil(minPrice / interval) * interval;\n    \n    // 눈금 그리기\n    let ticksDrawn = 0;\n    for (let price = firstTick; price <= maxPrice; price += interval) {\n      // Y축 캔버스의 좌표계에 맞게 변환\n      // viewport.priceToPixelY는 메인 캔버스 기준이므로, Y축 캔버스 높이에 맞게 재계산\n      const isLogScale = viewport.isLogScale();\n      let y: number;\n      \n      if (isLogScale && price > 0 && minPrice > 0) {\n        // 로그 스케일 계산\n        const logPrice = Math.log(price);\n        const logMin = Math.log(minPrice);\n        const logMax = Math.log(maxPrice);\n        const logRange = logMax - logMin;\n        y = ((logMax - logPrice) / logRange) * rect.height;\n      } else {\n        // 선형 스케일 계산\n        const normalized = (price - minPrice) / priceRange;\n        y = rect.height * (1 - normalized);\n      }\n      \n      // 가격 텍스트\n      const priceText = this.formatPrice(price);\n      ctx.fillText(priceText, rect.width - 10, y);\n      ticksDrawn++;\n      \n      // 눈금선\n      ctx.strokeStyle = this.theme.axis?.dividerColor || this.theme.axis?.unifiedColor || this.theme.grid || this.theme.gridColor;\n      ctx.lineWidth = 1;\n      ctx.beginPath();\n      ctx.moveTo(0, y);\n      ctx.lineTo(5, y);\n      ctx.stroke();\n    }\n  }\n  \n  private renderVolumeScale(ctx: CanvasRenderingContext2D, viewport: UnifiedCoordinateSystem, rect: DOMRect, data: ChartData): void {\n    // 보이는 영역의 최대 볼륨 계산\n    const visibleRange = viewport.getVisibleRange();\n    let maxVolume = 0;\n    \n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      if (data.volumes[i] > maxVolume) {\n        maxVolume = data.volumes[i];\n      }\n    }\n    \n    // 볼륨 눈금 그리기\n    const tickCount = Math.min(5, Math.floor(rect.height / 30));\n    \n    for (let i = 0; i <= tickCount; i++) {\n      const ratio = i / tickCount;\n      const volume = maxVolume * (1 - ratio);\n      const y = rect.height * ratio;\n      \n      // 볼륨 포맷팅\n      const volumeText = this.formatVolume(volume);\n      ctx.fillText(volumeText, rect.width - 10, y);\n      \n      // 눈금선\n      if (i > 0 && i < tickCount) {\n        ctx.strokeStyle = this.theme.grid || this.theme.gridColor;\n        ctx.lineWidth = 1;\n        ctx.beginPath();\n        ctx.moveTo(0, y);\n        ctx.lineTo(5, y);\n        ctx.stroke();\n      }\n    }\n  }\n  \n  renderXAxis(container: HTMLElement, viewport: UnifiedCoordinateSystem, data: ChartData): void {\n    // 컨테이너가 보이는지 확인\n    const rect = container.getBoundingClientRect();\n    if (rect.height === 0) {\n      console.warn('X-axis container has zero height');\n      return;\n    }\n    \n    // X축 캔버스 찾기 또는 생성\n    let canvas = container.querySelector('canvas') as HTMLCanvasElement;\n    if (!canvas) {\n      canvas = document.createElement('canvas');\n      canvas.style.cssText = `\n        position: absolute;\n        left: 0;\n        top: 0;\n        width: 100%;\n        height: 100%;\n        z-index: 15;\n      `;\n      container.appendChild(canvas);\n    }\n    \n    // 캔버스 크기 설정\n    const pixelRatio = window.devicePixelRatio || 1;\n    canvas.width = rect.width * pixelRatio;\n    canvas.height = rect.height * pixelRatio;\n    canvas.style.width = `${rect.width}px`;\n    canvas.style.height = `${rect.height}px`;\n    \n    const ctx = canvas.getContext('2d');\n    if (!ctx) return;\n    \n    // 클리어\n    ctx.clearRect(0, 0, canvas.width, canvas.height);\n    ctx.save();\n    ctx.scale(pixelRatio, pixelRatio);\n    \n    // 스타일 설정\n    ctx.fillStyle = this.theme.axis?.textColor || this.theme.axis?.unifiedColor || this.theme.axis?.text || this.theme.text || this.theme.textColor;\n    ctx.font = '11px -apple-system, BlinkMacSystemFont, sans-serif';\n    ctx.textAlign = 'center';\n    ctx.textBaseline = 'middle';\n    \n    // 시간 눈금 그리기\n    const visibleRange = viewport.getVisibleRange();\n    // const candleWidth = viewport.getCandleWidth();\n    \n    // 적절한 시간 간격 계산\n    const pixelsPerLabel = 100; // 100px마다 하나의 레이블\n    const labelsCount = Math.floor(rect.width / pixelsPerLabel);\n    const candlesPerLabel = Math.max(1, Math.floor((visibleRange.end - visibleRange.start) / labelsCount));\n    \n    for (let i = visibleRange.start; i <= visibleRange.end; i += candlesPerLabel) {\n      if (i >= data.length) break;\n      \n      const x = viewport.candleIndexToPixelX(i) + viewport.getPixelOffset();\n      // const time = data.times[i];\n      \n      // 중복 라벨 제거 - X축에서 이미 시간을 표시하므로 여기서는 표시하지 않음\n      // const timeText = this.formatTime(new Date(time * 1000));\n      // ctx.fillText(timeText, x, rect.height / 2);\n      \n      // 눈금선\n      ctx.strokeStyle = this.theme.axis?.dividerColor || this.theme.axis?.unifiedColor || this.theme.grid || this.theme.gridColor;\n      ctx.lineWidth = 1;\n      ctx.beginPath();\n      ctx.moveTo(x, 0);\n      ctx.lineTo(x, 5);\n      ctx.stroke();\n    }\n    \n    ctx.restore();\n  }\n  \n  private formatPrice(price: number): string {\n    if (price >= 1000000) {\n      return (price / 1000000).toFixed(2) + 'M';\n    } else if (price >= 1000) {\n      return (price / 1000).toFixed(2) + 'K';\n    } else if (price >= 100) {\n      return price.toFixed(2);\n    } else if (price >= 10) {\n      return price.toFixed(3);\n    } else {\n      return price.toFixed(4);\n    }\n  }\n  \n  private formatVolume(volume: number): string {\n    if (volume === 0) return '0';\n    if (volume >= 1e9) {\n      return (volume / 1e9).toFixed(1) + 'B';\n    } else if (volume >= 1e6) {\n      return (volume / 1e6).toFixed(1) + 'M';\n    } else if (volume >= 1e3) {\n      return (volume / 1e3).toFixed(1) + 'K';\n    } else {\n      return volume.toFixed(0);\n    }\n  }\n  \n  // 중복 라벨 제거로 인해 사용하지 않음\n  // private formatTime(date: Date): string {\n  //   const hours = date.getHours();\n  //   const minutes = date.getMinutes();\n  //   const month = date.getMonth() + 1;\n  //   const day = date.getDate();\n  //   \n  //   // 시간 간격에 따라 다른 포맷 사용\n  //   // TODO: 동적 포맷팅 (일봉, 분봉 등)\n  //   return `${month}/${day} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;\n  // }\n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n    \n    // 모든 Y축 컨테이너 업데이트\n    const yAxisContainers = document.querySelectorAll('.y-axis');\n    yAxisContainers.forEach((container: Element) => {\n      const element = container as HTMLElement;\n      element.style.background = theme.background || theme.backgroundColor || '#000000';\n      element.style.borderLeftColor = theme.axis?.dividerColor || theme.axis?.unifiedColor || theme.grid || theme.gridColor || '#333333';\n    });\n    \n    // 모든 X축 컨테이너 업데이트  \n    const xAxisContainers = document.querySelectorAll('.x-axis-container');\n    xAxisContainers.forEach((container: Element) => {\n      const element = container as HTMLElement;\n      element.style.background = theme.background || theme.backgroundColor || '#000000';\n      element.style.borderTopColor = theme.axis?.dividerColor || theme.axis?.unifiedColor || theme.grid || theme.gridColor || '#333333';\n    });\n  }\n  \n  getYAxisWidth(): number {\n    return this.width;\n  }\n  \n  getXAxisHeight(): number {\n    return this.height;\n  }\n}","import type { ChartData, Theme, ChartOptions } from '@/types';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { XAxisFormatter } from '@/utils/formatters';\n\nexport class XAxisRenderer {\n  private container: HTMLElement;\n  private canvas: HTMLCanvasElement;\n  private ctx: CanvasRenderingContext2D;\n  private theme: Theme;\n  private options: ChartOptions;\n  private xAxisFormatter: XAxisFormatter;\n  private currentCandleIndex: number = -1;\n  \n  constructor(container: HTMLElement, theme: Theme, options?: ChartOptions) {\n    this.container = container;\n    this.theme = theme;\n    this.options = options || {} as ChartOptions;\n    \n    const axisOptions = this.options.axis?.x;\n    this.xAxisFormatter = new XAxisFormatter(\n      axisOptions?.locale || 'en-US',\n      axisOptions?.format || 'short'\n    );\n    \n    // X축용 캔버스 생성\n    this.canvas = document.createElement('canvas');\n    this.canvas.style.cssText = `\n      position: absolute;\n      bottom: 0;\n      left: 0;\n      width: 100%;\n      height: ${axisOptions?.height || 30}px;\n      pointer-events: none;\n      z-index: 10;\n    `;\n    container.appendChild(this.canvas);\n    \n    const ctx = this.canvas.getContext('2d');\n    if (!ctx) throw new Error('Failed to get 2D context');\n    this.ctx = ctx;\n    \n    // 초기 크기 설정\n    this.resize();\n  }\n  \n  private resize(): void {\n    const rect = this.container.getBoundingClientRect();\n    const pixelRatio = window.devicePixelRatio || 1;\n    const axisOptions = this.options.axis?.x;\n    const height = axisOptions?.height || 30;\n    \n    this.canvas.width = rect.width * pixelRatio;\n    this.canvas.height = height * pixelRatio;\n    this.canvas.style.width = rect.width + 'px';\n    this.canvas.style.height = height + 'px';\n  }\n  \n  render(data: ChartData, viewport: UnifiedCoordinateSystem): void {\n    // X축 설정 확인\n    const axisOptions = this.options.axis?.x;\n    if (axisOptions?.show === false) return;\n    \n    // 크기 업데이트\n    this.resize();\n    \n    const width = this.canvas.width;\n    const height = this.canvas.height;\n    \n    // Clear canvas - 전체 캔버스 클리어\n    this.ctx.clearRect(0, 0, width, height);\n    \n    // 배경색 설정 (테마에 맞게)\n    this.ctx.fillStyle = this.theme.background || this.theme.backgroundColor;\n    this.ctx.fillRect(0, 0, width, height);\n    \n    // 시간 축 렌더링\n    this.renderTimeAxis(data, viewport);\n    \n    // 현재 캔들 하이라이트 렌더링\n    if (this.currentCandleIndex >= 0) {\n      this.renderCurrentTimeHighlight(data, viewport);\n    }\n  }\n  \n  /**\n   * 크로스헤어 위치의 캔들 인덱스 설정\n   */\n  setCurrentCandleIndex(index: number): void {\n    this.currentCandleIndex = index;\n  }\n  \n  private renderTimeAxis(data: ChartData, viewport: UnifiedCoordinateSystem): void {\n    const pixelRatio = window.devicePixelRatio || 1;\n    const visibleRange = viewport.getVisibleRange();\n    const width = this.canvas.width / pixelRatio;\n    \n    // 스타일 설정\n    this.ctx.save();\n    this.ctx.scale(pixelRatio, pixelRatio);\n    \n    // X축 폰트 설정 적용\n    const axisOptions = this.options.axis?.x;\n    const fontOptions = axisOptions?.font;\n    \n    this.ctx.fillStyle = fontOptions?.color || this.theme.axis?.textColor || this.theme.axis?.unifiedColor || this.theme.text || this.theme.textColor;\n    const fontSize = fontOptions?.size || 11;\n    const fontFamily = fontOptions?.family || 'Arial';\n    this.ctx.font = `${fontSize}px ${fontFamily}`;\n    this.ctx.textAlign = 'center';\n    \n    // 위쪽 테두리 그리기\n    this.ctx.strokeStyle = this.theme.axis?.dividerColor || this.theme.axis?.unifiedColor || this.theme.grid || this.theme.gridColor;\n    this.ctx.lineWidth = 1;\n    this.ctx.beginPath();\n    this.ctx.moveTo(0, 0);\n    this.ctx.lineTo(width, 0);\n    this.ctx.stroke();\n    \n    // 표시할 라벨 개수 계산 - 월간 표시를 위해 라벨 간격 늘림\n    const labelWidth = 200; // 각 라벨의 대략적인 너비 (월간 표시를 위해 증가)\n    const maxLabels = Math.floor(width / labelWidth);\n    const visibleCandles = visibleRange.end - visibleRange.start + 1;\n    const step = Math.max(1, Math.floor(visibleCandles / maxLabels));\n    \n    // 시간 범위 계산\n    const startTime = data.times[visibleRange.start];\n    const endTime = data.times[visibleRange.end];\n    const timeRange = endTime - startTime;\n    \n    // 라벨 그리기\n    for (let i = visibleRange.start; i <= visibleRange.end; i += step) {\n      if (i >= data.length) break;\n      \n      const time = data.times[i];\n      const x = viewport.candleIndexToPixelX(i) / pixelRatio;\n      \n      // 화면 밖의 라벨은 스킵\n      if (x < -50 || x > width + 50) continue;\n      \n      // 시간 포맷팅\n      const label = this.xAxisFormatter.formatTimeRange(time, timeRange);\n      \n      // 라벨 그리기\n      this.ctx.fillText(label, x, 18);\n      \n      // 눈금 그리기\n      this.ctx.beginPath();\n      this.ctx.moveTo(x, 0);\n      this.ctx.lineTo(x, 5);\n      this.ctx.stroke();\n    }\n    \n    this.ctx.restore();\n  }\n  \n  private renderCurrentTimeHighlight(data: ChartData, viewport: UnifiedCoordinateSystem): void {\n    if (this.currentCandleIndex < 0 || this.currentCandleIndex >= data.length) return;\n    \n    const pixelRatio = window.devicePixelRatio || 1;\n    const roundedIndex = Math.round(this.currentCandleIndex);\n    \n    // 인덱스 범위 검증 및 보정\n    let safeIndex = roundedIndex;\n    if (safeIndex < 0) {\n      safeIndex = 0;\n    } else if (safeIndex >= data.times.length) {\n      safeIndex = data.times.length - 1;\n    }\n    \n    const time = data.times[safeIndex];\n    const x = viewport.candleIndexToPixelX(safeIndex) / pixelRatio;\n    const width = this.canvas.width / pixelRatio;\n    const height = this.canvas.height / pixelRatio;\n    \n    this.ctx.save();\n    this.ctx.scale(pixelRatio, pixelRatio);\n    \n    // 하이라이트 박스 배경\n    // 시간 포맷팅 - YYYY-MM-DD HH:mm 형식\n    const timestamp = typeof time === 'number' && time < 10000000000 ? time * 1000 : time;\n    const date = new Date(timestamp);\n    const year = date.getFullYear();\n    const month = String(date.getMonth() + 1).padStart(2, '0');\n    const day = String(date.getDate()).padStart(2, '0');\n    const hours = String(date.getHours()).padStart(2, '0');\n    const minutes = String(date.getMinutes()).padStart(2, '0');\n    const label = `${year}-${month}-${day} ${hours}:${minutes}`;\n    const labelWidth = this.ctx.measureText(label).width + 20;\n    const boxX = Math.max(0, Math.min(x - labelWidth / 2, width - labelWidth));\n    \n    this.ctx.fillStyle = this.theme.crosshair.labelBackground || '#2962ff';\n    this.ctx.fillRect(boxX, 0, labelWidth, height);\n    \n    // 하이라이트 텍스트 - 테마에 따라 색상 변경\n    this.ctx.fillStyle = this.theme.crosshair.labelTextColor || '#ffffff';\n    this.ctx.font = 'bold 11px Arial';\n    this.ctx.textAlign = 'center';\n    this.ctx.fillText(label, x, 18);\n    \n    this.ctx.restore();\n  }\n  \n  updateTheme(theme: Theme): void {\n    this.theme = theme;\n  }\n  \n  updateOptions(options: ChartOptions): void {\n    this.options = options;\n    \n    const axisOptions = options.axis?.x;\n    if (axisOptions) {\n      if (axisOptions.locale) {\n        this.xAxisFormatter.updateLocale(axisOptions.locale);\n      }\n      if (axisOptions.format) {\n        this.xAxisFormatter.updateFormat(axisOptions.format);\n      }\n      \n      // 높이 변경시 캔버스 스타일 업데이트\n      if (axisOptions.height) {\n        this.canvas.style.height = `${axisOptions.height}px`;\n        this.resize();\n      }\n    }\n  }\n  \n  dispose(): void {\n    if (this.canvas.parentNode) {\n      this.canvas.parentNode.removeChild(this.canvas);\n    }\n  }\n}","import { MainChartPanel } from '@/panels/MainChartPanel';\nimport { VolumePanel } from '@/panels/VolumePanel';\nimport type { ChartPanel } from '@/core/ChartPanel';\nimport type { ChartData, Theme, ChartOptions } from '@/types';\nimport { IndicatorManager } from './IndicatorManager';\nimport { DrawingManager } from './DrawingManager';\nimport { MarkerManager } from './MarkerManager';\nimport { LineSeriesManager } from './LineSeriesManager';\nimport { StopLossManager } from './StopLossManager';\nimport { AxisRenderer } from '@/ui/AxisRenderer';\nimport { XAxisRenderer } from '@/renderers/XAxisRenderer';\nimport { WebGLRenderer } from './WebGLRenderer';\nimport { DataManager } from './DataManager';\nimport { UnifiedCoordinateSystem } from './UnifiedCoordinateSystem';\n\nexport interface PanelConfig {\n  type: 'main' | 'volume' | 'indicator';\n  heightRatio: number; // 0-1 사이의 비율\n  minHeight?: number;\n  maxHeight?: number;\n}\n\nexport class PanelManager {\n  private container: HTMLElement;\n  private panels: Map<string, ChartPanel> = new Map();\n  private panelContainers: Map<string, HTMLElement> = new Map();\n  private panelConfigs: PanelConfig[] = [];\n  private resizers: HTMLElement[] = [];\n  private theme: Theme;\n  private indicatorManager: IndicatorManager;\n  private drawingManager: DrawingManager;\n  private markerManager: MarkerManager | null = null;\n  private lineSeriesManager: LineSeriesManager | null = null;\n  private stopLossManager: StopLossManager | null = null;\n  private axisRenderer: AxisRenderer;\n  private xAxisRenderer: XAxisRenderer | null = null;\n  private xAxisContainer: HTMLElement | null = null;\n  private isResizing: boolean = false;\n  private resizeTimeout: number | null = null;\n  private currentData: ChartData | null = null;\n  private dataManager: DataManager | null = null;\n  // private webglRenderer: WebGLRenderer | null = null;\n  private options: ChartOptions;\n  private sharedCoordinateSystem: UnifiedCoordinateSystem | null = null;\n  private currentMouseCandleIndex: number = -1;\n  private resizerEventListeners: Array<{remove: () => void}> = [];\n  \n  constructor(\n    container: HTMLElement,\n    theme: Theme,\n    indicatorManager: IndicatorManager,\n    drawingManager: DrawingManager,\n    stopLossManager: StopLossManager,\n    options?: ChartOptions\n  ) {\n    this.container = container;\n    this.theme = theme;\n    this.indicatorManager = indicatorManager;\n    this.drawingManager = drawingManager;\n    this.stopLossManager = stopLossManager;\n    this.axisRenderer = new AxisRenderer(theme);\n    this.options = options || {} as ChartOptions;\n    \n    // 패널 설정 초기화\n    this.initPanelConfigs();\n  }\n  \n  setWebGLRenderer(_renderer: WebGLRenderer): void {\n    // this.webglRenderer = renderer;\n  }\n  \n  setDataManager(dataManager: DataManager): void {\n    this.dataManager = dataManager;\n  }\n  \n  setMarkerManager(markerManager: MarkerManager): void {\n    this.markerManager = markerManager;\n  }\n  \n  setLineSeriesManager(lineSeriesManager: LineSeriesManager): void {\n    this.lineSeriesManager = lineSeriesManager;\n  }\n  \n  setStopLossManager(stopLossManager: StopLossManager): void {\n    this.stopLossManager = stopLossManager;\n  }\n  \n  private initPanelConfigs(): void {\n    const volumeOptions = this.options.volume;\n    const showVolume = volumeOptions?.enabled !== false; // 기본값 true\n    \n    if (showVolume) {\n      const volumeHeight = volumeOptions?.height || 0.3;\n      const mainHeight = 1 - volumeHeight;\n      \n      this.panelConfigs = [\n        { \n          type: 'main', \n          heightRatio: mainHeight, \n          minHeight: 200 \n        },\n        { \n          type: 'volume', \n          heightRatio: volumeHeight, \n          minHeight: 50,\n          maxHeight: undefined\n        }\n      ];\n    } else {\n      // 볼륨 패널 없이 메인 패널만\n      this.panelConfigs = [\n        { type: 'main', heightRatio: 1, minHeight: 200 }\n      ];\n    }\n  }\n  \n  async init(): Promise<void> {\n    this.createPanelLayout();\n    await this.createPanels();\n  }\n  \n  private createPanelLayout(): void {\n    // 컨테이너 스타일 설정\n    // disableUI가 true면 헤더 오프셋을 0으로 설정\n    const headerOffset = (this.options.useHeader && !this.options.disableUI) ? 48 : 0; // 헤더 높이만큼 오프셋\n    this.container.style.cssText = `\n      position: relative;\n      width: 100%;\n      height: 100%;\n      background: ${this.theme.background};\n      display: flex;\n      flex-direction: column;\n      overflow: hidden;\n      padding-top: ${headerOffset}px;\n      box-sizing: border-box;\n    `;\n    \n    // X축 공간(30px)을 제외한 사용 가능한 높이 계산\n    \n    this.panelConfigs.forEach((config, index) => {\n      // 패널 컨테이너 생성\n      const panelContainer = document.createElement('div');\n      \n      panelContainer.className = `panel-container panel-${config.type}`;\n      \n      // flexbox를 사용하여 비율에 따라 자동 크기 조정\n      panelContainer.style.cssText = `\n        position: relative;\n        width: 100%;\n        flex: ${config.heightRatio};\n        overflow: hidden;\n        min-height: ${config.minHeight || 100}px;\n        box-sizing: border-box;\n      `;\n      \n      this.container.appendChild(panelContainer);\n      this.panelContainers.set(config.type, panelContainer);\n      \n      // 마지막 패널이 아니면 리사이저 추가\n      if (index < this.panelConfigs.length - 1) {\n        const resizer = this.createResizer(index);\n        this.container.appendChild(resizer);\n        this.resizers.push(resizer);\n      }\n    });\n    \n    // X축 컨테이너 추가\n    const xAxisContainer = document.createElement('div');\n    xAxisContainer.className = 'x-axis-container';\n    xAxisContainer.style.cssText = `\n      position: relative;\n      width: 100%;\n      height: 30px;\n      flex-shrink: 0;\n      background: ${this.theme.background};\n      border-top: 1px solid ${this.options.panels?.divider?.color || this.theme.axis?.dividerColor || this.theme.axis?.unifiedColor || this.theme.grid || '#333333'};\n      z-index: 10;\n    `;\n    this.container.appendChild(xAxisContainer);\n    this.xAxisContainer = xAxisContainer;\n    \n    // XAxisRenderer 생성\n    this.xAxisRenderer = new XAxisRenderer(xAxisContainer, this.theme, this.options);\n  }\n  \n  private createResizer(index: number): HTMLElement {\n    const resizer = document.createElement('div');\n    const dividerOptions = this.options.panels?.divider;\n    const thickness = dividerOptions?.thickness || 1;\n    const color = dividerOptions?.color || this.theme.grid || '#333333';\n    const hoverColor = dividerOptions?.hoverColor || this.theme.crosshair?.color || '#666666';\n    const cursor = dividerOptions?.cursor || 'ns-resize';\n    const draggable = dividerOptions?.draggable !== false; // 기본값 true\n    \n    resizer.style.cssText = `\n      position: relative;\n      width: 100%;\n      height: ${thickness}px;\n      background: ${color};\n      cursor: ${draggable ? cursor : 'default'};\n      z-index: 10;\n      transition: background 0.2s;\n    `;\n    \n    // 호버 효과\n    if (draggable) {\n      resizer.onmouseenter = () => {\n        resizer.style.background = hoverColor;\n      };\n      \n      resizer.onmouseleave = () => {\n        if (!isDragging) {\n          resizer.style.background = color;\n        }\n      };\n    }\n    \n    // 드래그 리사이즈\n    let isDragging = false;\n    let startY = 0;\n    let startHeights: number[] = [];\n    \n    if (!draggable) {\n      return resizer;\n    }\n    \n    resizer.onmousedown = (e) => {\n      isDragging = true;\n      startY = e.clientY;\n      startHeights = Array.from(this.panelContainers.values()).map(el => el.clientHeight);\n      \n      document.body.style.cursor = 'ns-resize';\n      e.preventDefault();\n    };\n    \n    const handleMouseMove = (e: MouseEvent) => {\n      if (!isDragging) return;\n      \n      const deltaY = e.clientY - startY;\n      const panels = Array.from(this.panelContainers.values());\n      \n      // 위 패널과 아래 패널의 새 높이 계산\n      const topPanel = panels[index];\n      const bottomPanel = panels[index + 1];\n      \n      const newTopHeight = startHeights[index] + deltaY;\n      const newBottomHeight = startHeights[index + 1] - deltaY;\n      \n      // 최소 높이 체크\n      const topConfig = this.panelConfigs[index];\n      const bottomConfig = this.panelConfigs[index + 1];\n      \n      if (newTopHeight >= (topConfig.minHeight || 50) && \n          newBottomHeight >= (bottomConfig.minHeight || 50)) {\n        // flex를 제거하고 고정 높이로 설정\n        topPanel.style.flex = 'none';\n        topPanel.style.height = `${newTopHeight}px`;\n        bottomPanel.style.flex = 'none';\n        bottomPanel.style.height = `${newBottomHeight}px`;\n        \n        // 리사이즈 중 플래그 설정\n        this.isResizing = true;\n        \n        // 패널 리사이즈 - debounce로 너무 빈번하게 호출되지 않도록\n        if (this.resizeTimeout) {\n          clearTimeout(this.resizeTimeout);\n        }\n        \n        this.resizeTimeout = window.setTimeout(() => {\n          this.resizePanels();\n          this.isResizing = false;\n        }, 10);\n      }\n    };\n    \n    const handleMouseUp = () => {\n      if (isDragging) {\n        isDragging = false;\n        document.body.style.cursor = '';\n        \n        // 비율 업데이트\n        this.updatePanelRatios();\n      }\n    };\n    \n    document.addEventListener('mousemove', handleMouseMove);\n    document.addEventListener('mouseup', handleMouseUp);\n    \n    // 이벤트 리스너 제거 함수 저장\n    this.resizerEventListeners.push({\n      remove: () => {\n        document.removeEventListener('mousemove', handleMouseMove);\n        document.removeEventListener('mouseup', handleMouseUp);\n      }\n    });\n    \n    return resizer;\n  }\n  \n  private async createPanels(): Promise<void> {\n    // 공유 좌표계 생성 (메인 패널의 크기를 기준으로)\n    if (!this.sharedCoordinateSystem) {\n      const pixelRatio = window.devicePixelRatio || 1;\n      const containerWidth = this.container.clientWidth || 800;\n      \n      // 메인 패널의 실제 높이 계산\n      const mainContainer = this.panelContainers.get('main');\n      const mainHeight = mainContainer ? mainContainer.clientHeight : this.container.clientHeight * 0.7;\n      \n      // console.log('[PanelManager] Creating shared coordinate system with:', {\n      //   containerWidth,\n      //   mainHeight,\n      //   pixelRatio\n      // });\n      \n      // 주의: 캔버스는 'width: calc(100% - 80px)'로 설정되어 있으므로\n      // WebGLRenderer가 반환하는 크기는 이미 Y축이 제외된 값입니다.\n      // 하지만 여기서는 컨테이너 전체 크기를 사용하므로 Y축을 제외해야 합니다.\n      const yAxisWidth = 80;\n      const chartAreaWidth = (containerWidth - yAxisWidth) * pixelRatio;\n      \n      this.sharedCoordinateSystem = new UnifiedCoordinateSystem(\n        chartAreaWidth,\n        mainHeight * pixelRatio,\n        pixelRatio\n      );\n      \n      // DataManager 설정\n      if (this.dataManager) {\n        this.sharedCoordinateSystem.setDataManager(this.dataManager);\n      }\n    }\n    \n    for (const config of this.panelConfigs) {\n      const container = this.panelContainers.get(config.type);\n      if (!container) continue;\n      \n      let panel: ChartPanel;\n      \n      switch (config.type) {\n        case 'main':\n          if (!this.dataManager) {\n            throw new Error('DataManager must be set before creating panels');\n          }\n          // MainChartPanel에 필요한 파라미터 전달\n          (container as any).mainChartParams = {\n            theme: this.theme,\n            drawingManager: this.drawingManager,\n            dataManager: this.dataManager,\n            markerManager: this.markerManager\n          };\n          panel = new MainChartPanel(\n            container, \n            this.theme, \n            null as any, \n            this.sharedCoordinateSystem, // 공유 좌표계 전달\n            this.drawingManager, \n            this.dataManager, \n            this.markerManager,\n            this.lineSeriesManager,\n            this.stopLossManager,\n            this.options\n          );\n          break;\n          \n        case 'volume':\n          // VolumePanel도 자체 WebGLRenderer 사용\n          panel = new VolumePanel(\n            container,\n            this.theme,\n            null,\n            this.sharedCoordinateSystem, // 공유 좌표계 전달\n            this.options\n          );\n          break;\n          \n        default:\n          continue;\n      }\n      \n      await panel.init();\n      this.panels.set(config.type, panel);\n    }\n    \n    // MainChartPanel과 VolumePanel 연결\n    const mainPanel = this.panels.get('main') as MainChartPanel;\n    const volumePanel = this.panels.get('volume');\n    \n    // 초기 마진 설정 적용\n    if (this.sharedCoordinateSystem && this.options) {\n      // 가격 스케일 마진 설정\n      if (this.options.priceScaleMargin && typeof this.options.priceScaleMargin === 'object') {\n        this.sharedCoordinateSystem.setPriceMargin(\n          this.options.priceScaleMargin.top || 0.1,\n          this.options.priceScaleMargin.bottom || 0.1\n        );\n      }\n      \n      // 오른쪽 마진 설정\n      if (this.options.rightMargin !== undefined) {\n        this.sharedCoordinateSystem.setRightMargin(this.options.rightMargin);\n      }\n    }\n    \n    if (mainPanel && volumePanel && 'setMouseXChangeCallback' in mainPanel) {\n      // MainChartPanel의 마우스 X 위치를 VolumePanel로 전달\n      mainPanel.setMouseXChangeCallback((x: number) => {\n        if ('setMouseX' in volumePanel) {\n          (volumePanel as any).setMouseX(x);\n        }\n      });\n    }\n    \n    // 패널 생성 후 resize 호출\n    this.resizePanels();\n  }\n  \n  render(data: ChartData): void {\n    // 리사이즈 중일 때는 렌더링 건너뛰기\n    if (this.isResizing) return;\n    \n    this.currentData = data;\n    \n    // 패널 렌더링\n    this.panels.forEach((panel, type) => {\n      if (type === 'main') {\n        // MainChartPanel은 indicators를 받아야 함\n        const indicators = this.indicatorManager.getIndicatorData();\n        (panel as any).render(data, indicators);\n      } else {\n        panel.render(data);\n      }\n      \n      // Y축 렌더링\n      const container = this.panelContainers.get(type);\n      if (container) {\n        this.axisRenderer.renderYAxis(\n          container,\n          panel.getViewport(),\n          type === 'main' ? 'price' : 'volume',\n          data\n        );\n      }\n    });\n    \n    // X축 렌더링 (하단에 한 번만)\n    const mainPanel = this.panels.get('main');\n    if (mainPanel && this.xAxisRenderer) {\n      this.xAxisRenderer.setCurrentCandleIndex(this.currentMouseCandleIndex);\n      this.xAxisRenderer.render(data, mainPanel.getViewport() as any);\n    }\n  }\n  \n  private resizePanels(): void {\n    // 공유 좌표계의 전체 크기는 유지하고, 패널별 높이만 업데이트\n    const pixelRatio = window.devicePixelRatio || 1;\n    \n    if (this.sharedCoordinateSystem) {\n      // 전체 컨테이너 크기로 설정 (X축 동기화를 위해)\n      this.sharedCoordinateSystem.resize(\n        this.container.clientWidth * pixelRatio,\n        this.container.clientHeight * pixelRatio\n      );\n    }\n    \n    this.panels.forEach((panel, type) => {\n      const container = this.panelContainers.get(type);\n      if (container) {\n        panel.resize(container.clientWidth, container.clientHeight);\n      }\n    });\n    \n    // 축 다시 렌더링\n    if (this.currentData) {\n      this.render(this.currentData);\n    }\n  }\n  \n  private updatePanelRatios(): void {\n    const totalHeight = this.container.clientHeight;\n    const containers = Array.from(this.panelContainers.values());\n    \n    containers.forEach((container, index) => {\n      const ratio = container.clientHeight / totalHeight;\n      this.panelConfigs[index].heightRatio = ratio;\n    });\n  }\n  \n  resize(): void {\n    // 전체 컨테이너 크기 변경 시\n    const totalHeight = this.container.clientHeight;\n    const xAxisHeight = 30;\n    const headerOffset = (this.options.useHeader && !this.options.disableUI) ? 48 : 0;\n    // 헤더와 X축을 제외한 실제 사용 가능한 높이\n    const availableHeight = Math.max(totalHeight - xAxisHeight - headerOffset, 200);\n    \n    if (availableHeight > 0) {\n      let accumulatedHeight = 0;\n      this.panelConfigs.forEach((config, index) => {\n        const container = this.panelContainers.get(config.type);\n        if (container) {\n          // 마지막 패널은 남은 공간을 모두 사용 (반올림 오차 방지)\n          const height = index === this.panelConfigs.length - 1\n            ? availableHeight - accumulatedHeight\n            : Math.floor(availableHeight * config.heightRatio);\n          \n          container.style.height = `${height}px`;\n          container.style.flex = `${config.heightRatio}`;\n          accumulatedHeight += height;\n        }\n      });\n    }\n    \n    this.resizePanels();\n  }\n  \n  getPanel(type: string): ChartPanel | undefined {\n    return this.panels.get(type);\n  }\n  \n  getMainPanel(): MainChartPanel | undefined {\n    return this.panels.get('main') as MainChartPanel;\n  }\n  \n  \n  updateTheme(theme: Theme, options?: Partial<ChartOptions>): void {\n    this.theme = theme;\n    this.axisRenderer.updateTheme(theme);\n    \n    // XAxisRenderer 테마 업데이트\n    if (this.xAxisRenderer) {\n      this.xAxisRenderer.updateTheme(theme);\n    }\n    \n    // 옵션 업데이트\n    if (options) {\n      this.options = { ...this.options, ...options };\n    }\n    \n    // X축 컨테이너 배경색 업데이트\n    if (this.xAxisContainer) {\n      this.xAxisContainer.style.background = theme.background || theme.backgroundColor;\n      this.xAxisContainer.style.borderTopColor = this.options.panels?.divider?.color || theme.axis?.dividerColor || theme.axis?.unifiedColor || theme.grid || '#333333';\n    }\n    \n    // 리사이저 배경색 및 스타일 업데이트\n    const dividerOptions = this.options.panels?.divider;\n    const color = dividerOptions?.color || theme.grid || '#333333';\n    const thickness = dividerOptions?.thickness || 1;\n    \n    this.resizers.forEach(resizer => {\n      resizer.style.background = color;\n      resizer.style.height = `${thickness}px`;\n    });\n    \n    // 컨테이너 배경색 업데이트\n    this.container.style.background = theme.background || theme.backgroundColor;\n    \n    // 각 패널에 테마 업데이트 전파\n    this.panels.forEach(panel => {\n      if ('updateTheme' in panel) {\n        (panel as any).updateTheme(theme, options);\n      }\n    });\n  }\n  \n  /**\n   * 마우스 위치에 해당하는 캔들 인덱스 설정\n   */\n  setMouseCandleIndex(index: number): void {\n    this.currentMouseCandleIndex = index;\n  }\n  \n  /**\n   * 마우스 X 위치를 모든 패널에 전파\n   */\n  setMouseX(x: number): void {\n    // VolumePanel에 마우스 X 위치 전달\n    const volumePanel = this.panels.get('volume');\n    if (volumePanel && 'setMouseX' in volumePanel) {\n      (volumePanel as any).setMouseX(x);\n    }\n  }\n  \n  dispose(): void {\n    // 타이머 정리\n    if (this.resizeTimeout) {\n      clearTimeout(this.resizeTimeout);\n      this.resizeTimeout = null;\n    }\n    \n    // 이벤트 리스너 제거\n    this.resizerEventListeners.forEach(listener => listener.remove());\n    this.resizerEventListeners = [];\n    \n    // 패널 정리\n    this.panels.forEach(panel => panel.dispose());\n    this.panels.clear();\n    this.panelContainers.clear();\n    this.resizers = [];\n    \n    if (this.xAxisRenderer) {\n      this.xAxisRenderer.dispose();\n      this.xAxisRenderer = null;\n    }\n  }\n}","import type { Theme, ChartOptions, ChartData, ChartType, IndicatorData } from '@/types';\nimport { PanelManager } from './PanelManager';\nimport { WebGLRenderer } from './WebGLRenderer';\nimport { UnifiedCoordinateSystem } from './UnifiedCoordinateSystem';\nimport { MainChartPanel } from '@/panels/MainChartPanel';\nimport { VolumePanel } from '@/panels/VolumePanel';\nimport type { DataManager } from './DataManager';\nimport type { InteractionManager } from './InteractionManager';\nimport type { PluginManager } from './PluginManager';\n\n/**\n * 렌더링 관련 기능을 통합 관리하는 매니저\n * - 패널 관리\n * - 렌더러 관리\n * - 좌표계 관리\n * - 테마 관리\n */\nexport class RenderingManager {\n  private panelManager: PanelManager;\n  private renderer: WebGLRenderer | null = null;\n  private coordSystem: UnifiedCoordinateSystem | null = null;\n  private _theme: Theme;  // updateTheme에서 사용\n  private options: ChartOptions;\n  private _container: HTMLElement;  // resize에서 사용\n  private chartType: ChartType = 'candle';\n\n  constructor(container: HTMLElement, theme: Theme, options: ChartOptions) {\n    this._container = container;\n    this._theme = theme;\n    this.options = options;\n    \n    // WebGLRenderer는 각 패널이 생성할 때 만들어짐\n    // 임시로 비워둡니다\n    this.renderer = null;\n    this.coordSystem = null;\n    \n    // PanelManager 생성 - 새로운 시그니처에 맞게\n    this.panelManager = new PanelManager(\n      container,\n      theme,\n      null as any, // indicatorManager - 나중에 설정\n      null as any, // drawingManager - 나중에 설정\n      null as any, // stopLossManager - 나중에 설정\n      options\n    );\n  }\n\n  async init(): Promise<void> {\n    // 렌더러는 생성자에서 이미 초기화됨\n    \n    // 패널 매니저 초기화\n    await this.panelManager.init();\n  }\n\n  // 의존성 주입을 위한 setter들\n  setDataManager(dataManager: DataManager): void {\n    this.panelManager['dataManager'] = dataManager;\n    if (this.coordSystem) {\n      this.coordSystem.setDataManager(dataManager);\n    }\n  }\n\n  setInteractionManager(interactionManager: InteractionManager): void {\n    // InteractionManager에서 필요한 매니저들 추출\n    this.panelManager['drawingManager'] = interactionManager.drawingManager;\n    this.panelManager['markerManager'] = interactionManager.markerManager;\n    this.panelManager['lineSeriesManager'] = interactionManager.lineSeriesManager;\n    this.panelManager['stopLossManager'] = interactionManager.stopLossManager;\n  }\n\n  setPluginManager(pluginManager: PluginManager): void {\n    // PluginManager에서 indicatorManager 추출\n    this.panelManager['indicatorManager'] = pluginManager.indicatorManager;\n  }\n\n  // PanelManager 위임 메서드들\n  getMainPanel(): MainChartPanel | null {\n    const panel = this.panelManager.getMainPanel();\n    return panel || null;\n  }\n\n  getVolumePanel(): VolumePanel | null {\n    const panel = this.panelManager.getPanel('volume') as VolumePanel;\n    return panel || null;\n  }\n\n  getPanels(): { main: MainChartPanel | null; volume: VolumePanel | null } {\n    return {\n      main: this.getMainPanel(),\n      volume: this.getVolumePanel()\n    };\n  }\n\n  getPanel(type: string): MainChartPanel | VolumePanel | null {\n    const panel = this.panelManager.getPanel(type);\n    return panel as MainChartPanel | VolumePanel | null;\n  }\n\n  // 렌더링 메서드\n  render(data: ChartData, _indicators?: Map<string, IndicatorData>): void {\n    this.panelManager.render(data);\n  }\n\n  // 마우스 위치 관리\n  setMouseCandleIndex(index: number): void {\n    this.panelManager.setMouseCandleIndex(index);\n  }\n\n  // 차트 타입 관리\n  setChartType(type: ChartType): void {\n    this.chartType = type;\n    const mainPanel = this.getMainPanel();\n    if (mainPanel) {\n      mainPanel.setChartType(type);\n    }\n  }\n\n  getChartType(): ChartType {\n    return this.chartType;\n  }\n\n  // 좌표계 접근\n  getCoordinateSystem(): UnifiedCoordinateSystem | null {\n    return this.coordSystem;\n  }\n\n  // 렌더러 접근\n  getRenderer(): WebGLRenderer | null {\n    return this.renderer;\n  }\n\n  // 크기 조정\n  resize(_width?: number, _height?: number): void {\n    // 컨테이너 크기 가져오기\n    // w, h 변수는 사용하지 않지만 나중을 위해 계산은 유지\n    \n    // 렌더러 크기 조정\n    if (this.renderer) {\n      this.renderer.resize();\n    }\n    \n    // 좌표계 크기 조정\n    if (this.coordSystem && this.renderer) {\n      this.coordSystem.resize(\n        this.renderer.getWidth(),\n        this.renderer.getHeight()\n      );\n    }\n    \n    // 패널 크기 조정\n    this.panelManager.resize();\n  }\n\n  // 테마 업데이트\n  updateTheme(theme: Theme): void {\n    this._theme = theme;\n    this.panelManager.updateTheme(theme);\n  }\n\n  // 옵션 업데이트\n  updateOptions(options: Partial<ChartOptions>): void {\n    this.options = { ...this.options, ...options };\n    // TODO: PanelManager에 updateOptions 메서드 구현 필요\n    // this.panelManager.updateOptions(options);\n  }\n\n  // 캔들 색상 업데이트\n  updateCandleColors(theme: Theme): void {\n    const mainPanel = this.getMainPanel();\n    if (mainPanel) {\n      mainPanel.updateCandleColors(theme);\n    }\n  }\n\n  // 범위 관련 메서드들\n  setVisibleRange(_startIndex: number, _endIndex: number): void {\n    if (this.coordSystem) {\n      // TODO: UnifiedCoordinateSystem에 setVisibleRange 메서드 구현 필요\n      // this.coordSystem.setVisibleRange(startIndex, endIndex);\n    }\n  }\n\n  pan(deltaX: number): void {\n    if (this.coordSystem) {\n      this.coordSystem.pan(deltaX);\n    }\n  }\n\n  zoom(factor: number, centerX?: number): void {\n    if (this.coordSystem) {\n      this.coordSystem.zoom(factor, centerX || (this.renderer?.getWidth() ?? 0) / 2);\n    }\n  }\n\n  zoomToRange(_startIndex: number, _endIndex: number): void {\n    if (this.coordSystem) {\n      // const padding = 10;  // 나중에 사용\n      // 나중에 사용할 수 있도록 계산은 유지\n      // TODO: UnifiedCoordinateSystem에 setVisibleRange 메서드 구현 필요\n      // this.coordSystem.setVisibleRange(adjustedStart, adjustedEnd);\n    }\n  }\n\n  getVisibleRange(): { start: number; end: number } {\n    if (this.coordSystem) {\n      return this.coordSystem.getVisibleRange();\n    }\n    return { start: 0, end: 0 };\n  }\n\n  // 마우스 좌표 변환\n  cssToCanvas(cssX: number, cssY: number): { x: number; y: number } {\n    if (this.coordSystem) {\n      return this.coordSystem.cssToCanvas(cssX, cssY);\n    }\n    return { x: 0, y: 0 };\n  }\n\n  canvasToChart(canvasX: number, canvasY: number): { time: number; price: number } {\n    if (this.coordSystem) {\n      return this.coordSystem.canvasToChart(canvasX, canvasY);\n    }\n    return { time: 0, price: 0 };\n  }\n\n  dispose(): void {\n    // 패널 매니저 정리\n    this.panelManager.dispose();\n    \n    // 렌더러 정리\n    if (this.renderer) {\n      this.renderer.dispose();\n      this.renderer = null;\n    }\n    \n    // 좌표계는 별도 dispose 없음\n    this.coordSystem = null;\n  }\n}","import type { ChartData, IndicatorParams } from '@/types';\n\n// IndicatorParams는 types/indicator.ts에서 import\n// 여기서는 확장된 타입만 정의\nexport interface ExtendedIndicatorParams extends Record<string, any> {\n  period?: number;\n  periods?: number[];\n  color?: string;\n  colors?: string[];\n  multiplier?: number;\n  source?: 'close' | 'open' | 'high' | 'low' | 'hl2' | 'hlc3' | 'ohlc4';\n}\n\n// 내부 플러그인용 설정 (엄격한 타입)\nexport interface InternalIndicatorConfig {\n  id: string;\n  name: string;\n  type: string;\n  params: ExtendedIndicatorParams;\n  style: {\n    color: string;\n    lineWidth: number;\n    lineStyle: 'solid' | 'dashed' | 'dotted';\n    opacity: number;\n  };\n  visible: boolean;\n}\n\nexport interface IndicatorPlugin {\n  id: string;\n  name: string;\n  description: string;\n  defaultConfig: Partial<InternalIndicatorConfig>;\n  \n  // 계산 함수\n  calculate(data: ChartData, params: IndicatorParams): Float32Array | null;\n  \n  // 여러 라인을 계산하는 경우 (MA Cluster 등)\n  calculateAll?(data: ChartData, params: IndicatorParams): Map<string, Float32Array>;\n  \n  // 프리셋 가져오기 (MA Cluster 등)\n  getPreset?(name: string): IndicatorParams | null;\n  \n  // 설정 스키마 (UI 생성용)\n  configSchema: {\n    params: Array<{\n      key: string;\n      label: string;\n      type: 'number' | 'select' | 'color' | 'range';\n      default: string | number | boolean;\n      min?: number;\n      max?: number;\n      step?: number;\n      options?: Array<{ value: string | number; label: string }>;\n    }>;\n  };\n}\n\n// 플러그인 레지스트리\nexport class IndicatorPluginRegistry {\n  private static plugins: Map<string, IndicatorPlugin> = new Map();\n  \n  static register(plugin: IndicatorPlugin): void {\n    this.plugins.set(plugin.id, plugin);\n  }\n  \n  static get(id: string): IndicatorPlugin | undefined {\n    return this.plugins.get(id);\n  }\n  \n  static getAll(): IndicatorPlugin[] {\n    return Array.from(this.plugins.values());\n  }\n}","/**\n * Simple Moving Average (SMA) 계산\n */\nexport function calculateSMA(data: Float32Array, period: number): Float32Array | null {\n  if (data.length < period) return null;\n  \n  const result = new Float32Array(data.length);\n  result.fill(NaN, 0, period - 1);\n  \n  // 첫 번째 SMA 계산\n  let sum = 0;\n  for (let i = 0; i < period; i++) {\n    sum += data[i];\n  }\n  result[period - 1] = sum / period;\n  \n  // 나머지 SMA 계산 (슬라이딩 윈도우)\n  for (let i = period; i < data.length; i++) {\n    sum = sum - data[i - period] + data[i];\n    result[i] = sum / period;\n  }\n  \n  return result;\n}","import type { IndicatorPlugin } from '../IndicatorPlugin';\nimport type { ChartData, IndicatorParams } from '@/types';\nimport { calculateSMA } from '@/indicators/SMA';\n\nexport const SMAPlugin: IndicatorPlugin = {\n  id: 'sma',\n  name: 'Simple Moving Average',\n  description: 'The Simple Moving Average (SMA) calculates the average price over a specific number of periods.',\n  \n  defaultConfig: {\n    params: {\n      period: 20,\n      source: 'close'\n    },\n    style: {\n      color: '#2196f3',\n      lineWidth: 2,\n      lineStyle: 'solid',\n      opacity: 1\n    }\n  },\n  \n  calculate(data: ChartData, params: IndicatorParams): Float32Array | null {\n    const source = params.source || 'close';\n    let values: Float32Array;\n    \n    switch (source) {\n      case 'open':\n        values = data.opens;\n        break;\n      case 'high':\n        values = data.highs;\n        break;\n      case 'low':\n        values = data.lows;\n        break;\n      case 'close':\n      default:\n        values = data.closes;\n        break;\n    }\n    \n    return calculateSMA(values, params.period || 20);\n  },\n  \n  configSchema: {\n    params: [\n      {\n        key: 'period',\n        label: 'Period',\n        type: 'number',\n        default: 20,\n        min: 1,\n        max: 500,\n        step: 1\n      },\n      {\n        key: 'source',\n        label: 'Source',\n        type: 'select',\n        default: 'close',\n        options: [\n          { value: 'open', label: 'Open' },\n          { value: 'high', label: 'High' },\n          { value: 'low', label: 'Low' },\n          { value: 'close', label: 'Close' }\n        ]\n      }\n    ]\n  }\n};","/**\n * Exponential Moving Average (EMA) 계산\n */\nexport function calculateEMA(data: Float32Array, period: number): Float32Array | null {\n  if (data.length < period) return null;\n  \n  const result = new Float32Array(data.length);\n  result.fill(NaN, 0, period - 1);\n  \n  // 승수 계산\n  const multiplier = 2 / (period + 1);\n  \n  // 첫 번째 EMA는 SMA로 시작\n  let sum = 0;\n  for (let i = 0; i < period; i++) {\n    sum += data[i];\n  }\n  result[period - 1] = sum / period;\n  \n  // 나머지 EMA 계산\n  for (let i = period; i < data.length; i++) {\n    result[i] = (data[i] - result[i - 1]) * multiplier + result[i - 1];\n  }\n  \n  return result;\n}","import type { IndicatorPlugin } from '../IndicatorPlugin';\nimport type { ChartData, IndicatorParams } from '@/types';\nimport { calculateEMA } from '@/indicators/EMA';\n\nexport const EMAPlugin: IndicatorPlugin = {\n  id: 'ema',\n  name: 'Exponential Moving Average',\n  description: 'The Exponential Moving Average (EMA) gives more weight to recent prices.',\n  \n  defaultConfig: {\n    params: {\n      period: 20,\n      source: 'close'\n    },\n    style: {\n      color: '#ff9800',\n      lineWidth: 2,\n      lineStyle: 'solid',\n      opacity: 1\n    }\n  },\n  \n  calculate(data: ChartData, params: IndicatorParams): Float32Array | null {\n    const source = params.source || 'close';\n    let values: Float32Array;\n    \n    switch (source) {\n      case 'open':\n        values = data.opens;\n        break;\n      case 'high':\n        values = data.highs;\n        break;\n      case 'low':\n        values = data.lows;\n        break;\n      case 'close':\n      default:\n        values = data.closes;\n        break;\n    }\n    \n    return calculateEMA(values, params.period || 20);\n  },\n  \n  configSchema: {\n    params: [\n      {\n        key: 'period',\n        label: 'Period',\n        type: 'number',\n        default: 20,\n        min: 1,\n        max: 500,\n        step: 1\n      },\n      {\n        key: 'source',\n        label: 'Source',\n        type: 'select',\n        default: 'close',\n        options: [\n          { value: 'open', label: 'Open' },\n          { value: 'high', label: 'High' },\n          { value: 'low', label: 'Low' },\n          { value: 'close', label: 'Close' }\n        ]\n      }\n    ]\n  }\n};","import { IndicatorPluginRegistry } from '../IndicatorPlugin';\nimport { SMAPlugin } from './SMAPlugin';\nimport { EMAPlugin } from './EMAPlugin';\n\n// 모든 인디케이터 플러그인 등록\nexport function registerIndicatorPlugins(): void {\n  IndicatorPluginRegistry.register(SMAPlugin);\n  IndicatorPluginRegistry.register(EMAPlugin);\n  \n  // console.log('Registered indicator plugins:', {\n  //   sma: IndicatorPluginRegistry.get('sma') ? 'OK' : 'Missing',\n  //   ema: IndicatorPluginRegistry.get('ema') ? 'OK' : 'Missing'\n  // });\n}\n\nexport { IndicatorPluginRegistry };","import type { ChartData, IndicatorData, IndicatorConfig, IndicatorParams } from '@/types';\nimport { IndicatorPluginRegistry } from '@/plugins/indicators';\n\nexport class IndicatorManager {\n  private indicators: Map<string, IndicatorConfig> = new Map();\n  private indicatorData: Map<string, IndicatorData> = new Map();\n  private nextId: number = 1;\n  \n  constructor() {}\n  \n  /**\n   * 인디케이터 추가\n   */\n  addIndicator(type: string | IndicatorConfig, params?: IndicatorParams): string {\n    let indicatorType: string;\n    let indicatorParams: IndicatorParams;\n    let indicatorStyle: IndicatorConfig['style'] | null = null;\n    let indicatorId: string | null = null;\n    \n    // type이 객체인 경우 (UI의 IndicatorManager에서 호출 또는 Chart.addSMA/addEMA에서 호출)\n    if (typeof type === 'object' && type.type) {\n      indicatorType = type.type;\n      indicatorParams = type.params || {};\n      indicatorStyle = type.style || null;\n      indicatorId = type.id || null;\n    } else if (typeof type === 'string') {\n      // type이 문자열인 경우 (직접 호출)\n      indicatorType = type;\n      indicatorParams = params || {};\n    } else {\n      console.error('Invalid indicator type:', type);\n      return '';\n    }\n    \n    const plugin = IndicatorPluginRegistry.get(indicatorType.toLowerCase());\n    if (!plugin) {\n      console.error(`Indicator plugin not found: ${indicatorType}`);\n      return '';\n    }\n    \n    const id = indicatorId || `indicator_${this.nextId++}`;\n    \n    // MA Cluster의 경우 defaultConfig의 lines를 깊은 복사\n    let finalParams = { ...plugin.defaultConfig.params, ...indicatorParams };\n    if (indicatorType === 'ma-cluster' && plugin.defaultConfig.params?.lines && !indicatorParams?.lines) {\n      finalParams.lines = JSON.parse(JSON.stringify(plugin.defaultConfig.params!.lines));\n    }\n    \n    const config: IndicatorConfig = {\n      id,\n      name: plugin.name,\n      type: plugin.id,\n      params: finalParams,\n      style: indicatorStyle ? { ...plugin.defaultConfig.style!, ...indicatorStyle } : { ...plugin.defaultConfig.style! },\n      visible: true\n    };\n    \n    // console.log('Adding indicator:', { id, type, params: finalParams, style: config.style });\n    \n    this.indicators.set(id, config);\n    return id;\n  }\n  \n  /**\n   * 인디케이터 제거\n   */\n  removeIndicator(id: string): void {\n    const indicator = this.indicators.get(id);\n    \n    // MA Cluster의 경우 모든 라인 제거\n    if (indicator && indicator.type === 'ma-cluster') {\n      // id로 시작하는 모든 데이터 제거\n      const keysToRemove: string[] = [];\n      this.indicatorData.forEach((_, key) => {\n        if (key.startsWith(id + '_')) {\n          keysToRemove.push(key);\n        }\n      });\n      keysToRemove.forEach(key => this.indicatorData.delete(key));\n    } else {\n      this.indicatorData.delete(id);\n    }\n    \n    this.indicators.delete(id);\n  }\n  \n  /**\n   * 인디케이터 표시/숨김\n   */\n  toggleIndicator(id: string): void {\n    const indicator = this.indicators.get(id);\n    if (indicator) {\n      indicator.visible = !indicator.visible;\n    }\n  }\n  \n  /**\n   * 인디케이터 업데이트\n   */\n  updateIndicator(id: string, config: Partial<IndicatorConfig>): void {\n    const indicator = this.indicators.get(id);\n    if (indicator) {\n      if (config.params) {\n        indicator.params = { ...indicator.params, ...config.params };\n      }\n      if (config.style) {\n        indicator.style = { ...indicator.style, ...config.style };\n      }\n      if (config.visible !== undefined) {\n        indicator.visible = config.visible;\n      }\n    }\n  }\n  \n  /**\n   * 인디케이터 가져오기\n   */\n  getIndicator(id: string): IndicatorConfig | undefined {\n    return this.indicators.get(id);\n  }\n  \n  /**\n   * 모든 인디케이터 계산\n   */\n  calculateAll(data: ChartData): void {\n    this.indicatorData.clear();\n    \n    // console.log('Calculating indicators:', this.indicators.size);\n    \n    for (const [id, config] of this.indicators) {\n      if (!config.visible) continue;\n      \n      const plugin = IndicatorPluginRegistry.get(config.type);\n      if (!plugin) {\n        console.error('Plugin not found:', config.type);\n        continue;\n      }\n      \n      // MA Cluster는 calculateAll 메서드를 사용\n      if (config.type === 'ma-cluster' && plugin.calculateAll) {\n        // console.log('Processing MA Cluster:', { id, config });\n        const allValues = plugin.calculateAll(data, config.params);\n        // console.log('MA Cluster calculated values:', allValues);\n        \n        // 각 라인을 별도의 IndicatorData로 저장\n        allValues.forEach((values, lineKey) => {\n          const lineIndex = parseInt(lineKey.split('_')[1]);\n          const lineConfig = config.params.lines[lineIndex];\n          // console.log(`Processing line ${lineIndex}:`, { lineKey, lineConfig, valuesLength: values.length });\n          \n          if (lineConfig && lineConfig.enabled) {\n            const lineId = `${id}_${lineKey}`;\n            // console.log(`Calculated MA Cluster line ${lineIndex}:`, {\n            //   lineId,\n            //   type: lineConfig.type,\n            //   period: lineConfig.period,\n            //   length: values.length\n            // });\n            \n            // 개별 라인의 설정을 포함한 새로운 config 생성\n            const lineIndicatorConfig = {\n              ...config,\n              style: {\n                ...config.style,\n                color: lineConfig.color || config.style?.color,\n                lineWidth: lineConfig.lineWidth || config.style?.lineWidth\n              },\n              // MA 라인 정보 추가\n              maLineInfo: {\n                type: lineConfig.type,\n                period: lineConfig.period,\n                color: lineConfig.color,\n                enabled: lineConfig.enabled\n              }\n            };\n            \n            // Float32Array를 IndicatorData 형식으로 변환\n            const convertedValues = [];\n            for (let i = 0; i < values.length; i++) {\n              convertedValues.push({\n                time: data.times[i],\n                value: values[i]\n              });\n            }\n            \n            this.indicatorData.set(lineId, {\n              id: lineId,\n              type: config.type,\n              values: convertedValues,\n              config: lineIndicatorConfig,\n              visible: config.visible && lineConfig.enabled\n            } as any);\n          }\n        });\n      } else {\n        // 기존 인디케이터는 calculate 메서드 사용\n        const values = plugin.calculate(data, config.params);\n        \n        if (values) {\n          // console.log(`Calculated ${config.type} indicator:`, {\n          //   id,\n          //   length: values.length,\n          //   sample: [values[20], values[21], values[22]]\n          // });\n          \n          // Float32Array를 IndicatorData 형식으로 변환\n          const convertedValues = [];\n          for (let i = 0; i < values.length; i++) {\n            convertedValues.push({\n              time: data.times[i],\n              value: values[i]\n            });\n          }\n          \n          this.indicatorData.set(id, {\n            id,\n            type: config.type,\n            values: convertedValues,\n            config,\n            visible: config.visible\n          } as any);\n        }\n      }\n    }\n    \n    // console.log('Visible indicators:', this.indicatorData.size);\n  }\n  \n  /**\n   * 표시할 인디케이터 데이터 가져오기\n   */\n  getVisibleIndicators(): IndicatorData[] {\n    const visibleIndicators = Array.from(this.indicatorData.values()).filter(data => {\n      const config = this.indicators.get(data.id);\n      return config?.visible ?? true;\n    });\n    // console.log('Getting visible indicators:', visibleIndicators.length, 'out of', this.indicatorData.size);\n    return visibleIndicators;\n  }\n  \n  /**\n   * 인디케이터 데이터 Map 가져오기 (PanelManager에서 사용)\n   */\n  getIndicatorData(): Map<string, IndicatorData> {\n    return this.indicatorData;\n  }\n  \n  /**\n   * 모든 인디케이터 가져오기\n   */\n  getIndicators(): IndicatorConfig[] {\n    return Array.from(this.indicators.values());\n  }\n  \n  /**\n   * 모든 인디케이터 설정 가져오기\n   */\n  getAllIndicators(): IndicatorConfig[] {\n    return Array.from(this.indicators.values());\n  }\n  \n  /**\n   * 모두 지우기\n   */\n  clear(): void {\n    this.indicators.clear();\n    this.indicatorData.clear();\n  }\n}","import type { ChartData, IndicatorData, IndicatorConfig, IndicatorParams } from '@/types';\nimport { IndicatorManager } from './IndicatorManager';\n\n/**\n * 플러그인 및 인디케이터 관련 기능을 통합 관리하는 매니저\n * - 인디케이터 관리 (기존 IndicatorManager 기능)\n * - 향후 다른 플러그인 확장 가능\n */\nexport class PluginManager {\n  public indicatorManager: IndicatorManager;\n  \n  constructor() {\n    this.indicatorManager = new IndicatorManager();\n  }\n  \n  // IndicatorManager 메서드들을 위임\n  addIndicator(type: string | IndicatorConfig, params?: IndicatorParams): string {\n    return this.indicatorManager.addIndicator(type, params);\n  }\n  \n  removeIndicator(id: string): void {\n    this.indicatorManager.removeIndicator(id);\n  }\n  \n  toggleIndicator(id: string): void {\n    this.indicatorManager.toggleIndicator(id);\n  }\n  \n  updateIndicator(id: string, config: Partial<IndicatorConfig>): void {\n    this.indicatorManager.updateIndicator(id, config);\n  }\n  \n  getIndicator(id: string): IndicatorConfig | undefined {\n    return this.indicatorManager.getIndicator(id);\n  }\n  \n  calculateAll(data: ChartData): void {\n    this.indicatorManager.calculateAll(data);\n  }\n  \n  getVisibleIndicators(): IndicatorData[] {\n    return this.indicatorManager.getVisibleIndicators();\n  }\n  \n  getIndicatorData(): Map<string, IndicatorData> {\n    return this.indicatorManager.getIndicatorData();\n  }\n  \n  getIndicators(): IndicatorConfig[] {\n    return this.indicatorManager.getIndicators();\n  }\n  \n  getAllIndicators(): IndicatorConfig[] {\n    return this.indicatorManager.getAllIndicators();\n  }\n  \n  clearIndicators(): void {\n    this.indicatorManager.clear();\n  }\n  \n  // 향후 플러그인 확장을 위한 메서드들\n  registerPlugin(_type: string, _plugin: any): void {\n    // TODO: 플러그인 등록 로직\n  }\n  \n  unregisterPlugin(_type: string): void {\n    // TODO: 플러그인 해제 로직\n  }\n  \n  getPlugin(_type: string): any {\n    // TODO: 플러그인 가져오기 로직\n    return null;\n  }\n  \n  dispose(): void {\n    this.indicatorManager.clear();\n  }\n}","import type { Theme } from '@/types';\n\nexport const darkTheme: Theme = {\n  backgroundColor: '#131722',\n  textColor: '#d1d4dc',\n  gridColor: '#1e222d',\n  borderColor: '#2a2e39',\n  \n  candle: {\n    upColor: '#26a69a',\n    downColor: '#ef5350',\n    borderUpColor: '#26a69a',\n    borderDownColor: '#ef5350',\n    wickUpColor: '#26a69a',\n    wickDownColor: '#ef5350'\n  },\n  \n  volume: {\n    upColor: '#26a69a',\n    downColor: '#ef5350'\n  },\n  \n  crosshair: {\n    color: '#a0a0a0',\n    labelBackgroundColor: '#1e222d',\n    labelTextColor: '#ffffff',\n    labelBackground: '#1e222d'\n  },\n  \n  selection: {\n    backgroundColor: '#131722',\n    borderColor: '#4c525e'\n  },\n  \n  // 레거시 호환성\n  background: '#131722',\n  grid: '#1e222d',\n  text: '#d1d4dc',\n  axis: {\n    text: '#758696',\n    line: '#2a2e39',\n    // 기본값: 텍스트와 구분선 모두 동일한 색상 사용\n    unifiedColor: '#758696',\n    dividerColor: '#2a2e39',\n    textColor: '#758696'\n  }\n};\n\nexport const lightTheme: Theme = {\n  backgroundColor: '#ffffff',\n  textColor: '#131722',\n  gridColor: '#f0f3fa',\n  borderColor: '#e1e4eb',\n  \n  candle: {\n    upColor: '#26a69a',\n    downColor: '#ef5350',\n    borderUpColor: '#26a69a',\n    borderDownColor: '#ef5350',\n    wickUpColor: '#26a69a',\n    wickDownColor: '#ef5350'\n  },\n  \n  volume: {\n    upColor: '#26a69a',\n    downColor: '#ef5350'\n  },\n  \n  crosshair: {\n    color: '#758696',\n    labelBackgroundColor: '#f0f3fa',\n    labelTextColor: '#000000',\n    labelBackground: '#f0f3fa'\n  },\n  \n  selection: {\n    backgroundColor: '#ffffff',\n    borderColor: '#c1c4cd'\n  },\n  \n  // 레거시 호환성\n  background: '#ffffff',\n  grid: '#f0f3fa',\n  text: '#131722',\n  axis: {\n    text: '#787b86',\n    line: '#e1e4eb',\n    // 기본값: 텍스트와 구분선 모두 동일한 색상 사용\n    unifiedColor: '#787b86',\n    dividerColor: '#e1e4eb',\n    textColor: '#787b86'\n  }\n};\n\nexport function getTheme(theme: 'dark' | 'light' | Theme): Theme {\n  if (typeof theme === 'string') {\n    return theme === 'dark' ? darkTheme : lightTheme;\n  }\n  return theme;\n}","import type { Chart } from '../Chart';\nimport type { ChartPoint } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\nexport class ChartEventHandler {\n  private chart: Chart;\n  \n  // 마우스 상태\n  private isDragging: boolean = false;\n  private lastMouseX: number = 0;\n  private currentMouseX: number = -1;\n  private currentMouseY: number = -1;\n  private lastMouseCSSPosition: { x: number, y: number } | null = null;\n  \n  // 드로잉 상태\n  private isMagneticMode: boolean = false;\n  \n  // 이벤트 핸들러 바인딩\n  private boundHandleResize = this.handleResize.bind(this);\n  private boundHandleWheel = this.handleWheel.bind(this);\n  private boundHandleMouseDown = this.handleMouseDown.bind(this);\n  private boundHandleMouseMove = this.handleMouseMove.bind(this);\n  private boundHandleMouseUp = this.handleMouseUp.bind(this);\n  private boundHandleMouseLeave = this.handleMouseLeave.bind(this);\n  private boundHandleKeyDown = this.handleKeyDown.bind(this);\n  private boundHandleKeyUp = this.handleKeyUp.bind(this);\n  private boundHandleContextMenu = this.handleContextMenu.bind(this);\n\n  constructor(chart: Chart) {\n    this.chart = chart;\n  }\n  \n  // 단축키 매칭 헬퍼 메서드\n  private matchesShortcut(event: KeyboardEvent, shortcut: string): boolean {\n    // shortcut 포맷: \"Alt+T\", \"Ctrl+Z\", \"Shift+Click\" 등\n    const parts = shortcut.toLowerCase().split('+');\n    const key = parts[parts.length - 1];\n    \n    // 특수 키 체크\n    const needsCtrl = parts.includes('ctrl');\n    const needsAlt = parts.includes('alt');\n    const needsShift = parts.includes('shift');\n    \n    // 현재 이벤트와 비교\n    if (needsCtrl && !event.ctrlKey) return false;\n    if (needsAlt && !event.altKey) return false;\n    if (needsShift && !event.shiftKey) return false;\n    \n    // 키 비교\n    return event.key.toLowerCase() === key;\n  }\n  \n  // 기본 단축키 또는 커스텀 단축키 가져오기\n  private getShortcut(action: string, defaultShortcut: string): string {\n    return this.chart['options'].shortcuts?.[action] || defaultShortcut;\n  }\n\n  setupEventListeners(): void {\n    // 윈도우 리사이즈\n    window.addEventListener('resize', this.boundHandleResize);\n    \n    // 마우스 이벤트 - 메인 패널 캔버스에서만\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (mainPanel) {\n      const canvas = mainPanel['canvas'];\n      canvas.addEventListener('wheel', this.boundHandleWheel);\n      canvas.addEventListener('mousedown', this.boundHandleMouseDown);\n      canvas.addEventListener('mousemove', this.boundHandleMouseMove);\n      canvas.addEventListener('mouseup', this.boundHandleMouseUp);\n      canvas.addEventListener('mouseleave', this.boundHandleMouseLeave);\n      canvas.addEventListener('contextmenu', this.boundHandleContextMenu);\n    }\n    \n    // 키보드 이벤트\n    document.addEventListener('keydown', this.boundHandleKeyDown);\n    document.addEventListener('keyup', this.boundHandleKeyUp);\n  }\n\n  removeEventListeners(): void {\n    window.removeEventListener('resize', this.boundHandleResize);\n    document.removeEventListener('keydown', this.boundHandleKeyDown);\n    document.removeEventListener('keyup', this.boundHandleKeyUp);\n    \n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (mainPanel) {\n      const canvas = mainPanel['canvas'];\n      canvas.removeEventListener('wheel', this.boundHandleWheel);\n      canvas.removeEventListener('mousedown', this.boundHandleMouseDown);\n      canvas.removeEventListener('mousemove', this.boundHandleMouseMove);\n      canvas.removeEventListener('mouseup', this.boundHandleMouseUp);\n      canvas.removeEventListener('mouseleave', this.boundHandleMouseLeave);\n      canvas.removeEventListener('contextmenu', this.boundHandleContextMenu);\n    }\n  }\n\n  private handleResize(): void {\n    this.chart['renderingManager'].resize();\n    this.chart.setDirty(true);\n  }\n\n  private handleWheel(event: WheelEvent): void {\n    event.preventDefault();\n    \n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (!mainPanel) return;\n    \n    const viewport = mainPanel.getViewport();\n    \n    // 뷰포트 오른쪽 끝 캔들을 중심으로 줌 (트레이딩뷰 방식)\n    const visibleRange = viewport.getVisibleRange();\n    const rightmostCandleX = viewport.indexToCanvasX(visibleRange.end);\n    \n    const delta = event.deltaY;\n    const factor = delta > 0 ? 0.9 : 1.1;\n    \n    viewport.zoom(factor, rightmostCandleX);\n    \n    // 모든 패널의 viewport 동기화\n    this.chart['renderingManager'].getPanel('volume')?.getViewport().zoom(factor, rightmostCandleX);\n    \n    // 오토스케일이 켜져있으면 가격 범위 재계산\n    if (viewport.isAutoScale()) {\n      this.chart.updatePriceRangeForVisibleData();\n    }\n    \n    this.chart.setDirty(true);\n  }\n\n  private handleMouseDown(event: MouseEvent): void {\n    if (event.button === 0) { // 왼쪽 버튼\n      this.getCanvasCoordinates(event);\n      \n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      if (!mainPanel) return;\n      \n      mainPanel.getViewport();\n      \n      // 드로잉 모드이거나 선택된 드로잉이 있는지 확인\n      if (this.chart['interactionManager'].getActiveTool() || \n          this.chart['interactionManager']['drawingManager'].getSelectedDrawing()) {\n        // MainChartPanel이 이미 클릭 처리하므로 여기서는 처리하지 않음\n        return;\n      } else {\n        // 일반 드래그 시작\n        this.isDragging = true;\n        this.lastMouseX = event.clientX;\n      }\n    }\n  }\n\n  private handleMouseMove(event: MouseEvent): void {\n    this.getCanvasCoordinates(event);\n    \n    // 크로스헤어를 위한 CSS 좌표 (캔버스 기준)\n    const rect = (event.target as HTMLElement).getBoundingClientRect();\n    this.currentMouseX = event.clientX - rect.left;\n    this.currentMouseY = event.clientY - rect.top;\n    \n    // CSS 좌표도 저장 (Alt+H 등에서 사용)\n    this.lastMouseCSSPosition = {\n      x: this.currentMouseX,\n      y: this.currentMouseY\n    };\n    \n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (!mainPanel) return;\n    \n    const viewport = mainPanel.getViewport() as any; // UnifiedCoordinateSystem으로 실제 사용됨\n    \n    // 현재 캔들 인덱스 계산 및 전달\n    const pixelRatio = window.devicePixelRatio || 1;\n    const canvasX = this.currentMouseX * pixelRatio;\n    const candleIndex = viewport.canvasXToIndex(canvasX);\n    \n    this.chart['renderingManager'].setMouseCandleIndex(candleIndex);\n    \n    // 드래그로 차트 이동 (드로잉 모드가 아니고 선택된 드로잉도 없을 때만)\n    if (this.isDragging && !this.chart['interactionManager'].getActiveTool() && \n        !this.chart['interactionManager']['drawingManager'].getSelectedDrawing()) {\n      const deltaX = event.clientX - this.lastMouseX;\n      this.lastMouseX = event.clientX;\n      \n      // 모든 패널의 viewport 이동\n      viewport.pan(deltaX);\n      \n      // 다른 패널도 동기화\n      this.chart['renderingManager'].getPanel('volume')?.getViewport().pan(deltaX);\n      \n      this.chart.setDirty(true);\n    }\n    \n    this.chart.setDirty(true);\n  }\n\n  private handleMouseUp(_event: MouseEvent): void {\n    // 드래그가 끝났을 때\n    if (this.isDragging) {\n      this.isDragging = false;\n      \n      // 드래그 후 오토스케일 적용\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        if (viewport && viewport.isAutoScale()) {\n          this.chart.updatePriceRangeForVisibleData();\n        }\n      }\n    }\n  }\n\n  private handleMouseLeave(_event: MouseEvent): void {\n    this.isDragging = false;\n    this.currentMouseX = -1;\n    this.currentMouseY = -1;\n    this.chart['renderingManager'].setMouseCandleIndex(-1);\n    this.chart.setDirty(true);\n  }\n\n  private handleContextMenu(event: MouseEvent): void {\n    event.preventDefault();\n    \n    // 드로잉 모드 취소\n    if (this.chart['interactionManager'].getActiveTool()) {\n      this.chart['interactionManager'].setActiveTool(null);\n      this.chart['interactionManager'].cancelDrawing();\n      this.chart.setDirty(true);\n    }\n    // 가격 비교 모드 취소\n    else if (this.chart['interactionManager'].isMeasureMode()) {\n      this.chart['interactionManager'].cancelMeasure();\n      this.chart.setDirty(true);\n    }\n    // 일반 모드에서는 이벤트 전파를 허용하여 상위 모달 매니저가 처리할 수 있도록 함\n    else {\n      // stopPropagation을 하지 않음으로써 이벤트가 상위로 전파됨\n    }\n  }\n\n  private handleKeyDown(event: KeyboardEvent): void {\n    // ESC: 취소\n    if (event.key === 'Escape') {\n      event.preventDefault();\n      \n      // 가격 비교 모드 취소\n      if (this.chart['interactionManager'].isMeasureMode()) {\n        this.chart['interactionManager'].cancelMeasure();\n        this.chart.setDirty(true);\n      }\n      // 드로잉 모드 취소\n      else if (this.chart['interactionManager'].getActiveTool()) {\n        this.chart['interactionManager'].setActiveTool(null);\n        this.chart['interactionManager'].cancelDrawing();\n        // DrawingToolbar removed - tool state managed by DrawingManager\n        this.chart.setDirty(true);\n      }\n    }\n    \n    // 트렌드라인 모드\n    if (this.matchesShortcut(event, this.getShortcut('trendLine', 'Alt+T'))) {\n      event.preventDefault();\n      this.chart['interactionManager'].setActiveTool('trendline');\n      // DrawingToolbar removed - tool state managed by DrawingManager\n      this.chart.setDirty(true);\n    }\n    \n    // 마커 모드\n    if (this.matchesShortcut(event, this.getShortcut('marker', 'Alt+M'))) {\n      event.preventDefault();\n      this.chart['interactionManager'].setActiveTool('marker');\n      // DrawingToolbar removed - tool state managed by DrawingManager\n      this.chart.setDirty(true);\n    }\n    \n    // 원 그리기 모드\n    if (this.matchesShortcut(event, this.getShortcut('circle', 'Alt+C'))) {\n      event.preventDefault();\n      this.chart['interactionManager'].setActiveTool('circle');\n      // DrawingToolbar removed - tool state managed by DrawingManager\n      this.chart.setDirty(true);\n    }\n    \n    // 사각형 그리기 모드\n    if (this.matchesShortcut(event, this.getShortcut('rectangle', 'Alt+R'))) {\n      event.preventDefault();\n      this.chart['interactionManager'].setActiveTool('rectangle');\n      // DrawingToolbar removed - tool state managed by DrawingManager\n      this.chart.setDirty(true);\n    }\n    \n    // 텍스트 모드\n    if (this.matchesShortcut(event, this.getShortcut('text', 'Alt+X'))) {\n      event.preventDefault();\n      this.chart['interactionManager'].setActiveTool('text');\n      // DrawingToolbar removed - tool state managed by DrawingManager\n      this.chart.setDirty(true);\n    }\n    \n    // 즉시 수평선 생성\n    if (this.matchesShortcut(event, this.getShortcut('horizontalLine', 'Alt+H'))) {\n      event.preventDefault();\n      \n      if (this.lastMouseCSSPosition) {\n        const mainPanel = this.chart['renderingManager'].getMainPanel();\n        if (!mainPanel) return;\n        \n        const viewport = mainPanel.getViewport();\n        \n        // 크로스헤어와 동일한 방식으로 변환\n        const chartPoint = this.pixelToChartPoint(\n          this.lastMouseCSSPosition.x, \n          this.lastMouseCSSPosition.y,\n          viewport\n        );\n        \n        // 즉시 수평선 생성\n        this.chart['interactionManager'].createHorizontalLineImmediate(chartPoint);\n        this.chart.setDirty(true);\n      }\n    }\n    \n    // 차트뷰 리셋 (초기 상태로)\n    if (this.matchesShortcut(event, this.getShortcut('viewReset', 'Alt+V'))) {\n      event.preventDefault();\n      \n      // 초기 뷰 설정 적용\n      this.chart.applyInitialView();\n      this.chart.setDirty(true);\n    }\n    \n    // 차트뷰 고정/해제 토글\n    if (this.matchesShortcut(event, this.getShortcut('viewLock', 'Ctrl+Shift+C'))) {\n      event.preventDefault();\n      \n      // 차트뷰 고정/해제 토글\n      this.chart.toggleViewLock();\n      this.chart.setDirty(true);\n    }\n    \n    // Undo\n    if (this.matchesShortcut(event, this.getShortcut('undo', 'Ctrl+Z'))) {\n      event.preventDefault();\n      if (this.chart['interactionManager'].undo()) {\n        this.chart.setDirty(true);\n      }\n    }\n    \n    // Delete: 선택된 드로잉 삭제\n    if (event.key === 'Delete') {\n      event.preventDefault();\n      if (this.chart['interactionManager'].deleteSelectedDrawing()) {\n        this.chart.setDirty(true);\n      }\n    }\n    \n    // Redo\n    if (this.matchesShortcut(event, this.getShortcut('redo', 'Ctrl+Y'))) {\n      event.preventDefault();\n      if (this.chart['interactionManager'].redo()) {\n        this.chart.setDirty(true);\n      }\n    }\n    \n    // Ctrl 키: 마그네틱 모드\n    if (event.ctrlKey || event.metaKey) {\n      this.isMagneticMode = true;\n      this.chart['interactionManager'].setMagneticMode(true);\n    }\n    \n    // 선택된 드로잉 삭제\n    if (this.matchesShortcut(event, this.getShortcut('delete', 'Delete')) && !this.chart['interactionManager'].getActiveTool()) {\n      this.chart['interactionManager'].deleteSelectedDrawing();\n      this.chart.setDirty(true);\n    }\n  }\n\n  private handleKeyUp(event: KeyboardEvent): void {\n    // Ctrl 키 해제: 마그네틱 모드 해제\n    if (!event.ctrlKey && !event.metaKey) {\n      this.isMagneticMode = false;\n      this.chart['interactionManager'].setMagneticMode(false);\n    }\n  }\n\n  /**\n   * 마우스 이벤트 좌표를 캔버스 픽셀 좌표로 변환\n   */\n  private getCanvasCoordinates(event: MouseEvent): { x: number, y: number } {\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (!mainPanel) return { x: 0, y: 0 };\n    \n    const canvas = mainPanel['canvas'];\n    if (!canvas) return { x: 0, y: 0 };\n    \n    const rect = canvas.getBoundingClientRect();\n    \n    // CSS 좌표 (마우스 이벤트 좌표)\n    const cssX = event.clientX - rect.left;\n    const cssY = event.clientY - rect.top;\n    \n    // Canvas의 실제 픽셀 크기와 CSS 크기의 비율 계산\n    const scaleX = canvas.width / rect.width;\n    const scaleY = canvas.height / rect.height;\n    \n    // 실제 캔버스 픽셀 좌표로 변환\n    return {\n      x: cssX * scaleX,\n      y: cssY * scaleY\n    };\n  }\n\n  /**\n   * CSS 픽셀 좌표를 차트 좌표로 변환\n   */\n  private pixelToChartPoint(cssX: number, cssY: number, viewport: UnifiedCoordinateSystem): ChartPoint {\n    // UnifiedCoordinateSystem 직접 사용 - main 패널 지정\n    const chartPoint = viewport.cssToChart(cssX, cssY, 'main');\n    return chartPoint;\n  }\n\n  getMagneticMode(): boolean {\n    return this.isMagneticMode;\n  }\n\n  getCurrentMousePosition(): { x: number, y: number } {\n    return {\n      x: this.currentMouseX,\n      y: this.currentMouseY\n    };\n  }\n}","import type { Chart } from '../Chart';\n\nexport class ChartLifecycle {\n  private chart: Chart;\n  private resizeObserver: ResizeObserver | null = null;\n  private initPromise: Promise<void> | null = null;\n  private isInitialized: boolean = false;\n  private state: 'initializing' | 'ready' | 'updating' | 'error' = 'initializing';\n  private stateListeners: Set<(state: string) => void> = new Set();\n\n  constructor(chart: Chart) {\n    this.chart = chart;\n  }\n\n  async init(): Promise<void> {\n    try {\n      this.setState('initializing');\n      this.chart.debugLog('Chart initialization started');\n      \n      // 컨테이너 크기 확인 및 대기\n      await this.waitForContainer();\n      \n      // RenderingManager 초기화\n      const renderingManager = this.chart['renderingManager'];\n      await renderingManager.init();\n      \n      // 초기 resize 호출하여 viewport 크기 설정\n      renderingManager.resize();\n      \n      // 초기 차트 타입 설정\n      const options = this.chart.getOptions();\n      if (options.chartType) {\n        this.chart.setChartType(options.chartType);\n      }\n      \n      // ResizeObserver 설정\n      this.setupResizeObserver();\n      \n      // WebGL context 이벤트 핸들러 설정\n      this.setupContextHandlers();\n      \n      // 이벤트 리스너 등록\n      this.chart.getEventHandler().setupEventListeners();\n      \n      // 렌더링 루프 시작\n      this.chart.startRenderLoop();\n      \n      this.isInitialized = true;\n      this.setState('ready');\n      this.chart.debugLog('Chart initialized successfully');\n      // console.log('Chart initialized successfully');\n\n      // pendingData가 있으면 처리\n      const pendingData = this.chart.getPendingData();\n      if (pendingData) {\n        this.chart.setData(pendingData.candles, pendingData.immediateRender);\n        this.chart.clearPendingData();\n      }\n    } catch (error) {\n      this.setState('error');\n      this.chart.debugLog(`Initialization failed: ${error}`);\n      console.error('Failed to initialize chart:', error);\n      throw error;\n    }\n  }\n\n  /**\n   * WebGL context lost/restored 이벤트 핸들러 설정\n   */\n  private setupContextHandlers(): void {\n    // WebGL context lost는 매우 드물게 발생하므로 \n    // 복잡한 복구 로직보다는 간단한 에러 로깅만 하도록 함\n    const container = this.chart.getContainer();\n    const canvas = container.querySelector('canvas');\n    \n    if (!canvas) {\n      return;\n    }\n    \n    canvas.addEventListener('webglcontextlost', (e) => {\n      e.preventDefault();\n      console.error('[ChartLifecycle] WebGL context lost - Please refresh the page');\n      this.setState('error');\n      this.chart.stopRenderLoop();\n    });\n    \n    canvas.addEventListener('webglcontextrestored', () => {\n      console.log('[ChartLifecycle] WebGL context restored - Please refresh the page');\n    });\n  }\n\n  /**\n   * 컨테이너가 준비될 때까지 대기\n   */\n  private async waitForContainer(): Promise<void> {\n    const container = this.chart.getContainer();\n    const isTauri = !!window.__TAURI__;\n    \n    if (isTauri) {\n      // Tauri 환경에서는 바로 준비됨\n      this.chart.debugLog(`[Tauri] Container ready immediately: ${container.offsetWidth}x${container.offsetHeight}`);\n      return;\n    }\n    \n    // 웹 환경에서만 복잡한 체크\n    const checkContainer = (): boolean => {\n      const rect = container.getBoundingClientRect();\n      return rect.width > 0 && rect.height > 0;\n    };\n    \n    if (checkContainer()) {\n      this.chart.debugLog(`Container ready: ${container.getBoundingClientRect().width}x${container.getBoundingClientRect().height}`);\n      return;\n    }\n    \n    this.chart.debugLog('Waiting for container to be ready...');\n    \n    // 웹에서만 대기 로직 실행\n    const maxWaitTime = 5000;\n    const checkInterval = 100;\n    let elapsed = 0;\n    \n    return new Promise((resolve, reject) => {\n      const intervalId = setInterval(() => {\n        if (checkContainer()) {\n          clearInterval(intervalId);\n          this.chart.debugLog(`Container ready after ${elapsed}ms`);\n          resolve();\n        } else if (elapsed >= maxWaitTime) {\n          clearInterval(intervalId);\n          reject(new Error('Container not ready after 5 seconds'));\n        }\n        elapsed += checkInterval;\n      }, checkInterval);\n    });\n  }\n\n  /**\n   * ResizeObserver 설정\n   */\n  private setupResizeObserver(): void {\n    const container = this.chart.getContainer();\n    const isTauri = !!window.__TAURI__;\n    \n    // Tauri에서는 ResizeObserver를 간단하게만 사용\n    if (isTauri) {\n      this.resizeObserver = new ResizeObserver(() => {\n        this.chart.debugLog('[Tauri] Window resized');\n        this.chart.resize();\n      });\n      this.resizeObserver.observe(container);\n      return;\n    }\n    \n    // 웹 환경에서만 복잡한 로직\n    if (!this.resizeObserver) {\n      this.resizeObserver = new ResizeObserver((entries) => {\n        for (const entry of entries) {\n          const { width, height } = entry.contentRect;\n          // console.log('ResizeObserver triggered:', { width, height });\n          \n          if (width > 0 && height > 0) {\n            // this.chart.debugLog(`Container resized: ${width}x${height}`);\n            this.chart.resize();\n            \n            // 대기 중인 데이터가 있으면 처리\n            const pendingData = this.chart.getPendingData();\n            if (pendingData && this.isReady()) {\n              console.log('Processing pending data after resize');\n              this.chart.debugLog('Processing pending data after resize');\n              // clearPendingData를 먼저 호출하여 무한 루프 방지\n              this.chart.clearPendingData();\n              this.chart.setData(pendingData.candles, pendingData.immediateRender);\n            }\n          }\n        }\n      });\n      \n      this.resizeObserver.observe(container);\n    }\n  }\n\n  /**\n   * 초기화 완료 대기\n   */\n  async waitUntilReady(): Promise<void> {\n    if (this.isReady()) {\n      return;\n    }\n    \n    if (this.initPromise) {\n      await this.initPromise;\n    }\n  }\n\n  /**\n   * 리소스 정리\n   */\n  dispose(): void {\n    // 렌더링 루프 중지\n    this.chart.stopRenderLoop();\n    \n    // 이벤트 리스너 제거\n    this.chart.getEventHandler().removeEventListeners();\n    \n    // WebGL context 이벤트 핸들러는 간단하므로 별도 제거 불필요\n    \n    // ResizeObserver 정리\n    if (this.resizeObserver) {\n      this.resizeObserver.disconnect();\n      this.resizeObserver = null;\n    }\n    \n    // 렌더링 매니저 정리 (패널 매니저 포함)\n    const renderingManager = this.chart['renderingManager'];\n    if (renderingManager) {\n      renderingManager.dispose();\n    }\n    \n    // UI 컴포넌트 정리\n    // IndicatorPanel removed - no cleanup needed\n    \n    // SettingsPanel removed - no cleanup needed\n    \n    // DrawingToolbar removed - no cleanup needed\n    \n    this.setState('error');\n    this.isInitialized = false;\n  }\n\n  /**\n   * 상태 변경\n   */\n  private setState(state: 'initializing' | 'ready' | 'updating' | 'error'): void {\n    this.state = state;\n    this.stateListeners.forEach(listener => listener(state));\n  }\n\n  /**\n   * 차트가 준비되었는지 확인\n   */\n  isReady(): boolean {\n    return this.isInitialized && this.state === 'ready';\n  }\n\n  /**\n   * 현재 상태 반환\n   */\n  getState(): string {\n    return this.state;\n  }\n\n  /**\n   * 상태 변경 이벤트 리스너 추가\n   */\n  on(event: 'stateChange', callback: (state: string) => void): void {\n    if (event === 'stateChange') {\n      this.stateListeners.add(callback);\n    }\n  }\n\n  /**\n   * 상태 변경 이벤트 리스너 제거\n   */\n  off(event: 'stateChange', callback: (state: string) => void): void {\n    if (event === 'stateChange') {\n      this.stateListeners.delete(callback);\n    }\n  }\n\n  setInitPromise(promise: Promise<void>): void {\n    this.initPromise = promise;\n  }\n}","import type { Chart } from '../Chart';\nimport type { LineSeriesOptions } from '@/core/LineSeriesManager';\n\n/**\n * 라인 시리즈 관련 메서드들을 모아놓은 헬퍼 클래스\n */\nexport class ChartLineSeriesHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 라인 시리즈 추가\n   */\n  addLineSeries(options: LineSeriesOptions): string {\n    const id = this.chart['interactionManager'].addLineSeries(options);\n    this.chart.setDirty(true);\n    return id;\n  }\n\n  /**\n   * 라인 시리즈 업데이트\n   */\n  updateLineSeries(id: string, data: Array<{ time: number; value: number }>): void {\n    this.chart['interactionManager'].updateLineSeries(id, data);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 라인 시리즈 제거\n   */\n  removeLineSeries(id: string): void {\n    this.chart['interactionManager'].removeLineSeries(id);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 라인 시리즈 가시성 토글\n   */\n  toggleLineSeriesVisibility(id: string): void {\n    this.chart['interactionManager'].toggleLineSeriesVisibility(id);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 라인 시리즈 스타일 업데이트\n   */\n  updateLineSeriesStyle(id: string, style: { color?: string; lineWidth?: number }): void {\n    this.chart['interactionManager'].updateLineSeriesStyle(id, style);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 모든 라인 시리즈 가져오기\n   */\n  getAllLineSeries() {\n    return this.chart['interactionManager'].getAllLineSeries();\n  }\n\n  /**\n   * 모든 라인 시리즈 제거\n   */\n  clearLineSeries(): void {\n    this.chart['interactionManager'].clearLineSeries();\n    this.chart.setDirty(true);\n  }\n}","import type { Chart } from '../Chart';\nimport type { StopLossOptions, StopLossLine } from '@/types/stopLoss';\n\n/**\n * 스톱로스 관련 메서드들을 모아놓은 헬퍼 클래스\n */\nexport class ChartStopLossHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 스톱로스 라인 추가\n   */\n  addStopLossLine(price: number, options?: StopLossOptions): string {\n    const id = this.chart['interactionManager'].addStopLossLine(price, options);\n    this.chart.setDirty(true);\n    return id;\n  }\n  \n  /**\n   * 스톱로스 라인 제거\n   */\n  removeStopLossLine(id: string): boolean {\n    const result = this.chart['interactionManager'].removeStopLossLine(id);\n    if (result) {\n      this.chart.setDirty(true);\n    }\n    return result;\n  }\n  \n  /**\n   * 모든 스톱로스 라인 제거\n   */\n  clearStopLossLines(): void {\n    this.chart['interactionManager'].clearStopLossLines();\n    this.chart.setDirty(true);\n  }\n  \n  /**\n   * 스톱로스 라인 업데이트\n   */\n  updateStopLossLine(id: string, updates: Partial<StopLossOptions & { price?: number }>): boolean {\n    const result = this.chart['interactionManager'].updateStopLossLine(id, updates);\n    if (result) {\n      this.chart.setDirty(true);\n    }\n    return result;\n  }\n  \n  /**\n   * 모든 스톱로스 라인 가져오기\n   */\n  getStopLossLines(): StopLossLine[] {\n    return this.chart['interactionManager'].getStopLossLines();\n  }\n\n  /**\n   * 평단선 추가 (스톱로스 매니저 활용)\n   */\n  addAveragePriceLine(price: number, options?: {\n    label?: string;\n    color?: string;\n    lineWidth?: number;\n    dashed?: boolean;\n  }): string {\n    const defaultOptions = {\n      label: options?.label || `평단가: ${price.toFixed(2)}`,\n      color: options?.color || '#4CAF50',\n      lineWidth: options?.lineWidth || 2,\n      dashed: options?.dashed ?? false,\n      dashLength: 10,\n      gapLength: 5,\n      opacity: 0.8\n    };\n    \n    return this.addStopLossLine(price, defaultOptions);\n  }\n\n  /**\n   * 평단선 업데이트\n   */\n  updateAveragePriceLine(id: string, updates: {\n    price?: number;\n    label?: string;\n    color?: string;\n    lineWidth?: number;\n  }): boolean {\n    return this.updateStopLossLine(id, updates);\n  }\n}","import type { Chart } from '../Chart';\nimport type { IndicatorConfig } from '@/types';\n\n/**\n * 차트 스타일 관련 메서드들을 모아놓은 헬퍼 클래스\n */\nexport class ChartStyleHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 캔들 색상 실시간 업데이트\n   */\n  updateCandleColors(colors: {\n    upColor?: string;\n    downColor?: string;\n    borderUpColor?: string;\n    borderDownColor?: string;\n    wickColor?: string;\n  }): void {\n    // 옵션 업데이트\n    const options = this.chart.getOptions();\n    if (!options.candle) {\n      options.candle = {};\n    }\n    Object.assign(options.candle, colors);\n    \n    // 테마 업데이트\n    const theme = this.chart.getTheme();\n    if (colors.upColor) theme.candleUp = colors.upColor;\n    if (colors.downColor) theme.candleDown = colors.downColor;\n    if (colors.wickColor) {\n      theme.candleUpWick = colors.wickColor;\n      theme.candleDownWick = colors.wickColor;\n    }\n    \n    // 메인 패널의 캔들 렌더러 업데이트\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (mainPanel) {\n      mainPanel.updateCandleColors(theme);\n    }\n    \n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 볼륨 색상 실시간 업데이트\n   */\n  updateVolumeColors(colors: {\n    up?: string;\n    down?: string;\n    maColor?: string;\n  }): void {\n    // 볼륨 패널 가져오기 및 타입 체크\n    const volumePanel = this.chart['renderingManager'].getVolumePanel();\n    if (volumePanel && colors) {\n      volumePanel.updateColors(colors);\n    }\n    \n    // 옵션 업데이트\n    const options = this.chart.getOptions();\n    if (!options.volume) {\n      options.volume = {};\n    }\n    \n    // volume 옵션에 색상 저장\n    if (colors.up) options.volume.upColor = colors.up;\n    if (colors.down) options.volume.downColor = colors.down;\n    \n    // panels.volume 옵션에도 색상 저장 (호환성)\n    if (options.panels?.volume) {\n      if (colors.up || colors.down) {\n        if (!options.panels.volume.colors) {\n          options.panels.volume.colors = {};\n        }\n        if (colors.up) options.panels.volume.colors.up = colors.up;\n        if (colors.down) options.panels.volume.colors.down = colors.down;\n      }\n      if (colors.maColor) {\n        options.panels.volume.maColor = colors.maColor;\n      }\n    }\n    \n    // 테마에도 볼륨 색상 업데이트\n    const theme = this.chart.getTheme();\n    if (!theme.volume) {\n      theme.volume = {\n        upColor: colors.up || '#26a69a',\n        downColor: colors.down || '#ef5350'\n      };\n    } else {\n      if (colors.up) theme.volume.upColor = colors.up;\n      if (colors.down) theme.volume.downColor = colors.down;\n    }\n    \n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 이동평균선 스타일 업데이트\n   */\n  updateMovingAverageStyle(id: string, style: {\n    color?: string;\n    lineWidth?: number;\n    lineStyle?: 'solid' | 'dashed' | 'dotted';\n    opacity?: number;\n  }): void {\n    const indicator = this.chart['pluginManager'].getIndicator(id);\n    if (indicator && (indicator.type === 'sma' || indicator.type === 'ema')) {\n      // 기존 스타일과 병합\n      const updatedStyle = { ...indicator.style, ...style };\n      \n      // 인디케이터 설정 업데이트\n      this.chart.updateIndicator(id, { style: updatedStyle });\n      \n      this.chart.setDirty(true);\n    }\n  }\n\n  /**\n   * 모든 이동평균선 스타일 일괄 업데이트\n   */\n  updateAllMovingAveragesStyle(style: {\n    color?: string;\n    lineWidth?: number;\n    lineStyle?: 'solid' | 'dashed' | 'dotted';\n    opacity?: number;\n  }): void {\n    const indicators = this.chart['pluginManager'].getIndicators();\n    indicators.forEach((indicator: IndicatorConfig) => {\n      if (indicator.type === 'sma' || indicator.type === 'ema') {\n        this.updateMovingAverageStyle(indicator.id, style);\n      }\n    });\n  }\n\n  /**\n   * 마커 스타일 업데이트\n   */\n  updateMarkerStyle(id: string, style: {\n    color?: string;\n    text?: string;\n    size?: number;\n  }): void {\n    const marker = this.chart['interactionManager'].getMarkerById(id);\n    if (marker) {\n      if (style.color) marker.color = style.color;\n      if (style.text) marker.text = style.text;\n      if (style.size) marker.size = style.size;\n      \n      this.chart.setDirty(true);\n    }\n  }\n\n  /**\n   * 모든 마커 스타일 일괄 업데이트 (타입별)\n   */\n  updateMarkersStyleByType(type: 'buy' | 'sell', style: {\n    color?: string;\n    text?: string;\n    size?: number;\n    shape?: 'arrowUp' | 'arrowDown' | 'circle' | 'square';\n  }): void {\n    const markers = this.chart['interactionManager'].getMarkers();\n    markers.forEach(marker => {\n      // buy/sell 타입 판별 (shape 또는 position 기반)\n      const isBuyType = marker.shape === 'arrowUp' || marker.position === 'belowBar';\n      const isSellType = marker.shape === 'arrowDown' || marker.position === 'aboveBar';\n      \n      if ((type === 'buy' && isBuyType) || (type === 'sell' && isSellType)) {\n        if (style.color) marker.color = style.color;\n        if (style.text) marker.text = style.text;\n        if (style.size) marker.size = style.size;\n        if (style.shape) marker.shape = style.shape;\n      }\n    });\n    \n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 스톱로스 라인 스타일 업데이트\n   */\n  updateStopLossStyle(id: string, style: {\n    color?: string;\n    lineWidth?: number;\n    label?: string;\n    opacity?: number;\n  }): void {\n    const updates: any = {};\n    if (style.color) updates.color = style.color;\n    if (style.lineWidth) updates.lineWidth = style.lineWidth;\n    if (style.label) updates.label = style.label;\n    if (style.opacity) updates.opacity = style.opacity;\n    \n    this.chart['stopLossHelper'].updateStopLossLine(id, updates);\n  }\n}","import type { Chart } from '../Chart';\nimport type { ChartData, ChartOptions } from '@/types';\nimport type { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\n\n/**\n * 뷰포트 관련 헬퍼 클래스\n */\nexport class ChartViewportHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 현재 보이는 데이터 범위에 맞춰 가격 범위 업데이트\n   */\n  updatePriceRangeForVisibleData(): void {\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (!mainPanel || this.chart['dataManager'].isEmpty()) return;\n    \n    const viewport = mainPanel.getViewport();\n    if (!viewport || !viewport.isAutoScale()) return;\n    \n    const data = this.chart['dataManager'].getData();\n    if (!data) return;\n    \n    const visibleRange = viewport.getVisibleRange();\n    \n    // 보이는 범위의 최고/최저가 계산\n    let minPrice = Infinity;\n    let maxPrice = -Infinity;\n    \n    for (let i = visibleRange.start; i <= visibleRange.end && i < data.length; i++) {\n      const high = data.highs[i];\n      const low = data.lows[i];\n      if (high > maxPrice) maxPrice = high;\n      if (low < minPrice) minPrice = low;\n    }\n    \n    // 인디케이터 값도 포함\n    const indicators = this.chart['pluginManager'].getIndicators();\n    indicators.forEach((indicator: any) => {\n      if (indicator.values && indicator.visible) {\n        for (let i = visibleRange.start; i <= visibleRange.end && i < indicator.values.length; i++) {\n          const value = indicator.values[i];\n          if (!isNaN(value)) {\n            if (value > maxPrice) maxPrice = value;\n            if (value < minPrice) minPrice = value;\n          }\n        }\n      }\n    });\n    \n    // 유효한 범위가 있으면 업데이트\n    if (minPrice < Infinity && maxPrice > -Infinity) {\n      viewport.setPriceRange(minPrice, maxPrice);\n      this.chart.setDirty(true);\n    }\n  }\n\n  /**\n   * initialView 옵션에 따른 뷰포트 설정\n   */\n  applyInitialView(viewport: UnifiedCoordinateSystem, data: ChartData, options: ChartOptions): void {\n    const initialView = options.initialView || 'latest';\n    const trades = options.trades || [];\n    \n    // 뷰포트 메서드가 있는지 확인\n    if (!viewport) {\n      console.warn('Viewport not available');\n      return;\n    }\n    \n    switch (initialView) {\n      case 'latest':\n        // 최신 데이터 표시 (기본값)\n        viewport.scrollToEnd();\n        break;\n        \n      case 'latest-100':\n      case 'latest-200':\n      case 'latest-300':\n      case 'latest-500':\n        // 최근 N개 캔들 표시\n        const candleCount = parseInt(initialView.split('-')[1]);\n        viewport.setVisibleCandles(Math.min(candleCount, data.length));\n        viewport.scrollToEnd();\n        break;\n        \n      case 'first-trade':\n        // 첫 매수 거래 중심으로 표시\n        if (trades.length > 0) {\n          const buyTrades = trades.filter(t => \n            t.type === 'buy' || t.type === 'Long'\n          );\n          if (buyTrades.length > 0 && buyTrades[0].date) {\n            const firstBuyTime = new Date(buyTrades[0].date).getTime() / 1000;\n            viewport.scrollToTime(firstBuyTime);\n          } else {\n            viewport.scrollToEnd();\n          }\n        } else {\n          viewport.scrollToEnd();\n        }\n        break;\n        \n      case 'last-trade':\n        // 마지막 매도 거래 중심으로 표시\n        if (trades.length > 0) {\n          const sellTrades = trades.filter(t => \n            t.type === 'sell' || t.type === 'Close'\n          );\n          if (sellTrades.length > 0) {\n            const lastSellDate = sellTrades[sellTrades.length - 1].date;\n            if (lastSellDate) {\n              const lastSellTime = new Date(lastSellDate).getTime() / 1000;\n              viewport.scrollToTime(lastSellTime);\n            } else {\n              viewport.scrollToEnd();\n            }\n          } else {\n            viewport.scrollToEnd();\n          }\n        } else {\n          viewport.scrollToEnd();\n        }\n        break;\n        \n      case 'all':\n        // 전체 데이터 표시\n        viewport.fitContent();\n        break;\n        \n      default:\n        // 객체 타입의 initialView 처리\n        if (typeof initialView === 'object' && initialView !== null && 'type' in initialView) {\n          switch ((initialView as any).type) {\n            case 'date':\n              // 특정 날짜로 이동\n              const targetTime = (initialView as any).date instanceof Date \n                ? (initialView as any).date.getTime() / 1000 \n                : (initialView as any).date;\n              viewport.scrollToTime(targetTime);\n              break;\n              \n            case 'candles':\n              // 최근 N개 캔들 표시\n              const visibleCandles = Math.min((initialView as any).count, data.length);\n              viewport.setVisibleCandles(visibleCandles);\n              viewport.scrollToEnd();\n              break;\n              \n            case 'range':\n              // 특정 범위 표시\n              const startTime = (initialView as any).start instanceof Date\n                ? (initialView as any).start.getTime() / 1000\n                : (initialView as any).start;\n              const endTime = (initialView as any).end instanceof Date\n                ? (initialView as any).end.getTime() / 1000\n                : (initialView as any).end;\n              viewport.setTimeRange(startTime, endTime);\n              break;\n          }\n        } else {\n          // 기본값: 최신 데이터\n          viewport.scrollToEnd();\n        }\n    }\n  }\n}","import type { Candle } from '@/types';\n\n/**\n * 캔들 데이터를 리샘플링하여 더 큰 시간 단위로 변환\n * @param candles 원본 캔들 데이터\n * @param groupSize 몇 개의 캔들을 하나로 합칠지 (예: 5분봉 13개 = 65분봉)\n * @returns 리샘플링된 캔들 데이터\n */\nexport function resampleCandles(candles: Candle[], groupSize: number): Candle[] {\n  if (!candles || candles.length === 0 || groupSize <= 1) {\n    return candles;\n  }\n\n  const resampledCandles: Candle[] = [];\n  \n  for (let i = 0; i < candles.length; i += groupSize) {\n    // 현재 그룹의 캔들들\n    const group = candles.slice(i, Math.min(i + groupSize, candles.length));\n    \n    if (group.length === 0) continue;\n    \n    // 새로운 캔들 생성\n    const newCandle: Candle = {\n      time: group[0].time, // 첫 번째 캔들의 시간\n      open: group[0].open, // 첫 번째 캔들의 시가\n      high: Math.max(...group.map(c => c.high)), // 그룹 내 최고가\n      low: Math.min(...group.map(c => c.low)), // 그룹 내 최저가\n      close: group[group.length - 1].close, // 마지막 캔들의 종가\n      volume: group.reduce((sum, c) => sum + c.volume, 0) // 거래량 합계\n    };\n    \n    resampledCandles.push(newCandle);\n  }\n  \n  return resampledCandles;\n}\n\n/**\n * 시간 기반으로 캔들 데이터를 리샘플링\n * @param candles 원본 캔들 데이터\n * @param targetMinutes 목표 시간 단위 (분)\n * @param sourceMinutes 원본 시간 단위 (분)\n * @returns 리샘플링된 캔들 데이터\n */\nexport function resampleCandlesByTime(\n  candles: Candle[], \n  targetMinutes: number, \n  sourceMinutes: number = 5\n): Candle[] {\n  if (targetMinutes <= sourceMinutes) {\n    return candles;\n  }\n  \n  const groupSize = Math.round(targetMinutes / sourceMinutes);\n  return resampleCandles(candles, groupSize);\n}\n\n/**\n * 5분봉을 다양한 시간 단위로 변환하는 헬퍼 함수들\n */\nexport const resampleHelpers = {\n  // 5분봉 → 15분봉\n  to15min: (candles: Candle[]) => resampleCandles(candles, 3),\n  \n  // 5분봉 → 30분봉\n  to30min: (candles: Candle[]) => resampleCandles(candles, 6),\n  \n  // 5분봉 → 1시간봉\n  to1hour: (candles: Candle[]) => resampleCandles(candles, 12),\n  \n  // 5분봉 → 65분봉\n  to65min: (candles: Candle[]) => resampleCandles(candles, 13),\n  \n  // 5분봉 → 2시간봉\n  to2hours: (candles: Candle[]) => resampleCandles(candles, 24),\n  \n  // 5분봉 → 4시간봉\n  to4hours: (candles: Candle[]) => resampleCandles(candles, 48),\n};\n\n/**\n * 캔들 데이터의 평균 간격을 분 단위로 계산\n */\nexport function getCandleIntervalMinutes(candles: Candle[]): number {\n  if (candles.length < 2) return 5; // 기본값\n  \n  // 처음 몇 개 캔들의 평균 간격 계산\n  const sampleSize = Math.min(10, candles.length - 1);\n  let totalInterval = 0;\n  \n  for (let i = 1; i <= sampleSize; i++) {\n    totalInterval += candles[i].time - candles[i - 1].time;\n  }\n  \n  // 초를 분으로 변환\n  return Math.round(totalInterval / sampleSize / 60);\n}","import type { Chart } from '../Chart';\nimport type { Candle } from '@/types';\nimport { resampleCandles, resampleCandlesByTime, resampleHelpers } from '@/utils/candleResampler';\n\n/**\n * 데이터 관련 헬퍼 클래스\n */\nexport class ChartDataHelper {\n  private originalData: Candle[] | null = null;\n  private isResampled: boolean = false;\n  \n  constructor(private chart: Chart) {}\n\n  /**\n   * 실제 데이터 설정 로직\n   */\n  actualSetData(candles: Candle[], immediateRender: boolean = false): void {\n    // 원본 데이터 저장\n    if (!this.isResampled) {\n      this.originalData = [...candles];\n    }\n    this.chart['dataManager'].setData(candles);\n    const data = this.chart['dataManager'].getData();\n    \n    if (data) {\n      // Viewport 초기화 - 공유 좌표계이므로 한 번만 설정\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        \n        viewport.setDataInfo(data.length, data.timeRange);\n        \n        // 가격 여백 설정\n        const options = this.chart.getOptions();\n        if (options.priceScaleMargin) {\n          if (typeof options.priceScaleMargin === 'number') {\n            viewport.setPriceMargin(\n              options.priceScaleMargin,\n              options.priceScaleMargin,\n              'main'  // 명시적으로 main 패널 지정\n            );\n          } else {\n            viewport.setPriceMargin(\n              options.priceScaleMargin.top || 0.02,\n              options.priceScaleMargin.bottom || 0.02,\n              'main'  // 명시적으로 main 패널 지정\n            );\n          }\n        }\n        \n        viewport.setPriceRange(data.priceRange[0], data.priceRange[1]);\n        \n        // 잠긴 뷰가 있으면 우선 적용\n        const isLocked = localStorage.getItem('chartViewLocked') === 'true';\n        if (isLocked) {\n          try {\n            const lockedViewState = JSON.parse(localStorage.getItem('lockedViewState') || '{}');\n            if (lockedViewState.visibleCandles) {\n              // 잠긴 뷰 적용\n              viewport.setVisibleCandles(lockedViewState.visibleCandles);\n              if (lockedViewState.rightMargin !== undefined) {\n                viewport.setRightMargin(lockedViewState.rightMargin);\n              }\n              viewport.scrollToEnd();\n            } else {\n              // 잠긴 뷰가 유효하지 않으면 일반 초기뷰 적용\n              this.chart['viewportHelper'].applyInitialView(viewport, data, options);\n            }\n          } catch (e) {\n            console.error('Failed to apply locked view state:', e);\n            // 오류 시 일반 초기뷰 적용\n            this.chart['viewportHelper'].applyInitialView(viewport, data, options);\n          }\n        } else {\n          // initialView 옵션에 따른 뷰포트 설정 - 한 번만 호출\n          this.chart['viewportHelper'].applyInitialView(viewport, data, options);\n        }\n      }\n      \n      // 인디케이터 계산\n      this.chart['pluginManager'].calculateAll(data);\n    }\n    \n    this.chart.setDirty(true);\n    \n    // 즉시 렌더링 옵션\n    if (immediateRender && !this.chart['dataManager'].isEmpty()) {\n      this.chart['render']();\n      this.chart.setDirty(false);\n    }\n  }\n\n  /**\n   * 캔들 데이터를 리샘플링하여 표시\n   * @param groupSize 몇 개의 캔들을 하나로 합칠지\n   */\n  resampleData(groupSize: number): void {\n    if (!this.originalData || this.originalData.length === 0) {\n      console.warn('No original data to resample');\n      return;\n    }\n\n    if (groupSize === 1) {\n      // 원본 데이터로 복원\n      this.isResampled = false;\n      this.actualSetData(this.originalData, true);\n      return;\n    }\n\n    // 리샘플링 수행\n    const resampledData = resampleCandles(this.originalData, groupSize);\n    this.isResampled = true;\n    this.actualSetData(resampledData, true);\n  }\n\n  /**\n   * 시간 단위로 캔들 데이터를 리샘플링\n   * @param targetMinutes 목표 시간 단위 (분)\n   * @param sourceMinutes 원본 시간 단위 (분)\n   */\n  resampleDataByTime(targetMinutes: number, sourceMinutes: number = 5): void {\n    if (!this.originalData || this.originalData.length === 0) {\n      console.warn('No original data to resample');\n      return;\n    }\n\n    if (targetMinutes === sourceMinutes) {\n      // 원본 데이터로 복원\n      this.isResampled = false;\n      this.actualSetData(this.originalData, true);\n      return;\n    }\n\n    // 리샘플링 수행\n    const resampledData = resampleCandlesByTime(this.originalData, targetMinutes, sourceMinutes);\n    this.isResampled = true;\n    this.actualSetData(resampledData, true);\n  }\n\n  /**\n   * 5분봉을 65분봉으로 변환\n   */\n  convertTo65Min(): void {\n    if (!this.originalData || this.originalData.length === 0) {\n      console.warn('No original data to convert');\n      return;\n    }\n\n    const resampledData = resampleHelpers.to65min(this.originalData);\n    this.isResampled = true;\n    this.actualSetData(resampledData, true);\n  }\n\n  /**\n   * 원본 데이터로 복원\n   */\n  restoreOriginalData(): void {\n    if (this.originalData && this.isResampled) {\n      this.isResampled = false;\n      this.actualSetData(this.originalData, true);\n    }\n  }\n\n  /**\n   * 현재 리샘플링 상태 확인\n   */\n  isDataResampled(): boolean {\n    return this.isResampled;\n  }\n\n  /**\n   * 원본 데이터 가져오기\n   */\n  getOriginalData(): Candle[] | null {\n    return this.originalData;\n  }\n}","import type { Chart } from '../Chart';\nimport type { DrawingOptions, DrawingToolType } from '@/types/drawing';\n\n/**\n * 드로잉 관련 헬퍼 클래스\n */\nexport class ChartDrawingHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 드로잉 추가\n   */\n  addDrawing(type: string, options?: DrawingOptions): void {\n    // 드로잉 도구를 활성화하고 사용자가 그리기 시작할 수 있도록 함\n    this.chart['interactionManager'].setActiveTool(type as DrawingToolType);\n    if (options) {\n      // options가 있으면 기본 스타일로 설정\n      this.chart['interactionManager'].setDefaultDrawingStyle({\n        color: options.color,\n        lineWidth: options.lineWidth,\n        opacity: options.opacity\n      });\n    }\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 드로잉 내보내기\n   */\n  exportDrawings(): string {\n    return this.chart['interactionManager'].exportDrawings();\n  }\n\n  /**\n   * 드로잉 가져오기\n   */\n  importDrawings(jsonData: string): void {\n    this.chart['interactionManager'].importDrawings(jsonData);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 모든 드로잉 제거\n   */\n  clearDrawings(): void {\n    this.chart['interactionManager'].clearDrawings();\n    this.chart.setDirty(true);\n  }\n  \n  /**\n   * 드로잉 도구 설정\n   */\n  setDrawingTool(tool: DrawingToolType | null): void {\n    this.chart['interactionManager'].setActiveTool(tool);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 현재 드로잉 도구 가져오기\n   */\n  getDrawingTool(): DrawingToolType | null {\n    return this.chart['interactionManager'].getActiveTool();\n  }\n\n  /**\n   * 자석 모드 설정\n   */\n  setMagneticMode(enabled: boolean): void {\n    this.chart['interactionManager'].setMagneticMode(enabled);\n  }\n\n  /**\n   * 자석 모드 상태 가져오기\n   */\n  getMagneticMode(): boolean {\n    return this.chart['interactionManager'].getMagneticMode();\n  }\n}","import type { Chart } from '../Chart';\nimport type { Marker } from '@/types/marker';\n\n/**\n * 마커 관련 헬퍼 클래스\n */\nexport class ChartMarkerHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 마커 추가\n   */\n  addMarker(marker: Marker): string {\n    const id = this.chart['interactionManager'].addMarker(marker);\n    this.chart.setDirty(true);\n    return id;\n  }\n  \n  /**\n   * 마커 설정\n   */\n  setMarkers(markers: Marker[]): void {\n    this.chart['interactionManager'].setMarkers(markers);\n    this.chart.setDirty(true);\n  }\n  \n  /**\n   * 마커 제거\n   */\n  removeMarker(id: string): void {\n    this.chart['interactionManager'].removeMarker(id);\n    this.chart.setDirty(true);\n  }\n  \n  /**\n   * 모든 마커 제거\n   */\n  clearMarkers(): void {\n    this.chart['interactionManager'].clearMarkers();\n    this.chart.setDirty(true);\n  }\n  \n  /**\n   * 모든 마커 가져오기\n   */\n  getMarkers(): Marker[] {\n    return this.chart['interactionManager'].getMarkers();\n  }\n}","import type { Chart } from '../Chart';\n\n/**\n * 차트 내보내기 관련 헬퍼 클래스\n */\nexport class ChartExportHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 차트를 이미지로 내보내기\n   * @param format 이미지 형식 ('png' 또는 'jpeg')\n   * @param quality JPEG 품질 (0-1, 기본값 0.9)\n   * @param scaleFactor 스케일 팩터 (기본값 2 = 2배 해상도, QHD+ 권장값 3-4)\n   * @returns Promise<Blob> 이미지 Blob\n   */\n  async toImage(format: 'png' | 'jpeg' = 'png', quality: number = 0.9, scaleFactor: number = 2): Promise<Blob> {\n    if (!this.chart.isReady()) {\n      throw new Error('Chart is not ready');\n    }\n\n    // 렌더링 강제 실행\n    if (this.chart['renderingManager']) {\n      const data = this.chart['dataManager'].getData();\n      if (data) {\n        const indicators = this.chart['pluginManager'].getIndicatorData();\n        this.chart['renderingManager'].render(data, indicators);\n        // 렌더링 완료 대기\n        await new Promise(resolve => setTimeout(resolve, 100));\n      }\n    }\n\n    // 모든 패널의 캔버스 가져오기\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    const volumePanel = this.chart['renderingManager'].getVolumePanel();\n    \n    if (!mainPanel) {\n      throw new Error('Main panel not found');\n    }\n\n    // 컨테이너에서 모든 캔버스 찾기\n    const container = this.chart['container'] as HTMLElement;\n    const allCanvases = container.querySelectorAll('canvas');\n    \n    // 전체 컨테이너 크기 계산\n    const containerRect = container.getBoundingClientRect();\n    const baseWidth = Math.floor(containerRect.width);\n    const baseHeight = Math.floor(containerRect.height);\n    \n    // 고해상도 캔버스 크기 계산\n    const width = Math.floor(baseWidth * scaleFactor);\n    const height = Math.floor(baseHeight * scaleFactor);\n\n    // 합성 캔버스 생성\n    const compositeCanvas = document.createElement('canvas');\n    compositeCanvas.width = width;\n    compositeCanvas.height = height;\n    const ctx = compositeCanvas.getContext('2d', { alpha: false });\n    \n    if (!ctx) {\n      throw new Error('Failed to get 2D context');\n    }\n\n    // 고해상도를 위한 스케일 설정\n    ctx.scale(scaleFactor, scaleFactor);\n\n    // 배경색 설정\n    ctx.fillStyle = this.chart['theme'].background || this.chart['theme'].backgroundColor || '#131722';\n    ctx.fillRect(0, 0, baseWidth, baseHeight);\n\n    // 캔버스 타입별로 분류\n    const canvasMap = new Map<string, HTMLCanvasElement>();\n    const processedCanvases = new Set<HTMLCanvasElement>();\n    \n    allCanvases.forEach((canvas: HTMLCanvasElement) => {\n      // Y축 캔버스 처리\n      const parentElement = canvas.parentElement;\n      if (parentElement && parentElement.classList.contains('y-axis')) {\n        // 패널 타입 확인\n        const panelType = parentElement.getAttribute('data-panel-type');\n        // price 타입의 Y축만 포함 (volume 타입은 제외)\n        if (panelType === 'price' && !canvasMap.has('y-axis-price')) {\n          canvasMap.set('y-axis-price', canvas);\n        }\n        return;\n      }\n      \n      // LabelRenderer의 Y축 캔버스 체크 (width 80px, right 0)\n      if (canvas.style.width === '80px' && canvas.style.right === '0') {\n        // LabelRenderer의 캔버스는 별도로 처리\n        if (!canvasMap.has('label-renderer')) {\n          canvasMap.set('label-renderer', canvas);\n        }\n        return;\n      }\n      \n      // WebGL 캔버스\n      const gl = canvas.getContext('webgl', { preserveDrawingBuffer: true });\n      if (gl) {\n        // WebGL 캔버스는 모두 포함\n        if (!processedCanvases.has(canvas)) {\n          processedCanvases.add(canvas);\n        }\n      } else {\n        // 2D 캔버스\n        const ctx2d = canvas.getContext('2d');\n        if (ctx2d && !processedCanvases.has(canvas)) {\n          processedCanvases.add(canvas);\n        }\n      }\n    });\n    \n    // WebGL 캔버스들을 먼저 그리기\n    processedCanvases.forEach((canvas: HTMLCanvasElement) => {\n      try {\n        const canvasRect = canvas.getBoundingClientRect();\n        const x = canvasRect.left - containerRect.left;\n        const y = canvasRect.top - containerRect.top;\n        \n        if (canvasRect.width > 0 && canvasRect.height > 0) {\n          ctx.drawImage(canvas, x, y, canvasRect.width, canvasRect.height);\n        }\n      } catch (e) {\n        console.error('Failed to draw canvas:', e);\n      }\n    });\n    \n    // Y축은 마지막에 한 번만 그리기\n    // LabelRenderer가 있으면 우선 사용 (Y축 텍스트 + 크로스헤어 라벨 포함)\n    // 없으면 AxisRenderer 사용\n    const labelCanvas = canvasMap.get('label-renderer');\n    const axisCanvas = canvasMap.get('y-axis-price');\n    const yAxisToRender = labelCanvas || axisCanvas;\n    \n    if (yAxisToRender) {\n      try {\n        const canvasRect = yAxisToRender.getBoundingClientRect();\n        const x = canvasRect.left - containerRect.left;\n        const y = canvasRect.top - containerRect.top;\n        \n        if (canvasRect.width > 0 && canvasRect.height > 0) {\n          ctx.drawImage(yAxisToRender, x, y, canvasRect.width, canvasRect.height);\n        }\n      } catch (e) {\n        console.error('Failed to draw y-axis canvas:', e);\n      }\n    }\n\n    // Blob으로 변환\n    return new Promise((resolve, reject) => {\n      compositeCanvas.toBlob(\n        (blob) => {\n          if (blob) {\n            resolve(blob);\n          } else {\n            reject(new Error('Failed to create image blob'));\n          }\n        },\n        format === 'jpeg' ? 'image/jpeg' : 'image/png',\n        quality\n      );\n    });\n  }\n\n  /**\n   * 차트를 고화질 이미지로 내보내기 (QHD+ 해상도)\n   * @param format 이미지 형식 ('png' 또는 'jpeg')\n   * @param quality JPEG 품질 (0-1, 기본값 0.95)\n   * @returns Promise<Blob> 고화질 이미지 Blob\n   */\n  async toHighResImage(format: 'png' | 'jpeg' = 'png', quality: number = 0.95): Promise<Blob> {\n    // QHD+ (2560x1440) 이상을 위한 스케일 팩터 계산\n    const container = this.chart['container'] as HTMLElement;\n    const containerRect = container.getBoundingClientRect();\n    const currentWidth = containerRect.width;\n    \n    // 목표 해상도 설정 (QHD+ 기준)\n    const targetWidth = 2560;\n    const scaleFactor = Math.max(3, targetWidth / currentWidth);\n    \n    return this.toImage(format, quality, scaleFactor);\n  }\n\n  /**\n   * 차트를 지정된 해상도로 내보내기\n   * @param targetWidth 목표 너비 (픽셀)\n   * @param format 이미지 형식 ('png' 또는 'jpeg')\n   * @param quality JPEG 품질 (0-1, 기본값 0.95)\n   * @returns Promise<Blob> 이미지 Blob\n   */\n  async toCustomResolution(targetWidth: number, format: 'png' | 'jpeg' = 'png', quality: number = 0.95): Promise<Blob> {\n    const container = this.chart['container'] as HTMLElement;\n    const containerRect = container.getBoundingClientRect();\n    const currentWidth = containerRect.width;\n    \n    // 스케일 팩터 계산\n    const scaleFactor = targetWidth / currentWidth;\n    \n    return this.toImage(format, quality, scaleFactor);\n  }\n}","import type { Theme, ChartOptions } from '@/types';\n\n/**\n * 테마 관련 헬퍼 클래스\n */\nexport class ChartThemeHelper {\n  /**\n   * 테마와 사용자 옵션 병합\n   */\n  static mergeThemeWithOptions(theme: Theme, options: ChartOptions): Theme {\n    const mergedTheme = { ...theme };\n    \n    // 캔들 색상\n    if (options.candle) {\n      if (options.candle.upColor) mergedTheme.candleUp = options.candle.upColor;\n      if (options.candle.downColor) mergedTheme.candleDown = options.candle.downColor;\n      if (options.candle.wickUpColor) mergedTheme.candleUpWick = options.candle.wickUpColor;\n      if (options.candle.wickDownColor) mergedTheme.candleDownWick = options.candle.wickDownColor;\n    }\n    \n    // 배경색\n    if (options.background) {\n      mergedTheme.background = options.background;\n    }\n    \n    // 그리드\n    if (options.grid) {\n      if (typeof options.grid === 'object') {\n        // grid 객체에 color 속성이 있는 경우 (확장된 타입)\n        const gridWithColor = options.grid as any;\n        if (gridWithColor.color) {\n          mergedTheme.grid = gridWithColor.color;\n          mergedTheme.gridColor = gridWithColor.color; // 하위 호환성\n        }\n        if (options.grid.horizontal?.color) {\n          mergedTheme.gridColor = options.grid.horizontal.color;\n        }\n      }\n    }\n    \n    // Crosshair\n    if (options.crosshair) {\n      if (options.crosshair.line?.color) mergedTheme.crosshair.color = options.crosshair.line.color;\n    }\n    \n    // Axis 색상\n    if (options.axis) {\n      mergedTheme.axis = {\n        ...mergedTheme.axis,\n        ...options.axis\n      };\n    }\n    \n    return mergedTheme;\n  }\n}","import type { Chart } from '../Chart';\nimport type { ChartType, ChartOptions } from '@/types';\nimport { getTheme } from '@/utils/theme';\nimport { ChartThemeHelper } from './ChartThemeHelper';\nimport type { CursorType } from '@/utils/cursor';\n\n/**\n * UI 관련 헬퍼 클래스\n */\nexport class ChartUIHelper {\n  constructor(private chart: Chart) {}\n\n  /**\n   * 차트 타입 설정\n   */\n  setChartType(type: ChartType): void {\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (mainPanel && 'setChartType' in mainPanel) {\n      (mainPanel as any).setChartType(type);\n    }\n    this.chart['isDirty'] = true;\n  }\n  \n  /**\n   * 테마 설정\n   */\n  setTheme(theme: 'dark' | 'light'): void {\n    // 옵션 업데이트\n    this.chart['options'].theme = theme;\n    \n    // 테마와 옵션 병합\n    this.chart['theme'] = ChartThemeHelper.mergeThemeWithOptions(getTheme(theme), this.chart['options']);\n    \n    // RenderingManager를 통해 모든 패널과 렌더러 업데이트\n    this.chart['renderingManager'].updateTheme(this.chart['theme']);\n    \n    // DrawingManager에 업데이트된 테마 전달\n    this.chart['interactionManager']['drawingManager'].setTheme(this.chart['theme']);\n    \n    this.chart['isDirty'] = true;\n  }\n  \n  /**\n   * 커서 타입 설정\n   */\n  setCursorType(type: CursorType): void {\n    // 옵션 업데이트\n    this.chart['options'].cursorType = type;\n    \n    // 메인 패널의 이벤트 컨트롤러에 전달\n    const mainPanel = this.chart['renderingManager'].getMainPanel();\n    if (mainPanel && mainPanel['eventController']) {\n      mainPanel['eventController'].setCursorType(type);\n    }\n    \n    this.chart['isDirty'] = true;\n  }\n  \n  /**\n   * 줌 모드 설정\n   */\n  setZoomMode(mode: 'mouse' | 'latest'): void {\n    this.chart['zoomMode'] = mode;\n  }\n  \n  /**\n   * 설정 업데이트\n   */\n  updateSettings(settings: Partial<ChartOptions>): void {\n    // 옵션 병합\n    this.chart['options'] = { ...this.chart['options'], ...settings };\n    \n    // 마진 설정 업데이트\n    if (settings.priceScaleMargin || settings.rightMargin !== undefined) {\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        if (viewport) {\n          // 가격 스케일 마진 업데이트\n          if (settings.priceScaleMargin && typeof settings.priceScaleMargin === 'object') {\n            viewport.setPriceMargin(\n              settings.priceScaleMargin.top || 0.1,\n              settings.priceScaleMargin.bottom || 0.1\n            );\n          }\n          \n          // 오른쪽 마진 업데이트\n          if (settings.rightMargin !== undefined) {\n            viewport.setRightMargin(settings.rightMargin);\n          }\n        }\n      }\n      \n      // 볼륨 패널도 동일하게 업데이트\n      const volumePanel = this.chart['renderingManager'].getVolumePanel();\n      if (volumePanel && settings.rightMargin !== undefined) {\n        const volumeViewport = volumePanel.getViewport();\n        if (volumeViewport) {\n          volumeViewport.setRightMargin(settings.rightMargin);\n        }\n      }\n      \n      this.chart['isDirty'] = true;\n    }\n    \n    // 테마 업데이트\n    if (settings.candle || settings.background || settings.grid || settings.crosshair || settings.line || settings.axis) {\n      // background가 있으면 옵션에 저장\n      if (settings.background) {\n        this.chart['options'].background = settings.background;\n      }\n      \n      // grid color가 있으면 옵션에 저장\n      const gridWithColor = settings.grid as any;\n      if (settings.grid && typeof settings.grid === 'object' && gridWithColor.color) {\n        if (!this.chart['options'].grid || typeof this.chart['options'].grid === 'boolean') {\n          this.chart['options'].grid = {};\n        }\n        (this.chart['options'].grid as any).color = gridWithColor.color;\n      }\n      \n      // axis 설정이 있으면 옵션에 저장\n      if (settings.axis) {\n        this.chart['options'].axis = settings.axis;\n      }\n      \n      const theme = ChartThemeHelper.mergeThemeWithOptions(\n        getTheme(this.chart['options'].theme || 'dark'), \n        this.chart['options']\n      );\n      this.chart['theme'] = theme;\n      this.chart['renderingManager'].updateTheme(theme);\n      \n      // 강제로 다시 렌더링\n      this.chart['isDirty'] = true;\n    }\n    \n    // 볼륨 색상 업데이트\n    if (settings.volume) {\n      const volumePanel = this.chart['renderingManager'].getVolumePanel();\n      if (volumePanel && volumePanel.updateColors) {\n        volumePanel.updateColors({\n          up: settings.volume.upColor,\n          down: settings.volume.downColor\n        });\n      }\n      \n      // 테마에도 볼륨 색상 반영\n      if (!this.chart['theme'].volume) {\n        this.chart['theme'].volume = {\n          upColor: settings.volume.upColor || '#26a69a',\n          downColor: settings.volume.downColor || '#ef5350'\n        };\n      } else {\n        if (settings.volume.upColor) this.chart['theme'].volume.upColor = settings.volume.upColor;\n        if (settings.volume.downColor) this.chart['theme'].volume.downColor = settings.volume.downColor;\n      }\n    }\n    \n    // 차트 타입 업데이트\n    if (settings.chartType) {\n      this.setChartType(settings.chartType);\n    }\n    \n    // 가격 여백 업데이트 - 메인 패널에만 적용\n    if (settings.priceScaleMargin) {\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      \n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        if (typeof settings.priceScaleMargin === 'object') {\n          viewport.setPriceMargin(\n            settings.priceScaleMargin.top || 0.02,\n            settings.priceScaleMargin.bottom || 0.02,\n            'main'  // 명시적으로 main 패널 지정\n          );\n        } else {\n          viewport.setPriceMargin(settings.priceScaleMargin, settings.priceScaleMargin, 'main');\n        }\n        \n        // 변경 사항을 즉시 반영하기 위해 render 호출\n        this.chart['isDirty'] = true;\n        this.chart['render']();\n      }\n      \n      // 볼륨 패널에는 마진을 0으로 설정\n      const volumePanel = this.chart['renderingManager'].getVolumePanel();\n      if (volumePanel) {\n        const viewport = volumePanel.getViewport();\n        viewport.setPriceMargin(0, 0, 'volume');\n      }\n    }\n    \n    // 오른쪽 여백 업데이트\n    if (settings.rightMargin !== undefined) {\n      console.log('[ChartUIHelper] Updating right margin:', settings.rightMargin);\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      const volumePanel = this.chart['renderingManager'].getVolumePanel();\n      \n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        viewport.setRightMargin(settings.rightMargin);\n        // 중요: 마진 설정 후 scrollToEnd를 호출해야 적용됨!\n        viewport.scrollToEnd();\n      }\n      if (volumePanel) {\n        const viewport = volumePanel.getViewport();\n        viewport.setRightMargin(settings.rightMargin);\n        viewport.scrollToEnd();\n      }\n    }\n    \n    // 로그 스케일 업데이트\n    if (settings.logScale !== undefined) {\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        viewport.setLogScale(settings.logScale);\n      }\n    }\n    \n    // 그리드 설정 업데이트\n    if (settings.grid !== undefined) {\n      const mainPanel = this.chart['renderingManager'].getMainPanel();\n      const volumePanel = this.chart['renderingManager'].getVolumePanel();\n      \n      if (mainPanel && 'updateOptions' in mainPanel) {\n        mainPanel.updateOptions({ grid: settings.grid });\n      }\n      \n      if (volumePanel && 'updateOptions' in volumePanel) {\n        volumePanel.updateOptions({ grid: settings.grid });\n      }\n    }\n    \n    // 패널 업데이트\n    if (settings.panels) {\n      // 볼륨 패널 설정\n      if (settings.panels.volume) {\n        const volumePanel = this.chart['renderingManager'].getVolumePanel();\n        if (volumePanel) {\n          // 볼륨 색상 업데이트\n          if (settings.panels.volume.colors) {\n            volumePanel.updateColors({\n              up: settings.panels.volume.colors.up,\n              down: settings.panels.volume.colors.down,\n              maColor: settings.panels.volume.maColor\n            });\n          }\n          \n          // 볼륨 옵션 업데이트\n          if ('updateOptions' in volumePanel) {\n            volumePanel.updateOptions({ panels: { volume: settings.panels.volume } });\n          }\n        }\n      }\n    }\n    \n    // 인디케이터 업데이트\n    if (settings.indicators) {\n      settings.indicators.forEach(indicator => {\n        if (indicator.id && this.chart['pluginManager'].getIndicator(indicator.id)) {\n          this.chart.updateIndicator(indicator.id, indicator);\n        } else if (!indicator.id) {\n          this.chart.addIndicator(indicator);\n        }\n      });\n    }\n    \n    // 자동 스케일 업데이트\n    if (settings.autoScale !== undefined) {\n      this.chart.getOptions().autoScale = settings.autoScale;\n      \n      // 현재 보이는 데이터에 맞춰 스케일 조정\n      if (settings.autoScale) {\n        const mainPanel = this.chart['renderingManager'].getMainPanel();\n        if (mainPanel) {\n          // updatePriceRangeForVisibleData 메서드가 있는지 확인\n          const viewport = mainPanel.getViewport();\n          if ('updatePriceRangeForVisibleData' in viewport) {\n            (viewport as any).updatePriceRangeForVisibleData();\n          }\n        }\n      }\n    }\n    \n    // 애니메이션 설정 업데이트\n    if (settings.animation !== undefined) {\n      this.chart.getOptions().animation = settings.animation;\n    }\n    \n    this.chart['isDirty'] = true;\n  }\n}","import type { ChartData } from '@/types';\n\nexport type Timeframe = '1m' | '5m' | '10m' | '30m' | '1h' | '4h' | '1d' | '1w' | '1M';\n\n/**\n * 차트 데이터의 캔들 간격을 감지하여 timeframe을 반환\n */\nexport function detectTimeframe(data: ChartData): Timeframe {\n  if (!data || data.length < 2) return '1m'; // 기본값\n  \n  // 처음 10개 캔들의 평균 간격 계산 (초 단위)\n  const sampleSize = Math.min(10, data.length - 1);\n  let totalInterval = 0;\n  \n  for (let i = 1; i <= sampleSize; i++) {\n    totalInterval += data.times[i] - data.times[i - 1];\n  }\n  \n  const avgInterval = totalInterval / sampleSize;\n  \n  // 간격에 따른 timeframe 판단 (약간의 오차 허용)\n  if (avgInterval <= 65) return '1m';        // 60초 ± 5초\n  else if (avgInterval <= 310) return '5m';   // 300초 ± 10초\n  else if (avgInterval <= 610) return '10m';  // 600초 ± 10초\n  else if (avgInterval <= 1810) return '30m'; // 1800초 ± 10초\n  else if (avgInterval <= 3700) return '1h';  // 3600초 ± 100초\n  else if (avgInterval <= 14500) return '4h'; // 14400초 ± 100초\n  else if (avgInterval <= 90000) return '1d'; // 86400초 ± 3600초\n  else if (avgInterval <= 648000) return '1w'; // 604800초 ± 43200초\n  else return '1M'; // 그 이상은 월봉으로 간주\n}\n\n/**\n * Timeframe별 기본 이동평균선 설정\n */\nexport const DEFAULT_MA_CONFIGS: Record<Timeframe, Array<{type: 'SMA' | 'EMA', period: number, color: string}>> = {\n  '1m': [\n    { type: 'EMA', period: 9, color: '#FF6B6B' },\n    { type: 'EMA', period: 21, color: '#4ECDC4' },\n    { type: 'EMA', period: 50, color: '#45B7D1' }\n  ],\n  '5m': [\n    { type: 'EMA', period: 9, color: '#FF6B6B' },\n    { type: 'EMA', period: 21, color: '#4ECDC4' },\n    { type: 'EMA', period: 50, color: '#45B7D1' }\n  ],\n  '10m': [\n    { type: 'SMA', period: 10, color: '#FF6B6B' },\n    { type: 'SMA', period: 30, color: '#4ECDC4' },\n    { type: 'SMA', period: 60, color: '#45B7D1' }\n  ],\n  '30m': [\n    { type: 'SMA', period: 10, color: '#FF6B6B' },\n    { type: 'SMA', period: 30, color: '#4ECDC4' },\n    { type: 'SMA', period: 60, color: '#45B7D1' },\n    { type: 'EMA', period: 200, color: '#FECA57' }\n  ],\n  '1h': [\n    { type: 'SMA', period: 20, color: '#FF6B6B' },\n    { type: 'SMA', period: 50, color: '#4ECDC4' },\n    { type: 'SMA', period: 100, color: '#45B7D1' },\n    { type: 'SMA', period: 200, color: '#FECA57' }\n  ],\n  '4h': [\n    { type: 'SMA', period: 20, color: '#FF6B6B' },\n    { type: 'SMA', period: 50, color: '#4ECDC4' },\n    { type: 'SMA', period: 100, color: '#45B7D1' },\n    { type: 'SMA', period: 200, color: '#FECA57' }\n  ],\n  '1d': [\n    { type: 'SMA', period: 5, color: '#FF6B6B' },\n    { type: 'SMA', period: 20, color: '#4ECDC4' },\n    { type: 'SMA', period: 60, color: '#45B7D1' },\n    { type: 'SMA', period: 120, color: '#FECA57' }\n  ],\n  '1w': [\n    { type: 'SMA', period: 5, color: '#FF6B6B' },\n    { type: 'SMA', period: 10, color: '#4ECDC4' },\n    { type: 'SMA', period: 20, color: '#45B7D1' }\n  ],\n  '1M': [\n    { type: 'SMA', period: 5, color: '#FF6B6B' },\n    { type: 'SMA', period: 12, color: '#4ECDC4' },\n    { type: 'SMA', period: 24, color: '#45B7D1' }\n  ]\n};","import type { Chart } from '../Chart';\nimport type { IndicatorConfig } from '@/types';\nimport { detectTimeframe, DEFAULT_MA_CONFIGS, type Timeframe } from '@/utils/timeframeDetector';\n\n/**\n * 인디케이터 관련 헬퍼 클래스\n */\nexport class ChartIndicatorHelper {\n  private timeframeMAIds: Map<Timeframe, string[]> = new Map();\n  \n  constructor(private chart: Chart) {}\n\n  /**\n   * 개별 SMA 추가 (간편 메서드)\n   */\n  addSMA(period: number, options?: { color?: string; lineWidth?: number; source?: 'open' | 'high' | 'low' | 'close' }): string {\n    // 타임스탬프를 추가하여 고유한 ID 생성\n    const timestamp = Date.now();\n    const randomSuffix = Math.random().toString(36).substring(2, 9);\n    const config: IndicatorConfig = {\n      id: `sma-${period}-${timestamp}-${randomSuffix}`,\n      name: `SMA ${period}`,\n      type: 'sma',\n      visible: true,\n      style: {\n        color: options?.color || '#2196F3',\n        lineWidth: options?.lineWidth || 1,\n        lineStyle: 'solid' as const,\n        opacity: 0.8\n      },\n      params: {\n        period,\n        source: options?.source || 'close'\n      }\n    };\n    return this.chart.addIndicator(config);\n  }\n\n  /**\n   * 개별 EMA 추가 (간편 메서드)\n   */\n  addEMA(period: number, options?: { color?: string; lineWidth?: number; source?: 'open' | 'high' | 'low' | 'close' }): string {\n    // 타임스탬프를 추가하여 고유한 ID 생성\n    const timestamp = Date.now();\n    const randomSuffix = Math.random().toString(36).substring(2, 9);\n    const config: IndicatorConfig = {\n      id: `ema-${period}-${timestamp}-${randomSuffix}`,\n      name: `EMA ${period}`,\n      type: 'ema',\n      visible: true,\n      style: {\n        color: options?.color || '#FF9800',\n        lineWidth: options?.lineWidth || 1,\n        lineStyle: 'solid' as const,\n        opacity: 0.8\n      },\n      params: {\n        period,\n        source: options?.source || 'close'\n      }\n    };\n    return this.chart.addIndicator(config);\n  }\n\n  /**\n   * 볼린저 밴드 추가 (간편 메서드)\n   */\n  addBollingerBands(period: number = 20, stdDev: number = 2, options?: { upperColor?: string; lowerColor?: string; middleColor?: string }): string {\n    const config: IndicatorConfig = {\n      id: `bb-${period}-${stdDev}`,\n      name: `BB (${period}, ${stdDev})`,\n      type: 'bollingerBands',\n      visible: true,\n      style: {\n        color: options?.middleColor || '#2196F3',\n        lineWidth: 1,\n        lineStyle: 'solid' as const,\n        opacity: 0.8\n      },\n      params: {\n        period,\n        stdDev,\n        upperColor: options?.upperColor || '#FF5252',\n        lowerColor: options?.lowerColor || '#4CAF50',\n        middleColor: options?.middleColor || '#2196F3'\n      }\n    };\n    return this.chart.addIndicator(config);\n  }\n\n  /**\n   * 모든 MA 라인 표시/숨김 토글\n   */\n  toggleAllMA(): void {\n    const indicators = this.chart['pluginManager'].getIndicators();\n    indicators.forEach((indicator: IndicatorConfig) => {\n      if (indicator.type === 'sma' || indicator.type === 'ema') {\n        this.chart.updateIndicator(indicator.id, { visible: !indicator.visible });\n      }\n    });\n  }\n\n  /**\n   * 인디케이터 추가\n   */\n  addIndicator(config: IndicatorConfig): string {\n    const id = this.chart['pluginManager'].addIndicator(config);\n    \n    // 데이터가 있으면 재계산\n    if (!this.chart['dataManager'].isEmpty()) {\n      const data = this.chart['dataManager'].getData()!;\n      this.chart['pluginManager'].calculateAll(data);\n    }\n    \n    this.chart.setDirty(true);\n    return id;\n  }\n\n  /**\n   * 인디케이터 제거\n   */\n  removeIndicator(id: string): void {\n    this.chart['pluginManager'].removeIndicator(id);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 인디케이터 업데이트\n   */\n  updateIndicator(id: string, updates: Partial<IndicatorConfig>): void {\n    this.chart['pluginManager'].updateIndicator(id, updates);\n    \n    // 데이터가 있으면 재계산\n    if (!this.chart['dataManager'].isEmpty()) {\n      const data = this.chart['dataManager'].getData()!;\n      this.chart['pluginManager'].calculateAll(data);\n    }\n    \n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 인디케이터 가져오기\n   */\n  getIndicator(id: string): IndicatorConfig | undefined {\n    return this.chart['pluginManager'].getIndicator(id);\n  }\n\n  /**\n   * 모든 인디케이터 가져오기\n   */\n  getIndicators(): IndicatorConfig[] {\n    return this.chart['pluginManager'].getIndicators();\n  }\n\n  /**\n   * 모든 인디케이터 제거\n   */\n  clearIndicators(): void {\n    const indicators = this.chart['pluginManager'].getIndicators();\n    indicators.forEach(indicator => {\n      this.chart['pluginManager'].removeIndicator(indicator.id);\n    });\n    this.chart.setDirty(true);\n  }\n  \n  /**\n   * 인디케이터 토글\n   */\n  toggleIndicator(id: string): void {\n    this.chart['pluginManager'].toggleIndicator(id);\n    this.chart.setDirty(true);\n  }\n\n  /**\n   * 현재 timeframe에 맞는 이동평균선 세트 적용\n   */\n  applyTimeframeMA(customConfigs?: Record<Timeframe, Array<{type: 'SMA' | 'EMA', period: number, color: string}>>): void {\n    // 현재 데이터의 timeframe 감지\n    const data = this.chart['dataManager'].getData();\n    if (!data) return;\n    \n    const timeframe = detectTimeframe(data);\n    \n    // 이전 timeframe의 MA들 제거\n    this.clearTimeframeMA();\n    \n    // 사용할 설정 결정 (사용자 정의 설정 또는 기본 설정)\n    const configs = customConfigs || DEFAULT_MA_CONFIGS;\n    const maConfigs = configs[timeframe];\n    \n    if (!maConfigs) return;\n    \n    // 새로운 MA들 추가\n    const ids: string[] = [];\n    maConfigs.forEach(config => {\n      let id: string;\n      if (config.type === 'SMA') {\n        id = this.addSMA(config.period, { color: config.color });\n      } else {\n        id = this.addEMA(config.period, { color: config.color });\n      }\n      ids.push(id);\n    });\n    \n    // timeframe별 ID 저장\n    this.timeframeMAIds.set(timeframe, ids);\n    \n    console.log(`Applied ${maConfigs.length} moving averages for ${timeframe} timeframe`);\n  }\n\n  /**\n   * timeframe별로 적용된 이동평균선 제거\n   */\n  clearTimeframeMA(): void {\n    // 모든 저장된 timeframe MA 제거\n    this.timeframeMAIds.forEach((ids) => {\n      ids.forEach(id => {\n        this.removeIndicator(id);\n      });\n    });\n    this.timeframeMAIds.clear();\n  }\n\n  /**\n   * 특정 timeframe의 이동평균선만 제거\n   */\n  clearTimeframeMAByTimeframe(timeframe: Timeframe): void {\n    const ids = this.timeframeMAIds.get(timeframe);\n    if (ids) {\n      ids.forEach(id => {\n        this.removeIndicator(id);\n      });\n      this.timeframeMAIds.delete(timeframe);\n    }\n  }\n\n  /**\n   * 현재 적용된 timeframe MA 정보 가져오기\n   */\n  getTimeframeMAInfo(): { timeframe: Timeframe | null, indicatorIds: string[] } {\n    const data = this.chart['dataManager'].getData();\n    if (!data) return { timeframe: null, indicatorIds: [] };\n    \n    const timeframe = detectTimeframe(data);\n    const indicatorIds = this.timeframeMAIds.get(timeframe) || [];\n    \n    return { timeframe, indicatorIds };\n  }\n}","import type { ChartOptions, Candle, Theme, ChartType, DrawingOptions, DrawingToolType, IndicatorConfig } from '@/types';\nimport type { StopLossOptions, StopLossLine } from '@/types/stopLoss';\nimport type { Marker } from '@/types/marker';\nimport { DataManager } from '@/core/DataManager';\nimport { InteractionManager } from '@/core/InteractionManager';\nimport { RenderingManager } from '@/core/RenderingManager';\nimport { PluginManager } from '@/core/PluginManager';\nimport type { LineSeriesOptions } from '@/core/LineSeriesManager';\nimport { UnifiedCoordinateSystem } from '@/core/UnifiedCoordinateSystem';\nimport { registerIndicatorPlugins } from '@/plugins/indicators';\nimport { getTheme } from '@/utils/theme';\n\nimport { ChartEventHandler } from './chart/ChartEventHandler';\nimport { ChartLifecycle } from './chart/ChartLifecycle';\nimport { ChartLineSeriesHelper } from './chart/ChartLineSeriesHelper';\nimport { ChartStopLossHelper } from './chart/ChartStopLossHelper';\nimport { ChartStyleHelper } from './chart/ChartStyleHelper';\nimport { ChartViewportHelper } from './chart/ChartViewportHelper';\nimport { ChartDataHelper } from './chart/ChartDataHelper';\nimport { ChartDrawingHelper } from './chart/ChartDrawingHelper';\nimport { ChartMarkerHelper } from './chart/ChartMarkerHelper';\nimport { ChartExportHelper } from './chart/ChartExportHelper';\nimport { ChartUIHelper } from './chart/ChartUIHelper';\nimport { ChartIndicatorHelper } from './chart/ChartIndicatorHelper';\nimport { ChartThemeHelper } from './chart/ChartThemeHelper';\n\nexport class Chart {\n  private container: HTMLElement;\n  private dataManager: DataManager;\n  private interactionManager: InteractionManager;\n  private renderingManager: RenderingManager;\n  private pluginManager: PluginManager;\n  \n  private theme: Theme;\n  private options: ChartOptions;\n  \n  // 컨트롤러들\n  private eventHandler: ChartEventHandler;\n  private lifecycle: ChartLifecycle;\n  \n  // 헬퍼들\n  private lineSeriesHelper: ChartLineSeriesHelper;\n  private stopLossHelper: ChartStopLossHelper;\n  private styleHelper: ChartStyleHelper;\n  private viewportHelper: ChartViewportHelper;\n  private dataHelper: ChartDataHelper;\n  private drawingHelper: ChartDrawingHelper;\n  private markerHelper: ChartMarkerHelper;\n  private exportHelper: ChartExportHelper;\n  private uiHelper: ChartUIHelper;\n  private indicatorHelper: ChartIndicatorHelper;\n  \n  // 상태\n  private animationFrameId: number | null = null;\n  private isDirty: boolean = true;\n  \n  // 디버그 모드\n  private debugMode: boolean = false;\n  private debugCallbacks: ((message: string) => void)[] = [];\n  \n  // 줌 옵션\n  private zoomMode: 'mouse' | 'latest' = 'mouse';\n  \n  // UI 컴포넌트 - 모두 제거됨\n  // IndicatorConfigPanel removed - use API methods instead\n  // IndicatorPanel removed - API methods available\n  // SettingsPanel removed - API methods available\n  // DrawingToolbar removed - API methods available\n\n  // 대기 중인 데이터\n  private pendingData: { candles: Candle[], immediateRender: boolean } | null = null;\n  \n  // 타이머 추적\n  private pendingDataTimeout: number | null = null;\n  \n  constructor(options: ChartOptions) {\n    registerIndicatorPlugins();\n    \n    // 컨테이너 엘리먼트 가져오기\n    if (typeof options.container === 'string') {\n      const element = document.getElementById(options.container);\n      if (!element) {\n        throw new Error(`Container element with id \"${options.container}\" not found`);\n      }\n      this.container = element;\n    } else {\n      this.container = options.container;\n    }\n    \n    this.options = options;\n    this.theme = ChartThemeHelper.mergeThemeWithOptions(getTheme(options.theme || 'dark'), options);\n    \n    // 디버그 모드 설정\n    this.debugMode = options.debug || false;\n    if (options.onDebug) {\n      this.debugCallbacks.push(options.onDebug);\n    }\n    \n    // 컨테이너의 기존 내용 정리\n    while (this.container.firstChild) {\n      this.container.removeChild(this.container.firstChild);\n    }\n    \n    // 컨테이너 스타일 설정\n    this.container.style.position = 'relative';\n    this.container.style.overflow = 'hidden';\n    \n    // 명시적 크기가 지정된 경우 설정\n    if (options.width) {\n      this.container.style.width = typeof options.width === 'number' ? `${options.width}px` : options.width;\n    }\n    if (options.height) {\n      this.container.style.height = typeof options.height === 'number' ? `${options.height}px` : options.height;\n    }\n    \n    // 컨테이너가 크기를 가지지 않은 경우 100% 설정\n    if (!this.container.style.width) {\n      this.container.style.width = '100%';\n    }\n    if (!this.container.style.height) {\n      this.container.style.height = '100%';\n    }\n    \n    // 차트 컨테이너 스타일 설정\n    // disableUI가 true인 경우에도 box-sizing은 적용\n    this.container.style.boxSizing = 'border-box';\n    \n    // 마진 설정을 패딩으로 변경 (차트가 컨테이너를 벗어나지 않도록)\n    if (options.margin) {\n      const paddingTop = options.margin.top || 0;\n      const paddingBottom = options.margin.bottom || 0;\n      const paddingLeft = options.margin.left || 0;\n      const paddingRight = options.margin.right || 0;\n      \n      this.container.style.padding = `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`;\n    }\n    \n    // 매니저 초기화\n    this.dataManager = new DataManager();\n    this.interactionManager = new InteractionManager();\n    this.pluginManager = new PluginManager();\n    this.renderingManager = new RenderingManager(this.container, this.theme, this.options);\n    \n    // 의존성 주입\n    this.renderingManager.setDataManager(this.dataManager);\n    this.renderingManager.setInteractionManager(this.interactionManager);\n    this.renderingManager.setPluginManager(this.pluginManager);\n    this.interactionManager.setDataManager(this.dataManager);\n    \n    this.interactionManager['drawingManager'].setTheme(this.theme);\n    this.interactionManager['drawingManager'].setChart(this);\n    \n    // 컨트롤러들을 먼저 초기화\n    this.eventHandler = new ChartEventHandler(this);\n    \n    // 헬퍼들 초기화\n    this.lineSeriesHelper = new ChartLineSeriesHelper(this);\n    this.stopLossHelper = new ChartStopLossHelper(this);\n    this.styleHelper = new ChartStyleHelper(this);\n    this.viewportHelper = new ChartViewportHelper(this);\n    this.dataHelper = new ChartDataHelper(this);\n    this.drawingHelper = new ChartDrawingHelper(this);\n    this.markerHelper = new ChartMarkerHelper(this);\n    this.exportHelper = new ChartExportHelper(this);\n    this.uiHelper = new ChartUIHelper(this);\n    this.indicatorHelper = new ChartIndicatorHelper(this);\n    \n    // UI 비활성화 옵션 체크\n    if (options.disableUI === true) {\n      // Trading Journal 통합 모드: 모든 UI 비활성화\n      this.debugLog('UI disabled for Trading Journal integration');\n    }\n    \n    this.lifecycle = new ChartLifecycle(this);\n\n    // 초기 데이터 처리 - 옵션에서 data를 무시하고 나중에 처리\n    if (options.data && options.data.length > 0) {\n      this.debugLog('Initial data provided, will set after initialization');\n      this.pendingData = { \n        candles: options.data, \n        immediateRender: options.immediateRender !== false \n      };\n    }\n    \n    // 초기화 완료 후 데이터 자동 설정\n    this.lifecycle.on('stateChange', (state) => {\n      if (state === 'ready' && this.pendingData) {\n        this.debugLog('Chart ready, setting pending data');\n        // 약간의 지연을 주어 DOM이 완전히 준비되도록 함\n        this.pendingDataTimeout = window.setTimeout(() => {\n          if (this.pendingData) {\n            const data = this.pendingData;\n            this.pendingData = null; // 무한 루프 방지\n            this.pendingDataTimeout = null;\n            this.setData(data.candles, data.immediateRender);\n          }\n        }, 50);\n      }\n    });\n    \n    // 비동기 초기화 시작\n    const initPromise = this.lifecycle.init();\n    this.lifecycle.setInitPromise(initPromise);\n  }\n  \n  /**\n   * 디버그 로깅\n   */\n  debugLog(message: string): void {\n    if (this.debugMode) {\n      const timestamp = new Date().toISOString();\n      const formattedMessage = `[Chart ${timestamp}] ${message}`;\n      console.log(formattedMessage);\n      this.debugCallbacks.forEach(callback => callback(formattedMessage));\n    }\n  }\n  \n  startRenderLoop(): void {\n    const render = () => {\n      if (this.isDirty && !this.dataManager.isEmpty()) {\n        this.render();\n        this.isDirty = false;\n      }\n      this.animationFrameId = requestAnimationFrame(render);\n    };\n    render();\n  }\n\n  stopRenderLoop(): void {\n    if (this.animationFrameId !== null) {\n      cancelAnimationFrame(this.animationFrameId);\n      this.animationFrameId = null;\n    }\n  }\n  \n  private render(): void {\n    const data = this.dataManager.getData();\n    if (!data) return;\n    \n    // 인디케이터 데이터를 포함하여 렌더링\n    const indicators = this.pluginManager.getIndicatorData();\n    this.renderingManager.render(data, indicators);\n  }\n  \n  /**\n   * 데이터 설정\n   * @param candles 캔들 데이터\n   * @param immediateRender 즉시 렌더링 여부 (React 환경에서 유용)\n   */\n  setData(candles: Candle[], immediateRender: boolean = false): void {\n    // 차트가 아직 초기화되지 않았으면 대기\n    if (!this.lifecycle.isReady()) {\n      this.debugLog('Chart not ready, queueing data update');\n      this.pendingData = { candles, immediateRender };\n      return;\n    }\n\n    // Tauri 환경인지 확인\n    const isTauri = !!window.__TAURI__;\n    \n    if (isTauri) {\n      // Tauri 환경에서는 복잡한 체크 없이 바로 실행\n      console.log('[Tauri] Setting data directly without size checks');\n      this.dataHelper.actualSetData(candles, immediateRender);\n    } else {\n      // 웹 환경에서만 복잡한 크기 체크\n      const rect = this.container.getBoundingClientRect();\n      const hasValidSize = rect.width > 0 && rect.height > 0;\n      \n      if (!hasValidSize) {\n        this.debugLog('Container has zero size in web environment, using requestAnimationFrame');\n        // 웹에서만 사용할 폴백 로직\n        requestAnimationFrame(() => {\n          this.dataHelper.actualSetData(candles, immediateRender);\n        });\n        return;\n      }\n      \n      this.dataHelper.actualSetData(candles, immediateRender);\n    }\n  }\n\n  // 캔들 리샘플링 메서드들\n  resampleData(groupSize: number): void {\n    this.dataHelper.resampleData(groupSize);\n  }\n  \n  resampleDataByTime(targetMinutes: number, sourceMinutes: number = 5): void {\n    this.dataHelper.resampleDataByTime(targetMinutes, sourceMinutes);\n  }\n  \n  convertTo65Min(): void {\n    this.dataHelper.convertTo65Min();\n  }\n  \n  restoreOriginalData(): void {\n    this.dataHelper.restoreOriginalData();\n  }\n  \n  isDataResampled(): boolean {\n    return this.dataHelper.isDataResampled();\n  }\n  \n  getOriginalData(): Candle[] | null {\n    return this.dataHelper.getOriginalData();\n  }\n  \n  /**\n   * 차트 크기 조정\n   */\n  resize(): void {\n    this.renderingManager.resize();\n    this.isDirty = true;\n  }\n  \n  /**\n   * 초기화 완료 대기\n   */\n  async waitUntilReady(): Promise<void> {\n    return this.lifecycle.waitUntilReady();\n  }\n  \n  /**\n   * 리소스 정리\n   */\n  dispose(): void {\n    // 타이머 정리\n    if (this.pendingDataTimeout) {\n      clearTimeout(this.pendingDataTimeout);\n      this.pendingDataTimeout = null;\n    }\n    \n    // 애니메이션 프레임 정리\n    if (this.animationFrameId) {\n      cancelAnimationFrame(this.animationFrameId);\n      this.animationFrameId = null;\n    }\n    \n    // 렌더 루프 중지\n    this.stopRenderLoop();\n    \n    // 라이프사이클 정리\n    this.lifecycle.dispose();\n  }\n  \n\n  // Getters\n  getContainer(): HTMLElement { return this.container; }\n  getDataManager(): DataManager { return this.dataManager; }\n  getTheme(): Theme { return this.theme; }\n  getOptions(): ChartOptions { return this.options; }\n  getEventHandler(): ChartEventHandler { return this.eventHandler; }\n  getZoomMode(): 'mouse' | 'latest' { return this.zoomMode; }\n  getPendingData(): { candles: Candle[], immediateRender: boolean } | null { return this.pendingData; }\n  clearPendingData(): void { this.pendingData = null; }\n\n  setDirty(value: boolean): void { this.isDirty = value; }\n\n  // Lifecycle\n  isReady(): boolean { return this.lifecycle.isReady(); }\n  getState(): string { return this.lifecycle.getState(); }\n  on(event: 'stateChange', callback: (state: string) => void): void {\n    this.lifecycle.on(event, callback);\n  }\n  off(event: 'stateChange', callback: (state: string) => void): void {\n    this.lifecycle.off(event, callback);\n  }\n  \n  // Indicators\n  addIndicator(config: IndicatorConfig): string {\n    return this.indicatorHelper.addIndicator(config);\n  }\n  removeIndicator(id: string): void {\n    this.indicatorHelper.removeIndicator(id);\n  }\n  clearIndicators(): void {\n    this.indicatorHelper.clearIndicators();\n  }\n  toggleIndicator(id: string): void {\n    this.indicatorHelper.toggleIndicator(id);\n  }\n  getIndicators(): IndicatorConfig[] {\n    return this.indicatorHelper.getIndicators();\n  }\n  updateIndicator(id: string, updates: Partial<IndicatorConfig>): void {\n    this.indicatorHelper.updateIndicator(id, updates);\n  }\n  addSMA(period: number, options?: { color?: string; lineWidth?: number; source?: 'open' | 'high' | 'low' | 'close' }): string {\n    return this.indicatorHelper.addSMA(period, options);\n  }\n  addEMA(period: number, options?: { color?: string; lineWidth?: number; source?: 'open' | 'high' | 'low' | 'close' }): string {\n    return this.indicatorHelper.addEMA(period, options);\n  }\n  addBollingerBands(period: number = 20, stdDev: number = 2, options?: { upperColor?: string; lowerColor?: string; middleColor?: string }): string {\n    return this.indicatorHelper.addBollingerBands(period, stdDev, options);\n  }\n  toggleAllMA(): void {\n    this.indicatorHelper.toggleAllMA();\n  }\n  \n  // Timeframe-based MA methods\n  applyTimeframeMA(customConfigs?: Record<string, Array<{type: 'SMA' | 'EMA', period: number, color: string}>>): void {\n    this.indicatorHelper.applyTimeframeMA(customConfigs as any);\n  }\n  clearTimeframeMA(): void {\n    this.indicatorHelper.clearTimeframeMA();\n  }\n  getTimeframeMAInfo(): { timeframe: string | null, indicatorIds: string[] } {\n    return this.indicatorHelper.getTimeframeMAInfo();\n  }\n  \n  // Drawing\n  addDrawing(type: string, options?: DrawingOptions): void {\n    this.drawingHelper.addDrawing(type, options);\n  }\n  exportDrawings(): string {\n    return this.drawingHelper.exportDrawings();\n  }\n  importDrawings(jsonData: string): void {\n    this.drawingHelper.importDrawings(jsonData);\n  }\n  clearDrawings(): void {\n    this.drawingHelper.clearDrawings();\n  }\n  setDrawingTool(tool: DrawingToolType | null): void {\n    this.drawingHelper.setDrawingTool(tool);\n  }\n  getDrawingTool(): DrawingToolType | null {\n    return this.drawingHelper.getDrawingTool();\n  }\n  setMagneticMode(enabled: boolean): void {\n    this.drawingHelper.setMagneticMode(enabled);\n  }\n  getMagneticMode(): boolean {\n    return this.drawingHelper.getMagneticMode();\n  }\n  \n  // Marker\n  addMarker(marker: Marker): string {\n    return this.markerHelper.addMarker(marker);\n  }\n  setMarkers(markers: Marker[]): void {\n    this.markerHelper.setMarkers(markers);\n  }\n  removeMarker(id: string): void {\n    this.markerHelper.removeMarker(id);\n  }\n  clearMarkers(): void {\n    this.markerHelper.clearMarkers();\n  }\n  getMarkers(): Marker[] {\n    return this.markerHelper.getMarkers();\n  }\n  \n  async toImage(format: 'png' | 'jpeg' = 'png', quality: number = 0.9, scaleFactor?: number): Promise<Blob> {\n    return this.exportHelper.toImage(format, quality, scaleFactor);\n  }\n\n  /**\n   * 차트를 고화질(QHD+) 이미지로 내보내기\n   */\n  async toHighResImage(format: 'png' | 'jpeg' = 'png', quality: number = 0.95): Promise<Blob> {\n    return this.exportHelper.toHighResImage(format, quality);\n  }\n\n  /**\n   * 차트를 지정된 해상도로 내보내기\n   */\n  async toCustomResolution(targetWidth: number, format: 'png' | 'jpeg' = 'png', quality: number = 0.95): Promise<Blob> {\n    return this.exportHelper.toCustomResolution(targetWidth, format, quality);\n  }\n  \n  // UI\n  setChartType(type: ChartType): void {\n    this.uiHelper.setChartType(type);\n  }\n  setTheme(theme: 'dark' | 'light'): void {\n    this.uiHelper.setTheme(theme);\n  }\n  setCursorType(type: 'default' | 'crosshair' | 'dot'): void {\n    this.uiHelper.setCursorType(type);\n  }\n  setZoomMode(mode: 'mouse' | 'latest'): void {\n    this.uiHelper.setZoomMode(mode);\n  }\n  updateSettings(settings: Partial<ChartOptions>): void {\n    this.uiHelper.updateSettings(settings);\n  }\n    getViewport(): UnifiedCoordinateSystem | null {\n    const mainPanel = this.renderingManager.getMainPanel();\n    return mainPanel ? mainPanel.getViewport() : null;\n  }\n\n  // Line Series Methods\n  addLineSeries(options: LineSeriesOptions): string {\n    return this.lineSeriesHelper.addLineSeries(options);\n  }\n  updateLineSeries(id: string, data: Array<{ time: number; value: number }>): void {\n    this.lineSeriesHelper.updateLineSeries(id, data);\n  }\n  removeLineSeries(id: string): void {\n    this.lineSeriesHelper.removeLineSeries(id);\n  }\n  toggleLineSeriesVisibility(id: string): void {\n    this.lineSeriesHelper.toggleLineSeriesVisibility(id);\n  }\n  updateLineSeriesStyle(id: string, style: { color?: string; lineWidth?: number }): void {\n    this.lineSeriesHelper.updateLineSeriesStyle(id, style);\n  }\n  getAllLineSeries() {\n    return this.lineSeriesHelper.getAllLineSeries();\n  }\n  clearLineSeries(): void {\n    this.lineSeriesHelper.clearLineSeries();\n  }\n  \n  // Stop Loss Methods\n  addStopLossLine(price: number, options?: StopLossOptions): string {\n    return this.stopLossHelper.addStopLossLine(price, options);\n  }\n  removeStopLossLine(id: string): boolean {\n    return this.stopLossHelper.removeStopLossLine(id);\n  }\n  clearStopLossLines(): void {\n    this.stopLossHelper.clearStopLossLines();\n  }\n  updateStopLossLine(id: string, updates: Partial<StopLossOptions & { price?: number }>): boolean {\n    return this.stopLossHelper.updateStopLossLine(id, updates);\n  }\n  getStopLossLines(): StopLossLine[] {\n    return this.stopLossHelper.getStopLossLines();\n  }\n\n\n  // Style Methods\n  updateCandleColors(colors: { upColor?: string; downColor?: string; borderUpColor?: string; borderDownColor?: string; wickColor?: string }): void {\n    this.styleHelper.updateCandleColors(colors);\n  }\n\n  updateVolumeColors(colors: { up?: string; down?: string; maColor?: string }): void {\n    this.styleHelper.updateVolumeColors(colors);\n  }\n\n  updateMovingAverageStyle(id: string, style: { color?: string; lineWidth?: number; lineStyle?: 'solid' | 'dashed' | 'dotted'; opacity?: number }): void {\n    this.styleHelper.updateMovingAverageStyle(id, style);\n  }\n\n  updateAllMovingAveragesStyle(style: { color?: string; lineWidth?: number; lineStyle?: 'solid' | 'dashed' | 'dotted'; opacity?: number }): void {\n    this.styleHelper.updateAllMovingAveragesStyle(style);\n  }\n\n  updateMarkerStyle(id: string, style: { color?: string; text?: string; size?: number }): void {\n    this.styleHelper.updateMarkerStyle(id, style);\n  }\n\n  updateMarkersStyleByType(type: 'buy' | 'sell', style: { color?: string; text?: string; size?: number; shape?: 'arrowUp' | 'arrowDown' | 'circle' | 'square' }): void {\n    this.styleHelper.updateMarkersStyleByType(type, style);\n  }\n\n  updateStopLossStyle(id: string, style: { color?: string; lineWidth?: number; label?: string; opacity?: number }): void {\n    this.styleHelper.updateStopLossStyle(id, style);\n  }\n\n  addAveragePriceLine(price: number, options?: { label?: string; color?: string; lineWidth?: number; dashed?: boolean }): string {\n    return this.stopLossHelper.addAveragePriceLine(price, options);\n  }\n\n  updateAveragePriceLine(id: string, updates: { price?: number; label?: string; color?: string; lineWidth?: number }): boolean {\n    return this.stopLossHelper.updateAveragePriceLine(id, updates);\n  }\n\n  updatePriceRangeForVisibleData(): void {\n    this.viewportHelper.updatePriceRangeForVisibleData();\n  }\n\n  /**\n   * 차트뷰를 초기 설정대로 리셋\n   */\n  applyInitialView(): void {\n    const mainPanel = this.renderingManager.getMainPanel();\n    const volumePanel = this.renderingManager.getVolumePanel();\n    \n    if (mainPanel) {\n      const viewport = mainPanel.getViewport();\n      const data = this.dataManager.getData();\n      \n      if (viewport && data) {\n        // 잠금 상태 확인\n        const isLocked = localStorage.getItem('chartViewLocked') === 'true';\n        \n        if (isLocked) {\n          // 잠금 상태일 때: 저장된 잠금 뷰로 리셋\n          try {\n            const lockedViewState = JSON.parse(localStorage.getItem('lockedViewState') || '{}');\n            if (lockedViewState.visibleCandles) {\n              viewport.setVisibleCandles(lockedViewState.visibleCandles);\n              if (lockedViewState.rightMargin !== undefined) {\n                viewport.setRightMargin(lockedViewState.rightMargin);\n              }\n              viewport.scrollToEnd();\n              \n              // 볼륨 패널도 동기화\n              if (volumePanel) {\n                const volumeViewport = volumePanel.getViewport();\n                volumeViewport.setVisibleCandles(lockedViewState.visibleCandles);\n                if (lockedViewState.rightMargin !== undefined) {\n                  volumeViewport.setRightMargin(lockedViewState.rightMargin);\n                }\n                volumeViewport.scrollToEnd();\n              }\n              \n              console.log('Reset to locked view state:', lockedViewState);\n            } else {\n              // 잠금 데이터가 없으면 설정값으로\n              this.applySettingsView(viewport, volumePanel, data);\n            }\n          } catch (e) {\n            console.error('Failed to apply locked view:', e);\n            this.applySettingsView(viewport, volumePanel, data);\n          }\n        } else {\n          // 잠금 해제 상태일 때: 설정값으로 리셋\n          this.applySettingsView(viewport, volumePanel, data);\n        }\n        \n        // 오토스케일이 켜져있으면 가격 범위 재계산\n        if (viewport.isAutoScale()) {\n          this.updatePriceRangeForVisibleData();\n        }\n      }\n    }\n  }\n  \n  /**\n   * 설정값으로 뷰 적용 (헬퍼 메서드)\n   */\n  private applySettingsView(viewport: any, volumePanel: any, data: any): void {\n    // 초기 뷰 적용\n    this.viewportHelper.applyInitialView(viewport, data, this.options);\n    \n    // 볼륨 패널도 동기화\n    if (volumePanel) {\n      const volumeViewport = volumePanel.getViewport();\n      this.viewportHelper.applyInitialView(volumeViewport, data, this.options);\n    }\n  }\n\n  /**\n   * 차트뷰 고정/해제 토글\n   */\n  toggleViewLock(): void {\n    const isLocked = localStorage.getItem('chartViewLocked') === 'true';\n    \n    if (!isLocked) {\n      // 현재 뷰 상태 저장\n      const mainPanel = this.renderingManager.getMainPanel();\n      if (mainPanel) {\n        const viewport = mainPanel.getViewport();\n        const chartAreaWidth = viewport.getChartAreaWidth();\n        const candleWidth = viewport.getCandleWidth();\n        \n        // 보이는 캔들 수 계산\n        const visibleCandles = Math.round(chartAreaWidth / candleWidth);\n        \n        // rightMargin 값 가져오기\n        const rightMargin = this.options.rightMargin || 0;\n        \n        // 뷰 상태 저장\n        const lockedViewState = {\n          visibleCandles,\n          rightMargin\n        };\n        \n        localStorage.setItem('chartViewLocked', 'true');\n        localStorage.setItem('lockedViewState', JSON.stringify(lockedViewState));\n        \n        console.log('Chart view locked:', lockedViewState);\n      }\n    } else {\n      // 잠금 해제\n      localStorage.setItem('chartViewLocked', 'false');\n      console.log('Chart view unlocked');\n      \n      // 설정값으로 되돌리기\n      this.applyInitialView();\n    }\n    \n    // TODO: UI 업데이트 (자물쇠 아이콘)\n  }\n  \n  /**\n   * 드로잉 기본 스타일 설정\n   */\n  setDefaultDrawingStyle(style: { color?: string; lineWidth?: number; opacity?: number; markerType?: string; markerSize?: number; markerColor?: string }): void {\n    this.interactionManager.setDefaultDrawingStyle(style);\n  }\n  \n  /**\n   * 드로잉 기본 스타일 가져오기\n   */\n  getDefaultDrawingStyle?(): any {\n    // 현재 구현되지 않음 - 추후 필요시 구현\n    return {};\n  }\n  \n  /**\n   * 텍스트 기본 스타일 설정\n   */\n  setTextDefaults(textDefaults: any): void {\n    this.interactionManager.setTextDefaults(textDefaults);\n  }\n\n\n}","/**\n * @license React\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var f=require(\"react\"),k=Symbol.for(\"react.element\"),l=Symbol.for(\"react.fragment\"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=\"\"+g);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}exports.Fragment=l;exports.jsx=q;exports.jsxs=q;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types.\nvar REACT_ELEMENT_TYPE = Symbol.for('react.element');\nvar REACT_PORTAL_TYPE = Symbol.for('react.portal');\nvar REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');\nvar REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');\nvar REACT_PROFILER_TYPE = Symbol.for('react.profiler');\nvar REACT_PROVIDER_TYPE = Symbol.for('react.provider');\nvar REACT_CONTEXT_TYPE = Symbol.for('react.context');\nvar REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');\nvar REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');\nvar REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');\nvar REACT_MEMO_TYPE = Symbol.for('react.memo');\nvar REACT_LAZY_TYPE = Symbol.for('react.lazy');\nvar REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n  {\n    {\n      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n        args[_key2 - 1] = arguments[_key2];\n      }\n\n      printWarning('error', format, args);\n    }\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n    var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n    var argsWithFormat = args.map(function (item) {\n      return String(item);\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// -----------------------------------------------------------------------------\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\nvar enableCacheElement = false;\nvar enableTransitionTracing = false; // No known bugs, but needs performance testing\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n// stuff. Intended to enable React core members to more easily debug scheduling\n// issues in DEV builds.\n\nvar enableDebugTracing = false; // Track which Fiber(s) schedule render work.\n\nvar REACT_MODULE_REFERENCE;\n\n{\n  REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');\n}\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing  || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden  || type === REACT_OFFSCREEN_TYPE || enableScopeAPI  || enableCacheElement  || enableTransitionTracing ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object\n    // types supported by any Flight configuration anywhere since\n    // we don't know which Flight build this will end up being used\n    // with.\n    type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var displayName = outerType.displayName;\n\n  if (displayName) {\n    return displayName;\n  }\n\n  var functionName = innerType.displayName || innerType.name || '';\n  return functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName;\n} // Keep in sync with react-reconciler/getComponentNameFromFiber\n\n\nfunction getContextName(type) {\n  return type.displayName || 'Context';\n} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.\n\n\nfunction getComponentNameFromType(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case REACT_FRAGMENT_TYPE:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return 'Profiler';\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        var context = type;\n        return getContextName(context) + '.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        var provider = type;\n        return getContextName(provider._context) + '.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        var outerName = type.displayName || null;\n\n        if (outerName !== null) {\n          return outerName;\n        }\n\n        return getComponentNameFromType(type.type) || 'Memo';\n\n      case REACT_LAZY_TYPE:\n        {\n          var lazyComponent = type;\n          var payload = lazyComponent._payload;\n          var init = lazyComponent._init;\n\n          try {\n            return getComponentNameFromType(init(payload));\n          } catch (x) {\n            return null;\n          }\n        }\n\n      // eslint-disable-next-line no-fallthrough\n    }\n  }\n\n  return null;\n}\n\nvar assign = Object.assign;\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n  {\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      prevLog = console.log;\n      prevInfo = console.info;\n      prevWarn = console.warn;\n      prevError = console.error;\n      prevGroup = console.group;\n      prevGroupCollapsed = console.groupCollapsed;\n      prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n      var props = {\n        configurable: true,\n        enumerable: true,\n        value: disabledLog,\n        writable: true\n      }; // $FlowFixMe Flow thinks console is immutable.\n\n      Object.defineProperties(console, {\n        info: props,\n        log: props,\n        warn: props,\n        error: props,\n        group: props,\n        groupCollapsed: props,\n        groupEnd: props\n      });\n      /* eslint-enable react-internal/no-production-logging */\n    }\n\n    disabledDepth++;\n  }\n}\nfunction reenableLogs() {\n  {\n    disabledDepth--;\n\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      var props = {\n        configurable: true,\n        enumerable: true,\n        writable: true\n      }; // $FlowFixMe Flow thinks console is immutable.\n\n      Object.defineProperties(console, {\n        log: assign({}, props, {\n          value: prevLog\n        }),\n        info: assign({}, props, {\n          value: prevInfo\n        }),\n        warn: assign({}, props, {\n          value: prevWarn\n        }),\n        error: assign({}, props, {\n          value: prevError\n        }),\n        group: assign({}, props, {\n          value: prevGroup\n        }),\n        groupCollapsed: assign({}, props, {\n          value: prevGroupCollapsed\n        }),\n        groupEnd: assign({}, props, {\n          value: prevGroupEnd\n        })\n      });\n      /* eslint-enable react-internal/no-production-logging */\n    }\n\n    if (disabledDepth < 0) {\n      error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n    }\n  }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n  {\n    if (prefix === undefined) {\n      // Extract the VM specific prefix used by each line.\n      try {\n        throw Error();\n      } catch (x) {\n        var match = x.stack.trim().match(/\\n( *(at )?)/);\n        prefix = match && match[1] || '';\n      }\n    } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n    return '\\n' + prefix + name;\n  }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n  var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n  componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n  // If something asked for a stack inside a fake render, it should get ignored.\n  if ( !fn || reentry) {\n    return '';\n  }\n\n  {\n    var frame = componentFrameCache.get(fn);\n\n    if (frame !== undefined) {\n      return frame;\n    }\n  }\n\n  var control;\n  reentry = true;\n  var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n  Error.prepareStackTrace = undefined;\n  var previousDispatcher;\n\n  {\n    previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n    // for warnings.\n\n    ReactCurrentDispatcher.current = null;\n    disableLogs();\n  }\n\n  try {\n    // This should throw.\n    if (construct) {\n      // Something should be setting the props in the constructor.\n      var Fake = function () {\n        throw Error();\n      }; // $FlowFixMe\n\n\n      Object.defineProperty(Fake.prototype, 'props', {\n        set: function () {\n          // We use a throwing setter instead of frozen or non-writable props\n          // because that won't throw in a non-strict mode function.\n          throw Error();\n        }\n      });\n\n      if (typeof Reflect === 'object' && Reflect.construct) {\n        // We construct a different control for this case to include any extra\n        // frames added by the construct call.\n        try {\n          Reflect.construct(Fake, []);\n        } catch (x) {\n          control = x;\n        }\n\n        Reflect.construct(fn, [], Fake);\n      } else {\n        try {\n          Fake.call();\n        } catch (x) {\n          control = x;\n        }\n\n        fn.call(Fake.prototype);\n      }\n    } else {\n      try {\n        throw Error();\n      } catch (x) {\n        control = x;\n      }\n\n      fn();\n    }\n  } catch (sample) {\n    // This is inlined manually because closure doesn't do it for us.\n    if (sample && control && typeof sample.stack === 'string') {\n      // This extracts the first frame from the sample that isn't also in the control.\n      // Skipping one frame that we assume is the frame that calls the two.\n      var sampleLines = sample.stack.split('\\n');\n      var controlLines = control.stack.split('\\n');\n      var s = sampleLines.length - 1;\n      var c = controlLines.length - 1;\n\n      while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n        // We expect at least one stack frame to be shared.\n        // Typically this will be the root most one. However, stack frames may be\n        // cut off due to maximum stack limits. In this case, one maybe cut off\n        // earlier than the other. We assume that the sample is longer or the same\n        // and there for cut off earlier. So we should find the root most frame in\n        // the sample somewhere in the control.\n        c--;\n      }\n\n      for (; s >= 1 && c >= 0; s--, c--) {\n        // Next we find the first one that isn't the same which should be the\n        // frame that called our sample function and the control.\n        if (sampleLines[s] !== controlLines[c]) {\n          // In V8, the first line is describing the message but other VMs don't.\n          // If we're about to return the first line, and the control is also on the same\n          // line, that's a pretty good indicator that our sample threw at same line as\n          // the control. I.e. before we entered the sample frame. So we ignore this result.\n          // This can happen if you passed a class to function component, or non-function.\n          if (s !== 1 || c !== 1) {\n            do {\n              s--;\n              c--; // We may still have similar intermediate frames from the construct call.\n              // The next one that isn't the same should be our match though.\n\n              if (c < 0 || sampleLines[s] !== controlLines[c]) {\n                // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n                var _frame = '\\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled \"<anonymous>\"\n                // but we have a user-provided \"displayName\"\n                // splice it in to make the stack more readable.\n\n\n                if (fn.displayName && _frame.includes('<anonymous>')) {\n                  _frame = _frame.replace('<anonymous>', fn.displayName);\n                }\n\n                {\n                  if (typeof fn === 'function') {\n                    componentFrameCache.set(fn, _frame);\n                  }\n                } // Return the line we found.\n\n\n                return _frame;\n              }\n            } while (s >= 1 && c >= 0);\n          }\n\n          break;\n        }\n      }\n    }\n  } finally {\n    reentry = false;\n\n    {\n      ReactCurrentDispatcher.current = previousDispatcher;\n      reenableLogs();\n    }\n\n    Error.prepareStackTrace = previousPrepareStackTrace;\n  } // Fallback to just using the name if we couldn't make it throw.\n\n\n  var name = fn ? fn.displayName || fn.name : '';\n  var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n\n  {\n    if (typeof fn === 'function') {\n      componentFrameCache.set(fn, syntheticFrame);\n    }\n  }\n\n  return syntheticFrame;\n}\nfunction describeFunctionComponentFrame(fn, source, ownerFn) {\n  {\n    return describeNativeComponentFrame(fn, false);\n  }\n}\n\nfunction shouldConstruct(Component) {\n  var prototype = Component.prototype;\n  return !!(prototype && prototype.isReactComponent);\n}\n\nfunction describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {\n\n  if (type == null) {\n    return '';\n  }\n\n  if (typeof type === 'function') {\n    {\n      return describeNativeComponentFrame(type, shouldConstruct(type));\n    }\n  }\n\n  if (typeof type === 'string') {\n    return describeBuiltInComponentFrame(type);\n  }\n\n  switch (type) {\n    case REACT_SUSPENSE_TYPE:\n      return describeBuiltInComponentFrame('Suspense');\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return describeBuiltInComponentFrame('SuspenseList');\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_FORWARD_REF_TYPE:\n        return describeFunctionComponentFrame(type.render);\n\n      case REACT_MEMO_TYPE:\n        // Memo may contain any component type so we recursively resolve it.\n        return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);\n\n      case REACT_LAZY_TYPE:\n        {\n          var lazyComponent = type;\n          var payload = lazyComponent._payload;\n          var init = lazyComponent._init;\n\n          try {\n            // Lazy may contain any component type so we recursively resolve it.\n            return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);\n          } catch (x) {}\n        }\n    }\n  }\n\n  return '';\n}\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement(element) {\n  {\n    if (element) {\n      var owner = element._owner;\n      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n      ReactDebugCurrentFrame.setExtraStackFrame(stack);\n    } else {\n      ReactDebugCurrentFrame.setExtraStackFrame(null);\n    }\n  }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            // eslint-disable-next-line react-internal/prod-error-codes\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare\n\nfunction isArray(a) {\n  return isArrayImpl(a);\n}\n\n/*\n * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol\n * and Temporal.* types. See https://github.com/facebook/react/pull/22064.\n *\n * The functions in this module will throw an easier-to-understand,\n * easier-to-debug exception with a clear errors message message explaining the\n * problem. (Instead of a confusing exception thrown inside the implementation\n * of the `value` object).\n */\n// $FlowFixMe only called in DEV, so void return is not possible.\nfunction typeName(value) {\n  {\n    // toStringTag is needed for namespaced types like Temporal.Instant\n    var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;\n    var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object';\n    return type;\n  }\n} // $FlowFixMe only called in DEV, so void return is not possible.\n\n\nfunction willCoercionThrow(value) {\n  {\n    try {\n      testStringCoercion(value);\n      return false;\n    } catch (e) {\n      return true;\n    }\n  }\n}\n\nfunction testStringCoercion(value) {\n  // If you ended up here by following an exception call stack, here's what's\n  // happened: you supplied an object or symbol value to React (as a prop, key,\n  // DOM attribute, CSS property, string ref, etc.) and when React tried to\n  // coerce it to a string using `'' + value`, an exception was thrown.\n  //\n  // The most common types that will cause this exception are `Symbol` instances\n  // and Temporal objects like `Temporal.Instant`. But any object that has a\n  // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this\n  // exception. (Library authors do this to prevent users from using built-in\n  // numeric operators like `+` or comparison operators like `>=` because custom\n  // methods are needed to perform accurate arithmetic or comparison.)\n  //\n  // To fix the problem, coerce this object or symbol value to a string before\n  // passing it to React. The most reliable way is usually `String(value)`.\n  //\n  // To find which value is throwing, check the browser or debugger console.\n  // Before this exception was thrown, there should be `console.error` output\n  // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the\n  // problem and how that type was used: key, atrribute, input value prop, etc.\n  // In most cases, this console output also shows the component and its\n  // ancestor components where the exception happened.\n  //\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  return '' + value;\n}\nfunction checkKeyStringCoercion(value) {\n  {\n    if (willCoercionThrow(value)) {\n      error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));\n\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n  {\n    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n      var componentName = getComponentNameFromType(ReactCurrentOwner.current.type);\n\n      if (!didWarnAboutStringRefs[componentName]) {\n        error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentNameFromType(ReactCurrentOwner.current.type), config.ref);\n\n        didWarnAboutStringRefs[componentName] = true;\n      }\n    }\n  }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      {\n        checkKeyStringCoercion(maybeKey);\n      }\n\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      {\n        checkKeyStringCoercion(config.key);\n      }\n\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n      warnIfStringRefCannotBeAutoConverted(config, self);\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n  {\n    if (element) {\n      var owner = element._owner;\n      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n      ReactDebugCurrentFrame$1.setExtraStackFrame(stack);\n    } else {\n      ReactDebugCurrentFrame$1.setExtraStackFrame(null);\n    }\n  }\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = getComponentNameFromType(ReactCurrentOwner$1.current.type);\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + getComponentNameFromType(element._owner.type) + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentNameFromType(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentNameFromType(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nvar didWarnAboutKeySpread = {};\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentNameFromType(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    {\n      if (hasOwnProperty.call(props, 'key')) {\n        var componentName = getComponentNameFromType(type);\n        var keys = Object.keys(props).filter(function (k) {\n          return k !== 'key';\n        });\n        var beforeExample = keys.length > 0 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}' : '{key: someKey}';\n\n        if (!didWarnAboutKeySpread[componentName + beforeExample]) {\n          var afterExample = keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';\n\n          error('A props object containing a \"key\" prop is being spread into JSX:\\n' + '  let props = %s;\\n' + '  <%s {...props} />\\n' + 'React keys must be passed directly to JSX without using spread:\\n' + '  let props = %s;\\n' + '  <%s key={someKey} {...props} />', beforeExample, componentName, afterExample, componentName);\n\n          didWarnAboutKeySpread[componentName + beforeExample] = true;\n        }\n      }\n    }\n\n    if (type === REACT_FRAGMENT_TYPE) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, true);\n  }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, false);\n  }\n}\n\nvar jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs =  jsxWithValidationStatic ;\n\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n  })();\n}\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport { Chart } from '../core/Chart';\nimport type { UseChartOptions } from './types';\nimport type { Candle, DrawingOptions } from '../types';\n\n// Tauri 타입 정의\ndeclare global {\n  interface Window {\n    __TAURI__?: {\n      event: {\n        listen: (event: string, handler: (event: { payload: unknown }) => void) => Promise<() => void>;\n      };\n    };\n  }\n}\n\nexport function useChart(options: UseChartOptions = {}) {\n  const {\n    data,\n    onReady,\n    onError,\n    debug = false,\n    autoResize = true,\n    ...chartOptions\n  } = options;\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const chartRef = useRef<Chart | null>(null);\n  const [isReady, setIsReady] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n  const [chartState, setChartState] = useState<string>('initializing');\n  const initializingRef = useRef(false);\n  const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n  // 차트 초기화 함수\n  const initializeChart = useCallback(async () => {\n    if (!containerRef.current || initializingRef.current || chartRef.current) {\n      return;\n    }\n\n    const container = containerRef.current;\n    let { width, height } = container.getBoundingClientRect();\n\n    // Tauri 환경에서 추가 체크\n    const isTauri = window.__TAURI__ !== undefined;\n    \n    // 컨테이너 크기 체크\n    if (width === 0 || height === 0) {\n      // Tauri에서는 컨테이너의 offsetWidth/offsetHeight도 체크\n      if (isTauri && container.offsetWidth > 0 && container.offsetHeight > 0) {\n        width = container.offsetWidth;\n        height = container.offsetHeight;\n        if (debug) {\n          console.log('[useChart] Using offset dimensions in Tauri:', { width, height });\n        }\n      } else {\n        if (debug) {\n          console.log('[useChart] Container has zero size, waiting...');\n        }\n        return;\n      }\n    }\n\n    initializingRef.current = true;\n\n    try {\n      if (debug) {\n        console.log('[useChart] Initializing chart with size:', { width, height });\n      }\n\n      // 차트 생성\n      const chart = new Chart({\n        container,\n        debug,\n        onDebug: debug ? (msg) => console.log(`[useChart] ${msg}`) : undefined,\n        ...chartOptions\n      });\n\n      chartRef.current = chart;\n      \n      // 상태 변경 리스너 등록\n      chart.on('stateChange', (state) => {\n        setChartState(state);\n        if (debug) {\n          console.log('[useChart] Chart state changed:', state);\n        }\n      });\n      \n      // 차트 준비 대기\n      await chart.waitUntilReady();\n\n      // Tauri 환경에서는 추가 검증\n      if (isTauri) {\n        // 차트가 실제로 렌더링되었는지 확인\n        const chartElement = container.querySelector('canvas');\n        if (!chartElement) {\n          throw new Error('Chart canvas not found after initialization');\n        }\n        \n        // 약간의 추가 지연으로 안정성 확보\n        await new Promise(resolve => setTimeout(resolve, 50));\n      }\n\n      // 데이터 설정\n      if (data && data.length > 0) {\n        chart.setData(data, true);\n      }\n\n      setIsReady(true);\n      setError(null);\n\n      // onReady 콜백 호출\n      if (onReady) {\n        onReady(chart);\n      }\n\n      if (debug) {\n        // console.log('[useChart] Chart initialized successfully');\n      }\n    } catch (err) {\n      const error = err instanceof Error ? err : new Error(String(err));\n      console.error('[useChart] Failed to initialize chart:', error);\n      setError(error);\n      setIsReady(false);\n      \n      if (onError) {\n        onError(error);\n      }\n    } finally {\n      initializingRef.current = false;\n    }\n  }, [chartOptions, data, onReady, onError, debug]);\n\n  // ResizeObserver 설정\n  useEffect(() => {\n    if (!containerRef.current || !autoResize) return;\n\n    const container = containerRef.current;\n    let initTimeoutId: NodeJS.Timeout | null = null;\n\n    // ResizeObserver 생성\n    resizeObserverRef.current = new ResizeObserver((entries) => {\n      for (const entry of entries) {\n        const { width, height } = entry.contentRect;\n        \n        if (width > 0 && height > 0) {\n          if (!chartRef.current && !initializingRef.current) {\n            // 차트가 없으면 초기화\n            initializeChart();\n          } else if (chartRef.current) {\n            // 차트가 있으면 리사이즈\n            if (debug) {\n              console.log('[useChart] Container resized:', { width, height });\n            }\n            chartRef.current.resize();\n          }\n        }\n      }\n    });\n\n    resizeObserverRef.current.observe(container);\n\n    // Tauri 환경에서 안정적인 초기화를 위한 지연\n    // 초기 초기화 시도 - Tauri에서는 약간의 지연이 필요할 수 있음\n    const isTauri = window.__TAURI__ !== undefined;\n    \n    if (isTauri) {\n      // Tauri 환경에서는 더 긴 지연 시간 사용\n      initTimeoutId = setTimeout(() => {\n        initializeChart();\n      }, 100);\n    } else {\n      // 일반 웹 환경에서는 즉시 시도\n      initializeChart();\n    }\n\n    return () => {\n      if (initTimeoutId) {\n        clearTimeout(initTimeoutId);\n      }\n      if (resizeObserverRef.current) {\n        resizeObserverRef.current.disconnect();\n        resizeObserverRef.current = null;\n      }\n    };\n  }, [autoResize, initializeChart]);\n\n  // 데이터 업데이트\n  useEffect(() => {\n    if (chartRef.current && data && isReady) {\n      try {\n        if (debug) {\n          console.log('[useChart] Updating data:', data.length, 'candles');\n        }\n        chartRef.current.setData(data, true);\n      } catch (err) {\n        const error = err instanceof Error ? err : new Error(String(err));\n        console.error('[useChart] Failed to update data:', error);\n        setError(error);\n        \n        if (onError) {\n          onError(error);\n        }\n      }\n    }\n  }, [data, isReady, onError, debug]);\n\n  // Cleanup\n  useEffect(() => {\n    return () => {\n      if (chartRef.current) {\n        if (debug) {\n          console.log('[useChart] Disposing chart');\n        }\n        \n        try {\n          chartRef.current.dispose();\n        } catch (err) {\n          console.error('[useChart] Error disposing chart:', err);\n        }\n        \n        chartRef.current = null;\n        setIsReady(false);\n      }\n    };\n  }, [debug]);\n\n  // Public API\n  const updateData = useCallback((newData: Candle[]) => {\n    if (chartRef.current && isReady) {\n      try {\n        chartRef.current.setData(newData, true);\n      } catch (err) {\n        const error = err instanceof Error ? err : new Error(String(err));\n        console.error('[useChart] Failed to update data:', error);\n        setError(error);\n        \n        if (onError) {\n          onError(error);\n        }\n      }\n    }\n  }, [isReady, onError]);\n\n  const resize = useCallback(() => {\n    if (chartRef.current) {\n      chartRef.current.resize();\n    }\n  }, []);\n\n  const dispose = useCallback(() => {\n    if (chartRef.current) {\n      chartRef.current.dispose();\n      chartRef.current = null;\n      setIsReady(false);\n      setChartState('disposed');\n    }\n  }, []);\n  \n  const addDrawing = useCallback((type: string, options?: DrawingOptions) => {\n    if (chartRef.current && chartRef.current.isReady()) {\n      chartRef.current.addDrawing(type, options);\n    } else {\n      console.warn('[useChart] Cannot add drawing: chart not ready');\n    }\n  }, []);\n\n  return {\n    containerRef,\n    chart: chartRef.current,\n    isReady,\n    error,\n    chartState,\n    updateData,\n    resize,\n    dispose,\n    addDrawing\n  };\n}","import { forwardRef, useImperativeHandle } from 'react';\nimport type { CSSProperties } from 'react';\nimport { useChart } from './useChart';\nimport type { ChartProps, ChartRef } from './types';\n\nexport const Chart = forwardRef<ChartRef, ChartProps>((props: ChartProps, ref) => {\n  const {\n    // 스타일 관련\n    width = '100%',\n    height = '500px',\n    className,\n    style,\n    \n    // 차트 옵션\n    data,\n    type,\n    theme,\n    candle,\n    background,\n    grid,\n    crosshair,\n    line,\n    priceScaleMargin,\n    logScale,\n    chartType,\n    // container는 useChart에서 자동 설정됨\n    \n    // 이벤트 핸들러\n    onReady,\n    onError,\n    onDataUpdate,\n    \n    // 옵션\n    debug = false,\n    autoResize = true,\n    \n    // 편의 props\n    backgroundColor,\n    volumeOpacity,\n    volumeUpColor,\n    volumeDownColor,\n    volumeMAColor,\n    showVolumeMA,\n    volumeMALength,\n    \n    ...restProps\n  } = props;\n\n  // 편의 props를 ChartOptions 형식으로 변환\n  const processedOptions = {\n    ...restProps,\n    background: backgroundColor ? { color: backgroundColor } : background,\n    panels: {\n      ...restProps.panels,\n      volume: {\n        ...restProps.panels?.volume,\n        opacity: volumeOpacity ?? restProps.panels?.volume?.opacity,\n        colors: {\n          up: volumeUpColor ?? restProps.panels?.volume?.colors?.up,\n          down: volumeDownColor ?? restProps.panels?.volume?.colors?.down,\n        },\n        maColor: volumeMAColor ?? restProps.panels?.volume?.maColor,\n        showMA: showVolumeMA ?? restProps.panels?.volume?.showMA,\n        maLength: volumeMALength ?? restProps.panels?.volume?.maLength,\n      }\n    }\n  };\n\n  // useChart hook 사용\n  const {\n    containerRef,\n    chart,\n    isReady,\n    error\n  } = useChart({\n    data,\n    theme,\n    chartType: type || chartType,\n    candle,\n    background: typeof processedOptions.background === 'string' ? processedOptions.background : undefined,\n    grid,\n    crosshair,\n    line,\n    priceScaleMargin,\n    logScale,\n    onReady,\n    onError,\n    debug,\n    autoResize,\n    panels: processedOptions.panels,\n    ...restProps\n  });\n\n  // ref를 통해 차트 인스턴스 노출\n  useImperativeHandle(ref, () => ({\n    chart,\n    container: containerRef.current\n  }), [chart]);\n\n  // 에러 상태 렌더링\n  if (error && debug) {\n    console.error('[Chart Component] Error:', error);\n  }\n\n  // 컨테이너 스타일 계산\n  const containerStyle: CSSProperties = {\n    width,\n    height,\n    position: 'relative',\n    overflow: 'hidden',\n    ...style\n  };\n\n  return (\n    <div\n      ref={containerRef}\n      className={className}\n      style={containerStyle}\n      data-chart-ready={isReady}\n      data-chart-error={error ? error.message : undefined}\n    >\n      {/* 로딩 상태 표시 (선택적) */}\n      {!isReady && !error && debug && (\n        <div\n          style={{\n            position: 'absolute',\n            top: '50%',\n            left: '50%',\n            transform: 'translate(-50%, -50%)',\n            color: '#666',\n            fontSize: '14px',\n            fontFamily: 'monospace'\n          }}\n        >\n          Initializing chart...\n        </div>\n      )}\n      \n      {/* 에러 상태 표시 (선택적) */}\n      {error && debug && (\n        <div\n          style={{\n            position: 'absolute',\n            top: '10px',\n            left: '10px',\n            right: '10px',\n            padding: '10px',\n            backgroundColor: 'rgba(255, 0, 0, 0.1)',\n            border: '1px solid rgba(255, 0, 0, 0.3)',\n            borderRadius: '4px',\n            color: '#ff6b6b',\n            fontSize: '12px',\n            fontFamily: 'monospace'\n          }}\n        >\n          <strong>Chart Error:</strong> {error.message}\n        </div>\n      )}\n    </div>\n  );\n});\n\nChart.displayName = 'Chart';","// Core exports\nexport { Chart } from './core/Chart';\nexport { DrawingManager } from './core/DrawingManager';\nexport { DataManager } from './core/DataManager';\n\n// Type exports\nexport * from './types';\n\n// Theme exports\nexport { darkTheme, lightTheme } from './utils/theme';\n\n// React exports\nexport { ChartComponent, useChart } from './react-integration';\nexport type { ChartProps, ChartRef } from './react-integration';\n\n// Utility exports\n// export { csvToCandles } from './utils/csvLoader';\n\n// 차트 생성 헬퍼 함수\nimport type { ChartOptions } from './types';\nimport { Chart } from './core/Chart';\n\nexport function createChart(options: ChartOptions): Chart {\n  const chart = new Chart(options);\n  \n  // debug 모드에서는 차트 인스턴스를 전역에 노출\n  if (options.debug && typeof window !== 'undefined') {\n    (window as unknown as { __chartDebugInstance?: Chart }).__chartDebugInstance = chart;\n  }\n  \n  return chart;\n}\n\n// 전역 디버그 모드 설정\nexport function setGlobalDebug(enabled: boolean): void {\n  if (typeof window !== 'undefined') {\n    (window as unknown as { __chartGlobalDebug?: boolean }).__chartGlobalDebug = enabled;\n  }\n}"],"names":["clickCSS","chartCoords","ReactDebugCurrentFrame","jsxRuntimeModule","require$$0","require$$1","useRef","useState","useCallback","Chart","error","useEffect","options","forwardRef","useImperativeHandle","jsxs","jsx"],"mappings":"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","x_google_ignoreList":[68,69,70]}