@tradecanvas/chart 0.4.0 → 0.6.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 (46) hide show
  1. package/README.md +120 -9
  2. package/dist/Chart-CrrTKx3r.js +1027 -0
  3. package/dist/Chart-CrrTKx3r.js.map +1 -0
  4. package/dist/Chart-DoR8L8Uk.cjs +2 -0
  5. package/dist/Chart-DoR8L8Uk.cjs.map +1 -0
  6. package/dist/Chart.d.ts +22 -8
  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/index.cjs +1 -1
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +4 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +31 -1010
  17. package/dist/index.js.map +1 -1
  18. package/dist/state/AutoSaveScheduler.d.ts +26 -0
  19. package/dist/state/AutoSaveScheduler.d.ts.map +1 -0
  20. package/dist/widget/ChartWidget.d.ts +43 -0
  21. package/dist/widget/ChartWidget.d.ts.map +1 -0
  22. package/dist/widget/WidgetDrawingSidebar.d.ts +19 -0
  23. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -0
  24. package/dist/widget/WidgetDropdown.d.ts +18 -0
  25. package/dist/widget/WidgetDropdown.d.ts.map +1 -0
  26. package/dist/widget/WidgetSettings.d.ts +25 -0
  27. package/dist/widget/WidgetSettings.d.ts.map +1 -0
  28. package/dist/widget/WidgetStatusBar.d.ts +15 -0
  29. package/dist/widget/WidgetStatusBar.d.ts.map +1 -0
  30. package/dist/widget/WidgetStyles.d.ts +9 -0
  31. package/dist/widget/WidgetStyles.d.ts.map +1 -0
  32. package/dist/widget/WidgetToolbar.d.ts +22 -0
  33. package/dist/widget/WidgetToolbar.d.ts.map +1 -0
  34. package/dist/widget/icons.d.ts +2 -0
  35. package/dist/widget/icons.d.ts.map +1 -0
  36. package/dist/widget/index.cjs +740 -0
  37. package/dist/widget/index.cjs.map +1 -0
  38. package/dist/widget/index.d.ts +3 -0
  39. package/dist/widget/index.d.ts.map +1 -0
  40. package/dist/widget/index.js +1058 -0
  41. package/dist/widget/index.js.map +1 -0
  42. package/dist/widget/types.d.ts +105 -0
  43. package/dist/widget/types.d.ts.map +1 -0
  44. package/dist/widget/widgetConfig.d.ts +16 -0
  45. package/dist/widget/widgetConfig.d.ts.map +1 -0
  46. package/package.json +14 -4
@@ -0,0 +1,740 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../Chart-DoR8L8Uk.cjs`);let t=require(`@tradecanvas/commons`);var n=[{label:`1m`,value:`1m`},{label:`5m`,value:`5m`},{label:`15m`,value:`15m`},{label:`1H`,value:`1h`},{label:`4H`,value:`4h`},{label:`1D`,value:`1d`}],r=[{label:`Candlestick`,value:`candlestick`},{label:`Line`,value:`line`},{label:`Area`,value:`area`},{label:`Bar`,value:`bar`},{label:`Heikin-Ashi`,value:`heikinAshi`},{label:`Hollow Candle`,value:`hollowCandle`},{label:`Baseline`,value:`baseline`}],i=[{label:`Lines`,tools:[{label:`Trend Line`,value:`trendLine`},{label:`Ray`,value:`ray`},{label:`Extended Line`,value:`extendedLine`}]},{label:`Horizontal/Vertical`,tools:[{label:`Horizontal Line`,value:`horizontalLine`},{label:`Vertical Line`,value:`verticalLine`}]},{label:`Channels`,tools:[{label:`Parallel Channel`,value:`parallelChannel`},{label:`Regression Channel`,value:`regressionChannel`}]},{label:`Fibonacci`,tools:[{label:`Fib Retracement`,value:`fibRetracement`},{label:`Fib Extension`,value:`fibExtension`}]},{label:`Shapes`,tools:[{label:`Rectangle`,value:`rectangle`},{label:`Ellipse`,value:`ellipse`},{label:`Triangle`,value:`triangle`}]},{label:`Gann & Advanced`,tools:[{label:`Pitchfork`,value:`pitchfork`},{label:`Gann Fan`,value:`gannFan`},{label:`Gann Box`,value:`gannBox`},{label:`Elliott Wave`,value:`elliottWave`}]},{label:`Measure`,tools:[{label:`Price Range`,value:`priceRange`},{label:`Date Range`,value:`dateRange`},{label:`Measure`,value:`measure`}]},{label:`Annotation`,tools:[{label:`Text`,value:`text`},{label:`Arrow`,value:`arrow`}]}],a=[{id:`sma`,name:`SMA`,type:`overlay`},{id:`ema`,name:`EMA`,type:`overlay`},{id:`bb`,name:`Bollinger Bands`,type:`overlay`},{id:`vwap`,name:`VWAP`,type:`overlay`},{id:`ichimoku`,name:`Ichimoku Cloud`,type:`overlay`},{id:`psar`,name:`Parabolic SAR`,type:`overlay`},{id:`supertrend`,name:`Supertrend`,type:`overlay`},{id:`keltner`,name:`Keltner Channel`,type:`overlay`},{id:`donchian`,name:`Donchian Channel`,type:`overlay`},{id:`rsi`,name:`RSI`,type:`panel`},{id:`macd`,name:`MACD`,type:`panel`},{id:`stochastic`,name:`Stochastic`,type:`panel`},{id:`atr`,name:`ATR`,type:`panel`},{id:`adx`,name:`ADX`,type:`panel`},{id:`obv`,name:`OBV`,type:`panel`},{id:`williamsR`,name:`Williams %R`,type:`panel`},{id:`cci`,name:`CCI`,type:`panel`},{id:`mfi`,name:`MFI`,type:`panel`},{id:`roc`,name:`ROC`,type:`panel`},{id:`tsi`,name:`TSI`,type:`panel`},{id:`cmf`,name:`CMF`,type:`panel`},{id:`aroon`,name:`Aroon`,type:`panel`},{id:`stddev`,name:`Std Deviation`,type:`panel`},{id:`vroc`,name:`Volume ROC`,type:`panel`},{id:`ad`,name:`Acc/Dist`,type:`panel`},{id:`volumeProfile`,name:`Volume Profile`,type:`panel`}],o=[`sma`,`ema`,`bb`,`rsi`,`macd`,`stochastic`,`vwap`,`atr`,`obv`,`ichimoku`],s=[`BTCUSDT`,`ETHUSDT`,`SOLUSDT`,`BNBUSDT`],c={candleUpColor:`#26A69A`,candleDownColor:`#EF5350`,candleUpWick:`#26A69A`,candleDownWick:`#EF5350`,backgroundColor:`#131722`,gridColor:`#1E222D`,gridVisible:!0,volumeVisible:!0,legendVisible:!0,barCountdown:!0,logScale:!1,autoScale:!0,crosshairMode:`magnet`,numberLocale:`en-US`},l=`/* === TradeCanvas Widget Styles === */
2
+
3
+ .tcw-root {
4
+ display: flex;
5
+ flex-direction: column;
6
+ width: 100%;
7
+ height: 100%;
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
9
+ font-size: 13px;
10
+ color: #d1d4dc;
11
+ background: #131722;
12
+ position: relative;
13
+ overflow: hidden;
14
+
15
+ /* Dark theme tokens (default) */
16
+ --tcw-bg: #131722;
17
+ --tcw-bg-elevated: #1E222D;
18
+ --tcw-border: #2A2E39;
19
+ --tcw-text: #d1d4dc;
20
+ --tcw-text-dim: #b2b5be;
21
+ --tcw-text-muted: #787b86;
22
+ --tcw-accent: #2962ff;
23
+ --tcw-accent-dim: rgba(41,98,255,0.15);
24
+ --tcw-accent-glow: rgba(41,98,255,0.12);
25
+ --tcw-red: #ef5350;
26
+ --tcw-green: #26a69a;
27
+ --tcw-transition: 0.15s ease;
28
+ --tcw-radius-lg: 8px;
29
+ --tcw-font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;
30
+ --tcw-hover-bg: rgba(255,255,255,0.04);
31
+ }
32
+
33
+ .tcw-root[data-tcw-theme="light"] {
34
+ color: #131722;
35
+ background: #ffffff;
36
+
37
+ --tcw-bg: #ffffff;
38
+ --tcw-bg-elevated: #f0f3fa;
39
+ --tcw-border: #e0e3eb;
40
+ --tcw-text: #131722;
41
+ --tcw-text-dim: #434651;
42
+ --tcw-text-muted: #787b86;
43
+ --tcw-accent: #2962ff;
44
+ --tcw-accent-dim: rgba(41,98,255,0.1);
45
+ --tcw-accent-glow: rgba(41,98,255,0.08);
46
+ --tcw-red: #ef5350;
47
+ --tcw-green: #26a69a;
48
+ --tcw-hover-bg: rgba(0,0,0,0.04);
49
+ }
50
+
51
+ /* === Toolbar === */
52
+
53
+ .tcw-toolbar {
54
+ display: flex;
55
+ align-items: center;
56
+ gap: 0;
57
+ padding: 0 12px;
58
+ height: 40px;
59
+ border-bottom: 1px solid var(--tcw-border);
60
+ background: var(--tcw-bg-elevated);
61
+ flex-shrink: 0;
62
+ position: relative;
63
+ z-index: 20;
64
+ }
65
+
66
+ .tcw-toolbar-symbol {
67
+ font-size: 13px;
68
+ font-weight: 700;
69
+ color: var(--tcw-text);
70
+ padding: 0 10px;
71
+ white-space: nowrap;
72
+ letter-spacing: -0.01em;
73
+ cursor: pointer;
74
+ border: none;
75
+ background: none;
76
+ font-family: inherit;
77
+ }
78
+
79
+ .tcw-toolbar-sep {
80
+ width: 1px;
81
+ height: 20px;
82
+ background: var(--tcw-border);
83
+ flex-shrink: 0;
84
+ }
85
+
86
+ .tcw-toolbar-group {
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 2px;
90
+ padding: 0 8px;
91
+ }
92
+
93
+ .tcw-toolbar-spacer {
94
+ flex: 1;
95
+ }
96
+
97
+ .tcw-btn {
98
+ padding: 4px 8px;
99
+ font-size: 12px;
100
+ font-family: inherit;
101
+ border: none;
102
+ border-radius: 4px;
103
+ background: transparent;
104
+ color: var(--tcw-text-dim);
105
+ cursor: pointer;
106
+ transition: all var(--tcw-transition);
107
+ white-space: nowrap;
108
+ line-height: 1;
109
+ }
110
+
111
+ .tcw-btn:hover {
112
+ background: var(--tcw-hover-bg);
113
+ color: var(--tcw-text);
114
+ }
115
+
116
+ .tcw-btn.tcw-active {
117
+ background: var(--tcw-accent);
118
+ color: white;
119
+ }
120
+
121
+ .tcw-btn-icon {
122
+ width: 32px;
123
+ height: 32px;
124
+ display: inline-flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ font-family: inherit;
128
+ border: none;
129
+ border-radius: 4px;
130
+ background: transparent;
131
+ color: var(--tcw-text-muted);
132
+ cursor: pointer;
133
+ transition: all var(--tcw-transition);
134
+ line-height: 1;
135
+ position: relative;
136
+ }
137
+
138
+ .tcw-btn-icon:hover {
139
+ background: var(--tcw-hover-bg);
140
+ color: var(--tcw-text);
141
+ }
142
+
143
+ .tcw-badge-count {
144
+ font-size: 10px;
145
+ color: var(--tcw-accent);
146
+ background: var(--tcw-accent-dim);
147
+ padding: 0 4px;
148
+ border-radius: 8px;
149
+ font-weight: 600;
150
+ }
151
+
152
+ .tcw-indicator-chips {
153
+ display: flex;
154
+ align-items: center;
155
+ gap: 4px;
156
+ padding: 0 4px;
157
+ flex-wrap: nowrap;
158
+ overflow: hidden;
159
+ }
160
+
161
+ .tcw-indicator-chip {
162
+ display: inline-flex;
163
+ align-items: center;
164
+ gap: 4px;
165
+ padding: 2px 6px 2px 8px;
166
+ font-size: 11px;
167
+ font-weight: 500;
168
+ background: var(--tcw-accent-dim);
169
+ color: var(--tcw-accent);
170
+ border-radius: 4px;
171
+ white-space: nowrap;
172
+ line-height: 1.4;
173
+ }
174
+
175
+ .tcw-chip-remove {
176
+ cursor: pointer;
177
+ opacity: 0.6;
178
+ padding: 0 2px;
179
+ transition: opacity var(--tcw-transition);
180
+ border: none;
181
+ background: none;
182
+ color: inherit;
183
+ display: inline-flex;
184
+ align-items: center;
185
+ }
186
+
187
+ .tcw-chip-remove:hover {
188
+ opacity: 1;
189
+ }
190
+
191
+ /* === Dropdown === */
192
+
193
+ .tcw-dropdown-trigger {
194
+ display: inline-flex;
195
+ align-items: center;
196
+ gap: 4px;
197
+ padding: 4px 8px;
198
+ font-size: 12px;
199
+ font-family: inherit;
200
+ border: none;
201
+ border-radius: 4px;
202
+ background: transparent;
203
+ color: var(--tcw-text-dim);
204
+ cursor: pointer;
205
+ transition: all var(--tcw-transition);
206
+ white-space: nowrap;
207
+ line-height: 1;
208
+ }
209
+
210
+ .tcw-dropdown-trigger:hover {
211
+ background: var(--tcw-hover-bg);
212
+ color: var(--tcw-text);
213
+ }
214
+
215
+ .tcw-dropdown {
216
+ position: absolute;
217
+ top: 100%;
218
+ margin-top: 4px;
219
+ background: var(--tcw-bg-elevated);
220
+ border: 1px solid var(--tcw-border);
221
+ border-radius: var(--tcw-radius-lg);
222
+ box-shadow: 0 8px 32px rgba(0,0,0,0.4);
223
+ z-index: 50;
224
+ padding: 4px 0;
225
+ max-height: 400px;
226
+ overflow-y: auto;
227
+ }
228
+
229
+ .tcw-dropdown-item {
230
+ display: flex;
231
+ align-items: center;
232
+ justify-content: space-between;
233
+ padding: 6px 12px;
234
+ font-size: 12px;
235
+ color: var(--tcw-text-dim);
236
+ cursor: pointer;
237
+ transition: background var(--tcw-transition), color var(--tcw-transition);
238
+ width: 100%;
239
+ border: none;
240
+ background: none;
241
+ font-family: inherit;
242
+ text-align: left;
243
+ }
244
+
245
+ .tcw-dropdown-item:hover {
246
+ background: var(--tcw-hover-bg);
247
+ color: var(--tcw-text);
248
+ }
249
+
250
+ .tcw-dropdown-item.tcw-active {
251
+ color: var(--tcw-accent);
252
+ }
253
+
254
+ .tcw-dropdown-label {
255
+ text-transform: uppercase;
256
+ font-size: 10px;
257
+ color: var(--tcw-text-muted);
258
+ letter-spacing: 0.05em;
259
+ padding: 6px 12px;
260
+ font-weight: 600;
261
+ }
262
+
263
+ .tcw-dropdown-divider {
264
+ border-top: 1px solid var(--tcw-border);
265
+ margin: 4px 0;
266
+ }
267
+
268
+ .tcw-tag {
269
+ font-size: 10px;
270
+ color: var(--tcw-text-muted);
271
+ padding: 1px 5px;
272
+ border-radius: 3px;
273
+ background: var(--tcw-hover-bg);
274
+ }
275
+
276
+ /* === Body === */
277
+
278
+ .tcw-body {
279
+ display: flex;
280
+ flex: 1;
281
+ min-height: 0;
282
+ }
283
+
284
+ .tcw-chart-container {
285
+ flex: 1;
286
+ min-width: 0;
287
+ min-height: 0;
288
+ width: 100%;
289
+ height: 100%;
290
+ }
291
+
292
+ /* === Sidebar === */
293
+
294
+ .tcw-sidebar {
295
+ width: 36px;
296
+ flex-shrink: 0;
297
+ background: var(--tcw-bg-elevated);
298
+ border-right: 1px solid var(--tcw-border);
299
+ display: flex;
300
+ flex-direction: column;
301
+ align-items: center;
302
+ padding: 4px 0;
303
+ overflow: visible;
304
+ }
305
+
306
+ .tcw-tool-group-wrap {
307
+ position: relative;
308
+ }
309
+
310
+ .tcw-sidebar-btn {
311
+ width: 36px;
312
+ height: 32px;
313
+ display: flex;
314
+ align-items: center;
315
+ justify-content: center;
316
+ border: none;
317
+ background: transparent;
318
+ color: var(--tcw-text-muted);
319
+ cursor: pointer;
320
+ font-family: inherit;
321
+ transition: all var(--tcw-transition);
322
+ position: relative;
323
+ flex-shrink: 0;
324
+ line-height: 1;
325
+ }
326
+
327
+ .tcw-sidebar-btn:hover {
328
+ color: var(--tcw-text);
329
+ background: var(--tcw-hover-bg);
330
+ }
331
+
332
+ .tcw-sidebar-btn.tcw-active {
333
+ color: var(--tcw-accent);
334
+ background: var(--tcw-accent-glow);
335
+ }
336
+
337
+ .tcw-sidebar-btn.tcw-danger:hover {
338
+ color: var(--tcw-red);
339
+ background: rgba(239,68,68,0.1);
340
+ }
341
+
342
+ .tcw-multi-dot {
343
+ position: absolute;
344
+ bottom: 2px;
345
+ right: 2px;
346
+ width: 4px;
347
+ height: 4px;
348
+ border-radius: 50%;
349
+ background: var(--tcw-text-muted);
350
+ }
351
+
352
+ .tcw-sidebar-divider {
353
+ width: 20px;
354
+ height: 1px;
355
+ background: var(--tcw-border);
356
+ margin: 4px 0;
357
+ flex-shrink: 0;
358
+ }
359
+
360
+ .tcw-sidebar-spacer {
361
+ flex: 1;
362
+ }
363
+
364
+ /* === Flyout === */
365
+
366
+ .tcw-flyout {
367
+ position: absolute;
368
+ left: 100%;
369
+ top: 0;
370
+ margin-left: 2px;
371
+ min-width: 160px;
372
+ background: var(--tcw-bg-elevated);
373
+ border: 1px solid var(--tcw-border);
374
+ border-radius: var(--tcw-radius-lg);
375
+ box-shadow: 0 8px 32px rgba(0,0,0,0.4);
376
+ z-index: 30;
377
+ padding: 4px 0;
378
+ }
379
+
380
+ .tcw-flyout-header {
381
+ text-transform: uppercase;
382
+ font-size: 10px;
383
+ color: var(--tcw-text-muted);
384
+ letter-spacing: 0.05em;
385
+ padding: 6px 12px;
386
+ font-weight: 600;
387
+ }
388
+
389
+ .tcw-flyout-item {
390
+ padding: 6px 12px;
391
+ font-size: 12px;
392
+ color: var(--tcw-text-dim);
393
+ cursor: pointer;
394
+ width: 100%;
395
+ display: block;
396
+ border: none;
397
+ background: none;
398
+ text-align: left;
399
+ font-family: inherit;
400
+ transition: background var(--tcw-transition), color var(--tcw-transition);
401
+ }
402
+
403
+ .tcw-flyout-item:hover {
404
+ background: var(--tcw-hover-bg);
405
+ color: var(--tcw-text);
406
+ }
407
+
408
+ .tcw-flyout-item.tcw-active {
409
+ color: var(--tcw-accent);
410
+ }
411
+
412
+ /* === Modal === */
413
+
414
+ .tcw-modal-backdrop {
415
+ position: fixed;
416
+ inset: 0;
417
+ background: rgba(0,0,0,0.5);
418
+ backdrop-filter: blur(4px);
419
+ -webkit-backdrop-filter: blur(4px);
420
+ z-index: 100;
421
+ }
422
+
423
+ .tcw-modal {
424
+ position: fixed;
425
+ z-index: 101;
426
+ top: 50%;
427
+ left: 50%;
428
+ transform: translate(-50%, -50%);
429
+ background: var(--tcw-bg-elevated);
430
+ border: 1px solid var(--tcw-border);
431
+ border-radius: var(--tcw-radius-lg);
432
+ width: 480px;
433
+ max-width: 90vw;
434
+ max-height: 80vh;
435
+ display: flex;
436
+ flex-direction: column;
437
+ box-shadow: 0 24px 64px rgba(0,0,0,0.5);
438
+ }
439
+
440
+ .tcw-modal-header {
441
+ display: flex;
442
+ align-items: center;
443
+ justify-content: space-between;
444
+ padding: 16px 20px;
445
+ border-bottom: 1px solid var(--tcw-border);
446
+ }
447
+
448
+ .tcw-modal-header h3 {
449
+ font-size: 15px;
450
+ font-weight: 600;
451
+ margin: 0;
452
+ color: var(--tcw-text);
453
+ }
454
+
455
+ .tcw-modal-close {
456
+ width: 28px;
457
+ height: 28px;
458
+ display: flex;
459
+ align-items: center;
460
+ justify-content: center;
461
+ border: none;
462
+ background: transparent;
463
+ color: var(--tcw-text-muted);
464
+ cursor: pointer;
465
+ border-radius: 4px;
466
+ transition: all var(--tcw-transition);
467
+ }
468
+
469
+ .tcw-modal-close:hover {
470
+ background: var(--tcw-hover-bg);
471
+ color: var(--tcw-text);
472
+ }
473
+
474
+ .tcw-modal-tabs {
475
+ display: flex;
476
+ gap: 0;
477
+ padding: 0 20px;
478
+ border-bottom: 1px solid var(--tcw-border);
479
+ }
480
+
481
+ .tcw-modal-tab {
482
+ padding: 10px 16px;
483
+ font-size: 12px;
484
+ font-weight: 500;
485
+ color: var(--tcw-text-muted);
486
+ border: none;
487
+ background: none;
488
+ cursor: pointer;
489
+ border-bottom: 2px solid transparent;
490
+ margin-bottom: -1px;
491
+ transition: color var(--tcw-transition);
492
+ font-family: inherit;
493
+ text-transform: capitalize;
494
+ }
495
+
496
+ .tcw-modal-tab:hover {
497
+ color: var(--tcw-text-dim);
498
+ }
499
+
500
+ .tcw-modal-tab.tcw-active {
501
+ color: var(--tcw-accent);
502
+ border-bottom-color: var(--tcw-accent);
503
+ }
504
+
505
+ .tcw-modal-body {
506
+ padding: 20px;
507
+ overflow-y: auto;
508
+ flex: 1;
509
+ }
510
+
511
+ .tcw-settings-section {
512
+ margin-bottom: 20px;
513
+ }
514
+
515
+ .tcw-settings-section:last-child {
516
+ margin-bottom: 0;
517
+ }
518
+
519
+ .tcw-settings-section-title {
520
+ font-size: 11px;
521
+ font-weight: 600;
522
+ text-transform: uppercase;
523
+ letter-spacing: 0.05em;
524
+ color: var(--tcw-text-muted);
525
+ margin-bottom: 12px;
526
+ }
527
+
528
+ .tcw-settings-row {
529
+ display: flex;
530
+ align-items: center;
531
+ justify-content: space-between;
532
+ padding: 8px 0;
533
+ }
534
+
535
+ .tcw-settings-row + .tcw-settings-row {
536
+ border-top: 1px solid rgba(255,255,255,0.03);
537
+ }
538
+
539
+ .tcw-root[data-tcw-theme="light"] .tcw-settings-row + .tcw-settings-row {
540
+ border-top: 1px solid rgba(0,0,0,0.04);
541
+ }
542
+
543
+ .tcw-settings-label {
544
+ font-size: 13px;
545
+ color: var(--tcw-text-dim);
546
+ }
547
+
548
+ .tcw-color-picker-wrap {
549
+ display: flex;
550
+ align-items: center;
551
+ gap: 6px;
552
+ }
553
+
554
+ .tcw-color-picker-wrap input[type='color'] {
555
+ width: 28px;
556
+ height: 28px;
557
+ border: 1px solid var(--tcw-border);
558
+ border-radius: 4px;
559
+ background: none;
560
+ cursor: pointer;
561
+ padding: 2px;
562
+ }
563
+
564
+ .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {
565
+ padding: 0;
566
+ }
567
+
568
+ .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {
569
+ border: none;
570
+ border-radius: 2px;
571
+ }
572
+
573
+ .tcw-color-hex {
574
+ font-size: 11px;
575
+ font-family: var(--tcw-font-mono);
576
+ color: var(--tcw-text-muted);
577
+ min-width: 60px;
578
+ }
579
+
580
+ .tcw-toggle {
581
+ width: 36px;
582
+ height: 20px;
583
+ background: rgba(255,255,255,0.1);
584
+ border-radius: 10px;
585
+ position: relative;
586
+ cursor: pointer;
587
+ transition: background var(--tcw-transition);
588
+ border: none;
589
+ padding: 0;
590
+ flex-shrink: 0;
591
+ }
592
+
593
+ .tcw-toggle::after {
594
+ content: '';
595
+ position: absolute;
596
+ top: 2px;
597
+ left: 2px;
598
+ width: 16px;
599
+ height: 16px;
600
+ border-radius: 50%;
601
+ background: var(--tcw-text-muted);
602
+ transition: all var(--tcw-transition);
603
+ }
604
+
605
+ .tcw-toggle.tcw-on {
606
+ background: var(--tcw-accent);
607
+ }
608
+
609
+ .tcw-toggle.tcw-on::after {
610
+ left: 18px;
611
+ background: white;
612
+ }
613
+
614
+ .tcw-root[data-tcw-theme="light"] .tcw-toggle {
615
+ background: rgba(0,0,0,0.1);
616
+ }
617
+
618
+ .tcw-root[data-tcw-theme="light"] .tcw-toggle::after {
619
+ background: #888;
620
+ }
621
+
622
+ .tcw-root[data-tcw-theme="light"] .tcw-toggle.tcw-on {
623
+ background: var(--tcw-accent);
624
+ }
625
+
626
+ .tcw-root[data-tcw-theme="light"] .tcw-toggle.tcw-on::after {
627
+ background: white;
628
+ }
629
+
630
+ .tcw-settings-select {
631
+ padding: 4px 8px;
632
+ font-size: 12px;
633
+ font-family: inherit;
634
+ background: var(--tcw-bg);
635
+ border: 1px solid var(--tcw-border);
636
+ border-radius: 4px;
637
+ color: var(--tcw-text);
638
+ cursor: pointer;
639
+ }
640
+
641
+ .tcw-modal-footer {
642
+ display: flex;
643
+ align-items: center;
644
+ justify-content: space-between;
645
+ padding: 12px 20px;
646
+ border-top: 1px solid var(--tcw-border);
647
+ }
648
+
649
+ .tcw-reset-link {
650
+ font-size: 12px;
651
+ color: var(--tcw-text-muted);
652
+ cursor: pointer;
653
+ border: none;
654
+ background: none;
655
+ font-family: inherit;
656
+ text-decoration: underline;
657
+ text-underline-offset: 2px;
658
+ transition: color var(--tcw-transition);
659
+ }
660
+
661
+ .tcw-reset-link:hover {
662
+ color: var(--tcw-text-dim);
663
+ }
664
+
665
+ .tcw-done-btn {
666
+ padding: 6px 16px;
667
+ font-size: 12px;
668
+ font-weight: 500;
669
+ background: var(--tcw-accent);
670
+ color: white;
671
+ border: none;
672
+ border-radius: 4px;
673
+ cursor: pointer;
674
+ font-family: inherit;
675
+ transition: background var(--tcw-transition);
676
+ }
677
+
678
+ .tcw-done-btn:hover {
679
+ background: #2563eb;
680
+ }
681
+
682
+ /* === Status Bar === */
683
+
684
+ .tcw-statusbar {
685
+ display: flex;
686
+ align-items: center;
687
+ justify-content: space-between;
688
+ padding: 6px 16px;
689
+ border-top: 1px solid var(--tcw-border);
690
+ background: var(--tcw-bg-elevated);
691
+ font-size: 11px;
692
+ color: var(--tcw-text-muted);
693
+ flex-shrink: 0;
694
+ }
695
+
696
+ .tcw-status-indicator {
697
+ display: flex;
698
+ align-items: center;
699
+ gap: 6px;
700
+ }
701
+
702
+ .tcw-status-dot {
703
+ width: 6px;
704
+ height: 6px;
705
+ border-radius: 50%;
706
+ background: var(--tcw-text-muted);
707
+ transition: background 0.3s;
708
+ }
709
+
710
+ .tcw-status-dot.tcw-connected {
711
+ background: var(--tcw-green);
712
+ }
713
+
714
+ .tcw-status-dot.tcw-error {
715
+ background: var(--tcw-red);
716
+ }
717
+
718
+ /* === Responsive === */
719
+
720
+ @media (max-width: 768px) {
721
+ .tcw-toolbar {
722
+ padding: 0 8px;
723
+ height: 36px;
724
+ }
725
+ .tcw-toolbar-sep {
726
+ display: none;
727
+ }
728
+ .tcw-indicator-chips {
729
+ display: none;
730
+ }
731
+ .tcw-sidebar {
732
+ width: 32px;
733
+ }
734
+ .tcw-sidebar-btn {
735
+ width: 32px;
736
+ height: 28px;
737
+ }
738
+ }
739
+ `,u=0,d=`tcw-styles`;function f(){if(u++,u>1||document.getElementById(d))return;let e=document.createElement(`style`);e.id=d,e.textContent=l,document.head.appendChild(e)}function p(){if(u--,u>0)return;let e=document.getElementById(d);e&&e.remove()}var m={cursor:`<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>`,trendingUp:`<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>`,minus:`<path d="M5 12h14"/>`,penLine:`<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,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"/>`,square:`<rect width="18" height="18" x="3" y="3" rx="2"/>`,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"/>`,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"/>`,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"/>`,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"/>`,undo:`<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,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"/>`,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"/>`,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"/>`,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"/>`,moon:`<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>`,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"/>`,chevronDown:`<path d="m6 9 6 6 6-6"/>`,chevronUp:`<path d="m18 15-6-6-6 6"/>`,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"/>`,x:`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,play:`<polygon points="6 3 20 12 6 21 6 3"/>`,pause:`<rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/>`,stop:`<rect width="14" height="14" x="5" y="5" rx="1"/>`,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"/>`};function h(e,t=14){let n=m[e];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>`:``}var g=class{trigger;panel;_isOpen=!1;onOutsideClick;onEscapeKey;onTriggerClick;constructor(e,t={}){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=()=>{this._isOpen?this.close():this.open()},this.onOutsideClick=e=>{this.trigger.contains(e.target)||this.close()},this.onEscapeKey=e=>{e.key===`Escape`&&this.close()},e.addEventListener(`click`,this.onTriggerClick)}setContent(e){this.panel.innerHTML=e}open(){this._isOpen||(this._isOpen=!0,this.panel.style.display=``,document.addEventListener(`mousedown`,this.onOutsideClick),document.addEventListener(`keydown`,this.onEscapeKey))}close(){this._isOpen&&(this._isOpen=!1,this.panel.style.display=`none`,document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey))}isOpen(){return this._isOpen}destroy(){this.trigger.removeEventListener(`click`,this.onTriggerClick),document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey),this.panel.remove()}},_=class{config;callbacks;el;chartTypeDropdown=null;indicatorDropdown=null;tfButtons=[];chipsContainer=null;themeBtn=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-toolbar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this,r=document.createElement(`button`);r.className=`tcw-toolbar-symbol`,r.dataset.role=`symbol`,r.addEventListener(`click`,t.onSymbolClick),n.appendChild(r),n.appendChild(this.sep());let i=document.createElement(`div`);i.className=`tcw-toolbar-group`;for(let n of e.timeframes){let e=document.createElement(`button`);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)}n.appendChild(i),n.appendChild(this.sep());let a=document.createElement(`div`);a.style.position=`relative`,a.style.display=`inline-flex`;let o=document.createElement(`button`);o.className=`tcw-dropdown-trigger`,o.dataset.role=`charttype`,a.appendChild(o),n.appendChild(a),this.chartTypeDropdown=new g(a,{width:`160px`}),this.buildChartTypeMenu(),n.appendChild(this.sep());let s=document.createElement(`div`);s.style.position=`relative`,s.style.display=`inline-flex`;let c=document.createElement(`button`);c.className=`tcw-dropdown-trigger`,c.dataset.role=`indicators`,s.appendChild(c),n.appendChild(s),this.indicatorDropdown=new g(s,{width:`280px`}),this.buildIndicatorMenu(),this.chipsContainer=document.createElement(`div`),this.chipsContainer.className=`tcw-indicator-chips`,n.appendChild(this.chipsContainer),n.appendChild(this.spacer());let l=this.iconBtn(`camera`,`Screenshot`,t.onScreenshot);n.appendChild(l);let u=this.iconBtn(`settings`,`Chart Settings`,t.onSettings);n.appendChild(u),this.themeBtn=this.iconBtn(`moon`,`Toggle theme`,t.onToggleTheme),this.themeBtn.dataset.role=`theme`,n.appendChild(this.themeBtn)}buildChartTypeMenu(){if(!this.chartTypeDropdown)return;let e=this.config.chartTypes.map(e=>`<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(``);this.chartTypeDropdown.setContent(e),this.chartTypeDropdown.panel.querySelectorAll(`.tcw-dropdown-item`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ct;this.callbacks.onChartType(t),this.chartTypeDropdown?.close()})})}buildIndicatorMenu(){if(!this.indicatorDropdown)return;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>`;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>`;i+=`<div class="tcw-dropdown-divider"></div>`,i+=`<div class="tcw-dropdown-label">All</div>`;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>`;this.indicatorDropdown.setContent(i),this.indicatorDropdown.panel.querySelectorAll(`.tcw-dropdown-item[data-ind]`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ind;this.callbacks.onAddIndicator(t)})})}update(e){let t=this.el.querySelector(`[data-role="symbol"]`);t&&(t.textContent=e.symbol);for(let t of this.tfButtons)t.classList.toggle(`tcw-active`,t.dataset.tf===e.timeframe);let n=this.el.querySelector(`[data-role="charttype"]`);if(n){let t=this.config.chartTypes.find(t=>t.value===e.chartType)?.label??`Candles`;n.innerHTML=`${h(`barChart`,14)} ${t} ${h(`chevronDown`,12)}`}let r=this.el.querySelector(`[data-role="indicators"]`);if(r){let t=e.activeIndicators.size,n=`${h(`trendingUp`,14)} Indicators`;t>0&&(n+=` <span class="tcw-badge-count">${t}</span>`),r.innerHTML=n}if(this.chipsContainer){let t=this.getActiveIndicatorList(e);this.chipsContainer.innerHTML=``;for(let e of t){let t=document.createElement(`div`);t.className=`tcw-indicator-chip`;let n=document.createElement(`span`);n.textContent=e.label,t.appendChild(n);let r=document.createElement(`button`);r.className=`tcw-chip-remove`,r.innerHTML=h(`x`,10),r.addEventListener(`click`,()=>this.callbacks.onRemoveIndicator(e.instanceId)),t.appendChild(r),this.chipsContainer.appendChild(t)}}this.themeBtn&&(this.themeBtn.innerHTML=e.isDark?h(`moon`,14):h(`sun`,14))}getActiveIndicatorList(e){let t=[];for(let[n,r]of e.activeIndicators.entries())t.push({instanceId:r,id:n,label:n.toUpperCase()});return t}sep(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-sep`,e}spacer(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-spacer`,e}iconBtn(e,t,n){let r=document.createElement(`button`);return r.className=`tcw-btn-icon`,r.title=t,r.innerHTML=h(e,14),r.addEventListener(`click`,n),r}destroy(){this.chartTypeDropdown?.destroy(),this.indicatorDropdown?.destroy(),this.el.remove()}},v=[`trendingUp`,`minus`,`penLine`,`hash`,`square`,`gitBranch`,`ruler`,`type`],y=class{config;callbacks;el;groupWraps=[];groupButtons=[];cursorBtn=null;magnetBtn=null;flyoutEl=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-sidebar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this;this.cursorBtn=document.createElement(`button`),this.cursorBtn.className=`tcw-sidebar-btn`,this.cursorBtn.title=`Cursor`,this.cursorBtn.innerHTML=h(`cursor`,14),this.cursorBtn.addEventListener(`click`,t.onCancelDrawing),n.appendChild(this.cursorBtn),n.appendChild(this.divider()),e.drawingToolGroups.forEach((e,r)=>{let i=document.createElement(`div`);i.className=`tcw-tool-group-wrap`;let a=document.createElement(`button`);if(a.className=`tcw-sidebar-btn`,a.title=e.label,a.innerHTML=h(v[r]??`square`,14),e.tools.length>1){let e=document.createElement(`span`);e.className=`tcw-multi-dot`,a.appendChild(e)}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)});let r=document.createElement(`div`);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=h(`magnet`,14),this.magnetBtn.addEventListener(`click`,t.onToggleMagnet),n.appendChild(this.magnetBtn);let i=document.createElement(`button`);i.className=`tcw-sidebar-btn`,i.title=`Undo`,i.innerHTML=h(`undo`,14),i.addEventListener(`click`,t.onUndo),n.appendChild(i);let a=document.createElement(`button`);a.className=`tcw-sidebar-btn`,a.title=`Redo`,a.innerHTML=h(`redo`,14),a.addEventListener(`click`,t.onRedo),n.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-sidebar-btn tcw-danger`,o.title=`Clear all`,o.innerHTML=h(`trash`,14),o.addEventListener(`click`,t.onClearDrawings),n.appendChild(o)}showFlyout(e){let t=this.config.drawingToolGroups[e];if(!t||t.tools.length<=1)return;this.hideFlyout();let n=document.createElement(`div`);n.className=`tcw-flyout`;let r=document.createElement(`div`);r.className=`tcw-flyout-header`,r.textContent=t.label,n.appendChild(r);for(let e of t.tools){let t=document.createElement(`button`);t.className=`tcw-flyout-item`,t.textContent=e.label,t.dataset.toolValue=e.value,t.addEventListener(`click`,()=>{this.callbacks.onDrawingTool(e.value),this.hideFlyout()}),n.appendChild(t)}this.flyoutEl=n,this.groupWraps[e].appendChild(n)}hideFlyout(){this.flyoutEl&&=(this.flyoutEl.remove(),null)}update(e){this.cursorBtn&&this.cursorBtn.classList.toggle(`tcw-active`,e.activeTool===null);let{drawingToolGroups:t}=this.config;for(let n=0;n<t.length;n++){let r=t[n].tools.some(t=>t.value===e.activeTool);this.groupButtons[n].classList.toggle(`tcw-active`,r)}this.flyoutEl&&this.flyoutEl.querySelectorAll(`.tcw-flyout-item`).forEach(t=>{let n=t;n.classList.toggle(`tcw-active`,n.dataset.toolValue===e.activeTool)}),this.magnetBtn&&(this.magnetBtn.classList.toggle(`tcw-active`,e.magnetEnabled),this.magnetBtn.title=e.magnetEnabled?`Magnet ON`:`Magnet OFF`)}divider(){let e=document.createElement(`div`);return e.className=`tcw-sidebar-divider`,e}destroy(){this.hideFlyout(),this.el.remove()}},b=[`style`,`display`,`scale`],x=class{callbacks;backdrop=null;modal=null;currentTab=`style`;currentSettings=null;bodyEl=null;tabButtons=[];constructor(e){this.callbacks=e}open(e){this.currentSettings={...e},this.currentTab=`style`,this.buildModal()}close(){this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.bodyEl=null,this.tabButtons=[]}buildModal(){this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),document.body.appendChild(this.backdrop),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal`;let e=document.createElement(`div`);e.className=`tcw-modal-header`;let t=document.createElement(`h3`);t.textContent=`Chart Settings`,e.appendChild(t);let n=document.createElement(`button`);n.className=`tcw-modal-close`,n.innerHTML=h(`x`,16),n.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),e.appendChild(n),this.modal.appendChild(e);let r=document.createElement(`div`);r.className=`tcw-modal-tabs`,this.tabButtons=[];for(let e of b){let t=document.createElement(`button`);t.className=`tcw-modal-tab`,t.textContent=e,t.dataset.tab=e,e===this.currentTab&&t.classList.add(`tcw-active`),t.addEventListener(`click`,()=>{this.currentTab=e,this.tabButtons.forEach(t=>t.classList.toggle(`tcw-active`,t.dataset.tab===e)),this.renderTabContent()}),r.appendChild(t),this.tabButtons.push(t)}this.modal.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.modal.appendChild(this.bodyEl),this.renderTabContent();let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.callbacks.onReset()),i.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),i.appendChild(o),this.modal.appendChild(i),document.body.appendChild(this.modal);let s=e=>{e.key===`Escape`&&(document.removeEventListener(`keydown`,s),this.callbacks.onClose(),this.close())};document.addEventListener(`keydown`,s)}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.innerHTML=``,this.currentTab){case`style`:this.renderStyleTab();break;case`display`:this.renderDisplayTab();break;case`scale`:this.renderScaleTab();break}}renderStyleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section(`Candle Colors`);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);let n=this.section(`Background`);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)}renderDisplayTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();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,[{label:`Magnet`,value:`magnet`},{label:`Normal`,value:`normal`},{label:`Hidden`,value:`hidden`}],e=>this.patch({crosshairMode:e}))),t.appendChild(this.selectRow(`Number Locale`,e.numberLocale,[{label:`en-US (65,234.00)`,value:`en-US`},{label:`de-DE (65.234,00)`,value:`de-DE`},{label:`fr-FR (65 234,00)`,value:`fr-FR`},{label:`vi-VN (65.234,00)`,value:`vi-VN`},{label:`en-IN (65,234.00)`,value:`en-IN`},{label:`ja-JP (65,234.00)`,value:`ja-JP`}],e=>this.patch({numberLocale:e}))),this.bodyEl.appendChild(t)}renderScaleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();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)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}section(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n)}return t}colorRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`div`);a.className=`tcw-color-picker-wrap`;let o=document.createElement(`input`);o.type=`color`,o.value=t;let s=document.createElement(`span`);return s.className=`tcw-color-hex`,s.textContent=t,o.addEventListener(`input`,()=>{s.textContent=o.value,n(o.value)}),a.appendChild(o),a.appendChild(s),r.appendChild(a),r}toggleRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`button`);return a.className=`tcw-toggle${t?` tcw-on`:``}`,a.addEventListener(`click`,()=>{let e=!a.classList.contains(`tcw-on`);a.classList.toggle(`tcw-on`,e),n(e)}),r.appendChild(a),r}selectRow(e,t,n,r){let i=document.createElement(`div`);i.className=`tcw-settings-row`;let a=document.createElement(`span`);a.className=`tcw-settings-label`,a.textContent=e,i.appendChild(a);let o=document.createElement(`select`);o.className=`tcw-settings-select`;for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),o.appendChild(n)}return o.addEventListener(`change`,()=>r(o.value)),i.appendChild(o),i}destroy(){this.close()}},S=class{el;dotEl;messageEl;infoEl;constructor(e){this.el=document.createElement(`div`),this.el.className=`tcw-statusbar`;let t=document.createElement(`div`);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)}update(e){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}`}destroy(){this.el.remove()}},C=class{chart;state;toolbar=null;sidebar=null;settings=null;statusBar=null;root;chartContainer;destroyed=!1;options;symbolIndex=0;symbols;settingsState;adapter=null;constructor(t,l={}){this.options=l,this.symbols=l.symbols??s,this.settingsState={...c};let u=this.resolveIsDark(l.theme),d=this.resolveTheme(l.theme);this.state={symbol:l.symbol??this.symbols[0]??`BTCUSDT`,timeframe:l.timeframe??`5m`,chartType:l.chartOptions?.chartType??`candlestick`,isDark:u,activeIndicators:new Map,activeTool:null,magnetEnabled:!0,connectionState:`connecting`,connectionMessage:`Connecting...`};let p=this.symbols.indexOf(this.state.symbol);p>=0&&(this.symbolIndex=p),f(),this.root=document.createElement(`div`),this.root.className=`tcw-root`,this.root.dataset.tcwTheme=u?`dark`:`light`,t.appendChild(this.root),l.toolbar!==!1&&(this.toolbar=new _(this.root,{symbols:this.symbols,timeframes:l.timeframes?n.filter(e=>l.timeframes.includes(e.value)):n,chartTypes:l.chartTypes?r.filter(e=>l.chartTypes.includes(e.value)):r,indicators:a,popularIndicatorIds:o},{onSymbolClick:()=>this.handleSymbolClick(),onTimeframe:e=>this.handleTimeframe(e),onChartType:e=>this.handleChartType(e),onAddIndicator:e=>this.handleAddIndicator(e),onRemoveIndicator:e=>this.handleRemoveIndicator(e),onScreenshot:()=>this.chart.screenshot(),onSettings:()=>this.openSettings(),onToggleTheme:()=>this.handleToggleTheme()}));let m=document.createElement(`div`);m.className=`tcw-body`,l.drawingTools!==!1&&(this.sidebar=new y(m,{drawingToolGroups:i},{onDrawingTool:e=>this.handleDrawingTool(e),onCancelDrawing:()=>this.handleCancelDrawing(),onToggleMagnet:()=>this.handleToggleMagnet(),onUndo:()=>this.chart.undo(),onRedo:()=>this.chart.redo(),onClearDrawings:()=>{this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI()}})),this.chartContainer=document.createElement(`div`),this.chartContainer.className=`tcw-chart-container`,m.appendChild(this.chartContainer),this.root.appendChild(m),this.chart=new e.t(this.chartContainer,{chartType:this.state.chartType,theme:d,autoScale:!0,crosshair:{mode:`magnet`},features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:l.trading!==!1,tradingContextMenu:l.trading!==!1,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0},...l.chartOptions}),l.statusBar!==!1&&(this.statusBar=new S(this.root)),l.settings!==!1&&(this.settings=new x({onChange:e=>this.applySettings(e),onReset:()=>this.resetSettings(),onClose:()=>{}})),l.adapter&&(this.adapter=l.adapter,this.connectStream()),this.updateUI(),l.onReady?.(this.chart)}async setSymbol(e){this.state={...this.state,symbol:e};let t=this.symbols.indexOf(e);t>=0&&(this.symbolIndex=t),this.options.onSymbolChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}async setTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}setTheme(e){let t=this.resolveIsDark(e),n=this.resolveTheme(e);this.state={...this.state,isDark:t},this.root.dataset.tcwTheme=t?`dark`:`light`,this.chart.setTheme(n),this.updateUI()}getChart(){return this.chart}destroy(){this.destroyed||(this.destroyed=!0,this.toolbar?.destroy(),this.sidebar?.destroy(),this.settings?.destroy(),this.statusBar?.destroy(),this.chart.destroy(),this.root.remove(),p())}handleSymbolClick(){this.symbolIndex=(this.symbolIndex+1)%this.symbols.length;let e=this.symbols[this.symbolIndex];this.state={...this.state,symbol:e},this.options.onSymbolChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleChartType(e){this.state={...this.state,chartType:e},this.chart.setChartType(e),this.updateUI()}handleAddIndicator(e){if(this.state.activeIndicators.has(e)){let t=this.state.activeIndicators.get(e);this.chart.removeIndicator(t);let n=new Map(this.state.activeIndicators);n.delete(e),this.state={...this.state,activeIndicators:n}}else{let t=this.chart.addIndicator(e);if(t){let n=new Map(this.state.activeIndicators);n.set(e,t),this.state={...this.state,activeIndicators:n}}}this.updateUI()}handleRemoveIndicator(e){this.chart.removeIndicator(e);let t=new Map(this.state.activeIndicators);for(let[n,r]of t.entries())if(r===e){t.delete(n);break}this.state={...this.state,activeIndicators:t},this.updateUI()}handleDrawingTool(e){this.state={...this.state,activeTool:e},this.chart.setDrawingTool(e),this.updateUI()}handleCancelDrawing(){this.state={...this.state,activeTool:null},this.chart.setDrawingTool(null),this.updateUI()}handleToggleMagnet(){let e=!this.state.magnetEnabled;this.state={...this.state,magnetEnabled:e},this.chart.setDrawingMagnet(e),this.updateUI()}handleToggleTheme(){let e=!this.state.isDark;this.state={...this.state,isDark:e},this.root.dataset.tcwTheme=e?`dark`:`light`,this.chart.setTheme(e?t.DARK_THEME:t.LIGHT_THEME),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:e?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.updateUI()}openSettings(){this.settings?.open(this.settingsState)}applySettings(e){this.settingsState={...this.settingsState,...e},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);let t={...this.chart.getTheme()},n=!1;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)}resetSettings(){this.settingsState={...c},this.applySettings(this.settingsState)}async connectStream(){if(this.adapter){this.state={...this.state,connectionState:`connecting`,connectionMessage:`Connecting...`},this.updateUI();try{this.chart.disconnectStream(),await this.chart.connect({adapter:this.adapter,symbol:this.state.symbol,timeframe:this.state.timeframe,historyLimit:this.options.historyLimit??500}),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:this.state.isDark?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.state={...this.state,connectionState:`connected`,connectionMessage:`Live`}}catch(e){this.state={...this.state,connectionState:`error`,connectionMessage:e instanceof Error?e.message:`Connection failed`}}this.updateUI()}}updateUI(){this.toolbar?.update(this.state),this.sidebar?.update(this.state),this.statusBar?.update({connectionState:this.state.connectionState,message:this.state.connectionMessage,symbol:this.state.symbol,timeframe:this.state.timeframe})}resolveIsDark(e){return e===void 0||e===`dark`?!0:e===`light`?!1:typeof e==`object`&&e.background?this.isColorDark(e.background):!0}resolveTheme(e){return e===void 0||e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:typeof e==`object`?e:t.DARK_THEME}isColorDark(e){if(e.startsWith(`#`)&&e.length>=7){let t=parseInt(e.slice(1,3),16),n=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return t+n+r<384}return!0}};exports.ChartWidget=C;
740
+ //# sourceMappingURL=index.cjs.map