@tradecanvas/chart 0.8.2 → 0.9.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 (42) hide show
  1. package/README.md +86 -4
  2. package/dist/Chart.d.ts +11 -0
  3. package/dist/Chart.d.ts.map +1 -1
  4. package/dist/{Chart-Cn_TSMO7.js → DragDropImporter-6QOjnfSj.js} +361 -85
  5. package/dist/DragDropImporter-6QOjnfSj.js.map +1 -0
  6. package/dist/DragDropImporter-CQ3EarQn.cjs +2 -0
  7. package/dist/DragDropImporter-CQ3EarQn.cjs.map +1 -0
  8. package/dist/index.cjs +1 -1
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +26 -26
  13. package/dist/index.js.map +1 -1
  14. package/dist/io/DragDropImporter.d.ts +34 -0
  15. package/dist/io/DragDropImporter.d.ts.map +1 -0
  16. package/dist/io/index.d.ts +5 -0
  17. package/dist/io/index.d.ts.map +1 -0
  18. package/dist/io/parseOHLCV.d.ts +21 -0
  19. package/dist/io/parseOHLCV.d.ts.map +1 -0
  20. package/dist/widget/ChartWidget.d.ts +46 -1
  21. package/dist/widget/ChartWidget.d.ts.map +1 -1
  22. package/dist/widget/WidgetHotkeySheet.d.ts +20 -0
  23. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -0
  24. package/dist/widget/WidgetReplayBar.d.ts +41 -0
  25. package/dist/widget/WidgetReplayBar.d.ts.map +1 -0
  26. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  27. package/dist/widget/WidgetSymbolSearch.d.ts +32 -0
  28. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -0
  29. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  30. package/dist/widget/WidgetWatchlist.d.ts +39 -0
  31. package/dist/widget/WidgetWatchlist.d.ts.map +1 -0
  32. package/dist/widget/index.cjs +1455 -877
  33. package/dist/widget/index.cjs.map +1 -1
  34. package/dist/widget/index.js +695 -92
  35. package/dist/widget/index.js.map +1 -1
  36. package/dist/widget/types.d.ts +19 -0
  37. package/dist/widget/types.d.ts.map +1 -1
  38. package/dist/widget/widgetConfig.d.ts.map +1 -1
  39. package/package.json +3 -3
  40. package/dist/Chart-Br_N-BCL.cjs +0 -2
  41. package/dist/Chart-Br_N-BCL.cjs.map +0 -1
  42. package/dist/Chart-Cn_TSMO7.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { t as e } from "../Chart-Cn_TSMO7.js";
2
- import { DARK_THEME as t, LIGHT_THEME as n } from "@tradecanvas/commons";
1
+ import { r as e, t } from "../DragDropImporter-6QOjnfSj.js";
2
+ import { DARK_THEME as n, LIGHT_THEME as r } from "@tradecanvas/commons";
3
3
  //#region src/widget/widgetConfig.ts
4
- var r = [
4
+ var i = [
5
5
  {
6
6
  label: "1m",
7
7
  value: "1m"
@@ -26,7 +26,7 @@ var r = [
26
26
  label: "1D",
27
27
  value: "1d"
28
28
  }
29
- ], i = [
29
+ ], a = [
30
30
  {
31
31
  label: "Candlestick",
32
32
  value: "candlestick"
@@ -75,7 +75,7 @@ var r = [
75
75
  label: "Line + Markers",
76
76
  value: "lineWithMarkers"
77
77
  }
78
- ], a = [
78
+ ], o = [
79
79
  {
80
80
  label: "Lines",
81
81
  tools: [
@@ -188,7 +188,7 @@ var r = [
188
188
  value: "arrow"
189
189
  }]
190
190
  }
191
- ], o = [
191
+ ], s = [
192
192
  {
193
193
  id: "sma",
194
194
  name: "SMA",
@@ -354,7 +354,7 @@ var r = [
354
354
  name: "Volume Profile",
355
355
  type: "panel"
356
356
  }
357
- ], s = [
357
+ ], c = [
358
358
  "sma",
359
359
  "ema",
360
360
  "bb",
@@ -365,12 +365,12 @@ var r = [
365
365
  "atr",
366
366
  "obv",
367
367
  "ichimoku"
368
- ], c = [
368
+ ], l = [
369
369
  "BTCUSDT",
370
370
  "ETHUSDT",
371
371
  "SOLUSDT",
372
372
  "BNBUSDT"
373
- ], l = {
373
+ ], u = {
374
374
  candleUpColor: "#26A69A",
375
375
  candleDownColor: "#EF5350",
376
376
  candleUpWick: "#26A69A",
@@ -379,26 +379,27 @@ var r = [
379
379
  gridColor: "#1E222D",
380
380
  gridVisible: !0,
381
381
  volumeVisible: !0,
382
+ volumeProfileVisible: !1,
382
383
  legendVisible: !0,
383
384
  barCountdown: !0,
384
385
  logScale: !1,
385
386
  autoScale: !0,
386
387
  crosshairMode: "magnet",
387
388
  numberLocale: "en-US"
388
- }, 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";
389
- function p() {
390
- if (d++, d > 1 || document.getElementById(f)) return;
389
+ }, d = "/* === TradeCanvas Widget — Premium Styles === */\n\n.tcw-root {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;\n font-feature-settings: 'cv11', 'ss01', 'ss03';\n font-size: 13px;\n line-height: 1.4;\n color: #d1d4dc;\n background: #0d0f17;\n position: relative;\n overflow: hidden;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* --- Dark theme tokens (default) --- */\n --tcw-bg: #0d0f17;\n --tcw-bg-surface: #131722;\n --tcw-bg-elevated: #1a1e2d;\n --tcw-bg-overlay: #20253480;\n --tcw-border: #2a2e39;\n --tcw-border-strong: #363a45;\n --tcw-text: #e9ebf0;\n --tcw-text-dim: #b2b5be;\n --tcw-text-muted: #6b6f7a;\n\n --tcw-accent: #4f88ff;\n --tcw-accent-hover: #6b9aff;\n --tcw-accent-soft: rgba(79, 136, 255, 0.14);\n --tcw-accent-glow: rgba(79, 136, 255, 0.22);\n --tcw-accent-line: rgba(79, 136, 255, 0.55);\n\n --tcw-red: #f23645;\n --tcw-red-soft: rgba(242, 54, 69, 0.12);\n --tcw-green: #26a17b;\n --tcw-green-soft: rgba(38, 161, 123, 0.12);\n --tcw-amber: #ff9f43;\n\n --tcw-hover-bg: rgba(255, 255, 255, 0.05);\n --tcw-active-bg: rgba(255, 255, 255, 0.08);\n --tcw-divider: rgba(255, 255, 255, 0.06);\n\n /* Motion */\n --tcw-ease: cubic-bezier(0.2, 0, 0, 1);\n --tcw-ease-out: cubic-bezier(0.16, 1, 0.3, 1);\n --tcw-dur-fast: 120ms;\n --tcw-dur-normal: 180ms;\n --tcw-dur-slow: 260ms;\n\n /* Shape */\n --tcw-radius-sm: 4px;\n --tcw-radius: 6px;\n --tcw-radius-lg: 10px;\n --tcw-radius-xl: 14px;\n\n /* Elevation */\n --tcw-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);\n --tcw-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.2);\n --tcw-shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3);\n --tcw-shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.55), 0 12px 24px rgba(0, 0, 0, 0.35);\n --tcw-ring: 0 0 0 2px rgba(79, 136, 255, 0.45);\n\n /* Type */\n --tcw-font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', 'Consolas', ui-monospace, monospace;\n}\n\n.tcw-root[data-tcw-theme='light'] {\n color: #131722;\n background: #fcfcfd;\n\n --tcw-bg: #fcfcfd;\n --tcw-bg-surface: #ffffff;\n --tcw-bg-elevated: #ffffff;\n --tcw-bg-overlay: rgba(255, 255, 255, 0.75);\n --tcw-border: #e7e9ef;\n --tcw-border-strong: #d4d7e0;\n --tcw-text: #131722;\n --tcw-text-dim: #50545e;\n --tcw-text-muted: #8b8f99;\n\n --tcw-accent: #2962ff;\n --tcw-accent-hover: #1e4fd6;\n --tcw-accent-soft: rgba(41, 98, 255, 0.10);\n --tcw-accent-glow: rgba(41, 98, 255, 0.16);\n --tcw-accent-line: rgba(41, 98, 255, 0.45);\n\n --tcw-hover-bg: rgba(0, 0, 0, 0.04);\n --tcw-active-bg: rgba(41, 98, 255, 0.08);\n --tcw-divider: rgba(0, 0, 0, 0.06);\n\n --tcw-shadow-sm: 0 1px 2px rgba(20, 28, 56, 0.05);\n --tcw-shadow-md: 0 4px 12px rgba(20, 28, 56, 0.08), 0 1px 3px rgba(20, 28, 56, 0.04);\n --tcw-shadow-lg: 0 12px 36px rgba(20, 28, 56, 0.14), 0 4px 12px rgba(20, 28, 56, 0.08);\n --tcw-shadow-xl: 0 24px 64px rgba(20, 28, 56, 0.18), 0 12px 24px rgba(20, 28, 56, 0.1);\n}\n\n/* === Toolbar === */\n\n.tcw-toolbar {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 10px;\n height: 44px;\n border-bottom: 1px solid var(--tcw-border);\n background:\n linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);\n flex-shrink: 0;\n position: relative;\n z-index: 20;\n box-shadow: var(--tcw-shadow-sm);\n}\n\n.tcw-toolbar-symbol {\n font-size: 14px;\n font-weight: 650;\n color: var(--tcw-text);\n padding: 6px 12px;\n white-space: nowrap;\n letter-spacing: -0.015em;\n cursor: pointer;\n border: none;\n background: transparent;\n font-family: inherit;\n border-radius: var(--tcw-radius);\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-toolbar-symbol:hover {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-toolbar-sep {\n width: 1px;\n height: 22px;\n background: var(--tcw-border);\n flex-shrink: 0;\n margin: 0 4px;\n}\n\n.tcw-toolbar-group {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 0 4px;\n}\n\n.tcw-toolbar-spacer {\n flex: 1;\n}\n\n.tcw-btn {\n padding: 6px 10px;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n color var(--tcw-dur-fast) var(--tcw-ease),\n transform var(--tcw-dur-fast) var(--tcw-ease);\n white-space: nowrap;\n line-height: 1;\n letter-spacing: -0.005em;\n}\n\n.tcw-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-btn:active {\n transform: translateY(0.5px);\n}\n\n.tcw-btn.tcw-active {\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n font-weight: 600;\n box-shadow: inset 0 0 0 1px var(--tcw-accent-line);\n}\n\n.tcw-btn:focus-visible,\n.tcw-btn-icon:focus-visible,\n.tcw-sidebar-btn:focus-visible,\n.tcw-dropdown-trigger:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-btn-icon {\n width: 32px;\n height: 32px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n color var(--tcw-dur-fast) var(--tcw-ease);\n line-height: 1;\n position: relative;\n}\n\n.tcw-btn-icon:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-btn-icon svg {\n display: block;\n}\n\n.tcw-badge-count {\n font-size: 10px;\n font-weight: 600;\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n padding: 1px 5px;\n border-radius: 9px;\n font-family: var(--tcw-font-mono);\n}\n\n.tcw-indicator-chips {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 4px;\n flex-wrap: nowrap;\n overflow: hidden;\n}\n\n.tcw-indicator-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 6px 3px 9px;\n font-size: 11px;\n font-weight: 500;\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n border-radius: 9999px;\n white-space: nowrap;\n line-height: 1.4;\n letter-spacing: -0.005em;\n border: 1px solid transparent;\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-indicator-chip:hover {\n border-color: var(--tcw-accent-line);\n}\n\n.tcw-chip-remove {\n cursor: pointer;\n opacity: 0.55;\n padding: 0 2px;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n border: none;\n background: transparent;\n color: inherit;\n display: inline-flex;\n align-items: center;\n}\n\n.tcw-chip-remove:hover {\n opacity: 1;\n}\n\n/* === Dropdown === */\n\n.tcw-dropdown-trigger {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 6px 10px;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n white-space: nowrap;\n line-height: 1;\n}\n\n.tcw-dropdown-trigger:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-dropdown {\n position: absolute;\n top: 100%;\n margin-top: 6px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n z-index: 50;\n padding: 6px;\n max-height: 420px;\n overflow-y: auto;\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n@keyframes tcw-pop-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n.tcw-dropdown-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 7px 10px;\n font-size: 12.5px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n width: 100%;\n border: none;\n background: transparent;\n font-family: inherit;\n text-align: left;\n border-radius: var(--tcw-radius-sm);\n gap: 12px;\n}\n\n.tcw-dropdown-item:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-dropdown-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: 600;\n}\n\n.tcw-dropdown-label {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.08em;\n padding: 8px 10px 4px;\n font-weight: 600;\n}\n\n.tcw-dropdown-divider {\n border-top: 1px solid var(--tcw-divider);\n margin: 6px 4px;\n}\n\n.tcw-tag {\n font-size: 10px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--tcw-hover-bg);\n letter-spacing: 0.02em;\n}\n\n/* === Body === */\n\n.tcw-body {\n display: flex;\n flex: 1;\n min-height: 0;\n background: var(--tcw-bg);\n}\n\n.tcw-chart-container {\n flex: 1;\n min-width: 0;\n min-height: 0;\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n/* === Sidebar === */\n\n.tcw-sidebar {\n width: 40px;\n flex-shrink: 0;\n background: linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);\n border-right: 1px solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 6px 0;\n overflow: visible;\n box-shadow: var(--tcw-shadow-sm);\n}\n\n.tcw-tool-group-wrap {\n position: relative;\n}\n\n.tcw-sidebar-btn {\n width: 32px;\n height: 32px;\n margin: 1px 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n font-family: inherit;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n color var(--tcw-dur-fast) var(--tcw-ease);\n position: relative;\n flex-shrink: 0;\n line-height: 1;\n border-radius: var(--tcw-radius);\n}\n\n.tcw-sidebar-btn:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-sidebar-btn.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n box-shadow: inset 2px 0 0 var(--tcw-accent);\n}\n\n.tcw-sidebar-btn.tcw-danger:hover {\n color: var(--tcw-red);\n background: var(--tcw-red-soft);\n}\n\n.tcw-multi-dot {\n position: absolute;\n bottom: 3px;\n right: 3px;\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n opacity: 0.7;\n}\n\n.tcw-sidebar-divider {\n width: 22px;\n height: 1px;\n background: var(--tcw-divider);\n margin: 6px 0;\n flex-shrink: 0;\n}\n\n.tcw-sidebar-spacer {\n flex: 1;\n}\n\n/* === Flyout === */\n\n.tcw-flyout {\n position: absolute;\n left: 100%;\n top: 0;\n margin-left: 6px;\n min-width: 180px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n z-index: 30;\n padding: 6px;\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n animation: tcw-slide-right var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n@keyframes tcw-slide-right {\n from { opacity: 0; transform: translateX(-4px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n.tcw-flyout-header {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.08em;\n padding: 6px 10px 4px;\n font-weight: 600;\n}\n\n.tcw-flyout-item {\n padding: 7px 10px;\n font-size: 12.5px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n display: block;\n border: none;\n background: transparent;\n text-align: left;\n font-family: inherit;\n border-radius: var(--tcw-radius-sm);\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-flyout-item:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-flyout-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: 600;\n}\n\n/* === Modal === */\n\n.tcw-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(8, 10, 18, 0.55);\n backdrop-filter: blur(6px) saturate(140%);\n -webkit-backdrop-filter: blur(6px) saturate(140%);\n z-index: 100;\n animation: tcw-fade-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n@keyframes tcw-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.tcw-modal {\n position: fixed;\n z-index: 101;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-xl);\n width: 520px;\n max-width: 92vw;\n max-height: 82vh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--tcw-shadow-xl);\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n}\n\n@keyframes tcw-modal-in {\n from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }\n to { opacity: 1; transform: translate(-50%, -50%) scale(1); }\n}\n\n.tcw-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 22px;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-modal-header h3 {\n font-size: 15px;\n font-weight: 650;\n margin: 0;\n color: var(--tcw-text);\n letter-spacing: -0.015em;\n}\n\n.tcw-modal-close {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n border-radius: var(--tcw-radius);\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-modal-close:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-modal-tabs {\n display: flex;\n gap: 4px;\n padding: 0 18px;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-modal-tab {\n padding: 11px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--tcw-text-muted);\n border: none;\n background: transparent;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n font-family: inherit;\n text-transform: capitalize;\n letter-spacing: -0.005em;\n}\n\n.tcw-modal-tab:hover {\n color: var(--tcw-text-dim);\n}\n\n.tcw-modal-tab.tcw-active {\n color: var(--tcw-accent);\n border-bottom-color: var(--tcw-accent);\n font-weight: 600;\n}\n\n.tcw-modal-body {\n padding: 20px 22px;\n overflow-y: auto;\n flex: 1;\n}\n\n.tcw-settings-section {\n margin-bottom: 22px;\n}\n\n.tcw-settings-section:last-child {\n margin-bottom: 0;\n}\n\n.tcw-settings-section-title {\n font-size: 10.5px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.09em;\n color: var(--tcw-text-muted);\n margin-bottom: 12px;\n}\n\n.tcw-settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 0;\n}\n\n.tcw-settings-row + .tcw-settings-row {\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-settings-label {\n font-size: 13px;\n color: var(--tcw-text-dim);\n letter-spacing: -0.005em;\n}\n\n.tcw-color-picker-wrap {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.tcw-color-picker-wrap input[type='color'] {\n width: 28px;\n height: 28px;\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n cursor: pointer;\n padding: 2px;\n}\n\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {\n border: none;\n border-radius: 2px;\n}\n\n.tcw-color-hex {\n font-size: 11px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n min-width: 64px;\n letter-spacing: 0.01em;\n}\n\n.tcw-toggle {\n width: 36px;\n height: 20px;\n background: rgba(255, 255, 255, 0.12);\n border-radius: 10px;\n position: relative;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n border: none;\n padding: 0;\n flex-shrink: 0;\n}\n\n.tcw-toggle::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n transition:\n left var(--tcw-dur-normal) var(--tcw-ease-out),\n background var(--tcw-dur-fast) var(--tcw-ease);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n}\n\n.tcw-toggle.tcw-on {\n background: var(--tcw-accent);\n box-shadow: 0 0 0 2px var(--tcw-accent-glow);\n}\n\n.tcw-toggle.tcw-on::after {\n left: 18px;\n background: #fff;\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle {\n background: rgba(0, 0, 0, 0.12);\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle::after {\n background: #999;\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on {\n background: var(--tcw-accent);\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on::after {\n background: #fff;\n}\n\n.tcw-settings-select {\n padding: 6px 10px;\n font-size: 12px;\n font-family: inherit;\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius);\n color: var(--tcw-text);\n cursor: pointer;\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-settings-select:hover {\n border-color: var(--tcw-border-strong);\n}\n\n.tcw-settings-select:focus-visible {\n outline: none;\n border-color: var(--tcw-accent);\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-modal-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 22px;\n border-top: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n border-radius: 0 0 var(--tcw-radius-xl) var(--tcw-radius-xl);\n}\n\n.tcw-reset-link {\n font-size: 12px;\n color: var(--tcw-text-muted);\n cursor: pointer;\n border: none;\n background: transparent;\n font-family: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n text-decoration-color: var(--tcw-border-strong);\n transition: color var(--tcw-dur-fast) var(--tcw-ease), text-decoration-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-reset-link:hover {\n color: var(--tcw-text-dim);\n text-decoration-color: currentColor;\n}\n\n.tcw-done-btn {\n padding: 8px 18px;\n font-size: 12.5px;\n font-weight: 600;\n background: var(--tcw-accent);\n color: #fff;\n border: none;\n border-radius: var(--tcw-radius);\n cursor: pointer;\n font-family: inherit;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n transform var(--tcw-dur-fast) var(--tcw-ease),\n box-shadow var(--tcw-dur-fast) var(--tcw-ease);\n letter-spacing: -0.005em;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.15);\n}\n\n.tcw-done-btn:hover {\n background: var(--tcw-accent-hover);\n box-shadow: var(--tcw-shadow-md), 0 0 0 3px var(--tcw-accent-glow);\n}\n\n.tcw-done-btn:active {\n transform: translateY(0.5px);\n}\n\n/* === Status Bar === */\n\n.tcw-statusbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 7px 16px;\n border-top: 1px solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n font-size: 11px;\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n font-feature-settings: 'tnum';\n}\n\n.tcw-status-indicator {\n display: flex;\n align-items: center;\n gap: 7px;\n font-weight: 500;\n}\n\n.tcw-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n transition: background var(--tcw-dur-normal) var(--tcw-ease), box-shadow var(--tcw-dur-normal) var(--tcw-ease);\n position: relative;\n}\n\n.tcw-status-dot.tcw-connected {\n background: var(--tcw-green);\n box-shadow: 0 0 0 3px rgba(38, 161, 123, 0.18);\n}\n\n.tcw-status-dot.tcw-connected::after {\n content: '';\n position: absolute;\n inset: -3px;\n border-radius: 50%;\n border: 2px solid var(--tcw-green);\n opacity: 0;\n animation: tcw-pulse 2.2s ease-out infinite;\n}\n\n@keyframes tcw-pulse {\n 0% { opacity: 0.6; transform: scale(0.6); }\n 100% { opacity: 0; transform: scale(2.2); }\n}\n\n.tcw-status-dot.tcw-error {\n background: var(--tcw-red);\n box-shadow: 0 0 0 3px rgba(242, 54, 69, 0.2);\n}\n\n/* === Command Palette === */\n\n.tcw-cmd-palette {\n position: fixed;\n z-index: 102;\n top: 18%;\n left: 50%;\n transform: translateX(-50%);\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-xl);\n width: 560px;\n max-width: 92vw;\n max-height: 62vh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--tcw-shadow-xl);\n overflow: hidden;\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n}\n\n.tcw-cmd-header {\n display: flex;\n align-items: center;\n padding: 14px 18px;\n border-bottom: 1px solid var(--tcw-divider);\n gap: 12px;\n}\n\n.tcw-cmd-icon {\n font-size: 18px;\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n}\n\n.tcw-cmd-input {\n flex: 1;\n background: transparent;\n border: none;\n outline: none;\n font-size: 14.5px;\n font-family: inherit;\n color: var(--tcw-text);\n caret-color: var(--tcw-accent);\n letter-spacing: -0.005em;\n}\n\n.tcw-cmd-input::placeholder {\n color: var(--tcw-text-muted);\n}\n\n.tcw-cmd-hint {\n font-size: 10px;\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n border: 1px solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n padding: 3px 7px;\n border-radius: 4px;\n flex-shrink: 0;\n box-shadow: inset 0 -1px 0 var(--tcw-border);\n}\n\n.tcw-cmd-list {\n overflow-y: auto;\n flex: 1;\n padding: 6px;\n max-height: 380px;\n}\n\n.tcw-cmd-category {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.09em;\n padding: 10px 10px 4px;\n font-weight: 600;\n}\n\n.tcw-cmd-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 9px 12px;\n font-size: 13px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n border: none;\n background: transparent;\n font-family: inherit;\n text-align: left;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n gap: 10px;\n border-radius: var(--tcw-radius);\n letter-spacing: -0.005em;\n}\n\n.tcw-cmd-item:hover,\n.tcw-cmd-item.tcw-selected {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-cmd-item.tcw-selected {\n box-shadow: inset 2px 0 0 var(--tcw-accent);\n}\n\n.tcw-cmd-item.tcw-active .tcw-cmd-item-label {\n color: var(--tcw-accent);\n font-weight: 600;\n}\n\n.tcw-cmd-item-label {\n flex: 1;\n}\n\n.tcw-cmd-check {\n color: var(--tcw-accent);\n font-size: 14px;\n font-weight: 700;\n}\n\n.tcw-cmd-kbd {\n font-size: 10px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n padding: 2px 6px;\n border-radius: 4px;\n box-shadow: inset 0 -1px 0 var(--tcw-border);\n}\n\n.tcw-cmd-empty {\n padding: 32px 16px;\n text-align: center;\n color: var(--tcw-text-muted);\n font-size: 13px;\n}\n\n.tcw-cmd-footer {\n display: flex;\n align-items: center;\n gap: 18px;\n padding: 10px 18px;\n border-top: 1px solid var(--tcw-divider);\n font-size: 11px;\n color: var(--tcw-text-muted);\n background: var(--tcw-bg-surface);\n}\n\n/* === Watchlist === */\n\n.tcw-watchlist {\n width: 220px;\n flex-shrink: 0;\n background: var(--tcw-bg-surface);\n border-left: 1px solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n box-shadow: var(--tcw-shadow-sm);\n}\n\n.tcw-watchlist-header {\n padding: 10px 14px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--tcw-text-muted);\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-watchlist-list {\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.tcw-watchlist-row {\n display: grid;\n grid-template-columns: 1fr auto auto;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n border-left: 2px solid transparent;\n outline: none;\n}\n\n.tcw-watchlist-row:hover {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-watchlist-row:focus-visible {\n background: var(--tcw-hover-bg);\n border-left-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-row.tcw-watchlist-active {\n background: var(--tcw-accent-soft);\n border-left-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-symbol {\n font-size: 12.5px;\n font-weight: 600;\n color: var(--tcw-text);\n letter-spacing: -0.005em;\n white-space: nowrap;\n}\n\n.tcw-watchlist-spark {\n width: 56px;\n height: 22px;\n align-self: center;\n}\n\n.tcw-watchlist-stats {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 1px;\n font-variant-numeric: tabular-nums;\n font-family: var(--tcw-font-mono);\n}\n\n.tcw-watchlist-price {\n font-size: 12px;\n color: var(--tcw-text);\n font-weight: 500;\n}\n\n.tcw-watchlist-change {\n font-size: 10.5px;\n color: var(--tcw-text-muted);\n font-weight: 500;\n}\n\n.tcw-watchlist-change.tcw-up {\n color: var(--tcw-green);\n}\n\n.tcw-watchlist-change.tcw-down {\n color: var(--tcw-red);\n}\n\n@media (max-width: 768px) {\n .tcw-watchlist {\n display: none;\n }\n}\n\n/* === Toast === */\n\n.tcw-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translate(-50%, 12px);\n z-index: 40;\n padding: 9px 14px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: 9999px;\n box-shadow: var(--tcw-shadow-lg);\n font-size: 12.5px;\n font-weight: 500;\n color: var(--tcw-text);\n opacity: 0;\n transition: opacity var(--tcw-dur-normal) var(--tcw-ease-out), transform var(--tcw-dur-normal) var(--tcw-ease-out);\n pointer-events: none;\n max-width: calc(100% - 32px);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n letter-spacing: -0.005em;\n}\n\n.tcw-toast.tcw-toast-in {\n opacity: 1;\n transform: translate(-50%, 0);\n}\n\n.tcw-toast-error {\n border-color: var(--tcw-red);\n color: var(--tcw-red);\n}\n\n/* === Replay scrubber === */\n\n.tcw-replay-bar {\n position: absolute;\n left: 50%;\n bottom: 16px;\n transform: translateX(-50%);\n z-index: 25;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: 9999px;\n box-shadow: var(--tcw-shadow-lg);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n font-size: 12px;\n color: var(--tcw-text);\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n.tcw-replay-btn {\n width: 28px;\n height: 28px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--tcw-text-dim);\n border-radius: 9999px;\n cursor: pointer;\n font-family: inherit;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-replay-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-replay-btn.tcw-replay-play {\n background: var(--tcw-accent);\n color: #fff;\n width: 32px;\n height: 32px;\n box-shadow: 0 0 0 3px var(--tcw-accent-glow);\n}\n\n.tcw-replay-btn.tcw-replay-play:hover {\n background: var(--tcw-accent-hover);\n}\n\n.tcw-replay-scrubber {\n appearance: none;\n -webkit-appearance: none;\n width: 220px;\n height: 4px;\n background: var(--tcw-border-strong);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n}\n\n.tcw-replay-scrubber::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--tcw-accent);\n border: 2px solid var(--tcw-bg-elevated);\n box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n}\n\n.tcw-replay-scrubber::-moz-range-thumb {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--tcw-accent);\n border: 2px solid var(--tcw-bg-elevated);\n box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n}\n\n.tcw-replay-progress {\n font-size: 11px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n min-width: 64px;\n text-align: center;\n font-feature-settings: 'tnum';\n}\n\n.tcw-replay-speed {\n padding: 4px 8px;\n font-size: 11px;\n font-family: var(--tcw-font-mono);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius);\n color: var(--tcw-text-dim);\n cursor: pointer;\n}\n\n.tcw-replay-speed:hover {\n border-color: var(--tcw-border-strong);\n}\n\n@media (max-width: 640px) {\n .tcw-replay-scrubber {\n width: 140px;\n }\n .tcw-replay-progress {\n display: none;\n }\n}\n\n/* === Hotkey sheet === */\n\n.tcw-hotkey-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 24px 32px;\n}\n\n.tcw-hotkey-section .tcw-settings-section-title {\n margin-bottom: 8px;\n}\n\n.tcw-hotkey-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 6px 0;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-hotkey-row:last-child {\n border-bottom: none;\n}\n\n.tcw-hotkey-keys {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.tcw-hotkey-sep {\n font-size: 10px;\n color: var(--tcw-text-muted);\n}\n\n.tcw-hotkey-label {\n font-size: 12.5px;\n color: var(--tcw-text-dim);\n text-align: right;\n letter-spacing: -0.005em;\n}\n\n@media (max-width: 640px) {\n .tcw-hotkey-grid {\n grid-template-columns: 1fr;\n gap: 18px;\n }\n}\n\n/* === Scrollbar (subtle, premium feel) === */\n\n.tcw-dropdown::-webkit-scrollbar,\n.tcw-modal-body::-webkit-scrollbar,\n.tcw-cmd-list::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.tcw-dropdown::-webkit-scrollbar-track,\n.tcw-modal-body::-webkit-scrollbar-track,\n.tcw-cmd-list::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.tcw-dropdown::-webkit-scrollbar-thumb,\n.tcw-modal-body::-webkit-scrollbar-thumb,\n.tcw-cmd-list::-webkit-scrollbar-thumb {\n background: var(--tcw-border-strong);\n border-radius: 4px;\n border: 2px solid transparent;\n background-clip: padding-box;\n}\n\n.tcw-dropdown::-webkit-scrollbar-thumb:hover,\n.tcw-modal-body::-webkit-scrollbar-thumb:hover,\n.tcw-cmd-list::-webkit-scrollbar-thumb:hover {\n background: var(--tcw-text-muted);\n background-clip: padding-box;\n border: 2px solid transparent;\n}\n\n/* === Responsive === */\n\n@media (max-width: 768px) {\n .tcw-toolbar {\n padding: 0 6px;\n height: 40px;\n }\n .tcw-toolbar-sep {\n display: none;\n }\n .tcw-indicator-chips {\n display: none;\n }\n .tcw-sidebar {\n width: 36px;\n }\n .tcw-sidebar-btn {\n width: 28px;\n height: 28px;\n }\n .tcw-modal {\n width: 94vw;\n border-radius: var(--tcw-radius-lg);\n }\n .tcw-cmd-palette {\n width: 94vw;\n border-radius: var(--tcw-radius-lg);\n }\n}\n\n/* === Reduced motion === */\n\n@media (prefers-reduced-motion: reduce) {\n .tcw-root *,\n .tcw-root *::before,\n .tcw-root *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n", f = 0, p = "tcw-styles";
390
+ function m() {
391
+ if (f++, f > 1 || document.getElementById(p)) return;
391
392
  let e = document.createElement("style");
392
- e.id = f, e.textContent = u, document.head.appendChild(e);
393
+ e.id = p, e.textContent = d, document.head.appendChild(e);
393
394
  }
394
- function m() {
395
- if (d--, d > 0) return;
396
- let e = document.getElementById(f);
395
+ function h() {
396
+ if (f--, f > 0) return;
397
+ let e = document.getElementById(p);
397
398
  e && e.remove();
398
399
  }
399
400
  //#endregion
400
401
  //#region src/widget/icons.ts
401
- var h = {
402
+ var g = {
402
403
  cursor: "<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>",
403
404
  trendingUp: "<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>",
404
405
  minus: "<path d=\"M5 12h14\"/>",
@@ -425,13 +426,13 @@ var h = {
425
426
  stop: "<rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"1\"/>",
426
427
  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\"/>"
427
428
  };
428
- function g(e, t = 14) {
429
- let n = h[e];
429
+ function _(e, t = 14) {
430
+ let n = g[e];
430
431
  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>` : "";
431
432
  }
432
433
  //#endregion
433
434
  //#region src/widget/WidgetDropdown.ts
434
- var _ = class {
435
+ var v = class {
435
436
  trigger;
436
437
  panel;
437
438
  _isOpen = !1;
@@ -462,7 +463,7 @@ var _ = class {
462
463
  destroy() {
463
464
  this.trigger.removeEventListener("click", this.onTriggerClick), document.removeEventListener("mousedown", this.onOutsideClick), document.removeEventListener("keydown", this.onEscapeKey), this.panel.remove();
464
465
  }
465
- }, v = class {
466
+ }, y = class {
466
467
  config;
467
468
  callbacks;
468
469
  el;
@@ -487,11 +488,14 @@ var _ = class {
487
488
  let a = document.createElement("div");
488
489
  a.style.position = "relative", a.style.display = "inline-flex";
489
490
  let o = document.createElement("button");
490
- 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());
491
+ o.className = "tcw-dropdown-trigger", o.dataset.role = "charttype", a.appendChild(o), n.appendChild(a), this.chartTypeDropdown = new v(a, { width: "160px" }), this.buildChartTypeMenu(), n.appendChild(this.sep());
491
492
  let s = document.createElement("div");
492
493
  s.style.position = "relative", s.style.display = "inline-flex";
493
494
  let c = document.createElement("button");
494
- 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());
495
+ if (c.className = "tcw-dropdown-trigger", c.dataset.role = "indicators", s.appendChild(c), n.appendChild(s), this.indicatorDropdown = new v(s, { width: "280px" }), this.buildIndicatorMenu(), this.chipsContainer = document.createElement("div"), this.chipsContainer.className = "tcw-indicator-chips", n.appendChild(this.chipsContainer), n.appendChild(this.spacer()), t.onToggleReplay) {
496
+ let e = this.iconBtn("play", "Bar replay", t.onToggleReplay);
497
+ e.dataset.role = "replay", n.appendChild(e);
498
+ }
495
499
  let l = this.iconBtn("camera", "Screenshot", t.onScreenshot);
496
500
  n.appendChild(l);
497
501
  let u = this.iconBtn("settings", "Chart Settings", t.onSettings);
@@ -527,11 +531,11 @@ var _ = class {
527
531
  let n = this.el.querySelector("[data-role=\"charttype\"]");
528
532
  if (n) {
529
533
  let t = this.config.chartTypes.find((t) => t.value === e.chartType)?.label ?? "Candles";
530
- n.innerHTML = `${g("barChart", 14)} ${t} ${g("chevronDown", 12)}`;
534
+ n.innerHTML = `${_("barChart", 14)} ${t} ${_("chevronDown", 12)}`;
531
535
  }
532
536
  let r = this.el.querySelector("[data-role=\"indicators\"]");
533
537
  if (r) {
534
- let t = e.activeIndicators.size, n = `${g("trendingUp", 14)} Indicators`;
538
+ let t = e.activeIndicators.size, n = `${_("trendingUp", 14)} Indicators`;
535
539
  t > 0 && (n += ` <span class="tcw-badge-count">${t}</span>`), r.innerHTML = n;
536
540
  }
537
541
  if (this.chipsContainer) {
@@ -543,10 +547,10 @@ var _ = class {
543
547
  let n = document.createElement("span");
544
548
  n.textContent = e.label, t.appendChild(n);
545
549
  let r = document.createElement("button");
546
- 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);
550
+ r.className = "tcw-chip-remove", r.innerHTML = _("x", 10), r.addEventListener("click", () => this.callbacks.onRemoveIndicator(e.instanceId)), t.appendChild(r), this.chipsContainer.appendChild(t);
547
551
  }
548
552
  }
549
- this.themeBtn && (this.themeBtn.innerHTML = e.isDark ? g("moon", 14) : g("sun", 14));
553
+ this.themeBtn && (this.themeBtn.innerHTML = e.isDark ? _("moon", 14) : _("sun", 14));
550
554
  }
551
555
  getActiveIndicatorList(e) {
552
556
  let t = [];
@@ -567,12 +571,12 @@ var _ = class {
567
571
  }
568
572
  iconBtn(e, t, n) {
569
573
  let r = document.createElement("button");
570
- return r.className = "tcw-btn-icon", r.title = t, r.innerHTML = g(e, 14), r.addEventListener("click", n), r;
574
+ return r.className = "tcw-btn-icon", r.title = t, r.innerHTML = _(e, 14), r.addEventListener("click", n), r;
571
575
  }
572
576
  destroy() {
573
577
  this.chartTypeDropdown?.destroy(), this.indicatorDropdown?.destroy(), this.el.remove();
574
578
  }
575
- }, y = [
579
+ }, b = [
576
580
  "trendingUp",
577
581
  "minus",
578
582
  "penLine",
@@ -581,7 +585,7 @@ var _ = class {
581
585
  "gitBranch",
582
586
  "ruler",
583
587
  "type"
584
- ], b = class {
588
+ ], x = class {
585
589
  config;
586
590
  callbacks;
587
591
  el;
@@ -595,24 +599,24 @@ var _ = class {
595
599
  }
596
600
  build() {
597
601
  let { config: e, callbacks: t, el: n } = this;
598
- 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) => {
602
+ this.cursorBtn = document.createElement("button"), this.cursorBtn.className = "tcw-sidebar-btn", this.cursorBtn.title = "Cursor", this.cursorBtn.innerHTML = _("cursor", 14), this.cursorBtn.addEventListener("click", t.onCancelDrawing), n.appendChild(this.cursorBtn), n.appendChild(this.divider()), e.drawingToolGroups.forEach((e, r) => {
599
603
  let i = document.createElement("div");
600
604
  i.className = "tcw-tool-group-wrap";
601
605
  let a = document.createElement("button");
602
- if (a.className = "tcw-sidebar-btn", a.title = e.label, a.innerHTML = g(y[r] ?? "square", 14), e.tools.length > 1) {
606
+ if (a.className = "tcw-sidebar-btn", a.title = e.label, a.innerHTML = _(b[r] ?? "square", 14), e.tools.length > 1) {
603
607
  let e = document.createElement("span");
604
608
  e.className = "tcw-multi-dot", a.appendChild(e);
605
609
  }
606
610
  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);
607
611
  });
608
612
  let r = document.createElement("div");
609
- 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);
613
+ 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 = _("magnet", 14), this.magnetBtn.addEventListener("click", t.onToggleMagnet), n.appendChild(this.magnetBtn);
610
614
  let i = document.createElement("button");
611
- i.className = "tcw-sidebar-btn", i.title = "Undo", i.innerHTML = g("undo", 14), i.addEventListener("click", t.onUndo), n.appendChild(i);
615
+ i.className = "tcw-sidebar-btn", i.title = "Undo", i.innerHTML = _("undo", 14), i.addEventListener("click", t.onUndo), n.appendChild(i);
612
616
  let a = document.createElement("button");
613
- a.className = "tcw-sidebar-btn", a.title = "Redo", a.innerHTML = g("redo", 14), a.addEventListener("click", t.onRedo), n.appendChild(a);
617
+ a.className = "tcw-sidebar-btn", a.title = "Redo", a.innerHTML = _("redo", 14), a.addEventListener("click", t.onRedo), n.appendChild(a);
614
618
  let o = document.createElement("button");
615
- o.className = "tcw-sidebar-btn tcw-danger", o.title = "Clear all", o.innerHTML = g("trash", 14), o.addEventListener("click", t.onClearDrawings), n.appendChild(o);
619
+ o.className = "tcw-sidebar-btn tcw-danger", o.title = "Clear all", o.innerHTML = _("trash", 14), o.addEventListener("click", t.onClearDrawings), n.appendChild(o);
616
620
  }
617
621
  showFlyout(e) {
618
622
  let t = this.config.drawingToolGroups[e];
@@ -652,11 +656,11 @@ var _ = class {
652
656
  destroy() {
653
657
  this.hideFlyout(), this.el.remove();
654
658
  }
655
- }, x = [
659
+ }, S = [
656
660
  "style",
657
661
  "display",
658
662
  "scale"
659
- ], S = class {
663
+ ], C = class {
660
664
  callbacks;
661
665
  backdrop = null;
662
666
  modal = null;
@@ -682,12 +686,12 @@ var _ = class {
682
686
  let t = document.createElement("h3");
683
687
  t.textContent = "Chart Settings", e.appendChild(t);
684
688
  let n = document.createElement("button");
685
- n.className = "tcw-modal-close", n.innerHTML = g("x", 16), n.addEventListener("click", () => {
689
+ n.className = "tcw-modal-close", n.innerHTML = _("x", 16), n.addEventListener("click", () => {
686
690
  this.callbacks.onClose(), this.close();
687
691
  }), e.appendChild(n), this.modal.appendChild(e);
688
692
  let r = document.createElement("div");
689
693
  r.className = "tcw-modal-tabs", this.tabButtons = [];
690
- for (let e of x) {
694
+ for (let e of S) {
691
695
  let t = document.createElement("button");
692
696
  t.className = "tcw-modal-tab", t.textContent = e, t.dataset.tab = e, e === this.currentTab && t.classList.add("tcw-active"), t.addEventListener("click", () => {
693
697
  this.currentTab = e, this.tabButtons.forEach((t) => t.classList.toggle("tcw-active", t.dataset.tab === e)), this.renderTabContent();
@@ -730,7 +734,7 @@ var _ = class {
730
734
  renderDisplayTab() {
731
735
  if (!this.bodyEl || !this.currentSettings) return;
732
736
  let e = this.currentSettings, t = this.section();
733
- 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, [
737
+ 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("Volume Profile", e.volumeProfileVisible, (e) => this.patch({ volumeProfileVisible: 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, [
734
738
  {
735
739
  label: "Magnet",
736
740
  value: "magnet"
@@ -827,7 +831,7 @@ var _ = class {
827
831
  destroy() {
828
832
  this.close();
829
833
  }
830
- }, C = class {
834
+ }, w = class {
831
835
  el;
832
836
  dotEl;
833
837
  messageEl;
@@ -843,7 +847,7 @@ var _ = class {
843
847
  destroy() {
844
848
  this.el.remove();
845
849
  }
846
- }, w = class {
850
+ }, T = class {
847
851
  backdrop = null;
848
852
  modal = null;
849
853
  input = null;
@@ -968,7 +972,470 @@ var _ = class {
968
972
  destroy() {
969
973
  this.close();
970
974
  }
971
- }, T = class {
975
+ }, E = class {
976
+ backdrop = null;
977
+ modal = null;
978
+ input = null;
979
+ list = null;
980
+ symbols = [];
981
+ current = "";
982
+ filtered = [];
983
+ selectedIndex = 0;
984
+ callbacks;
985
+ boundKeydown;
986
+ constructor(e) {
987
+ this.callbacks = e, this.boundKeydown = this.handleKeydown.bind(this);
988
+ }
989
+ open(e, t) {
990
+ if (this.backdrop) return;
991
+ this.symbols = e, this.current = t, this.filtered = e.map((e) => ({
992
+ symbol: e,
993
+ score: 0
994
+ })), this.selectedIndex = Math.max(0, e.indexOf(t)), 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";
995
+ let n = document.createElement("div");
996
+ n.className = "tcw-cmd-header";
997
+ let r = document.createElement("span");
998
+ r.className = "tcw-cmd-icon", r.innerHTML = A(), n.appendChild(r), this.input = document.createElement("input"), this.input.className = "tcw-cmd-input", this.input.type = "text", this.input.placeholder = "Search symbol… (e.g. BTC, ETH, AAPL)", this.input.autocomplete = "off", this.input.spellcheck = !1, this.input.addEventListener("input", () => this.filter()), n.appendChild(this.input);
999
+ let i = document.createElement("span");
1000
+ i.className = "tcw-cmd-hint", i.textContent = "ESC", n.appendChild(i), this.modal.appendChild(n), this.list = document.createElement("div"), this.list.className = "tcw-cmd-list", this.modal.appendChild(this.list);
1001
+ let a = document.createElement("div");
1002
+ a.className = "tcw-cmd-footer", a.innerHTML = "<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>", this.modal.appendChild(a), document.body.appendChild(this.backdrop), document.body.appendChild(this.modal), this.renderList(), this.input.focus(), document.addEventListener("keydown", this.boundKeydown);
1003
+ }
1004
+ close() {
1005
+ 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();
1006
+ }
1007
+ isOpen() {
1008
+ return this.backdrop !== null;
1009
+ }
1010
+ destroy() {
1011
+ this.close();
1012
+ }
1013
+ filter() {
1014
+ let e = (this.input?.value ?? "").toUpperCase().trim();
1015
+ e ? this.filtered = this.symbols.map((t) => ({
1016
+ symbol: t,
1017
+ score: D(t.toUpperCase(), e)
1018
+ })).filter((e) => e.score > 0).sort((e, t) => t.score - e.score) : this.filtered = this.symbols.map((e) => ({
1019
+ symbol: e,
1020
+ score: 0
1021
+ })), this.selectedIndex = 0, this.renderList();
1022
+ }
1023
+ renderList() {
1024
+ if (!this.list) return;
1025
+ if (this.list.innerHTML = "", this.filtered.length === 0) {
1026
+ let e = document.createElement("div");
1027
+ e.className = "tcw-cmd-empty", e.textContent = "No symbols match", this.list.appendChild(e);
1028
+ return;
1029
+ }
1030
+ let e = (this.input?.value ?? "").toUpperCase().trim();
1031
+ for (let t = 0; t < this.filtered.length; t++) {
1032
+ let { symbol: n } = this.filtered[t], r = document.createElement("button");
1033
+ r.className = "tcw-cmd-item", t === this.selectedIndex && r.classList.add("tcw-selected"), n === this.current && r.classList.add("tcw-active");
1034
+ let i = document.createElement("span");
1035
+ if (i.className = "tcw-cmd-item-label", i.innerHTML = O(n, e), r.appendChild(i), n === this.current) {
1036
+ let e = document.createElement("span");
1037
+ e.className = "tcw-cmd-check", e.textContent = "✓", r.appendChild(e);
1038
+ }
1039
+ r.addEventListener("click", () => this.pick(t)), r.addEventListener("mouseenter", () => {
1040
+ this.selectedIndex = t, this.updateSelection();
1041
+ }), this.list.appendChild(r);
1042
+ }
1043
+ }
1044
+ updateSelection() {
1045
+ if (!this.list) return;
1046
+ let e = this.list.querySelectorAll(".tcw-cmd-item");
1047
+ e.forEach((e, t) => e.classList.toggle("tcw-selected", t === this.selectedIndex)), e[this.selectedIndex]?.scrollIntoView({ block: "nearest" });
1048
+ }
1049
+ pick(e) {
1050
+ let t = this.filtered[e];
1051
+ t && (this.callbacks.onPick(t.symbol), this.close());
1052
+ }
1053
+ handleKeydown(e) {
1054
+ switch (e.key) {
1055
+ case "Escape":
1056
+ e.preventDefault(), this.close();
1057
+ break;
1058
+ case "ArrowDown":
1059
+ e.preventDefault(), this.filtered.length > 0 && (this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length, this.updateSelection());
1060
+ break;
1061
+ case "ArrowUp":
1062
+ e.preventDefault(), this.filtered.length > 0 && (this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length, this.updateSelection());
1063
+ break;
1064
+ case "Enter":
1065
+ e.preventDefault(), this.pick(this.selectedIndex);
1066
+ break;
1067
+ }
1068
+ }
1069
+ };
1070
+ function D(e, t) {
1071
+ if (e === t) return 1e3;
1072
+ if (e.startsWith(t)) return 500 + (50 - Math.min(50, e.length - t.length));
1073
+ if (e.includes(t)) return 200 + (50 - Math.min(50, e.length - t.length));
1074
+ let n = 0, r = -1, i = 0;
1075
+ for (let a = 0; a < e.length && n < t.length; a++) e[a] === t[n] && (r >= 0 && (i += a - r - 1), r = a, n++);
1076
+ return n < t.length ? 0 : 100 - Math.min(99, i);
1077
+ }
1078
+ function O(e, t) {
1079
+ if (!t) return k(e);
1080
+ let n = e.toUpperCase(), r = "", i = 0;
1081
+ for (let a = 0; a < e.length; a++) i < t.length && n[a] === t[i] ? (r += `<mark style="background:transparent;color:var(--tcw-accent);font-weight:700">${k(e[a])}</mark>`, i++) : r += k(e[a]);
1082
+ return r;
1083
+ }
1084
+ function k(e) {
1085
+ return e.replace(/[&<>"']/g, (e) => ({
1086
+ "&": "&amp;",
1087
+ "<": "&lt;",
1088
+ ">": "&gt;",
1089
+ "\"": "&quot;",
1090
+ "'": "&#39;"
1091
+ })[e]);
1092
+ }
1093
+ function A() {
1094
+ return "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/></svg>";
1095
+ }
1096
+ //#endregion
1097
+ //#region src/widget/WidgetHotkeySheet.ts
1098
+ var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent) ? "⌘" : "Ctrl", M = [
1099
+ {
1100
+ title: "Search & navigation",
1101
+ entries: [
1102
+ {
1103
+ keys: [j, "K"],
1104
+ label: "Command palette"
1105
+ },
1106
+ {
1107
+ keys: [j, "P"],
1108
+ label: "Symbol search"
1109
+ },
1110
+ {
1111
+ keys: ["?"],
1112
+ label: "Show this sheet"
1113
+ }
1114
+ ]
1115
+ },
1116
+ {
1117
+ title: "Chart manipulation",
1118
+ entries: [
1119
+ {
1120
+ keys: ["Shift", "Drag"],
1121
+ label: "Measure tool (bars × price Δ)"
1122
+ },
1123
+ {
1124
+ keys: ["Drag", "Price axis"],
1125
+ label: "Compress / expand vertical scale"
1126
+ },
1127
+ {
1128
+ keys: ["Drag", "Time axis"],
1129
+ label: "Zoom time axis"
1130
+ },
1131
+ {
1132
+ keys: ["Double-click", "Price axis"],
1133
+ label: "Re-enable auto-scale"
1134
+ },
1135
+ {
1136
+ keys: ["Double-click", "Time axis"],
1137
+ label: "Fit content"
1138
+ },
1139
+ {
1140
+ keys: ["Scroll"],
1141
+ label: "Zoom around cursor"
1142
+ }
1143
+ ]
1144
+ },
1145
+ {
1146
+ title: "Keyboard",
1147
+ entries: [
1148
+ {
1149
+ keys: ["←", "→"],
1150
+ label: "Pan one bar"
1151
+ },
1152
+ {
1153
+ keys: ["+", "−"],
1154
+ label: "Zoom in / out"
1155
+ },
1156
+ {
1157
+ keys: ["Home"],
1158
+ label: "Scroll to start"
1159
+ },
1160
+ {
1161
+ keys: ["End"],
1162
+ label: "Scroll to end (live edge)"
1163
+ },
1164
+ {
1165
+ keys: ["F"],
1166
+ label: "Fit content"
1167
+ }
1168
+ ]
1169
+ },
1170
+ {
1171
+ title: "Drawing",
1172
+ entries: [
1173
+ {
1174
+ keys: [j, "Z"],
1175
+ label: "Undo"
1176
+ },
1177
+ {
1178
+ keys: [
1179
+ j,
1180
+ "Shift",
1181
+ "Z"
1182
+ ],
1183
+ label: "Redo"
1184
+ },
1185
+ {
1186
+ keys: ["Esc"],
1187
+ label: "Cancel active drawing"
1188
+ }
1189
+ ]
1190
+ }
1191
+ ], N = class {
1192
+ backdrop = null;
1193
+ modal = null;
1194
+ callbacks;
1195
+ boundKeydown;
1196
+ constructor(e) {
1197
+ this.callbacks = e, this.boundKeydown = (e) => {
1198
+ e.key === "Escape" && (e.preventDefault(), this.close());
1199
+ };
1200
+ }
1201
+ open() {
1202
+ if (this.backdrop) return;
1203
+ 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-modal tcw-hotkey-sheet", this.modal.style.width = "640px";
1204
+ let e = document.createElement("div");
1205
+ e.className = "tcw-modal-header", e.innerHTML = "<h3>Keyboard shortcuts</h3>";
1206
+ let t = document.createElement("button");
1207
+ t.className = "tcw-modal-close", t.setAttribute("aria-label", "Close"), t.innerHTML = "×", t.addEventListener("click", () => this.close()), e.appendChild(t), this.modal.appendChild(e);
1208
+ let n = document.createElement("div");
1209
+ n.className = "tcw-modal-body";
1210
+ let r = document.createElement("div");
1211
+ r.className = "tcw-hotkey-grid";
1212
+ for (let e of M) {
1213
+ let t = document.createElement("section");
1214
+ t.className = "tcw-hotkey-section";
1215
+ let n = document.createElement("div");
1216
+ n.className = "tcw-settings-section-title", n.textContent = e.title, t.appendChild(n);
1217
+ for (let n of e.entries) {
1218
+ let e = document.createElement("div");
1219
+ e.className = "tcw-hotkey-row";
1220
+ let r = document.createElement("div");
1221
+ r.className = "tcw-hotkey-keys";
1222
+ for (let e = 0; e < n.keys.length; e++) {
1223
+ if (e > 0) {
1224
+ let e = document.createElement("span");
1225
+ e.className = "tcw-hotkey-sep", e.textContent = "+", r.appendChild(e);
1226
+ }
1227
+ let t = document.createElement("kbd");
1228
+ t.className = "tcw-cmd-kbd", t.textContent = n.keys[e], r.appendChild(t);
1229
+ }
1230
+ e.appendChild(r);
1231
+ let i = document.createElement("span");
1232
+ i.className = "tcw-hotkey-label", i.textContent = n.label, e.appendChild(i), t.appendChild(e);
1233
+ }
1234
+ r.appendChild(t);
1235
+ }
1236
+ n.appendChild(r), this.modal.appendChild(n);
1237
+ let i = document.createElement("div");
1238
+ i.className = "tcw-modal-footer", i.innerHTML = "<span style=\"font-size:11px;color:var(--tcw-text-muted)\">Press ? anytime to show this sheet</span>";
1239
+ let a = document.createElement("button");
1240
+ a.className = "tcw-done-btn", a.textContent = "Got it", a.addEventListener("click", () => this.close()), i.appendChild(a), this.modal.appendChild(i), document.body.appendChild(this.backdrop), document.body.appendChild(this.modal), document.addEventListener("keydown", this.boundKeydown);
1241
+ }
1242
+ close() {
1243
+ document.removeEventListener("keydown", this.boundKeydown), this.backdrop?.remove(), this.modal?.remove(), this.backdrop = null, this.modal = null, this.callbacks.onClose();
1244
+ }
1245
+ isOpen() {
1246
+ return this.backdrop !== null;
1247
+ }
1248
+ destroy() {
1249
+ this.close();
1250
+ }
1251
+ }, P = [
1252
+ .5,
1253
+ 1,
1254
+ 2,
1255
+ 5,
1256
+ 10,
1257
+ 20,
1258
+ 50,
1259
+ 100
1260
+ ], F = class {
1261
+ root = null;
1262
+ scrubber = null;
1263
+ progressLabel = null;
1264
+ playBtn = null;
1265
+ state = "stopped";
1266
+ total = 0;
1267
+ speed = 5;
1268
+ callbacks;
1269
+ constructor(e) {
1270
+ this.callbacks = e;
1271
+ }
1272
+ mount(e, t) {
1273
+ this.root || (this.total = Math.max(0, t.total), this.speed = t.speed ?? 5, this.state = "paused", this.root = document.createElement("div"), this.root.className = "tcw-replay-bar", this.root.innerHTML = this.markup(), e.appendChild(this.root), this.wireEvents(), this.syncUi());
1274
+ }
1275
+ unmount() {
1276
+ this.root?.remove(), this.root = null, this.scrubber = null, this.progressLabel = null, this.playBtn = null, this.state = "stopped";
1277
+ }
1278
+ isMounted() {
1279
+ return this.root !== null;
1280
+ }
1281
+ setState(e) {
1282
+ this.state = e, this.syncUi();
1283
+ }
1284
+ setProgress(e, t) {
1285
+ this.total = t, this.scrubber && (this.scrubber.max = String(Math.max(0, t - 1)), this.scrubber.value = String(e)), this.progressLabel && (this.progressLabel.textContent = `${e + 1} / ${t}`);
1286
+ }
1287
+ destroy() {
1288
+ this.unmount();
1289
+ }
1290
+ markup() {
1291
+ let e = P.map((e) => `<option value="${e}"${e === this.speed ? " selected" : ""}>${e}× bars/s</option>`).join("");
1292
+ return `
1293
+ <button class="tcw-replay-btn" data-act="close" title="Exit replay" aria-label="Exit replay">${B()}</button>
1294
+ <button class="tcw-replay-btn" data-act="stepBack" title="Step back" aria-label="Step back">${R()}</button>
1295
+ <button class="tcw-replay-btn tcw-replay-play" data-act="play" title="Play / pause" aria-label="Play / pause">${I()}</button>
1296
+ <button class="tcw-replay-btn" data-act="stepForward" title="Step forward" aria-label="Step forward">${z()}</button>
1297
+ <input type="range" class="tcw-replay-scrubber" data-act="seek" min="0" max="${Math.max(0, this.total - 1)}" value="0" step="1" />
1298
+ <span class="tcw-replay-progress" data-tcw="progress">1 / ${this.total}</span>
1299
+ <select class="tcw-replay-speed" data-act="speed">${e}</select>
1300
+ `;
1301
+ }
1302
+ wireEvents() {
1303
+ this.root && (this.scrubber = this.root.querySelector("input[data-act=\"seek\"]"), this.progressLabel = this.root.querySelector("[data-tcw=\"progress\"]"), this.playBtn = this.root.querySelector("button[data-act=\"play\"]"), this.root.querySelector("[data-act=\"close\"]")?.addEventListener("click", () => this.callbacks.onClose()), this.root.querySelector("[data-act=\"stepBack\"]")?.addEventListener("click", () => this.callbacks.onStepBack()), this.root.querySelector("[data-act=\"stepForward\"]")?.addEventListener("click", () => this.callbacks.onStepForward()), this.playBtn?.addEventListener("click", () => {
1304
+ this.state === "playing" ? this.callbacks.onPause() : this.callbacks.onPlay();
1305
+ }), this.scrubber?.addEventListener("input", () => {
1306
+ let e = Number(this.scrubber.value);
1307
+ this.callbacks.onSeek(e);
1308
+ }), this.root.querySelector("[data-act=\"speed\"]")?.addEventListener("change", (e) => {
1309
+ let t = Number(e.target.value);
1310
+ this.speed = t, this.callbacks.onSpeedChange(t);
1311
+ }));
1312
+ }
1313
+ syncUi() {
1314
+ this.playBtn && (this.playBtn.innerHTML = this.state === "playing" ? L() : I(), this.playBtn.title = this.state === "playing" ? "Pause" : "Play");
1315
+ }
1316
+ };
1317
+ function I() {
1318
+ return "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7L8 5z\"/></svg>";
1319
+ }
1320
+ function L() {
1321
+ return "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/></svg>";
1322
+ }
1323
+ function R() {
1324
+ return "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 6h2v12H6zM20 6L9 12l11 6V6z\"/></svg>";
1325
+ }
1326
+ function z() {
1327
+ return "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M4 6l11 6L4 18V6zM16 6h2v12h-2z\"/></svg>";
1328
+ }
1329
+ function B() {
1330
+ return "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>";
1331
+ }
1332
+ //#endregion
1333
+ //#region src/widget/WidgetWatchlist.ts
1334
+ var V = class {
1335
+ el;
1336
+ listEl;
1337
+ rowMap = /* @__PURE__ */ new Map();
1338
+ entries = /* @__PURE__ */ new Map();
1339
+ active = null;
1340
+ callbacks;
1341
+ constructor(e, t, n) {
1342
+ this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-watchlist";
1343
+ let r = document.createElement("div");
1344
+ r.className = "tcw-watchlist-header", r.textContent = "Watchlist", this.el.appendChild(r), this.listEl = document.createElement("div"), this.listEl.className = "tcw-watchlist-list", this.el.appendChild(this.listEl);
1345
+ for (let e of t) this.entries.set(e, { symbol: e }), this.appendRow(e);
1346
+ e.appendChild(this.el);
1347
+ }
1348
+ setSymbols(e) {
1349
+ let t = new Set(e);
1350
+ for (let e of this.rowMap.keys()) t.has(e) || this.removeRow(e);
1351
+ for (let t of e) this.rowMap.has(t) || (this.entries.set(t, this.entries.get(t) ?? { symbol: t }), this.appendRow(t));
1352
+ }
1353
+ setActive(e) {
1354
+ if (this.active === e) return;
1355
+ this.active && this.rowMap.has(this.active) && this.rowMap.get(this.active).row.classList.remove("tcw-watchlist-active"), this.active = e;
1356
+ let t = this.rowMap.get(e);
1357
+ t && t.row.classList.add("tcw-watchlist-active");
1358
+ }
1359
+ setEntry(e, t) {
1360
+ let n = {
1361
+ ...this.entries.get(e) ?? { symbol: e },
1362
+ ...t
1363
+ };
1364
+ this.entries.set(e, n), this.renderRow(e);
1365
+ }
1366
+ destroy() {
1367
+ this.el.remove(), this.rowMap.clear(), this.entries.clear();
1368
+ }
1369
+ appendRow(e) {
1370
+ let t = document.createElement("div");
1371
+ t.className = "tcw-watchlist-row", t.tabIndex = 0;
1372
+ let n = document.createElement("div");
1373
+ n.className = "tcw-watchlist-symbol", n.textContent = H(e);
1374
+ let r = document.createElement("canvas");
1375
+ r.className = "tcw-watchlist-spark", r.width = 64, r.height = 22;
1376
+ let i = document.createElement("div");
1377
+ i.className = "tcw-watchlist-stats";
1378
+ let a = document.createElement("span");
1379
+ a.className = "tcw-watchlist-price", a.textContent = "—";
1380
+ let o = document.createElement("span");
1381
+ o.className = "tcw-watchlist-change", o.textContent = "", i.appendChild(a), i.appendChild(o), t.appendChild(n), t.appendChild(r), t.appendChild(i), t.addEventListener("click", () => this.callbacks.onSelect(e)), t.addEventListener("keydown", (t) => {
1382
+ (t.key === "Enter" || t.key === " ") && (t.preventDefault(), this.callbacks.onSelect(e));
1383
+ }), this.listEl.appendChild(t), this.rowMap.set(e, {
1384
+ row: t,
1385
+ priceEl: a,
1386
+ changeEl: o,
1387
+ sparkCanvas: r
1388
+ }), e === this.active && t.classList.add("tcw-watchlist-active");
1389
+ }
1390
+ removeRow(e) {
1391
+ let t = this.rowMap.get(e);
1392
+ t && (t.row.remove(), this.rowMap.delete(e));
1393
+ }
1394
+ renderRow(e) {
1395
+ let t = this.rowMap.get(e), n = this.entries.get(e);
1396
+ if (!(!t || !n)) {
1397
+ if (n.lastPrice !== void 0 && (t.priceEl.textContent = U(n.lastPrice)), n.lastPrice !== void 0 && n.refPrice !== void 0 && n.refPrice !== 0) {
1398
+ let e = n.lastPrice - n.refPrice, r = e / n.refPrice * 100, i = e >= 0 ? "+" : "";
1399
+ t.changeEl.textContent = `${i}${r.toFixed(2)}%`, t.changeEl.className = `tcw-watchlist-change ${e >= 0 ? "tcw-up" : "tcw-down"}`;
1400
+ } else t.changeEl.textContent = "";
1401
+ n.sparkline && n.sparkline.length >= 2 && W(t.sparkCanvas, n.sparkline, n.refPrice ?? n.sparkline[0]);
1402
+ }
1403
+ }
1404
+ };
1405
+ function H(e) {
1406
+ for (let t of [
1407
+ "USDT",
1408
+ "USD",
1409
+ "BTC",
1410
+ "ETH",
1411
+ "EUR"
1412
+ ]) if (e.length > t.length && e.endsWith(t)) return e.slice(0, -t.length) + "/" + t;
1413
+ return e;
1414
+ }
1415
+ function U(e) {
1416
+ if (e === 0) return "0";
1417
+ let t = Math.abs(e);
1418
+ return t >= 1e3 ? e.toFixed(2) : t >= 1 ? e.toFixed(4) : e.toPrecision(4);
1419
+ }
1420
+ function W(e, t, n) {
1421
+ let r = e.getContext("2d");
1422
+ if (!r) return;
1423
+ let i = window.devicePixelRatio || 1;
1424
+ e.width !== e.clientWidth * i && (e.width = (e.clientWidth || 64) * i, e.height = (e.clientHeight || 22) * i);
1425
+ let a = e.width, o = e.height, s = Infinity, c = -Infinity;
1426
+ for (let e of t) e < s && (s = e), e > c && (c = e);
1427
+ let l = Math.max(c - s, 1e-9), u = t[t.length - 1] >= n ? "#26a17b" : "#f23645";
1428
+ r.clearRect(0, 0, a, o), r.lineWidth = 1.4 * i, r.strokeStyle = u, r.beginPath();
1429
+ let d = a / (t.length - 1);
1430
+ for (let e = 0; e < t.length; e++) {
1431
+ let n = e * d, i = o - (t[e] - s) / l * (o - 4) - 2;
1432
+ e === 0 ? r.moveTo(n, i) : r.lineTo(n, i);
1433
+ }
1434
+ r.stroke();
1435
+ }
1436
+ //#endregion
1437
+ //#region src/widget/ChartWidget.ts
1438
+ var G = class {
972
1439
  chart;
973
1440
  state;
974
1441
  toolbar = null;
@@ -976,36 +1443,50 @@ var _ = class {
976
1443
  settings = null;
977
1444
  statusBar = null;
978
1445
  commandPalette = null;
1446
+ symbolSearch = null;
1447
+ hotkeySheet = null;
1448
+ replayBar = null;
1449
+ dragDrop = null;
1450
+ watchlist = null;
1451
+ watchlistSparkBuffer = /* @__PURE__ */ new Map();
1452
+ sessionRefPrice = null;
1453
+ watchlistInterval = null;
1454
+ replayOriginalData = null;
1455
+ replayPollInterval = null;
1456
+ replaySpeed = 5;
1457
+ layoutKeyPrefix = null;
1458
+ layoutDebounceMs = 1500;
1459
+ activeLayoutKey = null;
979
1460
  root;
980
1461
  chartContainer;
981
1462
  destroyed = !1;
982
1463
  options;
983
- symbolIndex = 0;
984
1464
  symbols;
985
1465
  settingsState;
986
1466
  adapter = null;
987
1467
  boundGlobalKeydown = null;
988
- constructor(t, n = {}) {
989
- this.options = n, this.symbols = n.symbols ?? c, this.settingsState = { ...l };
990
- let u = this.resolveIsDark(n.theme), d = this.resolveTheme(n.theme);
1468
+ constructor(n, r = {}) {
1469
+ if (this.options = r, this.symbols = r.symbols ?? l, this.settingsState = { ...u }, r.persistLayouts) {
1470
+ let e = r.persistLayouts === !0 ? {} : r.persistLayouts;
1471
+ this.layoutKeyPrefix = e.keyPrefix ?? "tcw:layout:", this.layoutDebounceMs = e.debounceMs ?? 1500;
1472
+ }
1473
+ let d = this.resolveIsDark(r.theme), f = this.resolveTheme(r.theme);
991
1474
  this.state = {
992
- symbol: n.symbol ?? this.symbols[0] ?? "BTCUSDT",
993
- timeframe: n.timeframe ?? "5m",
994
- chartType: n.chartOptions?.chartType ?? "candlestick",
995
- isDark: u,
1475
+ symbol: r.symbol ?? this.symbols[0] ?? "BTCUSDT",
1476
+ timeframe: r.timeframe ?? "5m",
1477
+ chartType: r.chartOptions?.chartType ?? "candlestick",
1478
+ isDark: d,
996
1479
  activeIndicators: /* @__PURE__ */ new Map(),
997
1480
  activeTool: null,
998
1481
  magnetEnabled: !0,
999
1482
  connectionState: "connecting",
1000
1483
  connectionMessage: "Connecting..."
1001
- };
1002
- let f = this.symbols.indexOf(this.state.symbol);
1003
- 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, {
1484
+ }, m(), this.root = document.createElement("div"), this.root.className = "tcw-root", this.root.dataset.tcwTheme = d ? "dark" : "light", n.appendChild(this.root), r.toolbar !== !1 && (this.toolbar = new y(this.root, {
1004
1485
  symbols: this.symbols,
1005
- timeframes: n.timeframes ? r.filter((e) => n.timeframes.includes(e.value)) : r,
1006
- chartTypes: n.chartTypes ? i.filter((e) => n.chartTypes.includes(e.value)) : i,
1007
- indicators: o,
1008
- popularIndicatorIds: s
1486
+ timeframes: r.timeframes ? i.filter((e) => r.timeframes.includes(e.value)) : i,
1487
+ chartTypes: r.chartTypes ? a.filter((e) => r.chartTypes.includes(e.value)) : a,
1488
+ indicators: s,
1489
+ popularIndicatorIds: c
1009
1490
  }, {
1010
1491
  onSymbolClick: () => this.handleSymbolClick(),
1011
1492
  onTimeframe: (e) => this.handleTimeframe(e),
@@ -1014,10 +1495,11 @@ var _ = class {
1014
1495
  onRemoveIndicator: (e) => this.handleRemoveIndicator(e),
1015
1496
  onScreenshot: () => this.chart.screenshot(),
1016
1497
  onSettings: () => this.openSettings(),
1017
- onToggleTheme: () => this.handleToggleTheme()
1498
+ onToggleTheme: () => this.handleToggleTheme(),
1499
+ onToggleReplay: () => this.toggleReplay()
1018
1500
  }));
1019
- let m = document.createElement("div");
1020
- m.className = "tcw-body", n.drawingTools !== !1 && (this.sidebar = new b(m, { drawingToolGroups: a }, {
1501
+ let p = document.createElement("div");
1502
+ p.className = "tcw-body", r.drawingTools !== !1 && (this.sidebar = new x(p, { drawingToolGroups: o }, {
1021
1503
  onDrawingTool: (e) => this.handleDrawingTool(e),
1022
1504
  onCancelDrawing: () => this.handleCancelDrawing(),
1023
1505
  onToggleMagnet: () => this.handleToggleMagnet(),
@@ -1029,9 +1511,11 @@ var _ = class {
1029
1511
  activeTool: null
1030
1512
  }, this.updateUI();
1031
1513
  }
1032
- })), 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, {
1514
+ })), this.chartContainer = document.createElement("div"), this.chartContainer.className = "tcw-chart-container", p.appendChild(this.chartContainer), r.watchlist && (this.watchlist = new V(p, this.symbols, { onSelect: (e) => {
1515
+ this.setSymbol(e);
1516
+ } }), this.watchlist.setActive(this.state.symbol)), this.root.appendChild(p), this.chart = new e(this.chartContainer, {
1033
1517
  chartType: this.state.chartType,
1034
- theme: d,
1518
+ theme: f,
1035
1519
  autoScale: !0,
1036
1520
  crosshair: { mode: "magnet" },
1037
1521
  features: {
@@ -1039,8 +1523,8 @@ var _ = class {
1039
1523
  drawingMagnet: !0,
1040
1524
  drawingUndoRedo: !0,
1041
1525
  indicators: !0,
1042
- trading: n.trading !== !1,
1043
- tradingContextMenu: n.trading !== !1,
1526
+ trading: r.trading !== !1,
1527
+ tradingContextMenu: r.trading !== !1,
1044
1528
  volume: !0,
1045
1529
  legend: !0,
1046
1530
  crosshair: !0,
@@ -1051,12 +1535,24 @@ var _ = class {
1051
1535
  logScale: !0,
1052
1536
  watermark: !0
1053
1537
  },
1054
- ...n.chartOptions
1055
- }), n.statusBar !== !1 && (this.statusBar = new C(this.root)), n.settings !== !1 && (this.settings = new S({
1538
+ ...r.chartOptions
1539
+ }), r.dragDropImport !== !1 && (this.dragDrop = new t(this.chartContainer, {
1540
+ onData: (e, t, n) => {
1541
+ this.chart.setData(e), this.toast(`Loaded ${t.data.length} bars from ${n.name}` + (t.skipped > 0 ? ` (${t.skipped} skipped)` : ""));
1542
+ },
1543
+ onError: (e, t) => {
1544
+ this.toast(`${t.name}: ${e.message}`, "error");
1545
+ }
1546
+ }), this.dragDrop.attach()), r.statusBar !== !1 && (this.statusBar = new w(this.root)), r.settings !== !1 && (this.settings = new C({
1056
1547
  onChange: (e) => this.applySettings(e),
1057
1548
  onReset: () => this.resetSettings(),
1058
1549
  onClose: () => {}
1059
- })), this.commandPalette = new w({
1550
+ })), this.symbolSearch = new E({
1551
+ onPick: (e) => {
1552
+ this.setSymbol(e);
1553
+ },
1554
+ onClose: () => {}
1555
+ }), this.hotkeySheet = new N({ onClose: () => {} }), this.commandPalette = new T({
1060
1556
  onIndicator: (e) => this.handleAddIndicator(e),
1061
1557
  onChartType: (e) => this.handleChartType(e),
1062
1558
  onDrawingTool: (e) => this.handleDrawingTool(e),
@@ -1064,16 +1560,39 @@ var _ = class {
1064
1560
  onAction: (e) => this.handleAction(e),
1065
1561
  onClose: () => {}
1066
1562
  }), this.boundGlobalKeydown = (e) => {
1067
- (e.ctrlKey || e.metaKey) && e.key === "k" && (e.preventDefault(), this.toggleCommandPalette());
1068
- }, document.addEventListener("keydown", this.boundGlobalKeydown), n.adapter && (this.adapter = n.adapter, this.connectStream()), this.updateUI(), n.onReady?.(this.chart);
1563
+ if ((e.ctrlKey || e.metaKey) && e.key === "k") e.preventDefault(), this.toggleCommandPalette();
1564
+ else if ((e.ctrlKey || e.metaKey) && (e.key === "p" || e.key === "P")) e.preventDefault(), this.symbolSearch?.open(this.symbols, this.state.symbol);
1565
+ else if (e.key === "?" && !e.ctrlKey && !e.metaKey && !e.altKey) {
1566
+ let t = document.activeElement;
1567
+ if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
1568
+ e.preventDefault(), this.hotkeySheet?.open();
1569
+ }
1570
+ }, document.addEventListener("keydown", this.boundGlobalKeydown), r.adapter && (this.adapter = r.adapter, this.connectStream()), this.watchlist && (this.watchlistInterval = setInterval(() => this.tickWatchlist(), 1e3)), this.updateUI(), r.onReady?.(this.chart);
1571
+ }
1572
+ setSymbols(e) {
1573
+ this.symbols = e, this.watchlist?.setSymbols(e);
1069
1574
  }
1070
1575
  async setSymbol(e) {
1071
- this.state = {
1576
+ this.flushActiveLayout(), this.state = {
1072
1577
  ...this.state,
1073
1578
  symbol: e
1074
- };
1075
- let t = this.symbols.indexOf(e);
1076
- t >= 0 && (this.symbolIndex = t), this.options.onSymbolChange?.(e), this.updateUI(), this.adapter && await this.connectStream();
1579
+ }, this.sessionRefPrice = null, this.options.onSymbolChange?.(e), this.updateUI(), this.watchlist?.setActive(e), this.adapter && await this.connectStream();
1580
+ }
1581
+ setWatchlistEntry(e, t) {
1582
+ this.watchlist?.setEntry(e, t);
1583
+ }
1584
+ tickWatchlist() {
1585
+ if (!this.watchlist) return;
1586
+ let e = this.chart.getData();
1587
+ if (e.length === 0) return;
1588
+ let t = e[e.length - 1];
1589
+ this.sessionRefPrice === null && (this.sessionRefPrice = e[0].open);
1590
+ let n = this.watchlistSparkBuffer.get(this.state.symbol) ?? [];
1591
+ n.push(t.close), n.length > 40 && n.shift(), this.watchlistSparkBuffer.set(this.state.symbol, n), this.watchlist.setEntry(this.state.symbol, {
1592
+ lastPrice: t.close,
1593
+ refPrice: this.sessionRefPrice,
1594
+ sparkline: n.slice()
1595
+ });
1077
1596
  }
1078
1597
  async setTimeframe(e) {
1079
1598
  this.state = {
@@ -1092,15 +1611,10 @@ var _ = class {
1092
1611
  return this.chart;
1093
1612
  }
1094
1613
  destroy() {
1095
- 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());
1614
+ this.destroyed || (this.destroyed = !0, this.boundGlobalKeydown && document.removeEventListener("keydown", this.boundGlobalKeydown), this.flushActiveLayout(), this.commandPalette?.destroy(), this.symbolSearch?.destroy(), this.hotkeySheet?.destroy(), this.replayPollInterval && clearInterval(this.replayPollInterval), this.replayBar?.destroy(), this.dragDrop?.detach(), this.watchlistInterval && clearInterval(this.watchlistInterval), this.watchlist?.destroy(), this.toolbar?.destroy(), this.sidebar?.destroy(), this.settings?.destroy(), this.statusBar?.destroy(), this.chart.destroy(), this.root.remove(), h());
1096
1615
  }
1097
1616
  handleSymbolClick() {
1098
- this.symbolIndex = (this.symbolIndex + 1) % this.symbols.length;
1099
- let e = this.symbols[this.symbolIndex];
1100
- this.state = {
1101
- ...this.state,
1102
- symbol: e
1103
- }, this.options.onSymbolChange?.(e), this.updateUI(), this.adapter && this.connectStream();
1617
+ this.symbolSearch?.open(this.symbols, this.state.symbol);
1104
1618
  }
1105
1619
  handleTimeframe(e) {
1106
1620
  this.state = {
@@ -1156,25 +1670,25 @@ var _ = class {
1156
1670
  }
1157
1671
  buildCommandItems() {
1158
1672
  let e = [];
1159
- for (let t of o) e.push({
1673
+ for (let t of s) e.push({
1160
1674
  id: t.id,
1161
1675
  label: t.name,
1162
1676
  category: "indicator",
1163
1677
  active: this.state.activeIndicators.has(t.id)
1164
1678
  });
1165
- for (let t of i) e.push({
1679
+ for (let t of a) e.push({
1166
1680
  id: t.value,
1167
1681
  label: t.label,
1168
1682
  category: "chartType",
1169
1683
  active: this.state.chartType === t.value
1170
1684
  });
1171
- for (let t of a) for (let n of t.tools) e.push({
1685
+ for (let t of o) for (let n of t.tools) e.push({
1172
1686
  id: n.value,
1173
1687
  label: n.label,
1174
1688
  category: "drawing",
1175
1689
  active: this.state.activeTool === n.value
1176
1690
  });
1177
- for (let t of r) e.push({
1691
+ for (let t of i) e.push({
1178
1692
  id: t.value,
1179
1693
  label: t.label,
1180
1694
  category: "timeframe",
@@ -1242,7 +1756,7 @@ var _ = class {
1242
1756
  this.state = {
1243
1757
  ...this.state,
1244
1758
  isDark: e
1245
- }, this.root.dataset.tcwTheme = e ? "dark" : "light", this.chart.setTheme(e ? t : n), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
1759
+ }, this.root.dataset.tcwTheme = e ? "dark" : "light", this.chart.setTheme(e ? n : r), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
1246
1760
  fontSize: 48,
1247
1761
  color: e ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"
1248
1762
  }), this.updateUI();
@@ -1250,16 +1764,105 @@ var _ = class {
1250
1764
  openSettings() {
1251
1765
  this.settings?.open(this.settingsState);
1252
1766
  }
1767
+ toast(e, t = "info") {
1768
+ let n = document.createElement("div");
1769
+ n.className = `tcw-toast ${t === "error" ? "tcw-toast-error" : ""}`, n.textContent = e, this.root.appendChild(n), requestAnimationFrame(() => n.classList.add("tcw-toast-in")), setTimeout(() => {
1770
+ n.classList.remove("tcw-toast-in"), n.addEventListener("transitionend", () => n.remove(), { once: !0 }), setTimeout(() => n.remove(), 400);
1771
+ }, 3500);
1772
+ }
1773
+ clearSavedLayout(e) {
1774
+ if (!this.layoutKeyPrefix) return;
1775
+ let t = e ?? this.state.symbol;
1776
+ try {
1777
+ localStorage.removeItem(this.layoutKeyPrefix + t);
1778
+ } catch {}
1779
+ }
1780
+ applySymbolLayout(e) {
1781
+ if (!this.layoutKeyPrefix) return;
1782
+ let t = this.layoutKeyPrefix + e;
1783
+ this.activeLayoutKey = t;
1784
+ try {
1785
+ this.chart.loadStateFromStorage(t) && this.rebuildActiveIndicatorsMapFromChart();
1786
+ } catch {}
1787
+ this.chart.setAutoSave(t, this.layoutDebounceMs);
1788
+ }
1789
+ flushActiveLayout() {
1790
+ if (this.activeLayoutKey) {
1791
+ try {
1792
+ this.chart.saveState(this.activeLayoutKey);
1793
+ } catch {}
1794
+ this.chart.disableAutoSave(), this.activeLayoutKey = null;
1795
+ }
1796
+ }
1797
+ rebuildActiveIndicatorsMapFromChart() {
1798
+ let e = /* @__PURE__ */ new Map();
1799
+ for (let t of this.chart.getActiveIndicators()) e.set(t.id, t.instanceId);
1800
+ this.state = {
1801
+ ...this.state,
1802
+ activeIndicators: e
1803
+ }, this.updateUI();
1804
+ }
1805
+ toggleReplay() {
1806
+ this.replayBar?.isMounted() ? this.exitReplay() : this.enterReplay();
1807
+ }
1808
+ enterReplay() {
1809
+ let e = this.chart.getData();
1810
+ e.length < 2 || (this.replayOriginalData = e.slice(), this.replayBar = new F({
1811
+ onPlay: () => {
1812
+ this.chart.getReplayState() === "paused" ? this.chart.replayResume() : this.chart.replay({
1813
+ speed: this.replaySpeed,
1814
+ interval: 200
1815
+ }), this.replayBar?.setState("playing");
1816
+ },
1817
+ onPause: () => {
1818
+ this.chart.replayPause(), this.replayBar?.setState("paused");
1819
+ },
1820
+ onStop: () => {
1821
+ this.chart.replayStop(), this.replayBar?.setState("paused");
1822
+ },
1823
+ onStepBack: () => {
1824
+ let e = this.chart.getReplayProgress();
1825
+ this.chart.getReplayState() === "playing" && this.chart.replayPause(), this.chart.replaySeek(Math.max(0, e.current - 1)), this.replayBar?.setState("paused");
1826
+ },
1827
+ onStepForward: () => {
1828
+ let e = this.chart.getReplayProgress();
1829
+ this.chart.getReplayState() === "playing" && this.chart.replayPause(), this.chart.replaySeek(Math.min(e.total - 1, e.current + 1)), this.replayBar?.setState("paused");
1830
+ },
1831
+ onSeek: (e) => {
1832
+ this.chart.getReplayState() === "playing" && this.chart.replayPause(), this.chart.replaySeek(e), this.replayBar?.setState("paused");
1833
+ },
1834
+ onSpeedChange: (e) => {
1835
+ this.replaySpeed = e, this.chart.setReplaySpeed(e);
1836
+ },
1837
+ onClose: () => this.exitReplay()
1838
+ }), this.replayBar.mount(this.chartContainer, {
1839
+ total: e.length,
1840
+ speed: this.replaySpeed
1841
+ }), this.chart.replay({
1842
+ speed: this.replaySpeed,
1843
+ interval: 200,
1844
+ startIndex: 1
1845
+ }), this.chart.replayPause(), this.replayBar.setState("paused"), this.replayPollInterval = setInterval(() => {
1846
+ if (!this.replayBar?.isMounted()) return;
1847
+ let e = this.chart.getReplayProgress();
1848
+ this.replayBar.setProgress(e.current, e.total);
1849
+ let t = this.chart.getReplayState();
1850
+ t === "stopped" ? this.replayBar.setState("paused") : this.replayBar.setState(t);
1851
+ }, 150));
1852
+ }
1853
+ exitReplay() {
1854
+ this.replayPollInterval &&= (clearInterval(this.replayPollInterval), null), this.chart.replayStop(), this.replayBar?.unmount(), this.replayBar = null, this.replayOriginalData &&= (this.chart.setData(this.replayOriginalData), null);
1855
+ }
1253
1856
  applySettings(e) {
1254
1857
  this.settingsState = {
1255
1858
  ...this.settingsState,
1256
1859
  ...e
1257
- }, 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);
1860
+ }, e.gridVisible !== void 0 && this.chart.setGridVisible(e.gridVisible), e.volumeVisible !== void 0 && this.chart.setVolumeVisible(e.volumeVisible), e.volumeProfileVisible !== void 0 && this.chart.setVolumeProfileVisible(e.volumeProfileVisible), 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);
1258
1861
  let t = { ...this.chart.getTheme() }, n = !1;
1259
1862
  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);
1260
1863
  }
1261
1864
  resetSettings() {
1262
- this.settingsState = { ...l }, this.applySettings(this.settingsState);
1865
+ this.settingsState = { ...u }, this.applySettings(this.settingsState);
1263
1866
  }
1264
1867
  async connectStream() {
1265
1868
  if (this.adapter) {
@@ -1277,7 +1880,7 @@ var _ = class {
1277
1880
  }), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
1278
1881
  fontSize: 48,
1279
1882
  color: this.state.isDark ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"
1280
- }), this.state = {
1883
+ }), this.applySymbolLayout(this.state.symbol), this.state = {
1281
1884
  ...this.state,
1282
1885
  connectionState: "connected",
1283
1886
  connectionMessage: "Live"
@@ -1304,7 +1907,7 @@ var _ = class {
1304
1907
  return e === void 0 || e === "dark" ? !0 : e === "light" ? !1 : typeof e == "object" && e.background ? this.isColorDark(e.background) : !0;
1305
1908
  }
1306
1909
  resolveTheme(e) {
1307
- return e === void 0 || e === "dark" ? t : e === "light" ? n : typeof e == "object" ? e : t;
1910
+ return e === void 0 || e === "dark" ? n : e === "light" ? r : typeof e == "object" ? e : n;
1308
1911
  }
1309
1912
  isColorDark(e) {
1310
1913
  if (e.startsWith("#") && e.length >= 7) {
@@ -1315,6 +1918,6 @@ var _ = class {
1315
1918
  }
1316
1919
  };
1317
1920
  //#endregion
1318
- export { T as ChartWidget };
1921
+ export { G as ChartWidget };
1319
1922
 
1320
1923
  //# sourceMappingURL=index.js.map