@tradecanvas/chart 0.5.0 → 0.7.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 (50) hide show
  1. package/README.md +570 -442
  2. package/dist/Chart-0R7hFD6z.cjs +2 -0
  3. package/dist/Chart-0R7hFD6z.cjs.map +1 -0
  4. package/dist/Chart-BodmeuC5.js +1096 -0
  5. package/dist/Chart-BodmeuC5.js.map +1 -0
  6. package/dist/Chart.d.ts +25 -4
  7. package/dist/Chart.d.ts.map +1 -1
  8. package/dist/charts/ChartTypeStrategy.d.ts +18 -0
  9. package/dist/charts/ChartTypeStrategy.d.ts.map +1 -0
  10. package/dist/charts/IndicatorPriceRange.d.ts +16 -0
  11. package/dist/charts/IndicatorPriceRange.d.ts.map +1 -0
  12. package/dist/grid/ChartGrid.d.ts +39 -0
  13. package/dist/grid/ChartGrid.d.ts.map +1 -0
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +6 -4
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +163 -1004
  19. package/dist/index.js.map +1 -1
  20. package/dist/state/AutoSaveScheduler.d.ts +26 -0
  21. package/dist/state/AutoSaveScheduler.d.ts.map +1 -0
  22. package/dist/widget/ChartWidget.d.ts +48 -0
  23. package/dist/widget/ChartWidget.d.ts.map +1 -0
  24. package/dist/widget/WidgetCommandPalette.d.ts +39 -0
  25. package/dist/widget/WidgetCommandPalette.d.ts.map +1 -0
  26. package/dist/widget/WidgetDrawingSidebar.d.ts +19 -0
  27. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -0
  28. package/dist/widget/WidgetDropdown.d.ts +18 -0
  29. package/dist/widget/WidgetDropdown.d.ts.map +1 -0
  30. package/dist/widget/WidgetSettings.d.ts +25 -0
  31. package/dist/widget/WidgetSettings.d.ts.map +1 -0
  32. package/dist/widget/WidgetStatusBar.d.ts +15 -0
  33. package/dist/widget/WidgetStatusBar.d.ts.map +1 -0
  34. package/dist/widget/WidgetStyles.d.ts +9 -0
  35. package/dist/widget/WidgetStyles.d.ts.map +1 -0
  36. package/dist/widget/WidgetToolbar.d.ts +22 -0
  37. package/dist/widget/WidgetToolbar.d.ts.map +1 -0
  38. package/dist/widget/icons.d.ts +2 -0
  39. package/dist/widget/icons.d.ts.map +1 -0
  40. package/dist/widget/index.cjs +878 -0
  41. package/dist/widget/index.cjs.map +1 -0
  42. package/dist/widget/index.d.ts +3 -0
  43. package/dist/widget/index.d.ts.map +1 -0
  44. package/dist/widget/index.js +1316 -0
  45. package/dist/widget/index.js.map +1 -0
  46. package/dist/widget/types.d.ts +105 -0
  47. package/dist/widget/types.d.ts.map +1 -0
  48. package/dist/widget/widgetConfig.d.ts +16 -0
  49. package/dist/widget/widgetConfig.d.ts.map +1 -0
  50. package/package.json +14 -4
@@ -0,0 +1,1316 @@
1
+ import { t as e } from "../Chart-BodmeuC5.js";
2
+ import { DARK_THEME as t, LIGHT_THEME as n } from "@tradecanvas/commons";
3
+ //#region src/widget/widgetConfig.ts
4
+ var r = [
5
+ {
6
+ label: "1m",
7
+ value: "1m"
8
+ },
9
+ {
10
+ label: "5m",
11
+ value: "5m"
12
+ },
13
+ {
14
+ label: "15m",
15
+ value: "15m"
16
+ },
17
+ {
18
+ label: "1H",
19
+ value: "1h"
20
+ },
21
+ {
22
+ label: "4H",
23
+ value: "4h"
24
+ },
25
+ {
26
+ label: "1D",
27
+ value: "1d"
28
+ }
29
+ ], i = [
30
+ {
31
+ label: "Candlestick",
32
+ value: "candlestick"
33
+ },
34
+ {
35
+ label: "Line",
36
+ value: "line"
37
+ },
38
+ {
39
+ label: "Area",
40
+ value: "area"
41
+ },
42
+ {
43
+ label: "Bar",
44
+ value: "bar"
45
+ },
46
+ {
47
+ label: "Heikin-Ashi",
48
+ value: "heikinAshi"
49
+ },
50
+ {
51
+ label: "Hollow Candle",
52
+ value: "hollowCandle"
53
+ },
54
+ {
55
+ label: "Baseline",
56
+ value: "baseline"
57
+ },
58
+ {
59
+ label: "Volume Candles",
60
+ value: "volumeCandles"
61
+ },
62
+ {
63
+ label: "HLC Area",
64
+ value: "hlcArea"
65
+ },
66
+ {
67
+ label: "Step Line",
68
+ value: "stepLine"
69
+ },
70
+ {
71
+ label: "Line + Markers",
72
+ value: "lineWithMarkers"
73
+ }
74
+ ], a = [
75
+ {
76
+ label: "Lines",
77
+ tools: [
78
+ {
79
+ label: "Trend Line",
80
+ value: "trendLine"
81
+ },
82
+ {
83
+ label: "Ray",
84
+ value: "ray"
85
+ },
86
+ {
87
+ label: "Extended Line",
88
+ value: "extendedLine"
89
+ }
90
+ ]
91
+ },
92
+ {
93
+ label: "Horizontal/Vertical",
94
+ tools: [{
95
+ label: "Horizontal Line",
96
+ value: "horizontalLine"
97
+ }, {
98
+ label: "Vertical Line",
99
+ value: "verticalLine"
100
+ }]
101
+ },
102
+ {
103
+ label: "Channels",
104
+ tools: [{
105
+ label: "Parallel Channel",
106
+ value: "parallelChannel"
107
+ }, {
108
+ label: "Regression Channel",
109
+ value: "regressionChannel"
110
+ }]
111
+ },
112
+ {
113
+ label: "Fibonacci",
114
+ tools: [{
115
+ label: "Fib Retracement",
116
+ value: "fibRetracement"
117
+ }, {
118
+ label: "Fib Extension",
119
+ value: "fibExtension"
120
+ }]
121
+ },
122
+ {
123
+ label: "Shapes",
124
+ tools: [
125
+ {
126
+ label: "Rectangle",
127
+ value: "rectangle"
128
+ },
129
+ {
130
+ label: "Ellipse",
131
+ value: "ellipse"
132
+ },
133
+ {
134
+ label: "Triangle",
135
+ value: "triangle"
136
+ }
137
+ ]
138
+ },
139
+ {
140
+ label: "Gann & Advanced",
141
+ tools: [
142
+ {
143
+ label: "Pitchfork",
144
+ value: "pitchfork"
145
+ },
146
+ {
147
+ label: "Gann Fan",
148
+ value: "gannFan"
149
+ },
150
+ {
151
+ label: "Gann Box",
152
+ value: "gannBox"
153
+ },
154
+ {
155
+ label: "Elliott Wave",
156
+ value: "elliottWave"
157
+ }
158
+ ]
159
+ },
160
+ {
161
+ label: "Measure",
162
+ tools: [
163
+ {
164
+ label: "Price Range",
165
+ value: "priceRange"
166
+ },
167
+ {
168
+ label: "Date Range",
169
+ value: "dateRange"
170
+ },
171
+ {
172
+ label: "Measure",
173
+ value: "measure"
174
+ }
175
+ ]
176
+ },
177
+ {
178
+ label: "Annotation",
179
+ tools: [{
180
+ label: "Text",
181
+ value: "text"
182
+ }, {
183
+ label: "Arrow",
184
+ value: "arrow"
185
+ }]
186
+ }
187
+ ], o = [
188
+ {
189
+ id: "sma",
190
+ name: "SMA",
191
+ type: "overlay"
192
+ },
193
+ {
194
+ id: "ema",
195
+ name: "EMA",
196
+ type: "overlay"
197
+ },
198
+ {
199
+ id: "hma",
200
+ name: "Hull MA",
201
+ type: "overlay"
202
+ },
203
+ {
204
+ id: "bb",
205
+ name: "Bollinger Bands",
206
+ type: "overlay"
207
+ },
208
+ {
209
+ id: "vwap",
210
+ name: "VWAP",
211
+ type: "overlay"
212
+ },
213
+ {
214
+ id: "avwap",
215
+ name: "Anchored VWAP",
216
+ type: "overlay"
217
+ },
218
+ {
219
+ id: "ichimoku",
220
+ name: "Ichimoku Cloud",
221
+ type: "overlay"
222
+ },
223
+ {
224
+ id: "psar",
225
+ name: "Parabolic SAR",
226
+ type: "overlay"
227
+ },
228
+ {
229
+ id: "supertrend",
230
+ name: "Supertrend",
231
+ type: "overlay"
232
+ },
233
+ {
234
+ id: "keltner",
235
+ name: "Keltner Channel",
236
+ type: "overlay"
237
+ },
238
+ {
239
+ id: "donchian",
240
+ name: "Donchian Channel",
241
+ type: "overlay"
242
+ },
243
+ {
244
+ id: "pivots",
245
+ name: "Pivot Points",
246
+ type: "overlay"
247
+ },
248
+ {
249
+ id: "zigzag",
250
+ name: "ZigZag",
251
+ type: "overlay"
252
+ },
253
+ {
254
+ id: "lrc",
255
+ name: "Linear Regression Channel",
256
+ type: "overlay"
257
+ },
258
+ {
259
+ id: "rsi",
260
+ name: "RSI",
261
+ type: "panel"
262
+ },
263
+ {
264
+ id: "macd",
265
+ name: "MACD",
266
+ type: "panel"
267
+ },
268
+ {
269
+ id: "stochastic",
270
+ name: "Stochastic",
271
+ type: "panel"
272
+ },
273
+ {
274
+ id: "atr",
275
+ name: "ATR",
276
+ type: "panel"
277
+ },
278
+ {
279
+ id: "adx",
280
+ name: "ADX",
281
+ type: "panel"
282
+ },
283
+ {
284
+ id: "obv",
285
+ name: "OBV",
286
+ type: "panel"
287
+ },
288
+ {
289
+ id: "williamsR",
290
+ name: "Williams %R",
291
+ type: "panel"
292
+ },
293
+ {
294
+ id: "cci",
295
+ name: "CCI",
296
+ type: "panel"
297
+ },
298
+ {
299
+ id: "mfi",
300
+ name: "MFI",
301
+ type: "panel"
302
+ },
303
+ {
304
+ id: "roc",
305
+ name: "ROC",
306
+ type: "panel"
307
+ },
308
+ {
309
+ id: "tsi",
310
+ name: "TSI",
311
+ type: "panel"
312
+ },
313
+ {
314
+ id: "cmf",
315
+ name: "CMF",
316
+ type: "panel"
317
+ },
318
+ {
319
+ id: "aroon",
320
+ name: "Aroon",
321
+ type: "panel"
322
+ },
323
+ {
324
+ id: "stddev",
325
+ name: "Std Deviation",
326
+ type: "panel"
327
+ },
328
+ {
329
+ id: "vroc",
330
+ name: "Volume ROC",
331
+ type: "panel"
332
+ },
333
+ {
334
+ id: "ad",
335
+ name: "Acc/Dist",
336
+ type: "panel"
337
+ },
338
+ {
339
+ id: "ao",
340
+ name: "Awesome Oscillator",
341
+ type: "panel"
342
+ },
343
+ {
344
+ id: "chaikinOsc",
345
+ name: "Chaikin Oscillator",
346
+ type: "panel"
347
+ },
348
+ {
349
+ id: "volumeProfile",
350
+ name: "Volume Profile",
351
+ type: "panel"
352
+ }
353
+ ], s = [
354
+ "sma",
355
+ "ema",
356
+ "bb",
357
+ "rsi",
358
+ "macd",
359
+ "stochastic",
360
+ "vwap",
361
+ "atr",
362
+ "obv",
363
+ "ichimoku"
364
+ ], c = [
365
+ "BTCUSDT",
366
+ "ETHUSDT",
367
+ "SOLUSDT",
368
+ "BNBUSDT"
369
+ ], l = {
370
+ candleUpColor: "#26A69A",
371
+ candleDownColor: "#EF5350",
372
+ candleUpWick: "#26A69A",
373
+ candleDownWick: "#EF5350",
374
+ backgroundColor: "#131722",
375
+ gridColor: "#1E222D",
376
+ gridVisible: !0,
377
+ volumeVisible: !0,
378
+ legendVisible: !0,
379
+ barCountdown: !0,
380
+ logScale: !1,
381
+ autoScale: !0,
382
+ crosshairMode: "magnet",
383
+ numberLocale: "en-US"
384
+ }, u = "/* === TradeCanvas Widget Styles === */\r\n\r\n.tcw-root {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\r\n font-size: 13px;\r\n color: #d1d4dc;\r\n background: #131722;\r\n position: relative;\r\n overflow: hidden;\r\n\r\n /* Dark theme tokens (default) */\r\n --tcw-bg: #131722;\r\n --tcw-bg-elevated: #1E222D;\r\n --tcw-border: #2A2E39;\r\n --tcw-text: #d1d4dc;\r\n --tcw-text-dim: #b2b5be;\r\n --tcw-text-muted: #787b86;\r\n --tcw-accent: #2962ff;\r\n --tcw-accent-dim: rgba(41,98,255,0.15);\r\n --tcw-accent-glow: rgba(41,98,255,0.12);\r\n --tcw-red: #ef5350;\r\n --tcw-green: #26a69a;\r\n --tcw-transition: 0.15s ease;\r\n --tcw-radius-lg: 8px;\r\n --tcw-font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;\r\n --tcw-hover-bg: rgba(255,255,255,0.04);\r\n}\r\n\r\n.tcw-root[data-tcw-theme=\"light\"] {\r\n color: #131722;\r\n background: #ffffff;\r\n\r\n --tcw-bg: #ffffff;\r\n --tcw-bg-elevated: #f0f3fa;\r\n --tcw-border: #e0e3eb;\r\n --tcw-text: #131722;\r\n --tcw-text-dim: #434651;\r\n --tcw-text-muted: #787b86;\r\n --tcw-accent: #2962ff;\r\n --tcw-accent-dim: rgba(41,98,255,0.1);\r\n --tcw-accent-glow: rgba(41,98,255,0.08);\r\n --tcw-red: #ef5350;\r\n --tcw-green: #26a69a;\r\n --tcw-hover-bg: rgba(0,0,0,0.04);\r\n}\r\n\r\n/* === Toolbar === */\r\n\r\n.tcw-toolbar {\r\n display: flex;\r\n align-items: center;\r\n gap: 0;\r\n padding: 0 12px;\r\n height: 40px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n background: var(--tcw-bg-elevated);\r\n flex-shrink: 0;\r\n position: relative;\r\n z-index: 20;\r\n}\r\n\r\n.tcw-toolbar-symbol {\r\n font-size: 13px;\r\n font-weight: 700;\r\n color: var(--tcw-text);\r\n padding: 0 10px;\r\n white-space: nowrap;\r\n letter-spacing: -0.01em;\r\n cursor: pointer;\r\n border: none;\r\n background: none;\r\n font-family: inherit;\r\n}\r\n\r\n.tcw-toolbar-sep {\r\n width: 1px;\r\n height: 20px;\r\n background: var(--tcw-border);\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-toolbar-group {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n padding: 0 8px;\r\n}\r\n\r\n.tcw-toolbar-spacer {\r\n flex: 1;\r\n}\r\n\r\n.tcw-btn {\r\n padding: 4px 8px;\r\n font-size: 12px;\r\n font-family: inherit;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n transition: all var(--tcw-transition);\r\n white-space: nowrap;\r\n line-height: 1;\r\n}\r\n\r\n.tcw-btn:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-btn.tcw-active {\r\n background: var(--tcw-accent);\r\n color: white;\r\n}\r\n\r\n.tcw-btn-icon {\r\n width: 32px;\r\n height: 32px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-family: inherit;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n transition: all var(--tcw-transition);\r\n line-height: 1;\r\n position: relative;\r\n}\r\n\r\n.tcw-btn-icon:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-badge-count {\r\n font-size: 10px;\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-dim);\r\n padding: 0 4px;\r\n border-radius: 8px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-indicator-chips {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 0 4px;\r\n flex-wrap: nowrap;\r\n overflow: hidden;\r\n}\r\n\r\n.tcw-indicator-chip {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 2px 6px 2px 8px;\r\n font-size: 11px;\r\n font-weight: 500;\r\n background: var(--tcw-accent-dim);\r\n color: var(--tcw-accent);\r\n border-radius: 4px;\r\n white-space: nowrap;\r\n line-height: 1.4;\r\n}\r\n\r\n.tcw-chip-remove {\r\n cursor: pointer;\r\n opacity: 0.6;\r\n padding: 0 2px;\r\n transition: opacity var(--tcw-transition);\r\n border: none;\r\n background: none;\r\n color: inherit;\r\n display: inline-flex;\r\n align-items: center;\r\n}\r\n\r\n.tcw-chip-remove:hover {\r\n opacity: 1;\r\n}\r\n\r\n/* === Dropdown === */\r\n\r\n.tcw-dropdown-trigger {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n font-size: 12px;\r\n font-family: inherit;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n transition: all var(--tcw-transition);\r\n white-space: nowrap;\r\n line-height: 1;\r\n}\r\n\r\n.tcw-dropdown-trigger:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-dropdown {\r\n position: absolute;\r\n top: 100%;\r\n margin-top: 4px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\r\n z-index: 50;\r\n padding: 4px 0;\r\n max-height: 400px;\r\n overflow-y: auto;\r\n}\r\n\r\n.tcw-dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 6px 12px;\r\n font-size: 12px;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n transition: background var(--tcw-transition), color var(--tcw-transition);\r\n width: 100%;\r\n border: none;\r\n background: none;\r\n font-family: inherit;\r\n text-align: left;\r\n}\r\n\r\n.tcw-dropdown-item:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-dropdown-item.tcw-active {\r\n color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-dropdown-label {\r\n text-transform: uppercase;\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n letter-spacing: 0.05em;\r\n padding: 6px 12px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-dropdown-divider {\r\n border-top: 1px solid var(--tcw-border);\r\n margin: 4px 0;\r\n}\r\n\r\n.tcw-tag {\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n padding: 1px 5px;\r\n border-radius: 3px;\r\n background: var(--tcw-hover-bg);\r\n}\r\n\r\n/* === Body === */\r\n\r\n.tcw-body {\r\n display: flex;\r\n flex: 1;\r\n min-height: 0;\r\n}\r\n\r\n.tcw-chart-container {\r\n flex: 1;\r\n min-width: 0;\r\n min-height: 0;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n/* === Sidebar === */\r\n\r\n.tcw-sidebar {\r\n width: 36px;\r\n flex-shrink: 0;\r\n background: var(--tcw-bg-elevated);\r\n border-right: 1px solid var(--tcw-border);\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 4px 0;\r\n overflow: visible;\r\n}\r\n\r\n.tcw-tool-group-wrap {\r\n position: relative;\r\n}\r\n\r\n.tcw-sidebar-btn {\r\n width: 36px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: all var(--tcw-transition);\r\n position: relative;\r\n flex-shrink: 0;\r\n line-height: 1;\r\n}\r\n\r\n.tcw-sidebar-btn:hover {\r\n color: var(--tcw-text);\r\n background: var(--tcw-hover-bg);\r\n}\r\n\r\n.tcw-sidebar-btn.tcw-active {\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-glow);\r\n}\r\n\r\n.tcw-sidebar-btn.tcw-danger:hover {\r\n color: var(--tcw-red);\r\n background: rgba(239,68,68,0.1);\r\n}\r\n\r\n.tcw-multi-dot {\r\n position: absolute;\r\n bottom: 2px;\r\n right: 2px;\r\n width: 4px;\r\n height: 4px;\r\n border-radius: 50%;\r\n background: var(--tcw-text-muted);\r\n}\r\n\r\n.tcw-sidebar-divider {\r\n width: 20px;\r\n height: 1px;\r\n background: var(--tcw-border);\r\n margin: 4px 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-sidebar-spacer {\r\n flex: 1;\r\n}\r\n\r\n/* === Flyout === */\r\n\r\n.tcw-flyout {\r\n position: absolute;\r\n left: 100%;\r\n top: 0;\r\n margin-left: 2px;\r\n min-width: 160px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\r\n z-index: 30;\r\n padding: 4px 0;\r\n}\r\n\r\n.tcw-flyout-header {\r\n text-transform: uppercase;\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n letter-spacing: 0.05em;\r\n padding: 6px 12px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-flyout-item {\r\n padding: 6px 12px;\r\n font-size: 12px;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n width: 100%;\r\n display: block;\r\n border: none;\r\n background: none;\r\n text-align: left;\r\n font-family: inherit;\r\n transition: background var(--tcw-transition), color var(--tcw-transition);\r\n}\r\n\r\n.tcw-flyout-item:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-flyout-item.tcw-active {\r\n color: var(--tcw-accent);\r\n}\r\n\r\n/* === Modal === */\r\n\r\n.tcw-modal-backdrop {\r\n position: fixed;\r\n inset: 0;\r\n background: rgba(0,0,0,0.5);\r\n backdrop-filter: blur(4px);\r\n -webkit-backdrop-filter: blur(4px);\r\n z-index: 100;\r\n}\r\n\r\n.tcw-modal {\r\n position: fixed;\r\n z-index: 101;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-lg);\r\n width: 480px;\r\n max-width: 90vw;\r\n max-height: 80vh;\r\n display: flex;\r\n flex-direction: column;\r\n box-shadow: 0 24px 64px rgba(0,0,0,0.5);\r\n}\r\n\r\n.tcw-modal-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 16px 20px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n\r\n.tcw-modal-header h3 {\r\n font-size: 15px;\r\n font-weight: 600;\r\n margin: 0;\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-modal-close {\r\n width: 28px;\r\n height: 28px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n border-radius: 4px;\r\n transition: all var(--tcw-transition);\r\n}\r\n\r\n.tcw-modal-close:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-modal-tabs {\r\n display: flex;\r\n gap: 0;\r\n padding: 0 20px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n\r\n.tcw-modal-tab {\r\n padding: 10px 16px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n color: var(--tcw-text-muted);\r\n border: none;\r\n background: none;\r\n cursor: pointer;\r\n border-bottom: 2px solid transparent;\r\n margin-bottom: -1px;\r\n transition: color var(--tcw-transition);\r\n font-family: inherit;\r\n text-transform: capitalize;\r\n}\r\n\r\n.tcw-modal-tab:hover {\r\n color: var(--tcw-text-dim);\r\n}\r\n\r\n.tcw-modal-tab.tcw-active {\r\n color: var(--tcw-accent);\r\n border-bottom-color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-modal-body {\r\n padding: 20px;\r\n overflow-y: auto;\r\n flex: 1;\r\n}\r\n\r\n.tcw-settings-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.tcw-settings-section:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.tcw-settings-section-title {\r\n font-size: 11px;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n color: var(--tcw-text-muted);\r\n margin-bottom: 12px;\r\n}\r\n\r\n.tcw-settings-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 0;\r\n}\r\n\r\n.tcw-settings-row + .tcw-settings-row {\r\n border-top: 1px solid rgba(255,255,255,0.03);\r\n}\r\n\r\n.tcw-root[data-tcw-theme=\"light\"] .tcw-settings-row + .tcw-settings-row {\r\n border-top: 1px solid rgba(0,0,0,0.04);\r\n}\r\n\r\n.tcw-settings-label {\r\n font-size: 13px;\r\n color: var(--tcw-text-dim);\r\n}\r\n\r\n.tcw-color-picker-wrap {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n}\r\n\r\n.tcw-color-picker-wrap input[type='color'] {\r\n width: 28px;\r\n height: 28px;\r\n border: 1px solid var(--tcw-border);\r\n border-radius: 4px;\r\n background: none;\r\n cursor: pointer;\r\n padding: 2px;\r\n}\r\n\r\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {\r\n padding: 0;\r\n}\r\n\r\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {\r\n border: none;\r\n border-radius: 2px;\r\n}\r\n\r\n.tcw-color-hex {\r\n font-size: 11px;\r\n font-family: var(--tcw-font-mono);\r\n color: var(--tcw-text-muted);\r\n min-width: 60px;\r\n}\r\n\r\n.tcw-toggle {\r\n width: 36px;\r\n height: 20px;\r\n background: rgba(255,255,255,0.1);\r\n border-radius: 10px;\r\n position: relative;\r\n cursor: pointer;\r\n transition: background var(--tcw-transition);\r\n border: none;\r\n padding: 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-toggle::after {\r\n content: '';\r\n position: absolute;\r\n top: 2px;\r\n left: 2px;\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n background: var(--tcw-text-muted);\r\n transition: all var(--tcw-transition);\r\n}\r\n\r\n.tcw-toggle.tcw-on {\r\n background: var(--tcw-accent);\r\n}\r\n\r\n.tcw-toggle.tcw-on::after {\r\n left: 18px;\r\n background: white;\r\n}\r\n\r\n.tcw-root[data-tcw-theme=\"light\"] .tcw-toggle {\r\n background: rgba(0,0,0,0.1);\r\n}\r\n\r\n.tcw-root[data-tcw-theme=\"light\"] .tcw-toggle::after {\r\n background: #888;\r\n}\r\n\r\n.tcw-root[data-tcw-theme=\"light\"] .tcw-toggle.tcw-on {\r\n background: var(--tcw-accent);\r\n}\r\n\r\n.tcw-root[data-tcw-theme=\"light\"] .tcw-toggle.tcw-on::after {\r\n background: white;\r\n}\r\n\r\n.tcw-settings-select {\r\n padding: 4px 8px;\r\n font-size: 12px;\r\n font-family: inherit;\r\n background: var(--tcw-bg);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: 4px;\r\n color: var(--tcw-text);\r\n cursor: pointer;\r\n}\r\n\r\n.tcw-modal-footer {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 20px;\r\n border-top: 1px solid var(--tcw-border);\r\n}\r\n\r\n.tcw-reset-link {\r\n font-size: 12px;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n border: none;\r\n background: none;\r\n font-family: inherit;\r\n text-decoration: underline;\r\n text-underline-offset: 2px;\r\n transition: color var(--tcw-transition);\r\n}\r\n\r\n.tcw-reset-link:hover {\r\n color: var(--tcw-text-dim);\r\n}\r\n\r\n.tcw-done-btn {\r\n padding: 6px 16px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n background: var(--tcw-accent);\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: background var(--tcw-transition);\r\n}\r\n\r\n.tcw-done-btn:hover {\r\n background: #2563eb;\r\n}\r\n\r\n/* === Status Bar === */\r\n\r\n.tcw-statusbar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 6px 16px;\r\n border-top: 1px solid var(--tcw-border);\r\n background: var(--tcw-bg-elevated);\r\n font-size: 11px;\r\n color: var(--tcw-text-muted);\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-status-indicator {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n}\r\n\r\n.tcw-status-dot {\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n background: var(--tcw-text-muted);\r\n transition: background 0.3s;\r\n}\r\n\r\n.tcw-status-dot.tcw-connected {\r\n background: var(--tcw-green);\r\n}\r\n\r\n.tcw-status-dot.tcw-error {\r\n background: var(--tcw-red);\r\n}\r\n\r\n/* === Command Palette === */\r\n\r\n.tcw-cmd-palette {\r\n position: fixed;\r\n z-index: 102;\r\n top: 20%;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-lg);\r\n width: 520px;\r\n max-width: 90vw;\r\n max-height: 60vh;\r\n display: flex;\r\n flex-direction: column;\r\n box-shadow: 0 24px 64px rgba(0,0,0,0.5);\r\n overflow: hidden;\r\n}\r\n\r\n.tcw-cmd-header {\r\n display: flex;\r\n align-items: center;\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n gap: 10px;\r\n}\r\n\r\n.tcw-cmd-icon {\r\n font-size: 18px;\r\n color: var(--tcw-text-muted);\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-cmd-input {\r\n flex: 1;\r\n background: none;\r\n border: none;\r\n outline: none;\r\n font-size: 14px;\r\n font-family: inherit;\r\n color: var(--tcw-text);\r\n caret-color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-cmd-input::placeholder {\r\n color: var(--tcw-text-muted);\r\n}\r\n\r\n.tcw-cmd-hint {\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n border: 1px solid var(--tcw-border);\r\n padding: 2px 6px;\r\n border-radius: 3px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-cmd-list {\r\n overflow-y: auto;\r\n flex: 1;\r\n padding: 4px 0;\r\n max-height: 360px;\r\n}\r\n\r\n.tcw-cmd-category {\r\n text-transform: uppercase;\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n letter-spacing: 0.05em;\r\n padding: 8px 16px 4px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-cmd-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 16px;\r\n font-size: 13px;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n width: 100%;\r\n border: none;\r\n background: none;\r\n font-family: inherit;\r\n text-align: left;\r\n transition: background 80ms ease;\r\n gap: 8px;\r\n}\r\n\r\n.tcw-cmd-item:hover,\r\n.tcw-cmd-item.tcw-selected {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-cmd-item.tcw-active .tcw-cmd-item-label {\r\n color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-cmd-item-label {\r\n flex: 1;\r\n}\r\n\r\n.tcw-cmd-check {\r\n color: var(--tcw-accent);\r\n font-size: 14px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-cmd-kbd {\r\n font-size: 10px;\r\n font-family: var(--tcw-font-mono);\r\n color: var(--tcw-text-muted);\r\n background: var(--tcw-bg);\r\n border: 1px solid var(--tcw-border);\r\n padding: 1px 5px;\r\n border-radius: 3px;\r\n}\r\n\r\n.tcw-cmd-empty {\r\n padding: 24px 16px;\r\n text-align: center;\r\n color: var(--tcw-text-muted);\r\n font-size: 13px;\r\n}\r\n\r\n.tcw-cmd-footer {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n padding: 8px 16px;\r\n border-top: 1px solid var(--tcw-border);\r\n font-size: 11px;\r\n color: var(--tcw-text-muted);\r\n}\r\n\r\n/* === Responsive === */\r\n\r\n@media (max-width: 768px) {\r\n .tcw-toolbar {\r\n padding: 0 8px;\r\n height: 36px;\r\n }\r\n .tcw-toolbar-sep {\r\n display: none;\r\n }\r\n .tcw-indicator-chips {\r\n display: none;\r\n }\r\n .tcw-sidebar {\r\n width: 32px;\r\n }\r\n .tcw-sidebar-btn {\r\n width: 32px;\r\n height: 28px;\r\n }\r\n}\r\n", d = 0, f = "tcw-styles";
385
+ function p() {
386
+ if (d++, d > 1 || document.getElementById(f)) return;
387
+ let e = document.createElement("style");
388
+ e.id = f, e.textContent = u, document.head.appendChild(e);
389
+ }
390
+ function m() {
391
+ if (d--, d > 0) return;
392
+ let e = document.getElementById(f);
393
+ e && e.remove();
394
+ }
395
+ //#endregion
396
+ //#region src/widget/icons.ts
397
+ var h = {
398
+ cursor: "<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>",
399
+ trendingUp: "<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>",
400
+ minus: "<path d=\"M5 12h14\"/>",
401
+ penLine: "<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>",
402
+ hash: "<line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"4\" y1=\"15\" x2=\"20\" y2=\"15\"/><line x1=\"10\" y1=\"3\" x2=\"8\" y2=\"21\"/><line x1=\"16\" y1=\"3\" x2=\"14\" y2=\"21\"/>",
403
+ square: "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>",
404
+ gitBranch: "<line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>",
405
+ ruler: "<path d=\"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z\"/><path d=\"m14.5 12.5 2-2\"/><path d=\"m11.5 9.5 2-2\"/><path d=\"m8.5 6.5 2-2\"/><path d=\"m17.5 15.5 2-2\"/>",
406
+ type: "<polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"9\" y1=\"20\" x2=\"15\" y2=\"20\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/>",
407
+ magnet: "<path d=\"m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15\"/><path d=\"m5 8 4 4\"/><path d=\"m12 15 4 4\"/>",
408
+ undo: "<path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/>",
409
+ redo: "<path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/>",
410
+ trash: "<path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/>",
411
+ camera: "<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/>",
412
+ settings: "<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>",
413
+ moon: "<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>",
414
+ sun: "<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2\"/><path d=\"M12 20v2\"/><path d=\"m4.93 4.93 1.41 1.41\"/><path d=\"m17.66 17.66 1.41 1.41\"/><path d=\"M2 12h2\"/><path d=\"M20 12h2\"/><path d=\"m6.34 17.66-1.41 1.41\"/><path d=\"m19.07 4.93-1.41 1.41\"/>",
415
+ chevronDown: "<path d=\"m6 9 6 6 6-6\"/>",
416
+ chevronUp: "<path d=\"m18 15-6-6-6 6\"/>",
417
+ barChart: "<line x1=\"12\" y1=\"20\" x2=\"12\" y2=\"10\"/><line x1=\"18\" y1=\"20\" x2=\"18\" y2=\"4\"/><line x1=\"6\" y1=\"20\" x2=\"6\" y2=\"16\"/>",
418
+ x: "<path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/>",
419
+ play: "<polygon points=\"6 3 20 12 6 21 6 3\"/>",
420
+ pause: "<rect width=\"4\" height=\"16\" x=\"6\" y=\"4\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"4\"/>",
421
+ stop: "<rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"1\"/>",
422
+ receipt: "<path d=\"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z\"/><path d=\"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\"/><path d=\"M12 17.5v-11\"/>"
423
+ };
424
+ function g(e, t = 14) {
425
+ let n = h[e];
426
+ return n ? `<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>` : "";
427
+ }
428
+ //#endregion
429
+ //#region src/widget/WidgetDropdown.ts
430
+ var _ = class {
431
+ trigger;
432
+ panel;
433
+ _isOpen = !1;
434
+ onOutsideClick;
435
+ onEscapeKey;
436
+ onTriggerClick;
437
+ constructor(e, t = {}) {
438
+ this.trigger = e, this.panel = document.createElement("div"), this.panel.className = "tcw-dropdown", this.panel.style.width = t.width ?? "200px", t.align === "right" ? this.panel.style.right = "0" : this.panel.style.left = "0", this.panel.style.display = "none", e.style.position = "relative", e.appendChild(this.panel), this.onTriggerClick = () => {
439
+ this._isOpen ? this.close() : this.open();
440
+ }, this.onOutsideClick = (e) => {
441
+ this.trigger.contains(e.target) || this.close();
442
+ }, this.onEscapeKey = (e) => {
443
+ e.key === "Escape" && this.close();
444
+ }, e.addEventListener("click", this.onTriggerClick);
445
+ }
446
+ setContent(e) {
447
+ this.panel.innerHTML = e;
448
+ }
449
+ open() {
450
+ this._isOpen || (this._isOpen = !0, this.panel.style.display = "", document.addEventListener("mousedown", this.onOutsideClick), document.addEventListener("keydown", this.onEscapeKey));
451
+ }
452
+ close() {
453
+ this._isOpen && (this._isOpen = !1, this.panel.style.display = "none", document.removeEventListener("mousedown", this.onOutsideClick), document.removeEventListener("keydown", this.onEscapeKey));
454
+ }
455
+ isOpen() {
456
+ return this._isOpen;
457
+ }
458
+ destroy() {
459
+ this.trigger.removeEventListener("click", this.onTriggerClick), document.removeEventListener("mousedown", this.onOutsideClick), document.removeEventListener("keydown", this.onEscapeKey), this.panel.remove();
460
+ }
461
+ }, v = class {
462
+ config;
463
+ callbacks;
464
+ el;
465
+ chartTypeDropdown = null;
466
+ indicatorDropdown = null;
467
+ tfButtons = [];
468
+ chipsContainer = null;
469
+ themeBtn = null;
470
+ constructor(e, t, n) {
471
+ this.config = t, this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-toolbar", this.build(), e.appendChild(this.el);
472
+ }
473
+ build() {
474
+ let { config: e, callbacks: t, el: n } = this, r = document.createElement("button");
475
+ r.className = "tcw-toolbar-symbol", r.dataset.role = "symbol", r.addEventListener("click", t.onSymbolClick), n.appendChild(r), n.appendChild(this.sep());
476
+ let i = document.createElement("div");
477
+ i.className = "tcw-toolbar-group";
478
+ for (let n of e.timeframes) {
479
+ let e = document.createElement("button");
480
+ e.className = "tcw-btn", e.textContent = n.label, e.dataset.tf = n.value, e.addEventListener("click", () => t.onTimeframe(n.value)), i.appendChild(e), this.tfButtons.push(e);
481
+ }
482
+ n.appendChild(i), n.appendChild(this.sep());
483
+ let a = document.createElement("div");
484
+ a.style.position = "relative", a.style.display = "inline-flex";
485
+ let o = document.createElement("button");
486
+ o.className = "tcw-dropdown-trigger", o.dataset.role = "charttype", a.appendChild(o), n.appendChild(a), this.chartTypeDropdown = new _(a, { width: "160px" }), this.buildChartTypeMenu(), n.appendChild(this.sep());
487
+ let s = document.createElement("div");
488
+ s.style.position = "relative", s.style.display = "inline-flex";
489
+ let c = document.createElement("button");
490
+ c.className = "tcw-dropdown-trigger", c.dataset.role = "indicators", s.appendChild(c), n.appendChild(s), this.indicatorDropdown = new _(s, { width: "280px" }), this.buildIndicatorMenu(), this.chipsContainer = document.createElement("div"), this.chipsContainer.className = "tcw-indicator-chips", n.appendChild(this.chipsContainer), n.appendChild(this.spacer());
491
+ let l = this.iconBtn("camera", "Screenshot", t.onScreenshot);
492
+ n.appendChild(l);
493
+ let u = this.iconBtn("settings", "Chart Settings", t.onSettings);
494
+ n.appendChild(u), this.themeBtn = this.iconBtn("moon", "Toggle theme", t.onToggleTheme), this.themeBtn.dataset.role = "theme", n.appendChild(this.themeBtn);
495
+ }
496
+ buildChartTypeMenu() {
497
+ if (!this.chartTypeDropdown) return;
498
+ let e = this.config.chartTypes.map((e) => `<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join("");
499
+ this.chartTypeDropdown.setContent(e), this.chartTypeDropdown.panel.querySelectorAll(".tcw-dropdown-item").forEach((e) => {
500
+ e.addEventListener("click", (e) => {
501
+ let t = e.currentTarget.dataset.ct;
502
+ this.callbacks.onChartType(t), this.chartTypeDropdown?.close();
503
+ });
504
+ });
505
+ }
506
+ buildIndicatorMenu() {
507
+ if (!this.indicatorDropdown) return;
508
+ let { indicators: e, popularIndicatorIds: t } = this.config, n = e.filter((e) => t.includes(e.id)), r = e.filter((e) => !t.includes(e.id)), i = "<div class=\"tcw-dropdown-label\">Popular</div>";
509
+ for (let e of n) i += `<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;
510
+ i += "<div class=\"tcw-dropdown-divider\"></div>", i += "<div class=\"tcw-dropdown-label\">All</div>";
511
+ for (let e of r) i += `<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;
512
+ this.indicatorDropdown.setContent(i), this.indicatorDropdown.panel.querySelectorAll(".tcw-dropdown-item[data-ind]").forEach((e) => {
513
+ e.addEventListener("click", (e) => {
514
+ let t = e.currentTarget.dataset.ind;
515
+ this.callbacks.onAddIndicator(t);
516
+ });
517
+ });
518
+ }
519
+ update(e) {
520
+ let t = this.el.querySelector("[data-role=\"symbol\"]");
521
+ t && (t.textContent = e.symbol);
522
+ for (let t of this.tfButtons) t.classList.toggle("tcw-active", t.dataset.tf === e.timeframe);
523
+ let n = this.el.querySelector("[data-role=\"charttype\"]");
524
+ if (n) {
525
+ let t = this.config.chartTypes.find((t) => t.value === e.chartType)?.label ?? "Candles";
526
+ n.innerHTML = `${g("barChart", 14)} ${t} ${g("chevronDown", 12)}`;
527
+ }
528
+ let r = this.el.querySelector("[data-role=\"indicators\"]");
529
+ if (r) {
530
+ let t = e.activeIndicators.size, n = `${g("trendingUp", 14)} Indicators`;
531
+ t > 0 && (n += ` <span class="tcw-badge-count">${t}</span>`), r.innerHTML = n;
532
+ }
533
+ if (this.chipsContainer) {
534
+ let t = this.getActiveIndicatorList(e);
535
+ this.chipsContainer.innerHTML = "";
536
+ for (let e of t) {
537
+ let t = document.createElement("div");
538
+ t.className = "tcw-indicator-chip";
539
+ let n = document.createElement("span");
540
+ n.textContent = e.label, t.appendChild(n);
541
+ let r = document.createElement("button");
542
+ r.className = "tcw-chip-remove", r.innerHTML = g("x", 10), r.addEventListener("click", () => this.callbacks.onRemoveIndicator(e.instanceId)), t.appendChild(r), this.chipsContainer.appendChild(t);
543
+ }
544
+ }
545
+ this.themeBtn && (this.themeBtn.innerHTML = e.isDark ? g("moon", 14) : g("sun", 14));
546
+ }
547
+ getActiveIndicatorList(e) {
548
+ let t = [];
549
+ for (let [n, r] of e.activeIndicators.entries()) t.push({
550
+ instanceId: r,
551
+ id: n,
552
+ label: n.toUpperCase()
553
+ });
554
+ return t;
555
+ }
556
+ sep() {
557
+ let e = document.createElement("span");
558
+ return e.className = "tcw-toolbar-sep", e;
559
+ }
560
+ spacer() {
561
+ let e = document.createElement("span");
562
+ return e.className = "tcw-toolbar-spacer", e;
563
+ }
564
+ iconBtn(e, t, n) {
565
+ let r = document.createElement("button");
566
+ return r.className = "tcw-btn-icon", r.title = t, r.innerHTML = g(e, 14), r.addEventListener("click", n), r;
567
+ }
568
+ destroy() {
569
+ this.chartTypeDropdown?.destroy(), this.indicatorDropdown?.destroy(), this.el.remove();
570
+ }
571
+ }, y = [
572
+ "trendingUp",
573
+ "minus",
574
+ "penLine",
575
+ "hash",
576
+ "square",
577
+ "gitBranch",
578
+ "ruler",
579
+ "type"
580
+ ], b = class {
581
+ config;
582
+ callbacks;
583
+ el;
584
+ groupWraps = [];
585
+ groupButtons = [];
586
+ cursorBtn = null;
587
+ magnetBtn = null;
588
+ flyoutEl = null;
589
+ constructor(e, t, n) {
590
+ this.config = t, this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-sidebar", this.build(), e.appendChild(this.el);
591
+ }
592
+ build() {
593
+ let { config: e, callbacks: t, el: n } = this;
594
+ this.cursorBtn = document.createElement("button"), this.cursorBtn.className = "tcw-sidebar-btn", this.cursorBtn.title = "Cursor", this.cursorBtn.innerHTML = g("cursor", 14), this.cursorBtn.addEventListener("click", t.onCancelDrawing), n.appendChild(this.cursorBtn), n.appendChild(this.divider()), e.drawingToolGroups.forEach((e, r) => {
595
+ let i = document.createElement("div");
596
+ i.className = "tcw-tool-group-wrap";
597
+ let a = document.createElement("button");
598
+ if (a.className = "tcw-sidebar-btn", a.title = e.label, a.innerHTML = g(y[r] ?? "square", 14), e.tools.length > 1) {
599
+ let e = document.createElement("span");
600
+ e.className = "tcw-multi-dot", a.appendChild(e);
601
+ }
602
+ a.addEventListener("click", () => t.onDrawingTool(e.tools[0].value)), i.appendChild(a), i.addEventListener("mouseenter", () => this.showFlyout(r)), i.addEventListener("mouseleave", () => this.hideFlyout()), n.appendChild(i), this.groupWraps.push(i), this.groupButtons.push(a);
603
+ });
604
+ let r = document.createElement("div");
605
+ r.className = "tcw-sidebar-spacer", n.appendChild(r), n.appendChild(this.divider()), this.magnetBtn = document.createElement("button"), this.magnetBtn.className = "tcw-sidebar-btn", this.magnetBtn.title = "Magnet", this.magnetBtn.innerHTML = g("magnet", 14), this.magnetBtn.addEventListener("click", t.onToggleMagnet), n.appendChild(this.magnetBtn);
606
+ let i = document.createElement("button");
607
+ i.className = "tcw-sidebar-btn", i.title = "Undo", i.innerHTML = g("undo", 14), i.addEventListener("click", t.onUndo), n.appendChild(i);
608
+ let a = document.createElement("button");
609
+ a.className = "tcw-sidebar-btn", a.title = "Redo", a.innerHTML = g("redo", 14), a.addEventListener("click", t.onRedo), n.appendChild(a);
610
+ let o = document.createElement("button");
611
+ o.className = "tcw-sidebar-btn tcw-danger", o.title = "Clear all", o.innerHTML = g("trash", 14), o.addEventListener("click", t.onClearDrawings), n.appendChild(o);
612
+ }
613
+ showFlyout(e) {
614
+ let t = this.config.drawingToolGroups[e];
615
+ if (!t || t.tools.length <= 1) return;
616
+ this.hideFlyout();
617
+ let n = document.createElement("div");
618
+ n.className = "tcw-flyout";
619
+ let r = document.createElement("div");
620
+ r.className = "tcw-flyout-header", r.textContent = t.label, n.appendChild(r);
621
+ for (let e of t.tools) {
622
+ let t = document.createElement("button");
623
+ t.className = "tcw-flyout-item", t.textContent = e.label, t.dataset.toolValue = e.value, t.addEventListener("click", () => {
624
+ this.callbacks.onDrawingTool(e.value), this.hideFlyout();
625
+ }), n.appendChild(t);
626
+ }
627
+ this.flyoutEl = n, this.groupWraps[e].appendChild(n);
628
+ }
629
+ hideFlyout() {
630
+ this.flyoutEl &&= (this.flyoutEl.remove(), null);
631
+ }
632
+ update(e) {
633
+ this.cursorBtn && this.cursorBtn.classList.toggle("tcw-active", e.activeTool === null);
634
+ let { drawingToolGroups: t } = this.config;
635
+ for (let n = 0; n < t.length; n++) {
636
+ let r = t[n].tools.some((t) => t.value === e.activeTool);
637
+ this.groupButtons[n].classList.toggle("tcw-active", r);
638
+ }
639
+ this.flyoutEl && this.flyoutEl.querySelectorAll(".tcw-flyout-item").forEach((t) => {
640
+ let n = t;
641
+ n.classList.toggle("tcw-active", n.dataset.toolValue === e.activeTool);
642
+ }), this.magnetBtn && (this.magnetBtn.classList.toggle("tcw-active", e.magnetEnabled), this.magnetBtn.title = e.magnetEnabled ? "Magnet ON" : "Magnet OFF");
643
+ }
644
+ divider() {
645
+ let e = document.createElement("div");
646
+ return e.className = "tcw-sidebar-divider", e;
647
+ }
648
+ destroy() {
649
+ this.hideFlyout(), this.el.remove();
650
+ }
651
+ }, x = [
652
+ "style",
653
+ "display",
654
+ "scale"
655
+ ], S = class {
656
+ callbacks;
657
+ backdrop = null;
658
+ modal = null;
659
+ currentTab = "style";
660
+ currentSettings = null;
661
+ bodyEl = null;
662
+ tabButtons = [];
663
+ constructor(e) {
664
+ this.callbacks = e;
665
+ }
666
+ open(e) {
667
+ this.currentSettings = { ...e }, this.currentTab = "style", this.buildModal();
668
+ }
669
+ close() {
670
+ this.backdrop?.remove(), this.modal?.remove(), this.backdrop = null, this.modal = null, this.bodyEl = null, this.tabButtons = [];
671
+ }
672
+ buildModal() {
673
+ this.backdrop = document.createElement("div"), this.backdrop.className = "tcw-modal-backdrop", this.backdrop.addEventListener("click", () => {
674
+ this.callbacks.onClose(), this.close();
675
+ }), document.body.appendChild(this.backdrop), this.modal = document.createElement("div"), this.modal.className = "tcw-modal";
676
+ let e = document.createElement("div");
677
+ e.className = "tcw-modal-header";
678
+ let t = document.createElement("h3");
679
+ t.textContent = "Chart Settings", e.appendChild(t);
680
+ let n = document.createElement("button");
681
+ n.className = "tcw-modal-close", n.innerHTML = g("x", 16), n.addEventListener("click", () => {
682
+ this.callbacks.onClose(), this.close();
683
+ }), e.appendChild(n), this.modal.appendChild(e);
684
+ let r = document.createElement("div");
685
+ r.className = "tcw-modal-tabs", this.tabButtons = [];
686
+ for (let e of x) {
687
+ let t = document.createElement("button");
688
+ t.className = "tcw-modal-tab", t.textContent = e, t.dataset.tab = e, e === this.currentTab && t.classList.add("tcw-active"), t.addEventListener("click", () => {
689
+ this.currentTab = e, this.tabButtons.forEach((t) => t.classList.toggle("tcw-active", t.dataset.tab === e)), this.renderTabContent();
690
+ }), r.appendChild(t), this.tabButtons.push(t);
691
+ }
692
+ this.modal.appendChild(r), this.bodyEl = document.createElement("div"), this.bodyEl.className = "tcw-modal-body", this.modal.appendChild(this.bodyEl), this.renderTabContent();
693
+ let i = document.createElement("div");
694
+ i.className = "tcw-modal-footer";
695
+ let a = document.createElement("button");
696
+ a.className = "tcw-reset-link", a.textContent = "Reset to defaults", a.addEventListener("click", () => this.callbacks.onReset()), i.appendChild(a);
697
+ let o = document.createElement("button");
698
+ o.className = "tcw-done-btn", o.textContent = "Done", o.addEventListener("click", () => {
699
+ this.callbacks.onClose(), this.close();
700
+ }), i.appendChild(o), this.modal.appendChild(i), document.body.appendChild(this.modal);
701
+ let s = (e) => {
702
+ e.key === "Escape" && (document.removeEventListener("keydown", s), this.callbacks.onClose(), this.close());
703
+ };
704
+ document.addEventListener("keydown", s);
705
+ }
706
+ renderTabContent() {
707
+ if (!(!this.bodyEl || !this.currentSettings)) switch (this.bodyEl.innerHTML = "", this.currentTab) {
708
+ case "style":
709
+ this.renderStyleTab();
710
+ break;
711
+ case "display":
712
+ this.renderDisplayTab();
713
+ break;
714
+ case "scale":
715
+ this.renderScaleTab();
716
+ break;
717
+ }
718
+ }
719
+ renderStyleTab() {
720
+ if (!this.bodyEl || !this.currentSettings) return;
721
+ let e = this.currentSettings, t = this.section("Candle Colors");
722
+ t.appendChild(this.colorRow("Up Body", e.candleUpColor, (e) => this.patch({ candleUpColor: e }))), t.appendChild(this.colorRow("Down Body", e.candleDownColor, (e) => this.patch({ candleDownColor: e }))), t.appendChild(this.colorRow("Up Wick", e.candleUpWick, (e) => this.patch({ candleUpWick: e }))), t.appendChild(this.colorRow("Down Wick", e.candleDownWick, (e) => this.patch({ candleDownWick: e }))), this.bodyEl.appendChild(t);
723
+ let n = this.section("Background");
724
+ n.appendChild(this.colorRow("Background", e.backgroundColor, (e) => this.patch({ backgroundColor: e }))), n.appendChild(this.colorRow("Grid", e.gridColor, (e) => this.patch({ gridColor: e }))), this.bodyEl.appendChild(n);
725
+ }
726
+ renderDisplayTab() {
727
+ if (!this.bodyEl || !this.currentSettings) return;
728
+ let e = this.currentSettings, t = this.section();
729
+ t.appendChild(this.toggleRow("Grid Lines", e.gridVisible, (e) => this.patch({ gridVisible: e }))), t.appendChild(this.toggleRow("Volume", e.volumeVisible, (e) => this.patch({ volumeVisible: e }))), t.appendChild(this.toggleRow("OHLC Legend", e.legendVisible, (e) => this.patch({ legendVisible: e }))), t.appendChild(this.toggleRow("Bar Countdown", e.barCountdown, (e) => this.patch({ barCountdown: e }))), t.appendChild(this.selectRow("Crosshair Mode", e.crosshairMode, [
730
+ {
731
+ label: "Magnet",
732
+ value: "magnet"
733
+ },
734
+ {
735
+ label: "Normal",
736
+ value: "normal"
737
+ },
738
+ {
739
+ label: "Hidden",
740
+ value: "hidden"
741
+ }
742
+ ], (e) => this.patch({ crosshairMode: e }))), t.appendChild(this.selectRow("Number Locale", e.numberLocale, [
743
+ {
744
+ label: "en-US (65,234.00)",
745
+ value: "en-US"
746
+ },
747
+ {
748
+ label: "de-DE (65.234,00)",
749
+ value: "de-DE"
750
+ },
751
+ {
752
+ label: "fr-FR (65 234,00)",
753
+ value: "fr-FR"
754
+ },
755
+ {
756
+ label: "vi-VN (65.234,00)",
757
+ value: "vi-VN"
758
+ },
759
+ {
760
+ label: "en-IN (65,234.00)",
761
+ value: "en-IN"
762
+ },
763
+ {
764
+ label: "ja-JP (65,234.00)",
765
+ value: "ja-JP"
766
+ }
767
+ ], (e) => this.patch({ numberLocale: e }))), this.bodyEl.appendChild(t);
768
+ }
769
+ renderScaleTab() {
770
+ if (!this.bodyEl || !this.currentSettings) return;
771
+ let e = this.currentSettings, t = this.section();
772
+ t.appendChild(this.toggleRow("Auto Scale", e.autoScale, (e) => this.patch({ autoScale: e }))), t.appendChild(this.toggleRow("Log Scale", e.logScale, (e) => this.patch({ logScale: e }))), this.bodyEl.appendChild(t);
773
+ }
774
+ patch(e) {
775
+ this.currentSettings && Object.assign(this.currentSettings, e), this.callbacks.onChange(e);
776
+ }
777
+ section(e) {
778
+ let t = document.createElement("div");
779
+ if (t.className = "tcw-settings-section", e) {
780
+ let n = document.createElement("div");
781
+ n.className = "tcw-settings-section-title", n.textContent = e, t.appendChild(n);
782
+ }
783
+ return t;
784
+ }
785
+ colorRow(e, t, n) {
786
+ let r = document.createElement("div");
787
+ r.className = "tcw-settings-row";
788
+ let i = document.createElement("span");
789
+ i.className = "tcw-settings-label", i.textContent = e, r.appendChild(i);
790
+ let a = document.createElement("div");
791
+ a.className = "tcw-color-picker-wrap";
792
+ let o = document.createElement("input");
793
+ o.type = "color", o.value = t;
794
+ let s = document.createElement("span");
795
+ return s.className = "tcw-color-hex", s.textContent = t, o.addEventListener("input", () => {
796
+ s.textContent = o.value, n(o.value);
797
+ }), a.appendChild(o), a.appendChild(s), r.appendChild(a), r;
798
+ }
799
+ toggleRow(e, t, n) {
800
+ let r = document.createElement("div");
801
+ r.className = "tcw-settings-row";
802
+ let i = document.createElement("span");
803
+ i.className = "tcw-settings-label", i.textContent = e, r.appendChild(i);
804
+ let a = document.createElement("button");
805
+ return a.className = `tcw-toggle${t ? " tcw-on" : ""}`, a.addEventListener("click", () => {
806
+ let e = !a.classList.contains("tcw-on");
807
+ a.classList.toggle("tcw-on", e), n(e);
808
+ }), r.appendChild(a), r;
809
+ }
810
+ selectRow(e, t, n, r) {
811
+ let i = document.createElement("div");
812
+ i.className = "tcw-settings-row";
813
+ let a = document.createElement("span");
814
+ a.className = "tcw-settings-label", a.textContent = e, i.appendChild(a);
815
+ let o = document.createElement("select");
816
+ o.className = "tcw-settings-select";
817
+ for (let e of n) {
818
+ let n = document.createElement("option");
819
+ n.value = e.value, n.textContent = e.label, e.value === t && (n.selected = !0), o.appendChild(n);
820
+ }
821
+ return o.addEventListener("change", () => r(o.value)), i.appendChild(o), i;
822
+ }
823
+ destroy() {
824
+ this.close();
825
+ }
826
+ }, C = class {
827
+ el;
828
+ dotEl;
829
+ messageEl;
830
+ infoEl;
831
+ constructor(e) {
832
+ this.el = document.createElement("div"), this.el.className = "tcw-statusbar";
833
+ let t = document.createElement("div");
834
+ t.className = "tcw-status-indicator", this.dotEl = document.createElement("span"), this.dotEl.className = "tcw-status-dot", t.appendChild(this.dotEl), this.messageEl = document.createElement("span"), t.appendChild(this.messageEl), this.el.appendChild(t), this.infoEl = document.createElement("span"), this.el.appendChild(this.infoEl), e.appendChild(this.el);
835
+ }
836
+ update(e) {
837
+ this.dotEl.className = "tcw-status-dot", e.connectionState === "connected" ? this.dotEl.classList.add("tcw-connected") : e.connectionState === "error" && this.dotEl.classList.add("tcw-error"), this.messageEl.textContent = e.message, this.infoEl.textContent = `${e.symbol} ${e.timeframe}`;
838
+ }
839
+ destroy() {
840
+ this.el.remove();
841
+ }
842
+ }, w = class {
843
+ backdrop = null;
844
+ modal = null;
845
+ input = null;
846
+ list = null;
847
+ items = [];
848
+ filtered = [];
849
+ selectedIndex = 0;
850
+ callbacks;
851
+ boundKeydown;
852
+ constructor(e) {
853
+ this.callbacks = e, this.boundKeydown = this.handleKeydown.bind(this);
854
+ }
855
+ open(e) {
856
+ if (this.backdrop) return;
857
+ this.items = e, this.filtered = e, this.selectedIndex = 0, this.backdrop = document.createElement("div"), this.backdrop.className = "tcw-modal-backdrop", this.backdrop.addEventListener("click", () => this.close()), this.modal = document.createElement("div"), this.modal.className = "tcw-cmd-palette";
858
+ let t = document.createElement("div");
859
+ t.className = "tcw-cmd-header";
860
+ let n = document.createElement("span");
861
+ n.className = "tcw-cmd-icon", n.textContent = "⌕", t.appendChild(n), this.input = document.createElement("input"), this.input.className = "tcw-cmd-input", this.input.type = "text", this.input.placeholder = "Search indicators, chart types, tools...", this.input.addEventListener("input", () => this.filter()), t.appendChild(this.input);
862
+ let r = document.createElement("span");
863
+ r.className = "tcw-cmd-hint", r.textContent = "ESC", t.appendChild(r), this.modal.appendChild(t), this.list = document.createElement("div"), this.list.className = "tcw-cmd-list", this.modal.appendChild(this.list);
864
+ let i = document.createElement("div");
865
+ i.className = "tcw-cmd-footer", i.innerHTML = "<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>", this.modal.appendChild(i), document.body.appendChild(this.backdrop), document.body.appendChild(this.modal), this.renderList(), this.input.focus(), document.addEventListener("keydown", this.boundKeydown);
866
+ }
867
+ close() {
868
+ document.removeEventListener("keydown", this.boundKeydown), this.backdrop?.remove(), this.modal?.remove(), this.backdrop = null, this.modal = null, this.input = null, this.list = null, this.callbacks.onClose();
869
+ }
870
+ isOpen() {
871
+ return this.backdrop !== null;
872
+ }
873
+ filter() {
874
+ let e = this.input?.value.toLowerCase().trim() ?? "";
875
+ e ? this.filtered = this.items.filter((t) => t.label.toLowerCase().includes(e) || t.category.toLowerCase().includes(e) || t.id.toLowerCase().includes(e)) : this.filtered = this.items, this.selectedIndex = 0, this.renderList();
876
+ }
877
+ renderList() {
878
+ if (!this.list) return;
879
+ if (this.list.innerHTML = "", this.filtered.length === 0) {
880
+ let e = document.createElement("div");
881
+ e.className = "tcw-cmd-empty", e.textContent = "No results found", this.list.appendChild(e);
882
+ return;
883
+ }
884
+ let e = "";
885
+ for (let t = 0; t < this.filtered.length; t++) {
886
+ let n = this.filtered[t];
887
+ if (n.category !== e) {
888
+ e = n.category;
889
+ let t = document.createElement("div");
890
+ t.className = "tcw-cmd-category", t.textContent = this.categoryLabel(e), this.list.appendChild(t);
891
+ }
892
+ let r = document.createElement("button");
893
+ r.className = "tcw-cmd-item", t === this.selectedIndex && r.classList.add("tcw-selected"), n.active && r.classList.add("tcw-active"), r.dataset.index = String(t);
894
+ let i = document.createElement("span");
895
+ if (i.className = "tcw-cmd-item-label", i.textContent = n.label, r.appendChild(i), n.active) {
896
+ let e = document.createElement("span");
897
+ e.className = "tcw-cmd-check", e.textContent = "✓", r.appendChild(e);
898
+ }
899
+ if (n.shortcut) {
900
+ let e = document.createElement("kbd");
901
+ e.className = "tcw-cmd-kbd", e.textContent = n.shortcut, r.appendChild(e);
902
+ }
903
+ r.addEventListener("click", () => this.select(t)), r.addEventListener("mouseenter", () => {
904
+ this.selectedIndex = t, this.updateSelection();
905
+ }), this.list.appendChild(r);
906
+ }
907
+ }
908
+ updateSelection() {
909
+ if (!this.list) return;
910
+ let e = this.list.querySelectorAll(".tcw-cmd-item");
911
+ e.forEach((e, t) => {
912
+ e.classList.toggle("tcw-selected", t === this.selectedIndex);
913
+ }), e[this.selectedIndex]?.scrollIntoView({ block: "nearest" });
914
+ }
915
+ select(e) {
916
+ let t = this.filtered[e];
917
+ if (t) {
918
+ switch (t.category) {
919
+ case "indicator":
920
+ this.callbacks.onIndicator(t.id);
921
+ break;
922
+ case "chartType":
923
+ this.callbacks.onChartType(t.id);
924
+ break;
925
+ case "drawing":
926
+ this.callbacks.onDrawingTool(t.id);
927
+ break;
928
+ case "timeframe":
929
+ this.callbacks.onTimeframe(t.id);
930
+ break;
931
+ case "action":
932
+ this.callbacks.onAction(t.id);
933
+ break;
934
+ }
935
+ this.close();
936
+ }
937
+ }
938
+ handleKeydown(e) {
939
+ switch (e.key) {
940
+ case "Escape":
941
+ e.preventDefault(), this.close();
942
+ break;
943
+ case "ArrowDown":
944
+ e.preventDefault(), this.filtered.length > 0 && (this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length, this.updateSelection());
945
+ break;
946
+ case "ArrowUp":
947
+ e.preventDefault(), this.filtered.length > 0 && (this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length, this.updateSelection());
948
+ break;
949
+ case "Enter":
950
+ e.preventDefault(), this.select(this.selectedIndex);
951
+ break;
952
+ }
953
+ }
954
+ categoryLabel(e) {
955
+ switch (e) {
956
+ case "indicator": return "Indicators";
957
+ case "chartType": return "Chart Types";
958
+ case "drawing": return "Drawing Tools";
959
+ case "timeframe": return "Timeframes";
960
+ case "action": return "Actions";
961
+ default: return e;
962
+ }
963
+ }
964
+ destroy() {
965
+ this.close();
966
+ }
967
+ }, T = class {
968
+ chart;
969
+ state;
970
+ toolbar = null;
971
+ sidebar = null;
972
+ settings = null;
973
+ statusBar = null;
974
+ commandPalette = null;
975
+ root;
976
+ chartContainer;
977
+ destroyed = !1;
978
+ options;
979
+ symbolIndex = 0;
980
+ symbols;
981
+ settingsState;
982
+ adapter = null;
983
+ boundGlobalKeydown = null;
984
+ constructor(t, n = {}) {
985
+ this.options = n, this.symbols = n.symbols ?? c, this.settingsState = { ...l };
986
+ let u = this.resolveIsDark(n.theme), d = this.resolveTheme(n.theme);
987
+ this.state = {
988
+ symbol: n.symbol ?? this.symbols[0] ?? "BTCUSDT",
989
+ timeframe: n.timeframe ?? "5m",
990
+ chartType: n.chartOptions?.chartType ?? "candlestick",
991
+ isDark: u,
992
+ activeIndicators: /* @__PURE__ */ new Map(),
993
+ activeTool: null,
994
+ magnetEnabled: !0,
995
+ connectionState: "connecting",
996
+ connectionMessage: "Connecting..."
997
+ };
998
+ let f = this.symbols.indexOf(this.state.symbol);
999
+ f >= 0 && (this.symbolIndex = f), p(), this.root = document.createElement("div"), this.root.className = "tcw-root", this.root.dataset.tcwTheme = u ? "dark" : "light", t.appendChild(this.root), n.toolbar !== !1 && (this.toolbar = new v(this.root, {
1000
+ symbols: this.symbols,
1001
+ timeframes: n.timeframes ? r.filter((e) => n.timeframes.includes(e.value)) : r,
1002
+ chartTypes: n.chartTypes ? i.filter((e) => n.chartTypes.includes(e.value)) : i,
1003
+ indicators: o,
1004
+ popularIndicatorIds: s
1005
+ }, {
1006
+ onSymbolClick: () => this.handleSymbolClick(),
1007
+ onTimeframe: (e) => this.handleTimeframe(e),
1008
+ onChartType: (e) => this.handleChartType(e),
1009
+ onAddIndicator: (e) => this.handleAddIndicator(e),
1010
+ onRemoveIndicator: (e) => this.handleRemoveIndicator(e),
1011
+ onScreenshot: () => this.chart.screenshot(),
1012
+ onSettings: () => this.openSettings(),
1013
+ onToggleTheme: () => this.handleToggleTheme()
1014
+ }));
1015
+ let m = document.createElement("div");
1016
+ m.className = "tcw-body", n.drawingTools !== !1 && (this.sidebar = new b(m, { drawingToolGroups: a }, {
1017
+ onDrawingTool: (e) => this.handleDrawingTool(e),
1018
+ onCancelDrawing: () => this.handleCancelDrawing(),
1019
+ onToggleMagnet: () => this.handleToggleMagnet(),
1020
+ onUndo: () => this.chart.undo(),
1021
+ onRedo: () => this.chart.redo(),
1022
+ onClearDrawings: () => {
1023
+ this.chart.clearDrawings(), this.state = {
1024
+ ...this.state,
1025
+ activeTool: null
1026
+ }, this.updateUI();
1027
+ }
1028
+ })), this.chartContainer = document.createElement("div"), this.chartContainer.className = "tcw-chart-container", m.appendChild(this.chartContainer), this.root.appendChild(m), this.chart = new e(this.chartContainer, {
1029
+ chartType: this.state.chartType,
1030
+ theme: d,
1031
+ autoScale: !0,
1032
+ crosshair: { mode: "magnet" },
1033
+ features: {
1034
+ drawings: !0,
1035
+ drawingMagnet: !0,
1036
+ drawingUndoRedo: !0,
1037
+ indicators: !0,
1038
+ trading: n.trading !== !1,
1039
+ tradingContextMenu: n.trading !== !1,
1040
+ volume: !0,
1041
+ legend: !0,
1042
+ crosshair: !0,
1043
+ keyboard: !0,
1044
+ screenshot: !0,
1045
+ alerts: !0,
1046
+ barCountdown: !0,
1047
+ logScale: !0,
1048
+ watermark: !0
1049
+ },
1050
+ ...n.chartOptions
1051
+ }), n.statusBar !== !1 && (this.statusBar = new C(this.root)), n.settings !== !1 && (this.settings = new S({
1052
+ onChange: (e) => this.applySettings(e),
1053
+ onReset: () => this.resetSettings(),
1054
+ onClose: () => {}
1055
+ })), this.commandPalette = new w({
1056
+ onIndicator: (e) => this.handleAddIndicator(e),
1057
+ onChartType: (e) => this.handleChartType(e),
1058
+ onDrawingTool: (e) => this.handleDrawingTool(e),
1059
+ onTimeframe: (e) => this.handleTimeframe(e),
1060
+ onAction: (e) => this.handleAction(e),
1061
+ onClose: () => {}
1062
+ }), this.boundGlobalKeydown = (e) => {
1063
+ (e.ctrlKey || e.metaKey) && e.key === "k" && (e.preventDefault(), this.toggleCommandPalette());
1064
+ }, document.addEventListener("keydown", this.boundGlobalKeydown), n.adapter && (this.adapter = n.adapter, this.connectStream()), this.updateUI(), n.onReady?.(this.chart);
1065
+ }
1066
+ async setSymbol(e) {
1067
+ this.state = {
1068
+ ...this.state,
1069
+ symbol: e
1070
+ };
1071
+ let t = this.symbols.indexOf(e);
1072
+ t >= 0 && (this.symbolIndex = t), this.options.onSymbolChange?.(e), this.updateUI(), this.adapter && await this.connectStream();
1073
+ }
1074
+ async setTimeframe(e) {
1075
+ this.state = {
1076
+ ...this.state,
1077
+ timeframe: e
1078
+ }, this.options.onTimeframeChange?.(e), this.updateUI(), this.adapter && await this.connectStream();
1079
+ }
1080
+ setTheme(e) {
1081
+ let t = this.resolveIsDark(e), n = this.resolveTheme(e);
1082
+ this.state = {
1083
+ ...this.state,
1084
+ isDark: t
1085
+ }, this.root.dataset.tcwTheme = t ? "dark" : "light", this.chart.setTheme(n), this.updateUI();
1086
+ }
1087
+ getChart() {
1088
+ return this.chart;
1089
+ }
1090
+ destroy() {
1091
+ this.destroyed || (this.destroyed = !0, this.boundGlobalKeydown && document.removeEventListener("keydown", this.boundGlobalKeydown), this.commandPalette?.destroy(), this.toolbar?.destroy(), this.sidebar?.destroy(), this.settings?.destroy(), this.statusBar?.destroy(), this.chart.destroy(), this.root.remove(), m());
1092
+ }
1093
+ handleSymbolClick() {
1094
+ this.symbolIndex = (this.symbolIndex + 1) % this.symbols.length;
1095
+ let e = this.symbols[this.symbolIndex];
1096
+ this.state = {
1097
+ ...this.state,
1098
+ symbol: e
1099
+ }, this.options.onSymbolChange?.(e), this.updateUI(), this.adapter && this.connectStream();
1100
+ }
1101
+ handleTimeframe(e) {
1102
+ this.state = {
1103
+ ...this.state,
1104
+ timeframe: e
1105
+ }, this.options.onTimeframeChange?.(e), this.updateUI(), this.adapter && this.connectStream();
1106
+ }
1107
+ handleChartType(e) {
1108
+ this.state = {
1109
+ ...this.state,
1110
+ chartType: e
1111
+ }, this.chart.setChartType(e), this.updateUI();
1112
+ }
1113
+ handleAddIndicator(e) {
1114
+ if (this.state.activeIndicators.has(e)) {
1115
+ let t = this.state.activeIndicators.get(e);
1116
+ this.chart.removeIndicator(t);
1117
+ let n = new Map(this.state.activeIndicators);
1118
+ n.delete(e), this.state = {
1119
+ ...this.state,
1120
+ activeIndicators: n
1121
+ };
1122
+ } else {
1123
+ let t = this.chart.addIndicator(e);
1124
+ if (t) {
1125
+ let n = new Map(this.state.activeIndicators);
1126
+ n.set(e, t), this.state = {
1127
+ ...this.state,
1128
+ activeIndicators: n
1129
+ };
1130
+ }
1131
+ }
1132
+ this.updateUI();
1133
+ }
1134
+ handleRemoveIndicator(e) {
1135
+ this.chart.removeIndicator(e);
1136
+ let t = new Map(this.state.activeIndicators);
1137
+ for (let [n, r] of t.entries()) if (r === e) {
1138
+ t.delete(n);
1139
+ break;
1140
+ }
1141
+ this.state = {
1142
+ ...this.state,
1143
+ activeIndicators: t
1144
+ }, this.updateUI();
1145
+ }
1146
+ toggleCommandPalette() {
1147
+ if (this.commandPalette?.isOpen()) {
1148
+ this.commandPalette.close();
1149
+ return;
1150
+ }
1151
+ this.commandPalette?.open(this.buildCommandItems());
1152
+ }
1153
+ buildCommandItems() {
1154
+ let e = [];
1155
+ for (let t of o) e.push({
1156
+ id: t.id,
1157
+ label: t.name,
1158
+ category: "indicator",
1159
+ active: this.state.activeIndicators.has(t.id)
1160
+ });
1161
+ for (let t of i) e.push({
1162
+ id: t.value,
1163
+ label: t.label,
1164
+ category: "chartType",
1165
+ active: this.state.chartType === t.value
1166
+ });
1167
+ for (let t of a) for (let n of t.tools) e.push({
1168
+ id: n.value,
1169
+ label: n.label,
1170
+ category: "drawing",
1171
+ active: this.state.activeTool === n.value
1172
+ });
1173
+ for (let t of r) e.push({
1174
+ id: t.value,
1175
+ label: t.label,
1176
+ category: "timeframe",
1177
+ active: this.state.timeframe === t.value
1178
+ });
1179
+ return e.push({
1180
+ id: "screenshot",
1181
+ label: "Screenshot",
1182
+ category: "action",
1183
+ shortcut: ""
1184
+ }, {
1185
+ id: "toggleTheme",
1186
+ label: "Toggle Theme",
1187
+ category: "action"
1188
+ }, {
1189
+ id: "settings",
1190
+ label: "Settings",
1191
+ category: "action"
1192
+ }, {
1193
+ id: "clearDrawings",
1194
+ label: "Clear All Drawings",
1195
+ category: "action"
1196
+ }), e;
1197
+ }
1198
+ handleAction(e) {
1199
+ switch (e) {
1200
+ case "screenshot":
1201
+ this.chart.screenshot();
1202
+ break;
1203
+ case "toggleTheme":
1204
+ this.handleToggleTheme();
1205
+ break;
1206
+ case "settings":
1207
+ this.openSettings();
1208
+ break;
1209
+ case "clearDrawings":
1210
+ this.chart.clearDrawings(), this.state = {
1211
+ ...this.state,
1212
+ activeTool: null
1213
+ }, this.updateUI();
1214
+ break;
1215
+ }
1216
+ }
1217
+ handleDrawingTool(e) {
1218
+ this.state = {
1219
+ ...this.state,
1220
+ activeTool: e
1221
+ }, this.chart.setDrawingTool(e), this.updateUI();
1222
+ }
1223
+ handleCancelDrawing() {
1224
+ this.state = {
1225
+ ...this.state,
1226
+ activeTool: null
1227
+ }, this.chart.setDrawingTool(null), this.updateUI();
1228
+ }
1229
+ handleToggleMagnet() {
1230
+ let e = !this.state.magnetEnabled;
1231
+ this.state = {
1232
+ ...this.state,
1233
+ magnetEnabled: e
1234
+ }, this.chart.setDrawingMagnet(e), this.updateUI();
1235
+ }
1236
+ handleToggleTheme() {
1237
+ let e = !this.state.isDark;
1238
+ this.state = {
1239
+ ...this.state,
1240
+ isDark: e
1241
+ }, this.root.dataset.tcwTheme = e ? "dark" : "light", this.chart.setTheme(e ? t : n), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
1242
+ fontSize: 48,
1243
+ color: e ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"
1244
+ }), this.updateUI();
1245
+ }
1246
+ openSettings() {
1247
+ this.settings?.open(this.settingsState);
1248
+ }
1249
+ applySettings(e) {
1250
+ this.settingsState = {
1251
+ ...this.settingsState,
1252
+ ...e
1253
+ }, e.gridVisible !== void 0 && this.chart.setGridVisible(e.gridVisible), e.volumeVisible !== void 0 && this.chart.setVolumeVisible(e.volumeVisible), e.crosshairMode !== void 0 && this.chart.setCrosshairMode(e.crosshairMode), e.autoScale !== void 0 && this.chart.setAutoScale(e.autoScale), e.logScale !== void 0 && this.chart.setLogScale(e.logScale), e.numberLocale !== void 0 && this.chart.setNumberLocale(e.numberLocale);
1254
+ let t = { ...this.chart.getTheme() }, n = !1;
1255
+ e.candleUpColor !== void 0 && (t.candleUp = e.candleUpColor, n = !0), e.candleDownColor !== void 0 && (t.candleDown = e.candleDownColor, n = !0), e.candleUpWick !== void 0 && (t.candleUpWick = e.candleUpWick, n = !0), e.candleDownWick !== void 0 && (t.candleDownWick = e.candleDownWick, n = !0), e.backgroundColor !== void 0 && (t.background = e.backgroundColor, n = !0), e.gridColor !== void 0 && (t.grid = e.gridColor, n = !0), n && this.chart.setTheme(t);
1256
+ }
1257
+ resetSettings() {
1258
+ this.settingsState = { ...l }, this.applySettings(this.settingsState);
1259
+ }
1260
+ async connectStream() {
1261
+ if (this.adapter) {
1262
+ this.state = {
1263
+ ...this.state,
1264
+ connectionState: "connecting",
1265
+ connectionMessage: "Connecting..."
1266
+ }, this.updateUI();
1267
+ try {
1268
+ this.chart.disconnectStream(), await this.chart.connect({
1269
+ adapter: this.adapter,
1270
+ symbol: this.state.symbol,
1271
+ timeframe: this.state.timeframe,
1272
+ historyLimit: this.options.historyLimit ?? 500
1273
+ }), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
1274
+ fontSize: 48,
1275
+ color: this.state.isDark ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"
1276
+ }), this.state = {
1277
+ ...this.state,
1278
+ connectionState: "connected",
1279
+ connectionMessage: "Live"
1280
+ };
1281
+ } catch (e) {
1282
+ this.state = {
1283
+ ...this.state,
1284
+ connectionState: "error",
1285
+ connectionMessage: e instanceof Error ? e.message : "Connection failed"
1286
+ };
1287
+ }
1288
+ this.updateUI();
1289
+ }
1290
+ }
1291
+ updateUI() {
1292
+ this.toolbar?.update(this.state), this.sidebar?.update(this.state), this.statusBar?.update({
1293
+ connectionState: this.state.connectionState,
1294
+ message: this.state.connectionMessage,
1295
+ symbol: this.state.symbol,
1296
+ timeframe: this.state.timeframe
1297
+ });
1298
+ }
1299
+ resolveIsDark(e) {
1300
+ return e === void 0 || e === "dark" ? !0 : e === "light" ? !1 : typeof e == "object" && e.background ? this.isColorDark(e.background) : !0;
1301
+ }
1302
+ resolveTheme(e) {
1303
+ return e === void 0 || e === "dark" ? t : e === "light" ? n : typeof e == "object" ? e : t;
1304
+ }
1305
+ isColorDark(e) {
1306
+ if (e.startsWith("#") && e.length >= 7) {
1307
+ let t = parseInt(e.slice(1, 3), 16), n = parseInt(e.slice(3, 5), 16), r = parseInt(e.slice(5, 7), 16);
1308
+ return t + n + r < 384;
1309
+ }
1310
+ return !0;
1311
+ }
1312
+ };
1313
+ //#endregion
1314
+ export { T as ChartWidget };
1315
+
1316
+ //# sourceMappingURL=index.js.map