dipping-charts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +216 -0
  3. package/dist/__tests__/FullFeaturedChart.test.d.ts +2 -0
  4. package/dist/__tests__/FullFeaturedChart.test.d.ts.map +1 -0
  5. package/dist/__tests__/indicators-accuracy.test.d.ts +2 -0
  6. package/dist/__tests__/indicators-accuracy.test.d.ts.map +1 -0
  7. package/dist/__tests__/indicators.test.d.ts +2 -0
  8. package/dist/__tests__/indicators.test.d.ts.map +1 -0
  9. package/dist/__tests__/setup.d.ts +1 -0
  10. package/dist/__tests__/setup.d.ts.map +1 -0
  11. package/dist/__tests__/validateCandle.test.d.ts +2 -0
  12. package/dist/__tests__/validateCandle.test.d.ts.map +1 -0
  13. package/dist/chart/index.d.ts +2 -0
  14. package/dist/chart/index.js +5 -0
  15. package/dist/chart/index.js.map +1 -0
  16. package/dist/components/TradingChart.d.ts +24 -0
  17. package/dist/components/TradingChart.d.ts.map +1 -0
  18. package/dist/components/TradingChart.js +100 -0
  19. package/dist/components/TradingChart.js.map +1 -0
  20. package/dist/components/index.d.ts +3 -0
  21. package/dist/components/index.d.ts.map +1 -0
  22. package/dist/dipping-charts.css +1 -0
  23. package/dist/index.d.ts +5 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +28 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/indicators/atr.d.ts +15 -0
  28. package/dist/indicators/atr.d.ts.map +1 -0
  29. package/dist/indicators/atr.js +30 -0
  30. package/dist/indicators/atr.js.map +1 -0
  31. package/dist/indicators/bollingerBands.d.ts +11 -0
  32. package/dist/indicators/bollingerBands.d.ts.map +1 -0
  33. package/dist/indicators/bollingerBands.js +39 -0
  34. package/dist/indicators/bollingerBands.js.map +1 -0
  35. package/dist/indicators/currencyStrength.d.ts +43 -0
  36. package/dist/indicators/currencyStrength.d.ts.map +1 -0
  37. package/dist/indicators/currencyStrength.js +53 -0
  38. package/dist/indicators/currencyStrength.js.map +1 -0
  39. package/dist/indicators/ema.d.ts +11 -0
  40. package/dist/indicators/ema.d.ts.map +1 -0
  41. package/dist/indicators/ema.js +24 -0
  42. package/dist/indicators/ema.js.map +1 -0
  43. package/dist/indicators/index.d.ts +19 -0
  44. package/dist/indicators/index.d.ts.map +1 -0
  45. package/dist/indicators/index.js +23 -0
  46. package/dist/indicators/index.js.map +1 -0
  47. package/dist/indicators/macd.d.ts +11 -0
  48. package/dist/indicators/macd.d.ts.map +1 -0
  49. package/dist/indicators/macd.js +52 -0
  50. package/dist/indicators/macd.js.map +1 -0
  51. package/dist/indicators/rsi.d.ts +11 -0
  52. package/dist/indicators/rsi.d.ts.map +1 -0
  53. package/dist/indicators/rsi.js +29 -0
  54. package/dist/indicators/rsi.js.map +1 -0
  55. package/dist/indicators/sma.d.ts +13 -0
  56. package/dist/indicators/sma.d.ts.map +1 -0
  57. package/dist/indicators/sma.js +22 -0
  58. package/dist/indicators/sma.js.map +1 -0
  59. package/dist/indicators/stochastic.d.ts +15 -0
  60. package/dist/indicators/stochastic.d.ts.map +1 -0
  61. package/dist/indicators/stochastic.js +34 -0
  62. package/dist/indicators/stochastic.js.map +1 -0
  63. package/dist/indicators/types.d.ts +102 -0
  64. package/dist/indicators/types.d.ts.map +1 -0
  65. package/dist/indicators/vwap.d.ts +14 -0
  66. package/dist/indicators/vwap.d.ts.map +1 -0
  67. package/dist/indicators/vwap.js +17 -0
  68. package/dist/indicators/vwap.js.map +1 -0
  69. package/dist/indicators/williamsR.d.ts +17 -0
  70. package/dist/indicators/williamsR.d.ts.map +1 -0
  71. package/dist/indicators/williamsR.js +19 -0
  72. package/dist/indicators/williamsR.js.map +1 -0
  73. package/dist/react/FullFeaturedChart.d.ts +3 -0
  74. package/dist/react/FullFeaturedChart.d.ts.map +1 -0
  75. package/dist/react/FullFeaturedChart.js +640 -0
  76. package/dist/react/FullFeaturedChart.js.map +1 -0
  77. package/dist/react/components/IndicatorSettings.d.ts +20 -0
  78. package/dist/react/components/IndicatorSettings.d.ts.map +1 -0
  79. package/dist/react/components/IndicatorSettings.js +748 -0
  80. package/dist/react/components/IndicatorSettings.js.map +1 -0
  81. package/dist/react/hooks/useChart.d.ts +15 -0
  82. package/dist/react/hooks/useChart.d.ts.map +1 -0
  83. package/dist/react/hooks/useChart.js +155 -0
  84. package/dist/react/hooks/useChart.js.map +1 -0
  85. package/dist/react/hooks/useIndicators.d.ts +10 -0
  86. package/dist/react/hooks/useIndicators.d.ts.map +1 -0
  87. package/dist/react/hooks/useIndicators.js +264 -0
  88. package/dist/react/hooks/useIndicators.js.map +1 -0
  89. package/dist/react/hooks/useLineTools.d.ts +26 -0
  90. package/dist/react/hooks/useLineTools.d.ts.map +1 -0
  91. package/dist/react/hooks/useLineTools.js +189 -0
  92. package/dist/react/hooks/useLineTools.js.map +1 -0
  93. package/dist/react/hooks/useShiftSnap.d.ts +12 -0
  94. package/dist/react/hooks/useShiftSnap.d.ts.map +1 -0
  95. package/dist/react/hooks/useShiftSnap.js +54 -0
  96. package/dist/react/hooks/useShiftSnap.js.map +1 -0
  97. package/dist/react/index.d.ts +14 -0
  98. package/dist/react/index.d.ts.map +1 -0
  99. package/dist/react/index.js +18 -0
  100. package/dist/react/index.js.map +1 -0
  101. package/dist/react/loadLightweightCharts.d.ts +18 -0
  102. package/dist/react/loadLightweightCharts.d.ts.map +1 -0
  103. package/dist/react/loadLightweightCharts.js +32 -0
  104. package/dist/react/loadLightweightCharts.js.map +1 -0
  105. package/dist/react/locale.d.ts +79 -0
  106. package/dist/react/locale.d.ts.map +1 -0
  107. package/dist/react/locale.js +158 -0
  108. package/dist/react/locale.js.map +1 -0
  109. package/dist/react/types.d.ts +130 -0
  110. package/dist/react/types.d.ts.map +1 -0
  111. package/dist/types/index.d.ts +24 -0
  112. package/dist/types/index.d.ts.map +1 -0
  113. package/dist/utils/getToolId.d.ts +9 -0
  114. package/dist/utils/getToolId.d.ts.map +1 -0
  115. package/dist/utils/getToolId.js +12 -0
  116. package/dist/utils/getToolId.js.map +1 -0
  117. package/dist/utils/mockData.d.ts +10 -0
  118. package/dist/utils/mockData.d.ts.map +1 -0
  119. package/dist/utils/mockData.js +61 -0
  120. package/dist/utils/mockData.js.map +1 -0
  121. package/dist/utils/snapCrosshair.d.ts +25 -0
  122. package/dist/utils/snapCrosshair.d.ts.map +1 -0
  123. package/dist/utils/validateCandle.d.ts +30 -0
  124. package/dist/utils/validateCandle.d.ts.map +1 -0
  125. package/dist/utils/validateCandle.js +21 -0
  126. package/dist/utils/validateCandle.js.map +1 -0
  127. package/examples/css/base.css +209 -0
  128. package/examples/css/chart.css +282 -0
  129. package/examples/css/indicators.css +255 -0
  130. package/examples/index.html +163 -0
  131. package/examples/js/chart.js +370 -0
  132. package/examples/js/indicators.js +27 -0
  133. package/examples/js/main.js +6 -0
  134. package/examples/js/ui.js +1641 -0
  135. package/lib/lightweight-charts.standalone.production.js +7 -0
  136. package/package.json +106 -0
  137. package/src/react/FullFeaturedChart.css +1007 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndicatorSettings.js","sources":["../../../src/react/components/IndicatorSettings.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { IndicatorType, IndicatorConfig, BollingerBandsConfig, MACDConfig, StochasticConfig, VWAPConfig, IndicatorConfigs } from '../types';\nimport type { Locale, LocaleStrings } from '../locale';\nimport { getLocaleStrings } from '../locale';\n\nconst COLOR_PALETTE = [\n '#3C4043', '#1A73E8', '#9334E6', '#B80000', '#E37400', '#F9AB00', '#007B83', '#1E8E3E',\n '#5F6368', '#4285F4', '#A142F4', '#D93025', '#F57C00', '#FDD835', '#12B5CB', '#34A853',\n '#9AA0A6', '#8AB4F8', '#C58AF9', '#EE675C', '#FF8A65', '#FFB300', '#4DB6AC', '#81C995',\n '#DADCE0', '#AECBFA', '#D7AEFB', '#F28B82', '#FFAB91', '#FFD54F', '#80DEEA', '#A5D6A7'\n];\n\nconst DEFAULT_COLORS = ['#26a69a', '#ef5350', '#2196f3', '#ff6f00', '#ab47bc', '#66bb6a', '#ffa726', '#42a5f5'];\n\nfunction getIndicatorInfo(t: LocaleStrings) {\n return {\n sma: { title: t.ind_sma, desc: t.ind_sma_desc, defaultValue: 20 },\n ema: { title: t.ind_ema, desc: t.ind_ema_desc, defaultValue: 12 },\n rsi: { title: t.ind_rsi, desc: t.ind_rsi_desc, defaultValue: 14 },\n macd: { title: t.ind_macd, desc: t.ind_macd_desc, defaultValue: 26 },\n bbands: { title: t.ind_bbands, desc: t.ind_bbands_desc, defaultValue: 20 },\n stochastic: { title: t.ind_stochastic, desc: t.ind_stochastic_desc, defaultValue: 14 },\n atr: { title: t.ind_atr, desc: t.ind_atr_desc, defaultValue: 14 },\n vwap: { title: t.ind_vwap, desc: t.ind_vwap_desc, defaultValue: 0 },\n williamsR: { title: t.ind_williamsR, desc: t.ind_williamsR_desc, defaultValue: 14 },\n };\n}\n\ninterface ColorPalettePopupProps {\n currentColor: string;\n onSelect: (color: string) => void;\n onClose: () => void;\n position: { top: number; left: number };\n colorTitle?: string;\n}\n\nfunction ColorPalettePopup({ currentColor, onSelect, onClose, position, colorTitle = 'Color' }: ColorPalettePopupProps) {\n const paletteRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (paletteRef.current && !paletteRef.current.contains(e.target as Node)) {\n onClose();\n }\n };\n\n // 약간의 지연 후 이벤트 리스너 등록 (현재 클릭 이벤트가 완료된 후)\n const timer = setTimeout(() => {\n document.addEventListener('mousedown', handleClickOutside);\n }, 100);\n\n return () => {\n clearTimeout(timer);\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [onClose]);\n\n const paletteElement = (\n <div\n ref={paletteRef}\n className=\"color-palette-popup show\"\n style={{\n top: position.top,\n left: position.left\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"color-palette-title\">{colorTitle}</div>\n <div className=\"color-palette-grid\">\n {COLOR_PALETTE.map(color => (\n <div\n key={color}\n className={`color-palette-item ${color === currentColor ? 'selected' : ''}`}\n style={{ background: color }}\n onClick={(e) => {\n e.stopPropagation();\n onSelect(color);\n onClose();\n }}\n />\n ))}\n </div>\n </div>\n );\n\n // Portal을 사용해 document.body에 직접 렌더링\n return createPortal(paletteElement, document.body);\n}\n\ninterface IndicatorSettingsProps {\n indicator: IndicatorType | null;\n configs: IndicatorConfigs;\n isChecked: boolean;\n onConfigChange: (indicator: IndicatorType, configs: any[]) => void;\n macdColors: { line: string; signal: string };\n onMacdColorsChange: (colors: { line: string; signal: string }) => void;\n locale?: Locale;\n}\n\nexport function IndicatorSettings({\n indicator,\n configs,\n isChecked,\n onConfigChange,\n macdColors,\n onMacdColorsChange,\n locale: localeProp = 'en',\n}: IndicatorSettingsProps) {\n const t = getLocaleStrings(localeProp);\n const INDICATOR_INFO = getIndicatorInfo(t);\n const [colorPaletteOpen, setColorPaletteOpen] = useState<{ index?: number; type?: string; position: { top: number; left: number } } | null>(null);\n\n if (!indicator) {\n return <div className=\"indicator-empty-state\">{t.selectIndicator}</div>;\n }\n\n const info = INDICATOR_INFO[indicator];\n const config = configs[indicator];\n\n if (!isChecked || config.length === 0) {\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div className=\"indicator-empty-state\">{t.enableIndicator}</div>\n </div>\n );\n }\n\n const handleColorClick = (e: React.MouseEvent, index?: number, type?: string) => {\n e.preventDefault();\n e.stopPropagation();\n const rect = (e.target as HTMLElement).getBoundingClientRect();\n setColorPaletteOpen({\n index,\n type,\n position: { top: rect.bottom + 5, left: rect.left }\n });\n };\n\n // RSI\n if (indicator === 'rsi') {\n const rsiConfig = config[0] as IndicatorConfig;\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div style={{ marginTop: 16 }}>\n <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', marginBottom: 12 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.color}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: rsiConfig.color, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, 0)}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.period}</div>\n <input\n type=\"number\"\n value={rsiConfig.value}\n onChange={(e) => onConfigChange(indicator, [{ ...rsiConfig, value: parseInt(e.target.value) || 14 }])}\n min=\"1\"\n max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n </div>\n <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.oversold}</div>\n <input\n type=\"number\"\n value={rsiConfig.oversold ?? 30}\n onChange={(e) => onConfigChange(indicator, [{ ...rsiConfig, oversold: parseInt(e.target.value) || 30 }])}\n min=\"0\"\n max=\"100\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.overbought}</div>\n <input\n type=\"number\"\n value={rsiConfig.overbought ?? 70}\n onChange={(e) => onConfigChange(indicator, [{ ...rsiConfig, overbought: parseInt(e.target.value) || 70 }])}\n min=\"0\"\n max=\"100\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n </div>\n </div>\n {colorPaletteOpen && colorPaletteOpen.index === 0 && (\n <ColorPalettePopup\n currentColor={rsiConfig.color}\n onSelect={(color) => onConfigChange(indicator, [{ ...rsiConfig, color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n }\n\n // MACD\n if (indicator === 'macd') {\n const macdConfig = config[0] as MACDConfig;\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div style={{ marginTop: 16 }}>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.ind_macd}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: macdColors.line, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'macd-line')}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.signal}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: macdColors.signal, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'macd-signal')}\n />\n </div>\n </div>\n\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.bullish}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: macdConfig.histUpColor || '#26a69a', width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'hist-up')}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.bearish}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: macdConfig.histDownColor || '#ef5350', width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'hist-down')}\n />\n </div>\n </div>\n\n <div style={{ display: 'flex', gap: 8 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.fast}</div>\n <input\n type=\"number\"\n value={macdConfig.fastPeriod}\n onChange={(e) => onConfigChange(indicator, [{ ...macdConfig, fastPeriod: parseInt(e.target.value) || 12 }])}\n min=\"1\"\n max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.slow}</div>\n <input\n type=\"number\"\n value={macdConfig.slowPeriod}\n onChange={(e) => onConfigChange(indicator, [{ ...macdConfig, slowPeriod: parseInt(e.target.value) || 26 }])}\n min=\"1\"\n max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.signal}</div>\n <input\n type=\"number\"\n value={macdConfig.signalPeriod}\n onChange={(e) => onConfigChange(indicator, [{ ...macdConfig, signalPeriod: parseInt(e.target.value) || 9 }])}\n min=\"1\"\n max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n </div>\n </div>\n {colorPaletteOpen && colorPaletteOpen.type === 'macd-line' && (\n <ColorPalettePopup\n currentColor={macdColors.line}\n onSelect={(color) => onMacdColorsChange({ ...macdColors, line: color })}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n {colorPaletteOpen && colorPaletteOpen.type === 'macd-signal' && (\n <ColorPalettePopup\n currentColor={macdColors.signal}\n onSelect={(color) => onMacdColorsChange({ ...macdColors, signal: color })}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n {colorPaletteOpen && colorPaletteOpen.type === 'hist-up' && (\n <ColorPalettePopup\n currentColor={macdConfig.histUpColor || '#26a69a'}\n onSelect={(color) => onConfigChange(indicator, [{ ...macdConfig, histUpColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n {colorPaletteOpen && colorPaletteOpen.type === 'hist-down' && (\n <ColorPalettePopup\n currentColor={macdConfig.histDownColor || '#ef5350'}\n onSelect={(color) => onConfigChange(indicator, [{ ...macdConfig, histDownColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n }\n\n // Bollinger Bands\n if (indicator === 'bbands') {\n const bbConfig = config[0] as BollingerBandsConfig;\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div style={{ marginTop: 16 }}>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.upper}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: bbConfig.upperColor, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'bb-upper')}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.middle}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: bbConfig.middleColor, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'bb-middle')}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.lower}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: bbConfig.lowerColor, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'bb-lower')}\n />\n </div>\n </div>\n <div style={{ display: 'flex', gap: 8 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.period}</div>\n <input\n type=\"number\"\n value={bbConfig.value}\n onChange={(e) => onConfigChange(indicator, [{ ...bbConfig, value: parseInt(e.target.value) || 20 }])}\n min=\"1\"\n max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40 }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.stdDev}</div>\n <input\n type=\"number\"\n value={bbConfig.stdDev}\n onChange={(e) => onConfigChange(indicator, [{ ...bbConfig, stdDev: parseFloat(e.target.value) || 2 }])}\n min=\"0.5\"\n max=\"5\"\n step=\"0.1\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40 }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.thickness}</div>\n <div\n style={{ width: '100%', height: 40, border: '1px solid #e0e0e0', borderRadius: 6, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, fontWeight: 500, cursor: 'pointer', background: 'white' }}\n onClick={() => onConfigChange(indicator, [{ ...bbConfig, thickness: (bbConfig.thickness % 5) + 1 }])}\n >\n {bbConfig.thickness}px\n </div>\n </div>\n </div>\n </div>\n {colorPaletteOpen && colorPaletteOpen.type === 'bb-upper' && (\n <ColorPalettePopup\n currentColor={bbConfig.upperColor}\n onSelect={(color) => onConfigChange(indicator, [{ ...bbConfig, upperColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n {colorPaletteOpen && colorPaletteOpen.type === 'bb-middle' && (\n <ColorPalettePopup\n currentColor={bbConfig.middleColor}\n onSelect={(color) => onConfigChange(indicator, [{ ...bbConfig, middleColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n {colorPaletteOpen && colorPaletteOpen.type === 'bb-lower' && (\n <ColorPalettePopup\n currentColor={bbConfig.lowerColor}\n onSelect={(color) => onConfigChange(indicator, [{ ...bbConfig, lowerColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n }\n\n // Stochastic\n if (indicator === 'stochastic') {\n const stochConfig = config[0] as StochasticConfig;\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div style={{ marginTop: 16 }}>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.kLine}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: stochConfig.kColor, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'stoch-k')}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.dLine}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: stochConfig.dColor, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, undefined, 'stoch-d')}\n />\n </div>\n </div>\n <div style={{ display: 'flex', gap: 8 }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.kPeriod}</div>\n <input\n type=\"number\"\n value={stochConfig.kPeriod}\n onChange={(e) => onConfigChange(indicator, [{ ...stochConfig, kPeriod: parseInt(e.target.value) || 14 }])}\n min=\"1\" max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.dPeriod}</div>\n <input\n type=\"number\"\n value={stochConfig.dPeriod}\n onChange={(e) => onConfigChange(indicator, [{ ...stochConfig, dPeriod: parseInt(e.target.value) || 3 }])}\n min=\"1\" max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.smooth}</div>\n <input\n type=\"number\"\n value={stochConfig.smooth}\n onChange={(e) => onConfigChange(indicator, [{ ...stochConfig, smooth: parseInt(e.target.value) || 3 }])}\n min=\"1\" max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n </div>\n </div>\n {colorPaletteOpen && colorPaletteOpen.type === 'stoch-k' && (\n <ColorPalettePopup\n currentColor={stochConfig.kColor}\n onSelect={(color) => onConfigChange(indicator, [{ ...stochConfig, kColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n {colorPaletteOpen && colorPaletteOpen.type === 'stoch-d' && (\n <ColorPalettePopup\n currentColor={stochConfig.dColor}\n onSelect={(color) => onConfigChange(indicator, [{ ...stochConfig, dColor: color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n }\n\n // VWAP\n if (indicator === 'vwap') {\n const vwapConfig = config[0] as VWAPConfig;\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div style={{ marginTop: 16 }}>\n <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.color}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: vwapConfig.color, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, 0)}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.thickness}</div>\n <div\n style={{ width: '100%', height: 40, border: '1px solid #e0e0e0', borderRadius: 6, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, fontWeight: 500, cursor: 'pointer', background: 'white' }}\n onClick={() => onConfigChange(indicator, [{ ...vwapConfig, thickness: (vwapConfig.thickness % 5) + 1 }])}\n >\n {vwapConfig.thickness}px\n </div>\n </div>\n </div>\n </div>\n {colorPaletteOpen && colorPaletteOpen.index === 0 && (\n <ColorPalettePopup\n currentColor={vwapConfig.color}\n onSelect={(color) => onConfigChange(indicator, [{ ...vwapConfig, color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n }\n\n // ATR, Williams %R — single period indicator (like RSI but without oversold/overbought)\n if (indicator === 'atr' || indicator === 'williamsR') {\n const singleConfig = config[0] as IndicatorConfig;\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n <div style={{ marginTop: 16 }}>\n <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.color}</div>\n <div\n className=\"period-color-picker\"\n style={{ background: singleConfig.color, width: '100%', height: 40, cursor: 'pointer', borderRadius: 6, border: '1px solid #e0e0e0' }}\n onClick={(e) => handleColorClick(e, 0)}\n />\n </div>\n <div style={{ flex: 1 }}>\n <div style={{ fontSize: 13, color: '#666', marginBottom: 8 }}>{t.period}</div>\n <input\n type=\"number\"\n value={singleConfig.value}\n onChange={(e) => onConfigChange(indicator, [{ ...singleConfig, value: parseInt(e.target.value) || 14 }])}\n min=\"1\" max=\"500\"\n style={{ width: '100%', padding: 8, border: '1px solid #e0e0e0', borderRadius: 6, fontSize: 14, height: 40, boxSizing: 'border-box' }}\n />\n </div>\n </div>\n </div>\n {colorPaletteOpen && colorPaletteOpen.index === 0 && (\n <ColorPalettePopup\n currentColor={singleConfig.color}\n onSelect={(color) => onConfigChange(indicator, [{ ...singleConfig, color }])}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n }\n\n // SMA, EMA - 다중 기간 지원\n return (\n <div>\n <div className=\"indicator-settings-title\">{info.title}</div>\n <div className=\"indicator-settings-desc\">{info.desc}</div>\n {(config as IndicatorConfig[]).map((cfg, index) => (\n <div key={index} className=\"indicator-period-row\">\n <span className=\"period-label-col\">{t.periodN(index + 1)}</span>\n <div\n className=\"period-color-picker\"\n style={{ background: cfg.color, cursor: 'pointer' }}\n onClick={(e) => handleColorClick(e, index)}\n />\n <div\n className=\"period-thickness-display\"\n onClick={() => {\n const newConfigs = [...(config as IndicatorConfig[])];\n newConfigs[index] = { ...newConfigs[index], thickness: (newConfigs[index].thickness % 5) + 1 };\n onConfigChange(indicator, newConfigs);\n }}\n >\n {cfg.thickness}px\n </div>\n <select\n className=\"period-source-dropdown\"\n value={cfg.source}\n onChange={(e) => {\n const newConfigs = [...(config as IndicatorConfig[])];\n newConfigs[index] = { ...newConfigs[index], source: e.target.value as any };\n onConfigChange(indicator, newConfigs);\n }}\n >\n <option value=\"close\">{t.src_close}</option>\n <option value=\"open\">{t.src_open}</option>\n <option value=\"high\">{t.src_high}</option>\n <option value=\"low\">{t.src_low}</option>\n </select>\n <input\n type=\"number\"\n className=\"period-value-field\"\n value={cfg.value}\n onChange={(e) => {\n const newConfigs = [...(config as IndicatorConfig[])];\n newConfigs[index] = { ...newConfigs[index], value: parseInt(e.target.value) || 1 };\n onConfigChange(indicator, newConfigs);\n }}\n min=\"1\"\n max=\"500\"\n />\n {config.length > 1 && (\n <button\n className=\"period-delete-btn\"\n onClick={() => {\n const newConfigs = (config as IndicatorConfig[]).filter((_, i) => i !== index);\n onConfigChange(indicator, newConfigs);\n }}\n >\n ×\n </button>\n )}\n </div>\n ))}\n <button\n className=\"add-period-button\"\n onClick={() => {\n const lastConfig = (config as IndicatorConfig[])[config.length - 1];\n const nextColorIdx = (DEFAULT_COLORS.indexOf(lastConfig.color) + 1) % DEFAULT_COLORS.length;\n onConfigChange(indicator, [\n ...(config as IndicatorConfig[]),\n {\n color: DEFAULT_COLORS[nextColorIdx],\n thickness: 2,\n source: 'close' as const,\n value: info.defaultValue\n }\n ]);\n }}\n >\n {t.addPeriod}\n </button>\n {colorPaletteOpen && colorPaletteOpen.index !== undefined && (\n <ColorPalettePopup\n currentColor={(config as IndicatorConfig[])[colorPaletteOpen.index].color}\n onSelect={(color) => {\n const newConfigs = [...(config as IndicatorConfig[])];\n newConfigs[colorPaletteOpen.index!] = { ...newConfigs[colorPaletteOpen.index!], color };\n onConfigChange(indicator, newConfigs);\n }}\n onClose={() => setColorPaletteOpen(null)}\n position={colorPaletteOpen.position}\n colorTitle={t.colorPaletteTitle}\n />\n )}\n </div>\n );\n}\n"],"names":["COLOR_PALETTE","DEFAULT_COLORS","getIndicatorInfo","t","ColorPalettePopup","currentColor","onSelect","onClose","position","colorTitle","paletteRef","useRef","useEffect","handleClickOutside","e","timer","paletteElement","jsxs","jsx","color","createPortal","IndicatorSettings","indicator","configs","isChecked","onConfigChange","macdColors","onMacdColorsChange","localeProp","getLocaleStrings","INDICATOR_INFO","colorPaletteOpen","setColorPaletteOpen","useState","info","config","handleColorClick","index","type","rect","rsiConfig","macdConfig","bbConfig","stochConfig","vwapConfig","singleConfig","cfg","newConfigs","_","i","lastConfig","nextColorIdx"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { IChartApi, ISeriesApi } from 'lightweight-charts';
2
+ import { CandleData } from '../../types';
3
+ export interface UseChartOptions {
4
+ width?: number;
5
+ height?: number;
6
+ }
7
+ export interface UseChartReturn {
8
+ chartRef: React.RefObject<HTMLDivElement | null>;
9
+ chart: IChartApi | null;
10
+ candleSeries: ISeriesApi<'Candlestick'> | null;
11
+ volumeSeries: ISeriesApi<'Histogram'> | null;
12
+ setData: (data: CandleData[], shouldFit?: boolean) => void;
13
+ }
14
+ export declare function useChart(options?: UseChartOptions): UseChartReturn;
15
+ //# sourceMappingURL=useChart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChart.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useChart.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAQ,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAO9C,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACjD,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,UAAU,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC/C,YAAY,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5D;AAED,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,CAiRtE"}
@@ -0,0 +1,155 @@
1
+ import { useRef as s, useState as C, useEffect as V } from "react";
2
+ import { filterValidCandles as z } from "../../utils/validateCandle.js";
3
+ import { loadLightweightCharts as I } from "../loadLightweightCharts.js";
4
+ function x(h = {}) {
5
+ const i = s(null), r = s(null), a = s(null), u = s(null), n = s(!1), m = s(null), [L, v] = C(null), [F, y] = C(null), [k, S] = C(null);
6
+ V(() => {
7
+ if (!i.current) return;
8
+ let o = !1;
9
+ return n.current = !1, (async () => {
10
+ let l;
11
+ try {
12
+ l = await I();
13
+ } catch {
14
+ if (typeof LightweightCharts < "u")
15
+ l = LightweightCharts;
16
+ else {
17
+ console.error("[useChart] LightweightCharts is not loaded. Make sure to include the script in your HTML or place the standalone JS in a known path.");
18
+ return;
19
+ }
20
+ }
21
+ if (o || !i.current) return;
22
+ const { createChart: f } = l, d = h.width || i.current.clientWidth, b = h.height || 600, e = f(i.current, {
23
+ width: d,
24
+ height: b,
25
+ layout: {
26
+ background: { color: "#ffffff" },
27
+ textColor: "#333"
28
+ },
29
+ grid: {
30
+ vertLines: { color: "#f0f0f0" },
31
+ horzLines: { color: "#f0f0f0" }
32
+ },
33
+ crosshair: {
34
+ mode: 0
35
+ },
36
+ rightPriceScale: {
37
+ borderColor: "#cccccc"
38
+ },
39
+ timeScale: {
40
+ borderColor: "#cccccc",
41
+ timeVisible: !0,
42
+ secondsVisible: !1
43
+ }
44
+ }), p = e.addCandlestickSeries({
45
+ upColor: "#ef4444",
46
+ downColor: "#3b82f6",
47
+ borderUpColor: "#ef4444",
48
+ borderDownColor: "#3b82f6",
49
+ wickUpColor: "#ef4444",
50
+ wickDownColor: "#3b82f6"
51
+ }), t = e.addHistogramSeries({
52
+ color: "#ef4444",
53
+ priceFormat: { type: "volume" },
54
+ priceScaleId: ""
55
+ });
56
+ t.priceScale().applyOptions({
57
+ scaleMargins: {
58
+ top: 0.8,
59
+ bottom: 0
60
+ }
61
+ }), r.current = e, a.current = p, u.current = t, v(e), y(p), S(t);
62
+ const c = () => {
63
+ if (!n.current && i.current && r.current) {
64
+ const w = i.current.clientWidth, N = i.current.clientHeight;
65
+ if (w > 0 && N > 0)
66
+ try {
67
+ r.current.applyOptions({
68
+ width: w,
69
+ height: N
70
+ });
71
+ } catch {
72
+ }
73
+ }
74
+ }, R = new ResizeObserver(() => {
75
+ c();
76
+ });
77
+ R.observe(i.current), window.addEventListener("resize", c), m.current = () => {
78
+ R.disconnect(), window.removeEventListener("resize", c), r.current = null, a.current = null, u.current = null, v(null), y(null), S(null);
79
+ try {
80
+ e.remove();
81
+ } catch {
82
+ }
83
+ };
84
+ })(), () => {
85
+ o = !0, n.current = !0, m.current && (m.current(), m.current = null);
86
+ };
87
+ }, [h.width, h.height]);
88
+ const D = s(null);
89
+ return {
90
+ chartRef: i,
91
+ chart: L,
92
+ candleSeries: F,
93
+ volumeSeries: k,
94
+ setData: (o, g = !1) => {
95
+ if (n.current || !a.current || !u.current || !r.current) return;
96
+ if (!o || !Array.isArray(o) || o.length === 0) {
97
+ console.warn("[useChart] No data provided, skipping setData");
98
+ return;
99
+ }
100
+ let l = null;
101
+ if (!g && o.length > 0 && D.current !== null)
102
+ try {
103
+ const e = r.current.timeScale().getVisibleLogicalRange();
104
+ e && (l = { from: e.from, to: e.to });
105
+ } catch {
106
+ }
107
+ const f = z(o, "useChart");
108
+ if (f.length === 0) {
109
+ console.warn("[useChart] No valid candle data to display");
110
+ return;
111
+ }
112
+ D.current = f[0].time;
113
+ const d = f.map((e) => ({
114
+ time: e.time,
115
+ open: e.open,
116
+ high: e.high,
117
+ low: e.low,
118
+ close: e.close
119
+ })), b = f.map((e) => ({
120
+ time: e.time,
121
+ value: Number.isFinite(e.volume) ? e.volume : 0,
122
+ // NaN/Infinity/null/undefined 모두 0으로 처리
123
+ color: e.close >= e.open ? "#ef444466" : "#3b82f666"
124
+ }));
125
+ try {
126
+ if (n.current || !a.current || !u.current)
127
+ return;
128
+ const e = d.filter((t) => {
129
+ const c = typeof t.time == "number" ? t.time : Number(t.time);
130
+ return Number.isFinite(c) && c > 0 && Number.isFinite(t.open) && Number.isFinite(t.high) && Number.isFinite(t.low) && Number.isFinite(t.close);
131
+ }), p = b.filter((t) => {
132
+ const c = typeof t.time == "number" ? t.time : Number(t.time);
133
+ return Number.isFinite(c) && c > 0 && Number.isFinite(t.value);
134
+ });
135
+ if (e.length === 0) {
136
+ console.warn("[useChart] No valid candle data after final null check");
137
+ return;
138
+ }
139
+ if (a.current && !n.current && a.current.setData(e), u.current && !n.current && u.current.setData(p), g && r.current && !n.current)
140
+ r.current.timeScale().fitContent();
141
+ else if (l && r.current && !n.current)
142
+ try {
143
+ r.current.timeScale().setVisibleLogicalRange(l);
144
+ } catch {
145
+ }
146
+ } catch (e) {
147
+ n.current || console.error("[useChart] Error in setData:", e, "Data sample:", d.slice(0, 3));
148
+ }
149
+ }
150
+ };
151
+ }
152
+ export {
153
+ x as useChart
154
+ };
155
+ //# sourceMappingURL=useChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChart.js","sources":["../../../src/react/hooks/useChart.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport type { IChartApi, ISeriesApi, Time } from 'lightweight-charts';\nimport type { CandleData } from '../../types';\nimport { filterValidCandles } from '../../utils/validateCandle';\nimport { loadLightweightCharts } from '../loadLightweightCharts';\n\n// 전역 LightweightCharts 객체 (커스텀 빌드 - Line Tools 포함)\ndeclare const LightweightCharts: any;\n\nexport interface UseChartOptions {\n width?: number;\n height?: number;\n}\n\nexport interface UseChartReturn {\n chartRef: React.RefObject<HTMLDivElement | null>;\n chart: IChartApi | null;\n candleSeries: ISeriesApi<'Candlestick'> | null;\n volumeSeries: ISeriesApi<'Histogram'> | null;\n setData: (data: CandleData[], shouldFit?: boolean) => void;\n}\n\nexport function useChart(options: UseChartOptions = {}): UseChartReturn {\n const chartRef = useRef<HTMLDivElement>(null);\n const chartInstanceRef = useRef<IChartApi | null>(null);\n const candleSeriesRef = useRef<ISeriesApi<'Candlestick'> | null>(null);\n const volumeSeriesRef = useRef<ISeriesApi<'Histogram'> | null>(null);\n const isDestroyedRef = useRef<boolean>(false);\n const cleanupRef = useRef<(() => void) | null>(null);\n\n const [chart, setChart] = useState<IChartApi | null>(null);\n const [candleSeries, setCandleSeries] = useState<ISeriesApi<'Candlestick'> | null>(null);\n const [volumeSeries, setVolumeSeries] = useState<ISeriesApi<'Histogram'> | null>(null);\n\n // 차트 초기화\n useEffect(() => {\n if (!chartRef.current) return;\n\n let cancelled = false;\n\n // 초기화 시 파괴 플래그 리셋\n isDestroyedRef.current = false;\n\n const init = async () => {\n // 자동 로딩 시도 (이미 로드되어 있으면 즉시 resolve)\n let LWC: any;\n try {\n LWC = await loadLightweightCharts();\n } catch {\n // 폴백: 전역 LightweightCharts 확인 (수동 script 태그)\n if (typeof LightweightCharts !== 'undefined') {\n LWC = LightweightCharts;\n } else {\n console.error('[useChart] LightweightCharts is not loaded. Make sure to include the script in your HTML or place the standalone JS in a known path.');\n return;\n }\n }\n\n if (cancelled || !chartRef.current) return;\n\n const { createChart } = LWC;\n const width = options.width || chartRef.current.clientWidth;\n const height = options.height || 600;\n\n const chartInstance = createChart(chartRef.current, {\n width,\n height,\n layout: {\n background: { color: '#ffffff' },\n textColor: '#333',\n },\n grid: {\n vertLines: { color: '#f0f0f0' },\n horzLines: { color: '#f0f0f0' },\n },\n crosshair: {\n mode: 0,\n },\n rightPriceScale: {\n borderColor: '#cccccc',\n },\n timeScale: {\n borderColor: '#cccccc',\n timeVisible: true,\n secondsVisible: false,\n },\n });\n\n // 캔들스틱 시리즈\n const candleSeriesInstance = chartInstance.addCandlestickSeries({\n upColor: '#ef4444',\n downColor: '#3b82f6',\n borderUpColor: '#ef4444',\n borderDownColor: '#3b82f6',\n wickUpColor: '#ef4444',\n wickDownColor: '#3b82f6',\n });\n\n // 거래량 시리즈\n const volumeSeriesInstance = chartInstance.addHistogramSeries({\n color: '#ef4444',\n priceFormat: { type: 'volume' },\n priceScaleId: '',\n });\n\n volumeSeriesInstance.priceScale().applyOptions({\n scaleMargins: {\n top: 0.8,\n bottom: 0,\n },\n });\n\n chartInstanceRef.current = chartInstance;\n candleSeriesRef.current = candleSeriesInstance;\n volumeSeriesRef.current = volumeSeriesInstance;\n\n setChart(chartInstance);\n setCandleSeries(candleSeriesInstance);\n setVolumeSeries(volumeSeriesInstance);\n\n // 리사이즈 핸들러 - width와 height 모두 업데이트\n const handleResize = () => {\n // 차트가 파괴된 경우 무시\n if (isDestroyedRef.current) return;\n\n if (chartRef.current && chartInstanceRef.current) {\n const newWidth = chartRef.current.clientWidth;\n const newHeight = chartRef.current.clientHeight;\n if (newWidth > 0 && newHeight > 0) {\n try {\n chartInstanceRef.current.applyOptions({\n width: newWidth,\n height: newHeight,\n });\n } catch (e) {\n // 차트가 이미 파괴된 경우 무시\n }\n }\n }\n };\n\n // ResizeObserver로 컨테이너 크기 변화 감지 (height 포함)\n const resizeObserver = new ResizeObserver(() => {\n handleResize();\n });\n resizeObserver.observe(chartRef.current);\n\n // window resize도 백업으로 유지\n window.addEventListener('resize', handleResize);\n\n cleanupRef.current = () => {\n resizeObserver.disconnect();\n window.removeEventListener('resize', handleResize);\n\n // refs 정리\n chartInstanceRef.current = null;\n candleSeriesRef.current = null;\n volumeSeriesRef.current = null;\n\n // state 정리\n setChart(null);\n setCandleSeries(null);\n setVolumeSeries(null);\n\n // 차트 파괴\n try {\n chartInstance.remove();\n } catch (e) {\n // 이미 파괴된 경우 무시\n }\n };\n }; // end of init()\n\n init();\n\n return () => {\n cancelled = true;\n // 파괴 플래그 먼저 설정 (다른 effect들이 참조하지 않도록)\n isDestroyedRef.current = true;\n\n if (cleanupRef.current) {\n cleanupRef.current();\n cleanupRef.current = null;\n }\n };\n }, [options.width, options.height]);\n\n // 이전 데이터의 첫번째 timestamp 저장 (타임존 변경 시 오프셋 계산용)\n const prevFirstTimestampRef = useRef<number | null>(null);\n\n // 데이터 설정 함수\n const setData = (data: CandleData[], shouldFit: boolean = false) => {\n // 차트가 파괴된 경우 무시\n if (isDestroyedRef.current) return;\n if (!candleSeriesRef.current || !volumeSeriesRef.current || !chartInstanceRef.current) return;\n\n // 데이터가 없거나 빈 배열이면 무시 (에러 방지)\n if (!data || !Array.isArray(data) || data.length === 0) {\n console.warn('[useChart] No data provided, skipping setData');\n return;\n }\n\n // 현재 visible range 저장 (shouldFit이 false일 때만)\n let savedRange: { from: number; to: number } | null = null;\n\n if (!shouldFit && data.length > 0 && prevFirstTimestampRef.current !== null) {\n try {\n const visibleRange = chartInstanceRef.current.timeScale().getVisibleLogicalRange();\n if (visibleRange) {\n savedRange = { from: visibleRange.from, to: visibleRange.to };\n }\n } catch (e) {\n // ignore\n }\n }\n\n const validData = filterValidCandles(data, 'useChart');\n\n if (validData.length === 0) {\n console.warn('[useChart] No valid candle data to display');\n return;\n }\n\n // 첫번째 timestamp 저장\n prevFirstTimestampRef.current = validData[0].time as number;\n\n const candleData = validData.map(c => ({\n time: c.time as Time,\n open: c.open,\n high: c.high,\n low: c.low,\n close: c.close,\n }));\n\n const volumeData = validData.map(c => ({\n time: c.time as Time,\n value: Number.isFinite(c.volume) ? c.volume : 0, // NaN/Infinity/null/undefined 모두 0으로 처리\n color: c.close >= c.open ? '#ef444466' : '#3b82f666',\n }));\n\n try {\n // 차트가 파괴된 경우 재확인 (race condition 방지)\n if (isDestroyedRef.current || !candleSeriesRef.current || !volumeSeriesRef.current) {\n return;\n }\n\n const finalCandleData = candleData.filter(c => {\n const time = typeof c.time === 'number' ? c.time : Number(c.time);\n return Number.isFinite(time) && time > 0 &&\n Number.isFinite(c.open) && Number.isFinite(c.high) &&\n Number.isFinite(c.low) && Number.isFinite(c.close);\n });\n const finalVolumeData = volumeData.filter(v => {\n const time = typeof v.time === 'number' ? v.time : Number(v.time);\n return Number.isFinite(time) && time > 0 && Number.isFinite(v.value);\n });\n\n if (finalCandleData.length === 0) {\n console.warn('[useChart] No valid candle data after final null check');\n return;\n }\n\n // 각 setData 호출 전 ref 체크 (unmount 중 호출 방지)\n if (candleSeriesRef.current && !isDestroyedRef.current) {\n candleSeriesRef.current.setData(finalCandleData);\n }\n if (volumeSeriesRef.current && !isDestroyedRef.current) {\n volumeSeriesRef.current.setData(finalVolumeData);\n }\n\n if (shouldFit && chartInstanceRef.current && !isDestroyedRef.current) {\n chartInstanceRef.current.timeScale().fitContent();\n } else if (savedRange && chartInstanceRef.current && !isDestroyedRef.current) {\n // 저장된 range 복원 (logical range는 인덱스 기반이라 오프셋 불필요)\n try {\n chartInstanceRef.current.timeScale().setVisibleLogicalRange(savedRange);\n } catch (e) {\n // ignore\n }\n }\n } catch (e) {\n // 차트가 파괴된 경우 에러 무시 (정상 unmount)\n if (!isDestroyedRef.current) {\n console.error('[useChart] Error in setData:', e, 'Data sample:', candleData.slice(0, 3));\n }\n }\n };\n\n return {\n chartRef,\n chart,\n candleSeries,\n volumeSeries,\n setData,\n };\n}\n"],"names":["useChart","options","chartRef","useRef","chartInstanceRef","candleSeriesRef","volumeSeriesRef","isDestroyedRef","cleanupRef","chart","setChart","useState","candleSeries","setCandleSeries","volumeSeries","setVolumeSeries","useEffect","cancelled","LWC","loadLightweightCharts","createChart","width","height","chartInstance","candleSeriesInstance","volumeSeriesInstance","handleResize","newWidth","newHeight","resizeObserver","prevFirstTimestampRef","data","shouldFit","savedRange","visibleRange","validData","filterValidCandles","candleData","c","volumeData","finalCandleData","time","finalVolumeData","v"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { IChartApi } from 'lightweight-charts';
2
+ import { CandleData } from '../../types';
3
+ import { IndicatorConfigs } from '../types';
4
+ export declare function useIndicators(chart: IChartApi | null, candles: CandleData[]): {
5
+ applyIndicators: (configs: IndicatorConfigs, macdColors?: {
6
+ line: string;
7
+ signal: string;
8
+ }) => void;
9
+ };
10
+ //# sourceMappingURL=useIndicators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIndicators.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useIndicators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAmF,MAAM,UAAU,CAAC;AAclI,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE;+BAG5B,gBAAgB,eAAe;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;EAqU9G"}
@@ -0,0 +1,264 @@
1
+ import { useRef as g, useCallback as O } from "react";
2
+ import { calculateSMA as $ } from "../../indicators/sma.js";
3
+ import { calculateEMA as U } from "../../indicators/ema.js";
4
+ import { calculateRSI as H } from "../../indicators/rsi.js";
5
+ import { calculateMACD as T } from "../../indicators/macd.js";
6
+ import { calculateBollingerBands as K } from "../../indicators/bollingerBands.js";
7
+ import { calculateATR as C } from "../../indicators/atr.js";
8
+ import { calculateStochastic as j } from "../../indicators/stochastic.js";
9
+ import { calculateWilliamsR as q } from "../../indicators/williamsR.js";
10
+ import { calculateVWAP as z } from "../../indicators/vwap.js";
11
+ import { filterValidIndicatorPoints as G } from "../../utils/validateCandle.js";
12
+ function se(r, d) {
13
+ const o = g([]);
14
+ return { applyIndicators: O((n, m) => {
15
+ var P, k, y, I, w;
16
+ if (!r || !d || d.length === 0) return;
17
+ o.current.forEach((e) => {
18
+ try {
19
+ r.removeSeries(e);
20
+ } catch {
21
+ }
22
+ }), o.current = [];
23
+ const c = G, L = (((P = n.rsi) == null ? void 0 : P.length) ?? 0) > 0, v = (((k = n.macd) == null ? void 0 : k.length) ?? 0) > 0, D = (((y = n.stochastic) == null ? void 0 : y.length) ?? 0) > 0, f = (((I = n.atr) == null ? void 0 : I.length) ?? 0) > 0, M = (((w = n.williamsR) == null ? void 0 : w.length) ?? 0) > 0, b = [L, v, D, f, M].filter(Boolean).length, W = b > 0 ? Math.min(0.2, 0.5 / b) : 0;
24
+ let V = 1 - W * b;
25
+ const h = () => {
26
+ const e = V;
27
+ return V += W, { top: e, bottom: 1 - V };
28
+ }, R = L ? h() : { top: 0.75, bottom: 0 }, E = v ? h() : { top: 0.75, bottom: 0 }, F = D ? h() : { top: 0.75, bottom: 0 }, A = f ? h() : { top: 0.75, bottom: 0 }, B = M ? h() : { top: 0.75, bottom: 0 };
29
+ n.sma.forEach((e) => {
30
+ const a = $(d, { period: e.value }), l = c(a || []);
31
+ if (l.length > 0) {
32
+ const i = r.addLineSeries({
33
+ color: e.color,
34
+ lineWidth: e.thickness,
35
+ title: `SMA ${e.value}`,
36
+ lastValueVisible: !1,
37
+ priceLineVisible: !1
38
+ });
39
+ i.setData(l.map((t) => ({ ...t, time: t.time }))), o.current.push(i);
40
+ }
41
+ }), n.ema.forEach((e) => {
42
+ const a = U(d, { period: e.value }), l = c(a || []);
43
+ if (l.length > 0) {
44
+ const i = r.addLineSeries({
45
+ color: e.color,
46
+ lineWidth: e.thickness,
47
+ title: `EMA ${e.value}`,
48
+ lastValueVisible: !1,
49
+ priceLineVisible: !1
50
+ });
51
+ i.setData(l.map((t) => ({ ...t, time: t.time }))), o.current.push(i);
52
+ }
53
+ }), n.rsi.forEach((e) => {
54
+ const a = H(d, { period: e.value }), l = c(a || []);
55
+ if (l.length > 0) {
56
+ const i = r.addLineSeries({
57
+ color: e.color,
58
+ lineWidth: e.thickness,
59
+ title: `RSI ${e.value}`,
60
+ priceScaleId: "rsi",
61
+ lastValueVisible: !0,
62
+ priceLineVisible: !1
63
+ });
64
+ i.priceScale().applyOptions({
65
+ scaleMargins: R
66
+ }), i.setData(l.map((s) => ({ ...s, time: s.time })));
67
+ const t = e.oversold ?? 30, p = e.overbought ?? 70;
68
+ i.createPriceLine({
69
+ price: t,
70
+ color: "rgba(150,150,150,0.4)",
71
+ lineWidth: 1,
72
+ lineStyle: 1,
73
+ axisLabelVisible: !1,
74
+ title: "",
75
+ lineVisible: !0
76
+ }), i.createPriceLine({
77
+ price: p,
78
+ color: "rgba(150,150,150,0.4)",
79
+ lineWidth: 1,
80
+ lineStyle: 1,
81
+ axisLabelVisible: !1,
82
+ title: "",
83
+ lineVisible: !0
84
+ }), o.current.push(i);
85
+ }
86
+ }), n.macd.forEach((e) => {
87
+ const a = T(d, {
88
+ fastPeriod: e.fastPeriod,
89
+ slowPeriod: e.slowPeriod,
90
+ signalPeriod: e.signalPeriod
91
+ }), l = c(a.macd || []), i = c(a.signal || []), t = c(a.histogram || []);
92
+ if (l.length > 0) {
93
+ const p = r.addLineSeries({
94
+ color: (m == null ? void 0 : m.line) || "#2962FF",
95
+ lineWidth: e.thickness,
96
+ title: "MACD",
97
+ priceScaleId: "macd",
98
+ lastValueVisible: !0,
99
+ priceLineVisible: !1
100
+ });
101
+ if (p.priceScale().applyOptions({
102
+ scaleMargins: E
103
+ }), p.setData(l.map((s) => ({ ...s, time: s.time }))), o.current.push(p), i.length > 0) {
104
+ const s = r.addLineSeries({
105
+ color: (m == null ? void 0 : m.signal) || "#FF6D00",
106
+ lineWidth: e.thickness,
107
+ title: "Signal",
108
+ priceScaleId: "macd",
109
+ lastValueVisible: !0,
110
+ priceLineVisible: !1
111
+ });
112
+ s.setData(i.map((u) => ({ ...u, time: u.time }))), o.current.push(s);
113
+ }
114
+ if (t.length > 0) {
115
+ const s = r.addHistogramSeries({
116
+ priceScaleId: "macd"
117
+ }), u = e.histUpColor || "#26a69a", x = e.histDownColor || "#ef5350";
118
+ s.setData(t.map((S) => ({
119
+ time: S.time,
120
+ value: S.value,
121
+ color: S.value >= 0 ? u : x
122
+ }))), o.current.push(s);
123
+ }
124
+ }
125
+ }), n.bbands.forEach((e) => {
126
+ const a = K(d, { period: e.value, stdDev: e.stdDev || 2 }), l = c(a.upper || []), i = c(a.middle || []), t = c(a.lower || []);
127
+ if (l.length > 0) {
128
+ const p = r.addLineSeries({
129
+ color: e.upperColor || "#F23645",
130
+ lineWidth: 1,
131
+ lineStyle: 1,
132
+ title: "BB Upper",
133
+ crosshairMarkerVisible: !1,
134
+ lastValueVisible: !1,
135
+ priceLineVisible: !1
136
+ });
137
+ if (p.setData(l.map((s) => ({ ...s, time: s.time }))), o.current.push(p), i.length > 0) {
138
+ const s = r.addLineSeries({
139
+ color: e.middleColor || "#2962FF",
140
+ lineWidth: e.thickness,
141
+ lineStyle: 0,
142
+ title: "BB Middle",
143
+ lastValueVisible: !1,
144
+ priceLineVisible: !1
145
+ });
146
+ s.setData(i.map((u) => ({ ...u, time: u.time }))), o.current.push(s);
147
+ }
148
+ if (t.length > 0) {
149
+ const s = r.addLineSeries({
150
+ color: e.lowerColor || "#089981",
151
+ lineWidth: 1,
152
+ lineStyle: 1,
153
+ title: "BB Lower",
154
+ crosshairMarkerVisible: !1,
155
+ lastValueVisible: !1,
156
+ priceLineVisible: !1
157
+ });
158
+ s.setData(t.map((u) => ({ ...u, time: u.time }))), o.current.push(s);
159
+ }
160
+ }
161
+ }), (n.stochastic ?? []).forEach((e) => {
162
+ const a = j(d, {
163
+ kPeriod: e.kPeriod,
164
+ dPeriod: e.dPeriod,
165
+ smooth: e.smooth
166
+ }), l = c(a.k || []), i = c(a.d || []);
167
+ if (l.length > 0) {
168
+ const t = r.addLineSeries({
169
+ color: e.kColor || "#2962FF",
170
+ lineWidth: e.thickness,
171
+ title: "%K",
172
+ priceScaleId: "stochastic",
173
+ lastValueVisible: !0,
174
+ priceLineVisible: !1
175
+ });
176
+ if (t.priceScale().applyOptions({ scaleMargins: F }), t.setData(l.map((p) => ({ ...p, time: p.time }))), o.current.push(t), t.createPriceLine({
177
+ price: 80,
178
+ color: "rgba(150,150,150,0.4)",
179
+ lineWidth: 1,
180
+ lineStyle: 1,
181
+ axisLabelVisible: !1,
182
+ title: "",
183
+ lineVisible: !0
184
+ }), t.createPriceLine({
185
+ price: 20,
186
+ color: "rgba(150,150,150,0.4)",
187
+ lineWidth: 1,
188
+ lineStyle: 1,
189
+ axisLabelVisible: !1,
190
+ title: "",
191
+ lineVisible: !0
192
+ }), i.length > 0) {
193
+ const p = r.addLineSeries({
194
+ color: e.dColor || "#FF6D00",
195
+ lineWidth: e.thickness,
196
+ title: "%D",
197
+ priceScaleId: "stochastic",
198
+ lastValueVisible: !0,
199
+ priceLineVisible: !1
200
+ });
201
+ p.setData(i.map((s) => ({ ...s, time: s.time }))), o.current.push(p);
202
+ }
203
+ }
204
+ }), (n.atr ?? []).forEach((e) => {
205
+ const a = C(d, { period: e.value }), l = c(a || []);
206
+ if (l.length > 0) {
207
+ const i = r.addLineSeries({
208
+ color: e.color,
209
+ lineWidth: e.thickness,
210
+ title: `ATR ${e.value}`,
211
+ priceScaleId: "atr",
212
+ lastValueVisible: !0,
213
+ priceLineVisible: !1
214
+ });
215
+ i.priceScale().applyOptions({ scaleMargins: A }), i.setData(l.map((t) => ({ ...t, time: t.time }))), o.current.push(i);
216
+ }
217
+ }), (n.vwap ?? []).forEach((e) => {
218
+ const a = z(d), l = c(a || []);
219
+ if (l.length > 0) {
220
+ const i = r.addLineSeries({
221
+ color: e.color || "#E040FB",
222
+ lineWidth: e.thickness,
223
+ title: "VWAP",
224
+ lastValueVisible: !1,
225
+ priceLineVisible: !1
226
+ });
227
+ i.setData(l.map((t) => ({ ...t, time: t.time }))), o.current.push(i);
228
+ }
229
+ }), (n.williamsR ?? []).forEach((e) => {
230
+ const a = q(d, { period: e.value }), l = c(a || []);
231
+ if (l.length > 0) {
232
+ const i = r.addLineSeries({
233
+ color: e.color,
234
+ lineWidth: e.thickness,
235
+ title: `W%R ${e.value}`,
236
+ priceScaleId: "williamsR",
237
+ lastValueVisible: !0,
238
+ priceLineVisible: !1
239
+ });
240
+ i.priceScale().applyOptions({ scaleMargins: B }), i.setData(l.map((t) => ({ ...t, time: t.time }))), i.createPriceLine({
241
+ price: -20,
242
+ color: "rgba(150,150,150,0.4)",
243
+ lineWidth: 1,
244
+ lineStyle: 1,
245
+ axisLabelVisible: !1,
246
+ title: "",
247
+ lineVisible: !0
248
+ }), i.createPriceLine({
249
+ price: -80,
250
+ color: "rgba(150,150,150,0.4)",
251
+ lineWidth: 1,
252
+ lineStyle: 1,
253
+ axisLabelVisible: !1,
254
+ title: "",
255
+ lineVisible: !0
256
+ }), o.current.push(i);
257
+ }
258
+ });
259
+ }, [r, d]) };
260
+ }
261
+ export {
262
+ se as useIndicators
263
+ };
264
+ //# sourceMappingURL=useIndicators.js.map