@tradecanvas/chart
Advanced tools
| import { DARK_THEME as e, DEFAULT_PANEL_HEIGHT as t, LIGHT_THEME as n, LayerType as r, MIN_PANEL_HEIGHT as i, PRICE_AXIS_WIDTH as a, TIME_AXIS_HEIGHT as o, computePriceLimits as s, mergeBar as c, setLocale as l, timeframeToMs as u } from "@tradecanvas/commons"; | ||
| import { AlertManager as d, Animator as f, AreaRenderer as p, BarCountdown as m, BarRenderer as ee, BaselineRenderer as h, CandlestickRenderer as g, ChartLegend as te, ChartStateManager as _, CompareRenderer as v, CrosshairHandler as y, CrosshairTooltip as ne, CurrentPriceLine as re, DataExporter as b, DrawingManager as ie, DrawingRenderer as ae, EventBus as oe, GridRenderer as se, HollowCandleRenderer as ce, IndicatorEngine as x, InteractionManager as le, KagiRenderer as ue, KeyboardHandler as de, LineRenderer as S, PanHandler as C, PointAndFigureRenderer as w, PriceAxis as T, RenderEngine as E, RenkoRenderer as D, ReplayManager as O, Screenshot as k, SessionBreaks as A, StreamManager as j, TimeAxis as M, TradingManager as N, TradingRenderer as P, UndoRedoManager as F, Viewport as I, VolumeRenderer as L, Watermark as R, ZoomHandler as z, registerBuiltInDrawingTools as B, registerBuiltInIndicators as V, toHeikinAshi as H, toKagi as fe, toLineBreak as pe, toPointAndFigure as me, toRangeBars as he, toRenko as ge } from "@tradecanvas/core"; | ||
| //#region src/charts/ChartTypeStrategy.ts | ||
| function _e(e) { | ||
| switch (e) { | ||
| case "candlestick": | ||
| case "heikinAshi": | ||
| case "lineBreak": | ||
| case "rangeBars": return new g(); | ||
| case "line": return new S(); | ||
| case "area": return new p(); | ||
| case "bar": return new ee(); | ||
| case "hollowCandle": return new ce(); | ||
| case "baseline": return new h(); | ||
| case "renko": return new D(); | ||
| case "kagi": return new ue(); | ||
| case "pointAndFigure": return new w(); | ||
| default: return new g(); | ||
| } | ||
| } | ||
| function ve(e, t) { | ||
| if (t.length === 0) return t; | ||
| switch (e) { | ||
| case "heikinAshi": return H(t); | ||
| case "renko": return ge(t, { | ||
| brickSize: 0, | ||
| useATR: !0, | ||
| atrPeriod: 14 | ||
| }); | ||
| case "lineBreak": return pe(t, 3); | ||
| case "kagi": return fe(t, 4); | ||
| case "pointAndFigure": return me(t, U(t) * .01, 3); | ||
| case "rangeBars": return he(t, { rangeSize: U(t) * .005 }); | ||
| default: return t; | ||
| } | ||
| } | ||
| function U(e) { | ||
| let t = 0; | ||
| for (let n of e) t += n.close; | ||
| return t / e.length; | ||
| } | ||
| //#endregion | ||
| //#region src/charts/IndicatorPriceRange.ts | ||
| var W = { | ||
| min: 0, | ||
| max: 100 | ||
| }, G = .1; | ||
| function ye(e, t, n) { | ||
| if (!e) return { ...W }; | ||
| let r = Infinity, i = -Infinity, a = 0; | ||
| for (let [, o] of e.values) { | ||
| if (a >= t && a <= n) for (let e in o) { | ||
| let t = o[e]; | ||
| t !== void 0 && Number.isFinite(t) && (t < r && (r = t), t > i && (i = t)); | ||
| } | ||
| a++; | ||
| } | ||
| if (r === Infinity) return { ...W }; | ||
| let o = i - r || 1; | ||
| return { | ||
| min: r - o * G, | ||
| max: i + o * G | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/state/AutoSaveScheduler.ts | ||
| var be = class { | ||
| timer = null; | ||
| delayMs = 0; | ||
| key = null; | ||
| constructor(e) { | ||
| this.save = e; | ||
| } | ||
| enable(e, t) { | ||
| this.key = e, this.delayMs = t; | ||
| } | ||
| disable() { | ||
| this.key = null, this.delayMs = 0, this.cancel(); | ||
| } | ||
| schedule() { | ||
| this.delayMs <= 0 || !this.key || (this.timer && clearTimeout(this.timer), this.timer = setTimeout(() => { | ||
| this.timer = null, this.key && this.save(this.key); | ||
| }, this.delayMs)); | ||
| } | ||
| cancel() { | ||
| this.timer &&= (clearTimeout(this.timer), null); | ||
| } | ||
| isEnabled() { | ||
| return this.delayMs > 0 && this.key !== null; | ||
| } | ||
| hasPending() { | ||
| return this.timer !== null; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/DataManager.ts | ||
| function K(e) { | ||
| if (!e || typeof e.time != "number") return !1; | ||
| let { open: t, high: n, low: r, close: i } = e; | ||
| return !(!isFinite(t) || !isFinite(n) || !isFinite(r) || !isFinite(i) || t < 0 || n < 0 || r < 0 || i < 0 || n < r || e.volume !== void 0 && (!isFinite(e.volume) || e.volume < 0)); | ||
| } | ||
| function q(e) { | ||
| return { | ||
| ...e, | ||
| high: Math.max(e.open, e.high, e.low, e.close), | ||
| low: Math.min(e.open, e.high, e.low, e.close), | ||
| volume: e.volume === void 0 ? 0 : Math.max(0, e.volume) | ||
| }; | ||
| } | ||
| var J = class { | ||
| data = []; | ||
| getData() { | ||
| return this.data; | ||
| } | ||
| setData(e) { | ||
| this.data = e.filter(K).map(q); | ||
| } | ||
| appendBar(e) { | ||
| K(e) && this.data.push(q(e)); | ||
| } | ||
| updateLastBar(e) { | ||
| if (!K(e)) return; | ||
| let t = q(e); | ||
| if (this.data.length === 0) { | ||
| this.data.push(t); | ||
| return; | ||
| } | ||
| this.data[this.data.length - 1] = t; | ||
| } | ||
| updateLastBarFromTick(e) { | ||
| this.data.length !== 0 && (!isFinite(e.price) || e.price < 0 || e.volume !== void 0 && (!isFinite(e.volume) || e.volume < 0) || (this.data[this.data.length - 1] = c(this.data[this.data.length - 1], e))); | ||
| } | ||
| getLength() { | ||
| return this.data.length; | ||
| } | ||
| clear() { | ||
| this.data = []; | ||
| } | ||
| }, Y = class { | ||
| theme; | ||
| constructor(t) { | ||
| !t || t === "dark" ? this.theme = { ...e } : t === "light" ? this.theme = { ...n } : this.theme = { ...t }; | ||
| } | ||
| getTheme() { | ||
| return this.theme; | ||
| } | ||
| setTheme(t) { | ||
| t === "dark" ? this.theme = { ...e } : t === "light" ? this.theme = { ...n } : this.theme = { ...t }; | ||
| } | ||
| }, X = 200, Z = 80, Q = class { | ||
| panels = []; | ||
| containerWidth = 0; | ||
| containerHeight = 0; | ||
| resize(e, t) { | ||
| this.containerWidth = e, this.containerHeight = t; | ||
| } | ||
| addPanel(e, n = "bottom", r) { | ||
| let a = n === "left" || n === "right"; | ||
| this.panels.push({ | ||
| id: e, | ||
| position: n, | ||
| size: r ?? (a ? X : t), | ||
| minSize: a ? Z : i, | ||
| content: { | ||
| type: "indicator", | ||
| indicatorInstanceId: e | ||
| } | ||
| }); | ||
| } | ||
| removePanel(e) { | ||
| this.panels = this.panels.filter((t) => t.id !== e); | ||
| } | ||
| setPanelPosition(e, n) { | ||
| let r = this.panels.find((t) => t.id === e); | ||
| if (r) { | ||
| let e = r.position === "left" || r.position === "right", a = n === "left" || n === "right"; | ||
| r.position = n, e !== a && (r.size = a ? X : t, r.minSize = a ? Z : i); | ||
| } | ||
| } | ||
| setPanelSize(e, t) { | ||
| let n = this.panels.find((t) => t.id === e); | ||
| n && (n.size = Math.max(n.minSize, t)); | ||
| } | ||
| getPanels() { | ||
| return this.panels; | ||
| } | ||
| resolve() { | ||
| let e = this.panels.filter((e) => e.position === "left"), t = this.panels.filter((e) => e.position === "right"), n = this.panels.filter((e) => e.position === "top"), r = this.panels.filter((e) => e.position === "bottom"), i = e.reduce((e, t) => e + t.size, 0), s = t.reduce((e, t) => e + t.size, 0), c = n.reduce((e, t) => e + t.size, 0), l = r.reduce((e, t) => e + t.size, 0), u = { | ||
| x: i, | ||
| y: c, | ||
| width: Math.max(0, this.containerWidth - i - s - a), | ||
| height: Math.max(0, this.containerHeight - c - l - o) | ||
| }, d = [], f = [], p = 0; | ||
| for (let t of e) d.push({ | ||
| config: t, | ||
| rect: { | ||
| x: p, | ||
| y: 0, | ||
| width: t.size, | ||
| height: this.containerHeight - o | ||
| } | ||
| }), f.push({ | ||
| panelId: t.id, | ||
| rect: { | ||
| x: p + t.size - 2, | ||
| y: 0, | ||
| width: 4, | ||
| height: this.containerHeight | ||
| }, | ||
| orientation: "vertical" | ||
| }), p += t.size; | ||
| let m = 0; | ||
| for (let e of n) d.push({ | ||
| config: e, | ||
| rect: { | ||
| x: i, | ||
| y: m, | ||
| width: u.width, | ||
| height: e.size | ||
| } | ||
| }), f.push({ | ||
| panelId: e.id, | ||
| rect: { | ||
| x: i, | ||
| y: m + e.size - 2, | ||
| width: u.width, | ||
| height: 4 | ||
| }, | ||
| orientation: "horizontal" | ||
| }), m += e.size; | ||
| m = u.y + u.height; | ||
| for (let e of r) d.push({ | ||
| config: e, | ||
| rect: { | ||
| x: i, | ||
| y: m, | ||
| width: u.width, | ||
| height: e.size | ||
| } | ||
| }), f.push({ | ||
| panelId: e.id, | ||
| rect: { | ||
| x: i, | ||
| y: m - 2, | ||
| width: u.width, | ||
| height: 4 | ||
| }, | ||
| orientation: "horizontal" | ||
| }), m += e.size; | ||
| p = i + u.width + a; | ||
| for (let e of t) d.push({ | ||
| config: e, | ||
| rect: { | ||
| x: p, | ||
| y: 0, | ||
| width: e.size, | ||
| height: this.containerHeight - o | ||
| } | ||
| }), f.push({ | ||
| panelId: e.id, | ||
| rect: { | ||
| x: p - 2, | ||
| y: 0, | ||
| width: 4, | ||
| height: this.containerHeight | ||
| }, | ||
| orientation: "vertical" | ||
| }), p += e.size; | ||
| return { | ||
| mainChartRect: u, | ||
| panels: d, | ||
| dividers: f | ||
| }; | ||
| } | ||
| getMainChartRect() { | ||
| return this.resolve().mainChartRect; | ||
| } | ||
| }, $ = class { | ||
| constructor(e) { | ||
| this.indicatorEngine = e; | ||
| } | ||
| registerIndicator(e) { | ||
| this.indicatorEngine.register(e); | ||
| } | ||
| }, xe = class { | ||
| static version = "0.3.0"; | ||
| engine; | ||
| viewport; | ||
| dataManager; | ||
| themeManager; | ||
| layoutManager; | ||
| pluginManager; | ||
| indicatorEngine; | ||
| drawingManager; | ||
| drawingRenderer; | ||
| tradingManager; | ||
| tradingRenderer; | ||
| eventBus; | ||
| streamManager = null; | ||
| autoScrollOnNewBar = !0; | ||
| displayDataCache = null; | ||
| resolvedLayoutCache = null; | ||
| panelInfoCache = null; | ||
| renderScheduled = !1; | ||
| containerSizeCache = null; | ||
| containerSizeCacheTime = 0; | ||
| chartLegend; | ||
| watermark; | ||
| barCountdown; | ||
| sessionBreaks; | ||
| compareRenderer; | ||
| countdownInterval = null; | ||
| volumeRenderer; | ||
| alertManager; | ||
| replayManager; | ||
| undoRedoManager; | ||
| autoSaveScheduler = new be((e) => this.saveState(e)); | ||
| animator; | ||
| crosshairTooltip; | ||
| interactionManager; | ||
| crosshairHandler; | ||
| chartRenderer; | ||
| gridRenderer; | ||
| priceAxis; | ||
| timeAxis; | ||
| options; | ||
| features; | ||
| marketConfig = null; | ||
| container; | ||
| currentPriceLine; | ||
| numberLocale; | ||
| keyboardHandler = null; | ||
| onWindowKeyDown = null; | ||
| currentSymbol = ""; | ||
| constructor(e, t) { | ||
| this.container = e, this.options = t, this.numberLocale = t.numberLocale ?? "en-US"; | ||
| let n = t.features ?? {}; | ||
| this.features = { | ||
| drawings: n.drawings ?? !0, | ||
| drawingTools: n.drawingTools ?? [], | ||
| drawingMagnet: n.drawingMagnet ?? !0, | ||
| drawingUndoRedo: n.drawingUndoRedo ?? !0, | ||
| trading: n.trading ?? !0, | ||
| tradingContextMenu: n.tradingContextMenu ?? !0, | ||
| indicators: n.indicators ?? !0, | ||
| indicatorIds: n.indicatorIds ?? [], | ||
| panning: n.panning ?? !0, | ||
| zooming: n.zooming ?? !0, | ||
| crosshair: n.crosshair ?? !0, | ||
| keyboard: n.keyboard ?? !0, | ||
| priceAxis: n.priceAxis ?? !0, | ||
| timeAxis: n.timeAxis ?? !0, | ||
| grid: n.grid ?? t.grid?.visible ?? !0, | ||
| legend: n.legend ?? !0, | ||
| volume: n.volume ?? !0, | ||
| watermark: n.watermark ?? !0, | ||
| saveLoad: n.saveLoad ?? !0, | ||
| screenshot: n.screenshot ?? !0, | ||
| alerts: n.alerts ?? !0, | ||
| replay: n.replay ?? !0, | ||
| sessionBreaks: n.sessionBreaks ?? !0, | ||
| barCountdown: n.barCountdown ?? !0, | ||
| compareSymbols: n.compareSymbols ?? !0, | ||
| dataExport: n.dataExport ?? !0, | ||
| logScale: n.logScale ?? !0, | ||
| timeframes: n.timeframes ?? [], | ||
| defaultTimeframeFavorites: n.defaultTimeframeFavorites ?? [] | ||
| }, e.style.position = "relative", e.style.overflow = "hidden", e.tabIndex = 0, e.style.outline = "none", this.dataManager = new J(), this.themeManager = new Y(t.theme), this.layoutManager = new Q(), this.indicatorEngine = new x(), this.pluginManager = new $(this.indicatorEngine), this.eventBus = new oe(), V(this.indicatorEngine), this.drawingManager = new ie(), B(this.drawingManager), this.drawingRenderer = new ae(this.drawingManager), this.drawingManager.setRequestRender(() => { | ||
| this.syncRenderContext(), this.engine.requestRender(r.Overlay), this.scheduleAutoSave(); | ||
| }), this.drawingManager.setEventCallback((e, t) => { | ||
| this.eventBus.emit(e, t); | ||
| }), this.undoRedoManager = new F(), this.drawingManager.setUndoRedoManager(this.undoRedoManager), this.drawingManager.setDataGetter(() => this.dataManager.getData()), this.drawingManager.setDisplayDataGetter(() => this.getDisplayData()), t.crosshair?.mode === "magnet" && this.drawingManager.setMagnetMode("magnet"), this.tradingManager = new N(), this.tradingRenderer = new P(this.tradingManager), this.tradingManager.setContainer(e), this.tradingManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradingManager.setEventCallback((e, t) => { | ||
| this.eventBus.emit(e, t); | ||
| }), this.engine = new E(e); | ||
| let i = this.engine.dprManager.getContainerSize(); | ||
| this.viewport = new I(i.width, i.height, t.minBarSpacing ?? 2, t.maxBarSpacing ?? 30, t.rightMargin ?? 5), this.layoutManager.resize(i.width, i.height), this.engine.onContainerResize = (e) => { | ||
| if (e.width <= 0 || e.height <= 0) return; | ||
| let t = this.viewport.isAtEnd(); | ||
| this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(t); | ||
| }, this.chartRenderer = this.createChartRenderer(t.chartType), this.gridRenderer = new se(), t.grid?.visible === !1 && this.gridRenderer.setVisible(!1), this.priceAxis = new T(), this.priceAxis.setLocale(this.numberLocale), this.timeAxis = new M(), this.crosshairHandler = new y(), this.crosshairHandler.setLocale(this.numberLocale), t.crosshair?.mode && this.crosshairHandler.setMode(t.crosshair.mode), this.crosshairHandler.setCallback((e, t) => { | ||
| if (e !== null && t) { | ||
| let n = this.dataManager.getData(), r = e < n.length ? n[e] : void 0; | ||
| this.chartLegend.setHoverBar(r ?? null), r && this.crosshairTooltip.show(t, r, this.themeManager.getTheme(), this.cachedContainerSize()), this.eventBus.emit("crosshairMove", { | ||
| point: t, | ||
| bar: r, | ||
| barIndex: e | ||
| }); | ||
| } else this.crosshairTooltip.hide(), this.chartLegend.setHoverBar(null); | ||
| }), this.chartLegend = new te(), this.chartLegend.setChartType(t.chartType), this.watermark = new R(), t.watermark && this.watermark.setConfig(t.watermark), this.volumeRenderer = new L(), this.barCountdown = new m(), this.sessionBreaks = new A(), this.compareRenderer = new v(), t.sessionBreaks ? this.sessionBreaks.setConfig({ | ||
| visible: t.sessionBreaks.visible ?? !0, | ||
| color: t.sessionBreaks.color, | ||
| lineStyle: t.sessionBreaks.lineStyle, | ||
| lineWidth: t.sessionBreaks.lineWidth | ||
| }) : t.features?.sessionBreaks !== !1 && this.sessionBreaks.setVisible(!0), t.logScale && this.viewport.setLogScale(!0), this.animator = new f(), this.crosshairTooltip = new ne(), this.crosshairTooltip.create(e), this.keyboardHandler = new de({ | ||
| scrollBars: (e) => { | ||
| let t = this.viewport.getState().barWidth + this.viewport.getState().barSpacing; | ||
| this.viewport.scrollBy(e * t), this.updateViewportAndRender(); | ||
| }, | ||
| zoom: (e) => { | ||
| let t = this.viewport.getState().chartRect.width; | ||
| this.viewport.zoom(e, t / 2), this.updateViewportAndRender(); | ||
| }, | ||
| goToStart: () => { | ||
| this.viewport.scrollBy(-Infinity), this.updateViewportAndRender(); | ||
| }, | ||
| goToEnd: () => { | ||
| this.viewport.scrollToEnd(), this.updateViewportAndRender(); | ||
| }, | ||
| fitContent: () => this.fitContent() | ||
| }), this.keyboardHandler.setEnabled(this.features.keyboard), this.onWindowKeyDown = (e) => { | ||
| if (!this.keyboardHandler) return; | ||
| let t = document.activeElement; | ||
| t && t !== this.container && !this.container.contains(t) || t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) || this.keyboardHandler.handleKey(e) && e.preventDefault(); | ||
| }, window.addEventListener("keydown", this.onWindowKeyDown), this.currentPriceLine = new re(), this.alertManager = new d(), this.alertManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.alertManager.on("triggered", (e) => { | ||
| this.eventBus.emit("dataUpdate", { | ||
| alert: "triggered", | ||
| alertId: e.id, | ||
| price: e.price, | ||
| message: e.message | ||
| }); | ||
| }), this.replayManager = new O(), this.interactionManager = new le(e), this.features.panning && this.interactionManager.setPanHandler(new C((e) => { | ||
| this.viewport.scrollBy(e), this.updateViewportAndRender(); | ||
| })), this.features.zooming && this.interactionManager.setZoomHandler(new z((e, t) => { | ||
| this.viewport.zoom(e, t), this.updateViewportAndRender(); | ||
| })), this.features.crosshair && this.interactionManager.setCrosshairHandler(this.crosshairHandler), this.features.drawings && this.interactionManager.setDrawingManager(this.drawingManager, () => this.viewport.getState()), this.features.trading && this.interactionManager.setTradingManager(this.tradingManager, () => this.viewport.getState()), this.interactionManager.setOverlayDirtyCallback(() => { | ||
| this.engine.requestRender(r.Overlay), this.layoutManager.getPanels().length > 0 && this.engine.requestRender(r.UI); | ||
| }), this.interactionManager.attach(), this.syncRenderContext(), this.engine.start(); | ||
| } | ||
| setData(e) { | ||
| this.dataManager.setData(e), this.crosshairHandler.setData(this.dataManager.getData()), this.displayDataCache = null, this.sessionBreaks.invalidateCache(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), e.length > 0 && this.currentPriceLine.setPrice(e[e.length - 1].close), this.updateViewportAndRender(!0), this.eventBus.emit("dataUpdate", { length: e.length }); | ||
| } | ||
| appendBar(e) { | ||
| this.dataManager.appendBar(e), this.crosshairHandler.setData(this.dataManager.getData()), this.displayDataCache = null, this.autoScrollOnNewBar && this.viewport.scrollToEnd(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.updateViewportAndRender(); | ||
| } | ||
| appendBars(e) { | ||
| if (e.length !== 0) { | ||
| for (let t of e) this.dataManager.appendBar(t); | ||
| this.displayDataCache = null, this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.crosshairHandler.setData(this.dataManager.getData()), this.updateViewportAndRender(this.viewport.isAtEnd()); | ||
| } | ||
| } | ||
| updateLastBar(e) { | ||
| this.dataManager.updateLastBar(e), this.currentPriceLine.setPrice(e.close), this.options.chartType !== "candlestick" && this.options.chartType !== "line" && this.options.chartType !== "area" && this.options.chartType !== "bar" && this.options.chartType !== "hollowCandle" && (this.displayDataCache = null), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.scheduleRender(); | ||
| } | ||
| updateLastBarFromTick(e) { | ||
| this.dataManager.updateLastBarFromTick(e), this.currentPriceLine.setPrice(e.price), this.options.chartType !== "candlestick" && this.options.chartType !== "line" && this.options.chartType !== "area" && this.options.chartType !== "bar" && this.options.chartType !== "hollowCandle" && (this.displayDataCache = null), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.scheduleRender(); | ||
| } | ||
| setChartType(e) { | ||
| this.options.chartType = e, this.chartRenderer = this.createChartRenderer(e), this.chartLegend.setChartType(e), this.displayDataCache = null, this.updateViewportAndRender(!0); | ||
| } | ||
| addIndicator(e, t = {}, n = "bottom") { | ||
| if (!this.features.indicators || this.features.indicatorIds.length > 0 && !this.features.indicatorIds.includes(e)) return null; | ||
| let r = this.indicatorEngine.addIndicator(e, t, this.dataManager.getData()); | ||
| return this.indicatorEngine.getAvailableIndicators().find((t) => t.id === e)?.placement === "panel" ? (this.layoutManager.addPanel(r, n), this.updateViewportAndRender()) : this.engine.requestRender(), this.eventBus.emit("indicatorAdd", { | ||
| instanceId: r, | ||
| id: e | ||
| }), r; | ||
| } | ||
| updateIndicator(e, t) { | ||
| this.indicatorEngine.updateIndicator(e, t, this.dataManager.getData()), this.engine.requestRender(); | ||
| } | ||
| removeIndicator(e) { | ||
| let t = this.layoutManager.getPanels().some((t) => t.id === e); | ||
| this.indicatorEngine.removeIndicator(e), this.layoutManager.removePanel(e), this.eventBus.emit("indicatorRemove", { instanceId: e }), t ? this.updateViewportAndRender() : this.engine.requestRender(); | ||
| } | ||
| getIndicatorOutput(e) { | ||
| return this.indicatorEngine.getOutput(e); | ||
| } | ||
| registerIndicator(e) { | ||
| this.pluginManager.registerIndicator(e); | ||
| } | ||
| static indicators() { | ||
| let e = new x(); | ||
| return V(e), e.getAvailableIndicators(); | ||
| } | ||
| setPanelPosition(e, t) { | ||
| this.layoutManager.setPanelPosition(e, t), this.engine.requestRender(); | ||
| } | ||
| setPanelSize(e, t) { | ||
| this.layoutManager.setPanelSize(e, t), this.engine.requestRender(); | ||
| } | ||
| setDrawingTool(e) { | ||
| this.features.drawings && (e && this.features.drawingTools.length > 0 && !this.features.drawingTools.includes(e) || this.drawingManager.setActiveTool(e)); | ||
| } | ||
| getDrawingTool() { | ||
| return this.drawingManager.getActiveTool(); | ||
| } | ||
| setDrawingStyle(e) { | ||
| this.drawingManager.setStyle(e); | ||
| } | ||
| getDrawings() { | ||
| return this.drawingManager.getDrawings(); | ||
| } | ||
| setDrawings(e) { | ||
| this.drawingManager.setDrawings(e); | ||
| } | ||
| removeDrawing(e) { | ||
| this.drawingManager.removeDrawing(e); | ||
| } | ||
| clearDrawings() { | ||
| this.drawingManager.clearDrawings(); | ||
| } | ||
| registerDrawingTool(e) { | ||
| this.drawingManager.register(e); | ||
| } | ||
| undo() { | ||
| return this.features.drawingUndoRedo ? this.drawingManager.undo() : !1; | ||
| } | ||
| redo() { | ||
| return this.features.drawingUndoRedo ? this.drawingManager.redo() : !1; | ||
| } | ||
| getUndoRedoState() { | ||
| return this.undoRedoManager.getState(); | ||
| } | ||
| setDrawingMagnet(e) { | ||
| this.drawingManager.setMagnetMode(e ? "magnet" : "none"); | ||
| } | ||
| getDrawingMagnet() { | ||
| return this.drawingManager.getMagnetMode() === "magnet"; | ||
| } | ||
| lockAllDrawings() { | ||
| this.drawingManager.lockAllDrawings(); | ||
| } | ||
| unlockAllDrawings() { | ||
| this.drawingManager.unlockAllDrawings(); | ||
| } | ||
| hideAllDrawings() { | ||
| this.drawingManager.hideAllDrawings(); | ||
| } | ||
| showAllDrawings() { | ||
| this.drawingManager.showAllDrawings(); | ||
| } | ||
| duplicateDrawing(e) { | ||
| let t = e ?? this.drawingManager.getSelectedDrawingId(); | ||
| return t ? this.drawingManager.duplicateDrawing(t) : null; | ||
| } | ||
| exportVisibleData(e = "csv", t) { | ||
| let n = this.viewport.getState(), r = this.dataManager.getData(), i = Math.max(0, n.visibleRange.from), a = Math.min(r.length - 1, n.visibleRange.to), o = r.slice(i, a + 1); | ||
| if (e === "json") { | ||
| let e = b.toJSON(o); | ||
| b.download(e, t ?? "chart-data.json", "application/json"); | ||
| } else { | ||
| let e = b.toCSV(o); | ||
| b.download(e, t ?? "chart-data.csv", "text/csv"); | ||
| } | ||
| } | ||
| exportAllData(e = "csv", t) { | ||
| let n = this.dataManager.getData(); | ||
| if (e === "json") { | ||
| let e = b.toJSON(n); | ||
| b.download(e, t ?? "chart-data.json", "application/json"); | ||
| } else { | ||
| let e = b.toCSV(n); | ||
| b.download(e, t ?? "chart-data.csv", "text/csv"); | ||
| } | ||
| } | ||
| setAutoSave(e, t = 5e3) { | ||
| this.autoSaveScheduler.enable(e, t); | ||
| } | ||
| disableAutoSave() { | ||
| this.autoSaveScheduler.disable(); | ||
| } | ||
| scheduleAutoSave() { | ||
| this.autoSaveScheduler.schedule(); | ||
| } | ||
| getAvailableIndicators() { | ||
| return this.indicatorEngine.getAvailableIndicators(); | ||
| } | ||
| getIndicatorInputs(e) { | ||
| let t = this.indicatorEngine.getAvailableIndicators().find((t) => t.id === e); | ||
| return t ? { | ||
| id: t.id, | ||
| params: t.defaultConfig | ||
| } : null; | ||
| } | ||
| getActiveIndicators() { | ||
| return this.indicatorEngine.getActiveIndicators(); | ||
| } | ||
| getIndicatorConfig(e) { | ||
| let t = this.indicatorEngine.getIndicatorConfig(e); | ||
| return t ? { | ||
| id: t.id, | ||
| params: { ...t.params } | ||
| } : null; | ||
| } | ||
| updateIndicatorStyle(e, t) { | ||
| this.indicatorEngine.updateIndicatorStyle(e, t), this.engine.requestRender(); | ||
| } | ||
| setOrders(e) { | ||
| this.features.trading && this.tradingManager.setOrders(e); | ||
| } | ||
| setPositions(e) { | ||
| this.features.trading && this.tradingManager.setPositions(e); | ||
| } | ||
| setDepthData(e) { | ||
| this.features.trading && this.tradingManager.setDepthData(e); | ||
| } | ||
| setCurrentPrice(e, t) { | ||
| this.tradingManager.setCurrentPrice(e), this.currentPriceLine.setPrice(e), this.scheduleRender(), this.features.alerts && this.alertManager.checkPrice(e); | ||
| } | ||
| setTradingConfig(e) { | ||
| this.features.trading && this.tradingManager.setConfig(e); | ||
| } | ||
| async connect(e) { | ||
| this.disconnectStream(), this.streamManager = new j(), this.streamManager.on("snapshot", (e) => { | ||
| this.setData(e); | ||
| }), this.streamManager.on("barClose", (e) => { | ||
| this.dataManager.appendBar(e), this.crosshairHandler.setData(this.dataManager.getData()), this.autoScrollOnNewBar && this.viewport.scrollToEnd(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.updateViewportAndRender(); | ||
| }), this.streamManager.on("barUpdate", (e) => { | ||
| this.dataManager.updateLastBar(e), this.currentPriceLine.setPrice(e.close), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.scheduleRender(); | ||
| }), this.streamManager.on("priceChange", ({ price: e }) => { | ||
| this.tradingManager.setCurrentPrice(e), this.currentPriceLine.setPrice(e), this.engine.requestRender(r.Overlay), this.engine.requestRender(r.UI); | ||
| }), this.streamManager.on("connectionChange", (e) => { | ||
| this.eventBus.emit("dataUpdate", { connection: e }); | ||
| }), this.streamManager.on("error", (e) => { | ||
| this.eventBus.emit("dataUpdate", { error: e.message }); | ||
| }), this.autoScrollOnNewBar = e.autoScroll !== !1, this.currentSymbol = e.symbol, await this.streamManager.connect(e); | ||
| let t = u(e.timeframe); | ||
| this.barCountdown.setTimeframeMs(t), this.countdownInterval && clearInterval(this.countdownInterval), this.countdownInterval = setInterval(() => { | ||
| this.barCountdown.isVisible() && this.engine.requestRender(r.UI); | ||
| }, 1e3); | ||
| } | ||
| async switchStream(e, t) { | ||
| this.streamManager && (this.currentSymbol = e, await this.streamManager.switchTo(e, t)); | ||
| } | ||
| async setTimeframe(e) { | ||
| if (!this.streamManager) throw Error("No active stream. Call connect() first."); | ||
| await this.switchStream(this.currentSymbol, e); | ||
| } | ||
| disconnectStream() { | ||
| this.streamManager &&= (this.streamManager.dispose(), null); | ||
| } | ||
| setBarCountdownVisible(e) { | ||
| this.barCountdown.setVisible(e), this.engine.requestRender(r.UI); | ||
| } | ||
| setSessionBreaksVisible(e) { | ||
| this.sessionBreaks.setVisible(e), this.engine.requestRender(r.Background); | ||
| } | ||
| addCompareSymbol(e, t, n, i) { | ||
| this.compareRenderer.addSymbol({ | ||
| id: e, | ||
| label: t, | ||
| data: n, | ||
| color: i, | ||
| visible: !0 | ||
| }), this.engine.requestRender(r.Main); | ||
| } | ||
| removeCompareSymbol(e) { | ||
| this.compareRenderer.removeSymbol(e), this.engine.requestRender(r.Main); | ||
| } | ||
| updateCompareData(e, t) { | ||
| this.compareRenderer.setSymbolData(e, t), this.engine.requestRender(r.Main); | ||
| } | ||
| setCompareMode(e) { | ||
| this.compareRenderer.setMode(e), this.engine.requestRender(r.Main); | ||
| } | ||
| clearCompareSymbols() { | ||
| this.compareRenderer.clear(), this.engine.requestRender(r.Main); | ||
| } | ||
| setLogScale(e) { | ||
| this.viewport.setLogScale(e), this.updateViewportAndRender(); | ||
| } | ||
| isLogScale() { | ||
| return this.viewport.isLogScale(); | ||
| } | ||
| setSessionBreaksConfig(e) { | ||
| this.sessionBreaks.setConfig(e), this.engine.requestRender(r.Background); | ||
| } | ||
| getConnectionState() { | ||
| return this.streamManager?.getConnectionState() ?? "disconnected"; | ||
| } | ||
| getConnectionInfo() { | ||
| return this.streamManager?.getConnectionInfo() ?? { state: "disconnected" }; | ||
| } | ||
| setAutoScroll(e) { | ||
| this.autoScrollOnNewBar = e; | ||
| } | ||
| scrollTo(e) { | ||
| let t = this.dataManager.getData(); | ||
| for (let n = 0; n < t.length; n++) if (t[n].time >= e) { | ||
| let e = this.viewport.getState().barWidth + this.viewport.getState().barSpacing; | ||
| this.viewport.scrollBy(n * e - this.viewport.getState().offset), this.updateViewportAndRender(); | ||
| return; | ||
| } | ||
| } | ||
| scrollToEnd() { | ||
| this.viewport.scrollToEnd(), this.updateViewportAndRender(); | ||
| } | ||
| setVisibleRange(e, t) { | ||
| let n = this.dataManager.getData(), r = 0, i = n.length - 1; | ||
| for (let t = 0; t < n.length; t++) if (n[t].time >= e) { | ||
| r = t; | ||
| break; | ||
| } | ||
| for (let e = n.length - 1; e >= 0; e--) if (n[e].time <= t) { | ||
| i = e; | ||
| break; | ||
| } | ||
| let a = i - r + 1; | ||
| if (a > 0) { | ||
| let e = this.viewport.getState().chartRect.width, t = e / a, n = Math.max(2, t - this.viewport.getState().barSpacing); | ||
| this.viewport.zoom((n - this.viewport.getState().barWidth) / this.viewport.getState().barWidth, e / 2); | ||
| } | ||
| this.updateViewportAndRender(); | ||
| } | ||
| zoomIn() { | ||
| let e = this.viewport.getState().chartRect.width; | ||
| this.viewport.zoom(.2, e / 2), this.updateViewportAndRender(); | ||
| } | ||
| zoomOut() { | ||
| let e = this.viewport.getState().chartRect.width; | ||
| this.viewport.zoom(-.2, e / 2), this.updateViewportAndRender(); | ||
| } | ||
| fitContent() { | ||
| let e = this.dataManager.getData(); | ||
| e.length !== 0 && this.setVisibleRange(e[0].time, e[e.length - 1].time); | ||
| } | ||
| on(e, t) { | ||
| this.eventBus.on(e, t); | ||
| } | ||
| off(e, t) { | ||
| this.eventBus.off(e, t); | ||
| } | ||
| enableTauriBridge(e) { | ||
| this.eventBus.enableTauriBridge({ | ||
| enabled: !0, | ||
| ...e | ||
| }); | ||
| } | ||
| disableTauriBridge() { | ||
| this.eventBus.disableTauriBridge(); | ||
| } | ||
| setTheme(e) { | ||
| this.themeManager.setTheme(e), this.syncRenderContext(), this.container.style.backgroundColor = this.themeManager.getTheme().background, this.engine.requestRender(), this.eventBus.emit("themeChange", { theme: e }); | ||
| } | ||
| getTheme() { | ||
| return this.themeManager.getTheme(); | ||
| } | ||
| setWatermark(e, t) { | ||
| this.watermark.setConfig({ | ||
| text: e, | ||
| ...t | ||
| }), this.engine.requestRender(r.Background); | ||
| } | ||
| setAutoScale(e) { | ||
| this.options.autoScale = e, this.updateViewportAndRender(); | ||
| } | ||
| isAutoScale() { | ||
| return this.options.autoScale !== !1; | ||
| } | ||
| setCrosshairMode(e) { | ||
| this.crosshairHandler.setMode(e), this.engine.requestRender(r.Overlay); | ||
| } | ||
| getCrosshairMode() { | ||
| return this.crosshairHandler.getMode(); | ||
| } | ||
| setGridVisible(e) { | ||
| this.gridRenderer.setVisible(e), this.engine.requestRender(r.Background); | ||
| } | ||
| isGridVisible() { | ||
| return this.gridRenderer.isVisible(); | ||
| } | ||
| setVolumeVisible(e) { | ||
| this.volumeRenderer.setVisible(e), this.engine.requestRender(r.Main); | ||
| } | ||
| setTooltipVisible(e) { | ||
| e || this.crosshairTooltip.hide(); | ||
| } | ||
| setLegend(e) { | ||
| this.chartLegend.setConfig(e), this.engine.requestRender(r.UI); | ||
| } | ||
| setSymbolName(e) { | ||
| this.chartLegend.setSymbol(e), this.engine.requestRender(r.UI); | ||
| } | ||
| setStatusText(e) { | ||
| this.chartLegend.setStatusText(e), this.engine.requestRender(r.UI); | ||
| } | ||
| screenshot(e) { | ||
| this.features.screenshot && k.download(this.container, e, this.themeManager.getTheme().background); | ||
| } | ||
| screenshotDataURL() { | ||
| return this.features.screenshot ? k.toDataURL(this.container, this.themeManager.getTheme().background) : null; | ||
| } | ||
| async screenshotBlob() { | ||
| return this.features.screenshot ? k.toBlob(this.container, this.themeManager.getTheme().background) : null; | ||
| } | ||
| addAlert(e, t = "crossing", n) { | ||
| if (!this.features.alerts) return null; | ||
| let r = this.alertManager.addAlert(e, t, n); | ||
| return this.scheduleAutoSave(), r; | ||
| } | ||
| removeAlert(e) { | ||
| this.alertManager.removeAlert(e), this.scheduleAutoSave(); | ||
| } | ||
| getAlerts() { | ||
| return this.alertManager.getAlerts(); | ||
| } | ||
| clearAlerts() { | ||
| this.alertManager.clearAlerts(), this.scheduleAutoSave(); | ||
| } | ||
| saveAlerts(e) { | ||
| this.alertManager.saveToStorage(e); | ||
| } | ||
| loadAlerts(e) { | ||
| this.alertManager.loadFromStorage(e), this.engine.requestRender(r.Overlay); | ||
| } | ||
| replay(e) { | ||
| if (!this.features.replay) return; | ||
| let t = this.dataManager.getData(); | ||
| this.replayManager.load(t), this.replayManager.on("bar", ({ bar: e, index: n }) => { | ||
| let r = t.slice(0, n + 1); | ||
| this.dataManager.setData(r), this.crosshairHandler.setData(r), this.indicatorEngine.recalculateAll(r), this.updateViewportAndRender(); | ||
| }), this.replayManager.play(e); | ||
| } | ||
| replayPause() { | ||
| this.replayManager.pause(); | ||
| } | ||
| replayResume() { | ||
| this.replayManager.resume(); | ||
| } | ||
| replayStop() { | ||
| this.replayManager.stop(); | ||
| } | ||
| replaySeek(e) { | ||
| this.replayManager.seekTo(e); | ||
| } | ||
| setReplaySpeed(e) { | ||
| this.replayManager.setSpeed(e); | ||
| } | ||
| getReplayState() { | ||
| return this.replayManager.getState(); | ||
| } | ||
| getReplayProgress() { | ||
| return this.replayManager.getProgress(); | ||
| } | ||
| saveState(e) { | ||
| if (!this.features.saveLoad) return null; | ||
| let t = _.capture({ | ||
| getDrawings: () => this.getDrawings(), | ||
| getTheme: () => this.getTheme(), | ||
| getAlerts: () => this.getAlerts() | ||
| }, { chartType: this.options.chartType }), n = _.serialize(t); | ||
| return e && _.saveToStorage(e, t), n; | ||
| } | ||
| loadState(e) { | ||
| if (!this.features.saveLoad) return; | ||
| let t = _.deserialize(e); | ||
| if (t.chartType && this.setChartType(t.chartType), t.drawings && this.setDrawings(t.drawings), t.theme && this.setTheme(t.theme), t.alerts) { | ||
| this.clearAlerts(); | ||
| for (let e of t.alerts) this.addAlert(e.price, e.condition, e.message); | ||
| } | ||
| } | ||
| loadStateFromStorage(e) { | ||
| if (!this.features.saveLoad) return !1; | ||
| let t = _.loadFromStorage(e); | ||
| return t ? (this.loadState(_.serialize(t)), !0) : !1; | ||
| } | ||
| downloadState(e) { | ||
| if (!this.features.saveLoad) return; | ||
| let t = _.capture({ | ||
| getDrawings: () => this.getDrawings(), | ||
| getTheme: () => this.getTheme(), | ||
| getAlerts: () => this.getAlerts() | ||
| }, { chartType: this.options.chartType }); | ||
| _.downloadFile(t, e); | ||
| } | ||
| async loadStateFromFile() { | ||
| if (!this.features.saveLoad) return; | ||
| let e = await _.loadFromFile(); | ||
| this.loadState(_.serialize(e)); | ||
| } | ||
| setLocale(e) { | ||
| l(e), this.engine.requestRender(); | ||
| } | ||
| setNumberLocale(e) { | ||
| this.numberLocale = e, this.priceAxis.setLocale(e), this.crosshairHandler.setLocale(e), this.syncRenderContext(), this.engine.requestRender(); | ||
| } | ||
| getNumberLocale() { | ||
| return this.numberLocale; | ||
| } | ||
| setMarket(e) { | ||
| if (this.marketConfig = e, e.colorScheme) { | ||
| let t = { | ||
| ...this.themeManager.getTheme(), | ||
| candleUp: e.colorScheme.up, | ||
| candleDown: e.colorScheme.down, | ||
| candleUpWick: e.colorScheme.up, | ||
| candleDownWick: e.colorScheme.down, | ||
| volumeUp: e.colorScheme.up.replace(")", ", 0.3)").replace("rgb(", "rgba(") || `${e.colorScheme.up}4D`, | ||
| volumeDown: e.colorScheme.down.replace(")", ", 0.3)").replace("rgb(", "rgba(") || `${e.colorScheme.down}4D` | ||
| }; | ||
| this.themeManager.setTheme(t); | ||
| } | ||
| e.pricePrecision !== void 0 && (this.tradingManager.setConfig({ pricePrecision: e.pricePrecision }), this.alertManager.setPricePrecision(e.pricePrecision), this.streamManager?.priceLine.setPricePrecision(e.pricePrecision), this.crosshairHandler.setPricePrecision(e.pricePrecision)), this.syncRenderContext(), this.engine.requestRender(); | ||
| } | ||
| getMarket() { | ||
| return this.marketConfig; | ||
| } | ||
| setPriceLimits(e) { | ||
| this.marketConfig && (s(e, this.marketConfig) && (this.marketConfig.priceLimits = { | ||
| ...this.marketConfig.priceLimits, | ||
| referencePrice: e | ||
| }), this.engine.requestRender()); | ||
| } | ||
| getFeatures() { | ||
| return this.features; | ||
| } | ||
| setFeatures(e) { | ||
| Object.assign(this.features, e), e.crosshair === !1 && this.crosshairTooltip.hide(), e.grid !== void 0 && this.engine.requestRender(r.Background), e.volume !== void 0 && (this.volumeRenderer.setVisible(e.volume), this.engine.requestRender(r.Main)), e.drawings === !1 && this.drawingManager.setActiveTool(null), e.trading === !1 && (this.tradingManager.setOrders([]), this.tradingManager.setPositions([])), e.keyboard !== void 0 && this.keyboardHandler?.setEnabled(e.keyboard), this.engine.requestRender(); | ||
| } | ||
| resize() { | ||
| let e = this.engine.dprManager.readContainerSize(); | ||
| if (e.width <= 0 || e.height <= 0) return; | ||
| this.containerSizeCache = e, this.containerSizeCacheTime = Date.now(); | ||
| let t = this.engine.dprManager.getDpr(); | ||
| this.engine.layerManager.resize(e, t); | ||
| let n = this.viewport.isAtEnd(); | ||
| this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(n), this.eventBus.emit("resize", e); | ||
| } | ||
| destroy() { | ||
| this.countdownInterval && clearInterval(this.countdownInterval), this.disableAutoSave(), this.disconnectStream(), this.onWindowKeyDown &&= (window.removeEventListener("keydown", this.onWindowKeyDown), null), this.keyboardHandler = null, this.interactionManager.detach(), this.tradingManager.destroy(), this.animator.dispose(), this.crosshairTooltip.destroy(), this.replayManager.dispose(), this.undoRedoManager.clear(), this.engine.destroy(), this.eventBus.destroy(), this.container.innerHTML = ""; | ||
| } | ||
| createChartRenderer(e) { | ||
| return _e(e); | ||
| } | ||
| getDisplayData() { | ||
| if (this.displayDataCache) return this.displayDataCache; | ||
| let e = this.dataManager.getData(); | ||
| if (e.length === 0) return e; | ||
| let t = ve(this.options.chartType, e); | ||
| return this.displayDataCache = t, t; | ||
| } | ||
| scheduleRender() { | ||
| this.renderScheduled || (this.renderScheduled = !0, requestAnimationFrame(() => { | ||
| this.renderScheduled = !1; | ||
| let e = this.getDisplayData(); | ||
| this.viewport.updateData(e, this.options.autoScale !== !1), this.syncRenderContext(), this.engine.requestRender(); | ||
| })); | ||
| } | ||
| updateViewportAndRender(e = !1) { | ||
| this.resolvedLayoutCache = null, this.panelInfoCache = null; | ||
| let t = this.getResolvedLayout(); | ||
| this.viewport.setChartRect(t.mainChartRect); | ||
| let n = this.getDisplayData(); | ||
| if (this.viewport.updateData(n, this.options.autoScale !== !1), this.options.autoScale !== !1) { | ||
| let e = this.viewport.getState(), t = this.indicatorEngine.getOverlayPriceRange(e.visibleRange.from, Math.min(e.visibleRange.to, n.length - 1)); | ||
| if (t) { | ||
| let n = e.priceRange, r = Math.min(n.min, t.min), i = Math.max(n.max, t.max); | ||
| if (r < n.min || i > n.max) { | ||
| let e = i - r || 1; | ||
| this.viewport.setPriceRange(r - e * .02, i + e * .02); | ||
| } | ||
| } | ||
| } | ||
| e && this.viewport.scrollToEnd(), this.syncRenderContext(), this.engine.requestRender(); | ||
| } | ||
| getResolvedLayout() { | ||
| return this.resolvedLayoutCache ||= this.layoutManager.resolve(), this.resolvedLayoutCache; | ||
| } | ||
| cachedContainerSize() { | ||
| let e = Date.now(); | ||
| return (!this.containerSizeCache || e - this.containerSizeCacheTime > 500) && (this.containerSizeCache = this.engine.dprManager.getContainerSize(), this.containerSizeCacheTime = e), this.containerSizeCache; | ||
| } | ||
| buildPanelRenderInfos() { | ||
| if (this.panelInfoCache) return this.panelInfoCache; | ||
| let e = this.getResolvedLayout(), t = this.viewport.getState(), { from: n, to: r } = t.visibleRange, i = e.panels.map((e) => { | ||
| let i = ye(this.indicatorEngine.getOutput(e.config.id), n, r), a = { | ||
| x: e.rect.x, | ||
| y: e.rect.y + 20, | ||
| width: e.rect.width, | ||
| height: Math.max(0, e.rect.height - 20) | ||
| }; | ||
| return { | ||
| instanceId: e.config.id, | ||
| rect: e.rect, | ||
| viewport: { | ||
| ...t, | ||
| chartRect: a, | ||
| priceRange: i | ||
| } | ||
| }; | ||
| }); | ||
| return this.panelInfoCache = i, i; | ||
| } | ||
| syncRenderContext() { | ||
| let e = this.getResolvedLayout(), t = this.features.indicators ? this.buildPanelRenderInfos() : [], n = e.panels.filter((e) => e.config.position === "bottom").reduce((e, t) => e + t.rect.height, 0), r = e.mainChartRect.y + e.mainChartRect.height + n; | ||
| this.engine.setRenderContext({ | ||
| chartRenderer: this.chartRenderer, | ||
| gridRenderer: this.features.grid ? this.gridRenderer : null, | ||
| priceAxis: this.features.priceAxis ? this.priceAxis : null, | ||
| timeAxis: this.features.timeAxis ? this.timeAxis : null, | ||
| crosshairHandler: this.features.crosshair ? this.crosshairHandler : null, | ||
| indicatorEngine: this.features.indicators ? this.indicatorEngine : null, | ||
| drawingRenderer: this.features.drawings ? this.drawingRenderer : null, | ||
| tradingRenderer: this.features.trading ? this.tradingRenderer : null, | ||
| currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine, | ||
| chartLegend: this.features.legend ? this.chartLegend : null, | ||
| volumeRenderer: this.features.volume ? this.volumeRenderer : null, | ||
| watermark: this.features.watermark ? this.watermark : null, | ||
| barCountdown: this.barCountdown, | ||
| sessionBreaks: this.sessionBreaks, | ||
| compareRenderer: this.compareRenderer, | ||
| panels: t, | ||
| priceLimits: this.buildPriceLimits(), | ||
| timeAxisY: r, | ||
| viewport: this.viewport.getState(), | ||
| theme: this.themeManager.getTheme(), | ||
| data: this.getDisplayData(), | ||
| numberLocale: this.numberLocale | ||
| }); | ||
| } | ||
| buildPriceLimits() { | ||
| if (!this.marketConfig?.priceLimits?.enabled || !this.marketConfig.priceLimits.referencePrice) return null; | ||
| let e = s(this.marketConfig.priceLimits.referencePrice, this.marketConfig); | ||
| return e ? { | ||
| ...e, | ||
| colors: this.marketConfig.colorScheme ? { | ||
| ceiling: this.marketConfig.colorScheme.ceiling, | ||
| floor: this.marketConfig.colorScheme.floor, | ||
| reference: this.marketConfig.colorScheme.reference | ||
| } : void 0 | ||
| } : null; | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { J as a, Y as i, $ as n, Q as r, xe as t }; | ||
| //# sourceMappingURL=Chart-CrrTKx3r.js.map |
Sorry, the diff of this file is too big to display
| let e=require(`@tradecanvas/commons`),t=require(`@tradecanvas/core`);function n(e){switch(e){case`candlestick`:case`heikinAshi`:case`lineBreak`:case`rangeBars`:return new t.CandlestickRenderer;case`line`:return new t.LineRenderer;case`area`:return new t.AreaRenderer;case`bar`:return new t.BarRenderer;case`hollowCandle`:return new t.HollowCandleRenderer;case`baseline`:return new t.BaselineRenderer;case`renko`:return new t.RenkoRenderer;case`kagi`:return new t.KagiRenderer;case`pointAndFigure`:return new t.PointAndFigureRenderer;default:return new t.CandlestickRenderer}}function r(e,n){if(n.length===0)return n;switch(e){case`heikinAshi`:return(0,t.toHeikinAshi)(n);case`renko`:return(0,t.toRenko)(n,{brickSize:0,useATR:!0,atrPeriod:14});case`lineBreak`:return(0,t.toLineBreak)(n,3);case`kagi`:return(0,t.toKagi)(n,4);case`pointAndFigure`:return(0,t.toPointAndFigure)(n,i(n)*.01,3);case`rangeBars`:return(0,t.toRangeBars)(n,{rangeSize:i(n)*.005});default:return n}}function i(e){let t=0;for(let n of e)t+=n.close;return t/e.length}var a={min:0,max:100},o=.1;function s(e,t,n){if(!e)return{...a};let r=1/0,i=-1/0,s=0;for(let[,a]of e.values){if(s>=t&&s<=n)for(let e in a){let t=a[e];t!==void 0&&Number.isFinite(t)&&(t<r&&(r=t),t>i&&(i=t))}s++}if(r===1/0)return{...a};let c=i-r||1;return{min:r-c*o,max:i+c*o}}var c=class{timer=null;delayMs=0;key=null;constructor(e){this.save=e}enable(e,t){this.key=e,this.delayMs=t}disable(){this.key=null,this.delayMs=0,this.cancel()}schedule(){this.delayMs<=0||!this.key||(this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=null,this.key&&this.save(this.key)},this.delayMs))}cancel(){this.timer&&=(clearTimeout(this.timer),null)}isEnabled(){return this.delayMs>0&&this.key!==null}hasPending(){return this.timer!==null}};function l(e){if(!e||typeof e.time!=`number`)return!1;let{open:t,high:n,low:r,close:i}=e;return!(!isFinite(t)||!isFinite(n)||!isFinite(r)||!isFinite(i)||t<0||n<0||r<0||i<0||n<r||e.volume!==void 0&&(!isFinite(e.volume)||e.volume<0))}function u(e){return{...e,high:Math.max(e.open,e.high,e.low,e.close),low:Math.min(e.open,e.high,e.low,e.close),volume:e.volume===void 0?0:Math.max(0,e.volume)}}var d=class{data=[];getData(){return this.data}setData(e){this.data=e.filter(l).map(u)}appendBar(e){l(e)&&this.data.push(u(e))}updateLastBar(e){if(!l(e))return;let t=u(e);if(this.data.length===0){this.data.push(t);return}this.data[this.data.length-1]=t}updateLastBarFromTick(t){this.data.length!==0&&(!isFinite(t.price)||t.price<0||t.volume!==void 0&&(!isFinite(t.volume)||t.volume<0)||(this.data[this.data.length-1]=(0,e.mergeBar)(this.data[this.data.length-1],t)))}getLength(){return this.data.length}clear(){this.data=[]}},f=class{theme;constructor(t){!t||t===`dark`?this.theme={...e.DARK_THEME}:t===`light`?this.theme={...e.LIGHT_THEME}:this.theme={...t}}getTheme(){return this.theme}setTheme(t){t===`dark`?this.theme={...e.DARK_THEME}:t===`light`?this.theme={...e.LIGHT_THEME}:this.theme={...t}}},p=200,m=80,h=class{panels=[];containerWidth=0;containerHeight=0;resize(e,t){this.containerWidth=e,this.containerHeight=t}addPanel(t,n=`bottom`,r){let i=n===`left`||n===`right`;this.panels.push({id:t,position:n,size:r??(i?p:e.DEFAULT_PANEL_HEIGHT),minSize:i?m:e.MIN_PANEL_HEIGHT,content:{type:`indicator`,indicatorInstanceId:t}})}removePanel(e){this.panels=this.panels.filter(t=>t.id!==e)}setPanelPosition(t,n){let r=this.panels.find(e=>e.id===t);if(r){let t=r.position===`left`||r.position===`right`,i=n===`left`||n===`right`;r.position=n,t!==i&&(r.size=i?p:e.DEFAULT_PANEL_HEIGHT,r.minSize=i?m:e.MIN_PANEL_HEIGHT)}}setPanelSize(e,t){let n=this.panels.find(t=>t.id===e);n&&(n.size=Math.max(n.minSize,t))}getPanels(){return this.panels}resolve(){let t=this.panels.filter(e=>e.position===`left`),n=this.panels.filter(e=>e.position===`right`),r=this.panels.filter(e=>e.position===`top`),i=this.panels.filter(e=>e.position===`bottom`),a=t.reduce((e,t)=>e+t.size,0),o=n.reduce((e,t)=>e+t.size,0),s=r.reduce((e,t)=>e+t.size,0),c=i.reduce((e,t)=>e+t.size,0),l={x:a,y:s,width:Math.max(0,this.containerWidth-a-o-e.PRICE_AXIS_WIDTH),height:Math.max(0,this.containerHeight-s-c-e.TIME_AXIS_HEIGHT)},u=[],d=[],f=0;for(let n of t)u.push({config:n,rect:{x:f,y:0,width:n.size,height:this.containerHeight-e.TIME_AXIS_HEIGHT}}),d.push({panelId:n.id,rect:{x:f+n.size-2,y:0,width:4,height:this.containerHeight},orientation:`vertical`}),f+=n.size;let p=0;for(let e of r)u.push({config:e,rect:{x:a,y:p,width:l.width,height:e.size}}),d.push({panelId:e.id,rect:{x:a,y:p+e.size-2,width:l.width,height:4},orientation:`horizontal`}),p+=e.size;p=l.y+l.height;for(let e of i)u.push({config:e,rect:{x:a,y:p,width:l.width,height:e.size}}),d.push({panelId:e.id,rect:{x:a,y:p-2,width:l.width,height:4},orientation:`horizontal`}),p+=e.size;f=a+l.width+e.PRICE_AXIS_WIDTH;for(let t of n)u.push({config:t,rect:{x:f,y:0,width:t.size,height:this.containerHeight-e.TIME_AXIS_HEIGHT}}),d.push({panelId:t.id,rect:{x:f-2,y:0,width:4,height:this.containerHeight},orientation:`vertical`}),f+=t.size;return{mainChartRect:l,panels:u,dividers:d}}getMainChartRect(){return this.resolve().mainChartRect}},g=class{constructor(e){this.indicatorEngine=e}registerIndicator(e){this.indicatorEngine.register(e)}},_=class{static version=`0.3.0`;engine;viewport;dataManager;themeManager;layoutManager;pluginManager;indicatorEngine;drawingManager;drawingRenderer;tradingManager;tradingRenderer;eventBus;streamManager=null;autoScrollOnNewBar=!0;displayDataCache=null;resolvedLayoutCache=null;panelInfoCache=null;renderScheduled=!1;containerSizeCache=null;containerSizeCacheTime=0;chartLegend;watermark;barCountdown;sessionBreaks;compareRenderer;countdownInterval=null;volumeRenderer;alertManager;replayManager;undoRedoManager;autoSaveScheduler=new c(e=>this.saveState(e));animator;crosshairTooltip;interactionManager;crosshairHandler;chartRenderer;gridRenderer;priceAxis;timeAxis;options;features;marketConfig=null;container;currentPriceLine;numberLocale;keyboardHandler=null;onWindowKeyDown=null;currentSymbol=``;constructor(n,r){this.container=n,this.options=r,this.numberLocale=r.numberLocale??`en-US`;let i=r.features??{};this.features={drawings:i.drawings??!0,drawingTools:i.drawingTools??[],drawingMagnet:i.drawingMagnet??!0,drawingUndoRedo:i.drawingUndoRedo??!0,trading:i.trading??!0,tradingContextMenu:i.tradingContextMenu??!0,indicators:i.indicators??!0,indicatorIds:i.indicatorIds??[],panning:i.panning??!0,zooming:i.zooming??!0,crosshair:i.crosshair??!0,keyboard:i.keyboard??!0,priceAxis:i.priceAxis??!0,timeAxis:i.timeAxis??!0,grid:i.grid??r.grid?.visible??!0,legend:i.legend??!0,volume:i.volume??!0,watermark:i.watermark??!0,saveLoad:i.saveLoad??!0,screenshot:i.screenshot??!0,alerts:i.alerts??!0,replay:i.replay??!0,sessionBreaks:i.sessionBreaks??!0,barCountdown:i.barCountdown??!0,compareSymbols:i.compareSymbols??!0,dataExport:i.dataExport??!0,logScale:i.logScale??!0,timeframes:i.timeframes??[],defaultTimeframeFavorites:i.defaultTimeframeFavorites??[]},n.style.position=`relative`,n.style.overflow=`hidden`,n.tabIndex=0,n.style.outline=`none`,this.dataManager=new d,this.themeManager=new f(r.theme),this.layoutManager=new h,this.indicatorEngine=new t.IndicatorEngine,this.pluginManager=new g(this.indicatorEngine),this.eventBus=new t.EventBus,(0,t.registerBuiltInIndicators)(this.indicatorEngine),this.drawingManager=new t.DrawingManager,(0,t.registerBuiltInDrawingTools)(this.drawingManager),this.drawingRenderer=new t.DrawingRenderer(this.drawingManager),this.drawingManager.setRequestRender(()=>{this.syncRenderContext(),this.engine.requestRender(e.LayerType.Overlay),this.scheduleAutoSave()}),this.drawingManager.setEventCallback((e,t)=>{this.eventBus.emit(e,t)}),this.undoRedoManager=new t.UndoRedoManager,this.drawingManager.setUndoRedoManager(this.undoRedoManager),this.drawingManager.setDataGetter(()=>this.dataManager.getData()),this.drawingManager.setDisplayDataGetter(()=>this.getDisplayData()),r.crosshair?.mode===`magnet`&&this.drawingManager.setMagnetMode(`magnet`),this.tradingManager=new t.TradingManager,this.tradingRenderer=new t.TradingRenderer(this.tradingManager),this.tradingManager.setContainer(n),this.tradingManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.tradingManager.setEventCallback((e,t)=>{this.eventBus.emit(e,t)}),this.engine=new t.RenderEngine(n);let a=this.engine.dprManager.getContainerSize();this.viewport=new t.Viewport(a.width,a.height,r.minBarSpacing??2,r.maxBarSpacing??30,r.rightMargin??5),this.layoutManager.resize(a.width,a.height),this.engine.onContainerResize=e=>{if(e.width<=0||e.height<=0)return;let t=this.viewport.isAtEnd();this.viewport.resize(e.width,e.height),this.layoutManager.resize(e.width,e.height),this.updateViewportAndRender(t)},this.chartRenderer=this.createChartRenderer(r.chartType),this.gridRenderer=new t.GridRenderer,r.grid?.visible===!1&&this.gridRenderer.setVisible(!1),this.priceAxis=new t.PriceAxis,this.priceAxis.setLocale(this.numberLocale),this.timeAxis=new t.TimeAxis,this.crosshairHandler=new t.CrosshairHandler,this.crosshairHandler.setLocale(this.numberLocale),r.crosshair?.mode&&this.crosshairHandler.setMode(r.crosshair.mode),this.crosshairHandler.setCallback((e,t)=>{if(e!==null&&t){let n=this.dataManager.getData(),r=e<n.length?n[e]:void 0;this.chartLegend.setHoverBar(r??null),r&&this.crosshairTooltip.show(t,r,this.themeManager.getTheme(),this.cachedContainerSize()),this.eventBus.emit(`crosshairMove`,{point:t,bar:r,barIndex:e})}else this.crosshairTooltip.hide(),this.chartLegend.setHoverBar(null)}),this.chartLegend=new t.ChartLegend,this.chartLegend.setChartType(r.chartType),this.watermark=new t.Watermark,r.watermark&&this.watermark.setConfig(r.watermark),this.volumeRenderer=new t.VolumeRenderer,this.barCountdown=new t.BarCountdown,this.sessionBreaks=new t.SessionBreaks,this.compareRenderer=new t.CompareRenderer,r.sessionBreaks?this.sessionBreaks.setConfig({visible:r.sessionBreaks.visible??!0,color:r.sessionBreaks.color,lineStyle:r.sessionBreaks.lineStyle,lineWidth:r.sessionBreaks.lineWidth}):r.features?.sessionBreaks!==!1&&this.sessionBreaks.setVisible(!0),r.logScale&&this.viewport.setLogScale(!0),this.animator=new t.Animator,this.crosshairTooltip=new t.CrosshairTooltip,this.crosshairTooltip.create(n),this.keyboardHandler=new t.KeyboardHandler({scrollBars:e=>{let t=this.viewport.getState().barWidth+this.viewport.getState().barSpacing;this.viewport.scrollBy(e*t),this.updateViewportAndRender()},zoom:e=>{let t=this.viewport.getState().chartRect.width;this.viewport.zoom(e,t/2),this.updateViewportAndRender()},goToStart:()=>{this.viewport.scrollBy(-1/0),this.updateViewportAndRender()},goToEnd:()=>{this.viewport.scrollToEnd(),this.updateViewportAndRender()},fitContent:()=>this.fitContent()}),this.keyboardHandler.setEnabled(this.features.keyboard),this.onWindowKeyDown=e=>{if(!this.keyboardHandler)return;let t=document.activeElement;t&&t!==this.container&&!this.container.contains(t)||t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.isContentEditable)||this.keyboardHandler.handleKey(e)&&e.preventDefault()},window.addEventListener(`keydown`,this.onWindowKeyDown),this.currentPriceLine=new t.CurrentPriceLine,this.alertManager=new t.AlertManager,this.alertManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.alertManager.on(`triggered`,e=>{this.eventBus.emit(`dataUpdate`,{alert:`triggered`,alertId:e.id,price:e.price,message:e.message})}),this.replayManager=new t.ReplayManager,this.interactionManager=new t.InteractionManager(n),this.features.panning&&this.interactionManager.setPanHandler(new t.PanHandler(e=>{this.viewport.scrollBy(e),this.updateViewportAndRender()})),this.features.zooming&&this.interactionManager.setZoomHandler(new t.ZoomHandler((e,t)=>{this.viewport.zoom(e,t),this.updateViewportAndRender()})),this.features.crosshair&&this.interactionManager.setCrosshairHandler(this.crosshairHandler),this.features.drawings&&this.interactionManager.setDrawingManager(this.drawingManager,()=>this.viewport.getState()),this.features.trading&&this.interactionManager.setTradingManager(this.tradingManager,()=>this.viewport.getState()),this.interactionManager.setOverlayDirtyCallback(()=>{this.engine.requestRender(e.LayerType.Overlay),this.layoutManager.getPanels().length>0&&this.engine.requestRender(e.LayerType.UI)}),this.interactionManager.attach(),this.syncRenderContext(),this.engine.start()}setData(e){this.dataManager.setData(e),this.crosshairHandler.setData(this.dataManager.getData()),this.displayDataCache=null,this.sessionBreaks.invalidateCache(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),e.length>0&&this.currentPriceLine.setPrice(e[e.length-1].close),this.updateViewportAndRender(!0),this.eventBus.emit(`dataUpdate`,{length:e.length})}appendBar(e){this.dataManager.appendBar(e),this.crosshairHandler.setData(this.dataManager.getData()),this.displayDataCache=null,this.autoScrollOnNewBar&&this.viewport.scrollToEnd(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.updateViewportAndRender()}appendBars(e){if(e.length!==0){for(let t of e)this.dataManager.appendBar(t);this.displayDataCache=null,this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.crosshairHandler.setData(this.dataManager.getData()),this.updateViewportAndRender(this.viewport.isAtEnd())}}updateLastBar(e){this.dataManager.updateLastBar(e),this.currentPriceLine.setPrice(e.close),this.options.chartType!==`candlestick`&&this.options.chartType!==`line`&&this.options.chartType!==`area`&&this.options.chartType!==`bar`&&this.options.chartType!==`hollowCandle`&&(this.displayDataCache=null),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.scheduleRender()}updateLastBarFromTick(e){this.dataManager.updateLastBarFromTick(e),this.currentPriceLine.setPrice(e.price),this.options.chartType!==`candlestick`&&this.options.chartType!==`line`&&this.options.chartType!==`area`&&this.options.chartType!==`bar`&&this.options.chartType!==`hollowCandle`&&(this.displayDataCache=null),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.scheduleRender()}setChartType(e){this.options.chartType=e,this.chartRenderer=this.createChartRenderer(e),this.chartLegend.setChartType(e),this.displayDataCache=null,this.updateViewportAndRender(!0)}addIndicator(e,t={},n=`bottom`){if(!this.features.indicators||this.features.indicatorIds.length>0&&!this.features.indicatorIds.includes(e))return null;let r=this.indicatorEngine.addIndicator(e,t,this.dataManager.getData());return this.indicatorEngine.getAvailableIndicators().find(t=>t.id===e)?.placement===`panel`?(this.layoutManager.addPanel(r,n),this.updateViewportAndRender()):this.engine.requestRender(),this.eventBus.emit(`indicatorAdd`,{instanceId:r,id:e}),r}updateIndicator(e,t){this.indicatorEngine.updateIndicator(e,t,this.dataManager.getData()),this.engine.requestRender()}removeIndicator(e){let t=this.layoutManager.getPanels().some(t=>t.id===e);this.indicatorEngine.removeIndicator(e),this.layoutManager.removePanel(e),this.eventBus.emit(`indicatorRemove`,{instanceId:e}),t?this.updateViewportAndRender():this.engine.requestRender()}getIndicatorOutput(e){return this.indicatorEngine.getOutput(e)}registerIndicator(e){this.pluginManager.registerIndicator(e)}static indicators(){let e=new t.IndicatorEngine;return(0,t.registerBuiltInIndicators)(e),e.getAvailableIndicators()}setPanelPosition(e,t){this.layoutManager.setPanelPosition(e,t),this.engine.requestRender()}setPanelSize(e,t){this.layoutManager.setPanelSize(e,t),this.engine.requestRender()}setDrawingTool(e){this.features.drawings&&(e&&this.features.drawingTools.length>0&&!this.features.drawingTools.includes(e)||this.drawingManager.setActiveTool(e))}getDrawingTool(){return this.drawingManager.getActiveTool()}setDrawingStyle(e){this.drawingManager.setStyle(e)}getDrawings(){return this.drawingManager.getDrawings()}setDrawings(e){this.drawingManager.setDrawings(e)}removeDrawing(e){this.drawingManager.removeDrawing(e)}clearDrawings(){this.drawingManager.clearDrawings()}registerDrawingTool(e){this.drawingManager.register(e)}undo(){return this.features.drawingUndoRedo?this.drawingManager.undo():!1}redo(){return this.features.drawingUndoRedo?this.drawingManager.redo():!1}getUndoRedoState(){return this.undoRedoManager.getState()}setDrawingMagnet(e){this.drawingManager.setMagnetMode(e?`magnet`:`none`)}getDrawingMagnet(){return this.drawingManager.getMagnetMode()===`magnet`}lockAllDrawings(){this.drawingManager.lockAllDrawings()}unlockAllDrawings(){this.drawingManager.unlockAllDrawings()}hideAllDrawings(){this.drawingManager.hideAllDrawings()}showAllDrawings(){this.drawingManager.showAllDrawings()}duplicateDrawing(e){let t=e??this.drawingManager.getSelectedDrawingId();return t?this.drawingManager.duplicateDrawing(t):null}exportVisibleData(e=`csv`,n){let r=this.viewport.getState(),i=this.dataManager.getData(),a=Math.max(0,r.visibleRange.from),o=Math.min(i.length-1,r.visibleRange.to),s=i.slice(a,o+1);if(e===`json`){let e=t.DataExporter.toJSON(s);t.DataExporter.download(e,n??`chart-data.json`,`application/json`)}else{let e=t.DataExporter.toCSV(s);t.DataExporter.download(e,n??`chart-data.csv`,`text/csv`)}}exportAllData(e=`csv`,n){let r=this.dataManager.getData();if(e===`json`){let e=t.DataExporter.toJSON(r);t.DataExporter.download(e,n??`chart-data.json`,`application/json`)}else{let e=t.DataExporter.toCSV(r);t.DataExporter.download(e,n??`chart-data.csv`,`text/csv`)}}setAutoSave(e,t=5e3){this.autoSaveScheduler.enable(e,t)}disableAutoSave(){this.autoSaveScheduler.disable()}scheduleAutoSave(){this.autoSaveScheduler.schedule()}getAvailableIndicators(){return this.indicatorEngine.getAvailableIndicators()}getIndicatorInputs(e){let t=this.indicatorEngine.getAvailableIndicators().find(t=>t.id===e);return t?{id:t.id,params:t.defaultConfig}:null}getActiveIndicators(){return this.indicatorEngine.getActiveIndicators()}getIndicatorConfig(e){let t=this.indicatorEngine.getIndicatorConfig(e);return t?{id:t.id,params:{...t.params}}:null}updateIndicatorStyle(e,t){this.indicatorEngine.updateIndicatorStyle(e,t),this.engine.requestRender()}setOrders(e){this.features.trading&&this.tradingManager.setOrders(e)}setPositions(e){this.features.trading&&this.tradingManager.setPositions(e)}setDepthData(e){this.features.trading&&this.tradingManager.setDepthData(e)}setCurrentPrice(e,t){this.tradingManager.setCurrentPrice(e),this.currentPriceLine.setPrice(e),this.scheduleRender(),this.features.alerts&&this.alertManager.checkPrice(e)}setTradingConfig(e){this.features.trading&&this.tradingManager.setConfig(e)}async connect(n){this.disconnectStream(),this.streamManager=new t.StreamManager,this.streamManager.on(`snapshot`,e=>{this.setData(e)}),this.streamManager.on(`barClose`,e=>{this.dataManager.appendBar(e),this.crosshairHandler.setData(this.dataManager.getData()),this.autoScrollOnNewBar&&this.viewport.scrollToEnd(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.updateViewportAndRender()}),this.streamManager.on(`barUpdate`,e=>{this.dataManager.updateLastBar(e),this.currentPriceLine.setPrice(e.close),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.scheduleRender()}),this.streamManager.on(`priceChange`,({price:t})=>{this.tradingManager.setCurrentPrice(t),this.currentPriceLine.setPrice(t),this.engine.requestRender(e.LayerType.Overlay),this.engine.requestRender(e.LayerType.UI)}),this.streamManager.on(`connectionChange`,e=>{this.eventBus.emit(`dataUpdate`,{connection:e})}),this.streamManager.on(`error`,e=>{this.eventBus.emit(`dataUpdate`,{error:e.message})}),this.autoScrollOnNewBar=n.autoScroll!==!1,this.currentSymbol=n.symbol,await this.streamManager.connect(n);let r=(0,e.timeframeToMs)(n.timeframe);this.barCountdown.setTimeframeMs(r),this.countdownInterval&&clearInterval(this.countdownInterval),this.countdownInterval=setInterval(()=>{this.barCountdown.isVisible()&&this.engine.requestRender(e.LayerType.UI)},1e3)}async switchStream(e,t){this.streamManager&&(this.currentSymbol=e,await this.streamManager.switchTo(e,t))}async setTimeframe(e){if(!this.streamManager)throw Error(`No active stream. Call connect() first.`);await this.switchStream(this.currentSymbol,e)}disconnectStream(){this.streamManager&&=(this.streamManager.dispose(),null)}setBarCountdownVisible(t){this.barCountdown.setVisible(t),this.engine.requestRender(e.LayerType.UI)}setSessionBreaksVisible(t){this.sessionBreaks.setVisible(t),this.engine.requestRender(e.LayerType.Background)}addCompareSymbol(t,n,r,i){this.compareRenderer.addSymbol({id:t,label:n,data:r,color:i,visible:!0}),this.engine.requestRender(e.LayerType.Main)}removeCompareSymbol(t){this.compareRenderer.removeSymbol(t),this.engine.requestRender(e.LayerType.Main)}updateCompareData(t,n){this.compareRenderer.setSymbolData(t,n),this.engine.requestRender(e.LayerType.Main)}setCompareMode(t){this.compareRenderer.setMode(t),this.engine.requestRender(e.LayerType.Main)}clearCompareSymbols(){this.compareRenderer.clear(),this.engine.requestRender(e.LayerType.Main)}setLogScale(e){this.viewport.setLogScale(e),this.updateViewportAndRender()}isLogScale(){return this.viewport.isLogScale()}setSessionBreaksConfig(t){this.sessionBreaks.setConfig(t),this.engine.requestRender(e.LayerType.Background)}getConnectionState(){return this.streamManager?.getConnectionState()??`disconnected`}getConnectionInfo(){return this.streamManager?.getConnectionInfo()??{state:`disconnected`}}setAutoScroll(e){this.autoScrollOnNewBar=e}scrollTo(e){let t=this.dataManager.getData();for(let n=0;n<t.length;n++)if(t[n].time>=e){let e=this.viewport.getState().barWidth+this.viewport.getState().barSpacing;this.viewport.scrollBy(n*e-this.viewport.getState().offset),this.updateViewportAndRender();return}}scrollToEnd(){this.viewport.scrollToEnd(),this.updateViewportAndRender()}setVisibleRange(e,t){let n=this.dataManager.getData(),r=0,i=n.length-1;for(let t=0;t<n.length;t++)if(n[t].time>=e){r=t;break}for(let e=n.length-1;e>=0;e--)if(n[e].time<=t){i=e;break}let a=i-r+1;if(a>0){let e=this.viewport.getState().chartRect.width,t=e/a,n=Math.max(2,t-this.viewport.getState().barSpacing);this.viewport.zoom((n-this.viewport.getState().barWidth)/this.viewport.getState().barWidth,e/2)}this.updateViewportAndRender()}zoomIn(){let e=this.viewport.getState().chartRect.width;this.viewport.zoom(.2,e/2),this.updateViewportAndRender()}zoomOut(){let e=this.viewport.getState().chartRect.width;this.viewport.zoom(-.2,e/2),this.updateViewportAndRender()}fitContent(){let e=this.dataManager.getData();e.length!==0&&this.setVisibleRange(e[0].time,e[e.length-1].time)}on(e,t){this.eventBus.on(e,t)}off(e,t){this.eventBus.off(e,t)}enableTauriBridge(e){this.eventBus.enableTauriBridge({enabled:!0,...e})}disableTauriBridge(){this.eventBus.disableTauriBridge()}setTheme(e){this.themeManager.setTheme(e),this.syncRenderContext(),this.container.style.backgroundColor=this.themeManager.getTheme().background,this.engine.requestRender(),this.eventBus.emit(`themeChange`,{theme:e})}getTheme(){return this.themeManager.getTheme()}setWatermark(t,n){this.watermark.setConfig({text:t,...n}),this.engine.requestRender(e.LayerType.Background)}setAutoScale(e){this.options.autoScale=e,this.updateViewportAndRender()}isAutoScale(){return this.options.autoScale!==!1}setCrosshairMode(t){this.crosshairHandler.setMode(t),this.engine.requestRender(e.LayerType.Overlay)}getCrosshairMode(){return this.crosshairHandler.getMode()}setGridVisible(t){this.gridRenderer.setVisible(t),this.engine.requestRender(e.LayerType.Background)}isGridVisible(){return this.gridRenderer.isVisible()}setVolumeVisible(t){this.volumeRenderer.setVisible(t),this.engine.requestRender(e.LayerType.Main)}setTooltipVisible(e){e||this.crosshairTooltip.hide()}setLegend(t){this.chartLegend.setConfig(t),this.engine.requestRender(e.LayerType.UI)}setSymbolName(t){this.chartLegend.setSymbol(t),this.engine.requestRender(e.LayerType.UI)}setStatusText(t){this.chartLegend.setStatusText(t),this.engine.requestRender(e.LayerType.UI)}screenshot(e){this.features.screenshot&&t.Screenshot.download(this.container,e,this.themeManager.getTheme().background)}screenshotDataURL(){return this.features.screenshot?t.Screenshot.toDataURL(this.container,this.themeManager.getTheme().background):null}async screenshotBlob(){return this.features.screenshot?t.Screenshot.toBlob(this.container,this.themeManager.getTheme().background):null}addAlert(e,t=`crossing`,n){if(!this.features.alerts)return null;let r=this.alertManager.addAlert(e,t,n);return this.scheduleAutoSave(),r}removeAlert(e){this.alertManager.removeAlert(e),this.scheduleAutoSave()}getAlerts(){return this.alertManager.getAlerts()}clearAlerts(){this.alertManager.clearAlerts(),this.scheduleAutoSave()}saveAlerts(e){this.alertManager.saveToStorage(e)}loadAlerts(t){this.alertManager.loadFromStorage(t),this.engine.requestRender(e.LayerType.Overlay)}replay(e){if(!this.features.replay)return;let t=this.dataManager.getData();this.replayManager.load(t),this.replayManager.on(`bar`,({bar:e,index:n})=>{let r=t.slice(0,n+1);this.dataManager.setData(r),this.crosshairHandler.setData(r),this.indicatorEngine.recalculateAll(r),this.updateViewportAndRender()}),this.replayManager.play(e)}replayPause(){this.replayManager.pause()}replayResume(){this.replayManager.resume()}replayStop(){this.replayManager.stop()}replaySeek(e){this.replayManager.seekTo(e)}setReplaySpeed(e){this.replayManager.setSpeed(e)}getReplayState(){return this.replayManager.getState()}getReplayProgress(){return this.replayManager.getProgress()}saveState(e){if(!this.features.saveLoad)return null;let n=t.ChartStateManager.capture({getDrawings:()=>this.getDrawings(),getTheme:()=>this.getTheme(),getAlerts:()=>this.getAlerts()},{chartType:this.options.chartType}),r=t.ChartStateManager.serialize(n);return e&&t.ChartStateManager.saveToStorage(e,n),r}loadState(e){if(!this.features.saveLoad)return;let n=t.ChartStateManager.deserialize(e);if(n.chartType&&this.setChartType(n.chartType),n.drawings&&this.setDrawings(n.drawings),n.theme&&this.setTheme(n.theme),n.alerts){this.clearAlerts();for(let e of n.alerts)this.addAlert(e.price,e.condition,e.message)}}loadStateFromStorage(e){if(!this.features.saveLoad)return!1;let n=t.ChartStateManager.loadFromStorage(e);return n?(this.loadState(t.ChartStateManager.serialize(n)),!0):!1}downloadState(e){if(!this.features.saveLoad)return;let n=t.ChartStateManager.capture({getDrawings:()=>this.getDrawings(),getTheme:()=>this.getTheme(),getAlerts:()=>this.getAlerts()},{chartType:this.options.chartType});t.ChartStateManager.downloadFile(n,e)}async loadStateFromFile(){if(!this.features.saveLoad)return;let e=await t.ChartStateManager.loadFromFile();this.loadState(t.ChartStateManager.serialize(e))}setLocale(t){(0,e.setLocale)(t),this.engine.requestRender()}setNumberLocale(e){this.numberLocale=e,this.priceAxis.setLocale(e),this.crosshairHandler.setLocale(e),this.syncRenderContext(),this.engine.requestRender()}getNumberLocale(){return this.numberLocale}setMarket(e){if(this.marketConfig=e,e.colorScheme){let t={...this.themeManager.getTheme(),candleUp:e.colorScheme.up,candleDown:e.colorScheme.down,candleUpWick:e.colorScheme.up,candleDownWick:e.colorScheme.down,volumeUp:e.colorScheme.up.replace(`)`,`, 0.3)`).replace(`rgb(`,`rgba(`)||`${e.colorScheme.up}4D`,volumeDown:e.colorScheme.down.replace(`)`,`, 0.3)`).replace(`rgb(`,`rgba(`)||`${e.colorScheme.down}4D`};this.themeManager.setTheme(t)}e.pricePrecision!==void 0&&(this.tradingManager.setConfig({pricePrecision:e.pricePrecision}),this.alertManager.setPricePrecision(e.pricePrecision),this.streamManager?.priceLine.setPricePrecision(e.pricePrecision),this.crosshairHandler.setPricePrecision(e.pricePrecision)),this.syncRenderContext(),this.engine.requestRender()}getMarket(){return this.marketConfig}setPriceLimits(t){this.marketConfig&&((0,e.computePriceLimits)(t,this.marketConfig)&&(this.marketConfig.priceLimits={...this.marketConfig.priceLimits,referencePrice:t}),this.engine.requestRender())}getFeatures(){return this.features}setFeatures(t){Object.assign(this.features,t),t.crosshair===!1&&this.crosshairTooltip.hide(),t.grid!==void 0&&this.engine.requestRender(e.LayerType.Background),t.volume!==void 0&&(this.volumeRenderer.setVisible(t.volume),this.engine.requestRender(e.LayerType.Main)),t.drawings===!1&&this.drawingManager.setActiveTool(null),t.trading===!1&&(this.tradingManager.setOrders([]),this.tradingManager.setPositions([])),t.keyboard!==void 0&&this.keyboardHandler?.setEnabled(t.keyboard),this.engine.requestRender()}resize(){let e=this.engine.dprManager.readContainerSize();if(e.width<=0||e.height<=0)return;this.containerSizeCache=e,this.containerSizeCacheTime=Date.now();let t=this.engine.dprManager.getDpr();this.engine.layerManager.resize(e,t);let n=this.viewport.isAtEnd();this.viewport.resize(e.width,e.height),this.layoutManager.resize(e.width,e.height),this.updateViewportAndRender(n),this.eventBus.emit(`resize`,e)}destroy(){this.countdownInterval&&clearInterval(this.countdownInterval),this.disableAutoSave(),this.disconnectStream(),this.onWindowKeyDown&&=(window.removeEventListener(`keydown`,this.onWindowKeyDown),null),this.keyboardHandler=null,this.interactionManager.detach(),this.tradingManager.destroy(),this.animator.dispose(),this.crosshairTooltip.destroy(),this.replayManager.dispose(),this.undoRedoManager.clear(),this.engine.destroy(),this.eventBus.destroy(),this.container.innerHTML=``}createChartRenderer(e){return n(e)}getDisplayData(){if(this.displayDataCache)return this.displayDataCache;let e=this.dataManager.getData();if(e.length===0)return e;let t=r(this.options.chartType,e);return this.displayDataCache=t,t}scheduleRender(){this.renderScheduled||(this.renderScheduled=!0,requestAnimationFrame(()=>{this.renderScheduled=!1;let e=this.getDisplayData();this.viewport.updateData(e,this.options.autoScale!==!1),this.syncRenderContext(),this.engine.requestRender()}))}updateViewportAndRender(e=!1){this.resolvedLayoutCache=null,this.panelInfoCache=null;let t=this.getResolvedLayout();this.viewport.setChartRect(t.mainChartRect);let n=this.getDisplayData();if(this.viewport.updateData(n,this.options.autoScale!==!1),this.options.autoScale!==!1){let e=this.viewport.getState(),t=this.indicatorEngine.getOverlayPriceRange(e.visibleRange.from,Math.min(e.visibleRange.to,n.length-1));if(t){let n=e.priceRange,r=Math.min(n.min,t.min),i=Math.max(n.max,t.max);if(r<n.min||i>n.max){let e=i-r||1;this.viewport.setPriceRange(r-e*.02,i+e*.02)}}}e&&this.viewport.scrollToEnd(),this.syncRenderContext(),this.engine.requestRender()}getResolvedLayout(){return this.resolvedLayoutCache||=this.layoutManager.resolve(),this.resolvedLayoutCache}cachedContainerSize(){let e=Date.now();return(!this.containerSizeCache||e-this.containerSizeCacheTime>500)&&(this.containerSizeCache=this.engine.dprManager.getContainerSize(),this.containerSizeCacheTime=e),this.containerSizeCache}buildPanelRenderInfos(){if(this.panelInfoCache)return this.panelInfoCache;let e=this.getResolvedLayout(),t=this.viewport.getState(),{from:n,to:r}=t.visibleRange,i=e.panels.map(e=>{let i=s(this.indicatorEngine.getOutput(e.config.id),n,r),a={x:e.rect.x,y:e.rect.y+20,width:e.rect.width,height:Math.max(0,e.rect.height-20)};return{instanceId:e.config.id,rect:e.rect,viewport:{...t,chartRect:a,priceRange:i}}});return this.panelInfoCache=i,i}syncRenderContext(){let e=this.getResolvedLayout(),t=this.features.indicators?this.buildPanelRenderInfos():[],n=e.panels.filter(e=>e.config.position===`bottom`).reduce((e,t)=>e+t.rect.height,0),r=e.mainChartRect.y+e.mainChartRect.height+n;this.engine.setRenderContext({chartRenderer:this.chartRenderer,gridRenderer:this.features.grid?this.gridRenderer:null,priceAxis:this.features.priceAxis?this.priceAxis:null,timeAxis:this.features.timeAxis?this.timeAxis:null,crosshairHandler:this.features.crosshair?this.crosshairHandler:null,indicatorEngine:this.features.indicators?this.indicatorEngine:null,drawingRenderer:this.features.drawings?this.drawingRenderer:null,tradingRenderer:this.features.trading?this.tradingRenderer:null,currentPriceLine:this.streamManager?.priceLine??this.currentPriceLine,chartLegend:this.features.legend?this.chartLegend:null,volumeRenderer:this.features.volume?this.volumeRenderer:null,watermark:this.features.watermark?this.watermark:null,barCountdown:this.barCountdown,sessionBreaks:this.sessionBreaks,compareRenderer:this.compareRenderer,panels:t,priceLimits:this.buildPriceLimits(),timeAxisY:r,viewport:this.viewport.getState(),theme:this.themeManager.getTheme(),data:this.getDisplayData(),numberLocale:this.numberLocale})}buildPriceLimits(){if(!this.marketConfig?.priceLimits?.enabled||!this.marketConfig.priceLimits.referencePrice)return null;let t=(0,e.computePriceLimits)(this.marketConfig.priceLimits.referencePrice,this.marketConfig);return t?{...t,colors:this.marketConfig.colorScheme?{ceiling:this.marketConfig.colorScheme.ceiling,floor:this.marketConfig.colorScheme.floor,reference:this.marketConfig.colorScheme.reference}:void 0}:null}};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return _}}); | ||
| //# sourceMappingURL=Chart-DoR8L8Uk.cjs.map |
Sorry, the diff of this file is too big to display
| import { ChartType, DataSeries } from '@tradecanvas/commons'; | ||
| import { ChartRendererInterface } from '@tradecanvas/core'; | ||
| /** | ||
| * Pure mapping from `ChartType` to the renderer class that draws it. Several | ||
| * chart types reuse `CandlestickRenderer` against transformed data | ||
| * (heikinAshi, lineBreak, rangeBars). | ||
| */ | ||
| export declare function createRendererFor(type: ChartType): ChartRendererInterface; | ||
| /** | ||
| * Transform raw OHLC bars into the display series for a given chart type. | ||
| * Returns the input unchanged for chart types that render raw OHLC directly. | ||
| * | ||
| * Centralized so adding a new chart type only requires editing one file. | ||
| */ | ||
| export declare function transformDisplayData(type: ChartType, raw: DataSeries): DataSeries; | ||
| /** Chart types that materially transform raw OHLC into a different series. */ | ||
| export declare function isTransformedChartType(type: ChartType): boolean; | ||
| //# sourceMappingURL=ChartTypeStrategy.d.ts.map |
| {"version":3,"file":"ChartTypeStrategy.d.ts","sourceRoot":"","sources":["../../src/charts/ChartTypeStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAkBlE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,sBAAsB,CA0BzE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,GAAG,UAAU,CAuBjF;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAY/D"} |
| import { IndicatorOutput } from '@tradecanvas/commons'; | ||
| export interface PriceRange { | ||
| min: number; | ||
| max: number; | ||
| } | ||
| /** | ||
| * Compute a padded {min, max} price range for an indicator panel from the | ||
| * visible slice of its output. Returns a sensible default range when the | ||
| * output is empty or has no values inside [from, to]. | ||
| * | ||
| * Pure — no canvas, no viewport object, just the values map and bar bounds. | ||
| * Iterates the output's `values` map in insertion order; we treat its index | ||
| * (0…N-1) as the bar index, matching how the engine inserts values. | ||
| */ | ||
| export declare function computeIndicatorPriceRange(output: IndicatorOutput | null, from: number, to: number): PriceRange; | ||
| //# sourceMappingURL=IndicatorPriceRange.d.ts.map |
| {"version":3,"file":"IndicatorPriceRange.d.ts","sourceRoot":"","sources":["../../src/charts/IndicatorPriceRange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAKD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,eAAe,GAAG,IAAI,EAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,UAAU,CA0BZ"} |
| /** | ||
| * Debounced auto-save scheduler. Coalesces a burst of `schedule()` calls into | ||
| * a single `save(key)` invocation after `delayMs` of quiet time. Pure state | ||
| * machine — owner injects the actual save callback so this stays testable. | ||
| */ | ||
| export declare class AutoSaveScheduler { | ||
| private save; | ||
| private timer; | ||
| private delayMs; | ||
| private key; | ||
| constructor(save: (key: string) => void); | ||
| /** Enable auto-save with the given storage key and quiet-time debounce. */ | ||
| enable(key: string, delayMs: number): void; | ||
| /** Disable auto-save and cancel any pending fire. */ | ||
| disable(): void; | ||
| /** | ||
| * Reset the quiet-time window. If currently disabled (no key or delay ≤ 0), | ||
| * this is a no-op. Subsequent calls within the window restart the timer. | ||
| */ | ||
| schedule(): void; | ||
| /** Cancel any pending fire without changing enabled state. */ | ||
| cancel(): void; | ||
| isEnabled(): boolean; | ||
| hasPending(): boolean; | ||
| } | ||
| //# sourceMappingURL=AutoSaveScheduler.d.ts.map |
| {"version":3,"file":"AutoSaveScheduler.d.ts","sourceRoot":"","sources":["../../src/state/AutoSaveScheduler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,iBAAiB;IAKhB,OAAO,CAAC,IAAI;IAJxB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,GAAG,CAAuB;gBAEd,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI;IAE/C,2EAA2E;IAC3E,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAK1C,qDAAqD;IACrD,OAAO,IAAI,IAAI;IAMf;;;OAGG;IACH,QAAQ,IAAI,IAAI;IAShB,8DAA8D;IAC9D,MAAM,IAAI,IAAI;IAOd,SAAS,IAAI,OAAO;IAIpB,UAAU,IAAI,OAAO;CAGtB"} |
| import { Theme, TimeFrame } from '@tradecanvas/commons'; | ||
| import { Chart } from '../Chart.js'; | ||
| import { ChartWidgetOptions } from './types.js'; | ||
| export declare class ChartWidget { | ||
| private chart; | ||
| private state; | ||
| private toolbar; | ||
| private sidebar; | ||
| private settings; | ||
| private statusBar; | ||
| private root; | ||
| private chartContainer; | ||
| private destroyed; | ||
| private options; | ||
| private symbolIndex; | ||
| private symbols; | ||
| private settingsState; | ||
| private adapter; | ||
| constructor(container: HTMLElement, options?: ChartWidgetOptions); | ||
| setSymbol(symbol: string): Promise<void>; | ||
| setTimeframe(tf: TimeFrame): Promise<void>; | ||
| setTheme(theme: import('@tradecanvas/commons').ThemeName | Theme): void; | ||
| getChart(): Chart; | ||
| destroy(): void; | ||
| private handleSymbolClick; | ||
| private handleTimeframe; | ||
| private handleChartType; | ||
| private handleAddIndicator; | ||
| private handleRemoveIndicator; | ||
| private handleDrawingTool; | ||
| private handleCancelDrawing; | ||
| private handleToggleMagnet; | ||
| private handleToggleTheme; | ||
| private openSettings; | ||
| private applySettings; | ||
| private resetSettings; | ||
| private connectStream; | ||
| private updateUI; | ||
| private resolveIsDark; | ||
| private resolveTheme; | ||
| private isColorDark; | ||
| } | ||
| //# sourceMappingURL=ChartWidget.d.ts.map |
| {"version":3,"file":"ChartWidget.d.ts","sourceRoot":"","sources":["../../src/widget/ChartWidget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,KAAK,EAAE,kBAAkB,EAAmC,MAAM,YAAY,CAAC;AAQtF,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,OAAO,CAA2D;gBAE9D,SAAS,EAAE,WAAW,EAAE,OAAO,GAAE,kBAAuB;IAkJ9D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,QAAQ,CAAC,KAAK,EAAE,OAAO,sBAAsB,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI;IASvE,QAAQ,IAAI,KAAK;IAIjB,OAAO,IAAI,IAAI;IAef,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,aAAa;YAKP,aAAa;IAwC3B,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;CAUpB"} |
| export declare function createIcon(name: string, size?: number): string; | ||
| //# sourceMappingURL=icons.d.ts.map |
| {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/widget/icons.ts"],"names":[],"mappings":"AA4BA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,MAAM,CAI1D"} |
| Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../Chart-DoR8L8Uk.cjs`);let t=require(`@tradecanvas/commons`);var n=[{label:`1m`,value:`1m`},{label:`5m`,value:`5m`},{label:`15m`,value:`15m`},{label:`1H`,value:`1h`},{label:`4H`,value:`4h`},{label:`1D`,value:`1d`}],r=[{label:`Candlestick`,value:`candlestick`},{label:`Line`,value:`line`},{label:`Area`,value:`area`},{label:`Bar`,value:`bar`},{label:`Heikin-Ashi`,value:`heikinAshi`},{label:`Hollow Candle`,value:`hollowCandle`},{label:`Baseline`,value:`baseline`}],i=[{label:`Lines`,tools:[{label:`Trend Line`,value:`trendLine`},{label:`Ray`,value:`ray`},{label:`Extended Line`,value:`extendedLine`}]},{label:`Horizontal/Vertical`,tools:[{label:`Horizontal Line`,value:`horizontalLine`},{label:`Vertical Line`,value:`verticalLine`}]},{label:`Channels`,tools:[{label:`Parallel Channel`,value:`parallelChannel`},{label:`Regression Channel`,value:`regressionChannel`}]},{label:`Fibonacci`,tools:[{label:`Fib Retracement`,value:`fibRetracement`},{label:`Fib Extension`,value:`fibExtension`}]},{label:`Shapes`,tools:[{label:`Rectangle`,value:`rectangle`},{label:`Ellipse`,value:`ellipse`},{label:`Triangle`,value:`triangle`}]},{label:`Gann & Advanced`,tools:[{label:`Pitchfork`,value:`pitchfork`},{label:`Gann Fan`,value:`gannFan`},{label:`Gann Box`,value:`gannBox`},{label:`Elliott Wave`,value:`elliottWave`}]},{label:`Measure`,tools:[{label:`Price Range`,value:`priceRange`},{label:`Date Range`,value:`dateRange`},{label:`Measure`,value:`measure`}]},{label:`Annotation`,tools:[{label:`Text`,value:`text`},{label:`Arrow`,value:`arrow`}]}],a=[{id:`sma`,name:`SMA`,type:`overlay`},{id:`ema`,name:`EMA`,type:`overlay`},{id:`bb`,name:`Bollinger Bands`,type:`overlay`},{id:`vwap`,name:`VWAP`,type:`overlay`},{id:`ichimoku`,name:`Ichimoku Cloud`,type:`overlay`},{id:`psar`,name:`Parabolic SAR`,type:`overlay`},{id:`supertrend`,name:`Supertrend`,type:`overlay`},{id:`keltner`,name:`Keltner Channel`,type:`overlay`},{id:`donchian`,name:`Donchian Channel`,type:`overlay`},{id:`rsi`,name:`RSI`,type:`panel`},{id:`macd`,name:`MACD`,type:`panel`},{id:`stochastic`,name:`Stochastic`,type:`panel`},{id:`atr`,name:`ATR`,type:`panel`},{id:`adx`,name:`ADX`,type:`panel`},{id:`obv`,name:`OBV`,type:`panel`},{id:`williamsR`,name:`Williams %R`,type:`panel`},{id:`cci`,name:`CCI`,type:`panel`},{id:`mfi`,name:`MFI`,type:`panel`},{id:`roc`,name:`ROC`,type:`panel`},{id:`tsi`,name:`TSI`,type:`panel`},{id:`cmf`,name:`CMF`,type:`panel`},{id:`aroon`,name:`Aroon`,type:`panel`},{id:`stddev`,name:`Std Deviation`,type:`panel`},{id:`vroc`,name:`Volume ROC`,type:`panel`},{id:`ad`,name:`Acc/Dist`,type:`panel`},{id:`volumeProfile`,name:`Volume Profile`,type:`panel`}],o=[`sma`,`ema`,`bb`,`rsi`,`macd`,`stochastic`,`vwap`,`atr`,`obv`,`ichimoku`],s=[`BTCUSDT`,`ETHUSDT`,`SOLUSDT`,`BNBUSDT`],c={candleUpColor:`#26A69A`,candleDownColor:`#EF5350`,candleUpWick:`#26A69A`,candleDownWick:`#EF5350`,backgroundColor:`#131722`,gridColor:`#1E222D`,gridVisible:!0,volumeVisible:!0,legendVisible:!0,barCountdown:!0,logScale:!1,autoScale:!0,crosshairMode:`magnet`,numberLocale:`en-US`},l=`/* === TradeCanvas Widget Styles === */ | ||
| .tcw-root { | ||
| display: flex; | ||
| flex-direction: column; | ||
| width: 100%; | ||
| height: 100%; | ||
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; | ||
| font-size: 13px; | ||
| color: #d1d4dc; | ||
| background: #131722; | ||
| position: relative; | ||
| overflow: hidden; | ||
| /* Dark theme tokens (default) */ | ||
| --tcw-bg: #131722; | ||
| --tcw-bg-elevated: #1E222D; | ||
| --tcw-border: #2A2E39; | ||
| --tcw-text: #d1d4dc; | ||
| --tcw-text-dim: #b2b5be; | ||
| --tcw-text-muted: #787b86; | ||
| --tcw-accent: #2962ff; | ||
| --tcw-accent-dim: rgba(41,98,255,0.15); | ||
| --tcw-accent-glow: rgba(41,98,255,0.12); | ||
| --tcw-red: #ef5350; | ||
| --tcw-green: #26a69a; | ||
| --tcw-transition: 0.15s ease; | ||
| --tcw-radius-lg: 8px; | ||
| --tcw-font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace; | ||
| --tcw-hover-bg: rgba(255,255,255,0.04); | ||
| } | ||
| .tcw-root[data-tcw-theme="light"] { | ||
| color: #131722; | ||
| background: #ffffff; | ||
| --tcw-bg: #ffffff; | ||
| --tcw-bg-elevated: #f0f3fa; | ||
| --tcw-border: #e0e3eb; | ||
| --tcw-text: #131722; | ||
| --tcw-text-dim: #434651; | ||
| --tcw-text-muted: #787b86; | ||
| --tcw-accent: #2962ff; | ||
| --tcw-accent-dim: rgba(41,98,255,0.1); | ||
| --tcw-accent-glow: rgba(41,98,255,0.08); | ||
| --tcw-red: #ef5350; | ||
| --tcw-green: #26a69a; | ||
| --tcw-hover-bg: rgba(0,0,0,0.04); | ||
| } | ||
| /* === Toolbar === */ | ||
| .tcw-toolbar { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 0; | ||
| padding: 0 12px; | ||
| height: 40px; | ||
| border-bottom: 1px solid var(--tcw-border); | ||
| background: var(--tcw-bg-elevated); | ||
| flex-shrink: 0; | ||
| position: relative; | ||
| z-index: 20; | ||
| } | ||
| .tcw-toolbar-symbol { | ||
| font-size: 13px; | ||
| font-weight: 700; | ||
| color: var(--tcw-text); | ||
| padding: 0 10px; | ||
| white-space: nowrap; | ||
| letter-spacing: -0.01em; | ||
| cursor: pointer; | ||
| border: none; | ||
| background: none; | ||
| font-family: inherit; | ||
| } | ||
| .tcw-toolbar-sep { | ||
| width: 1px; | ||
| height: 20px; | ||
| background: var(--tcw-border); | ||
| flex-shrink: 0; | ||
| } | ||
| .tcw-toolbar-group { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 2px; | ||
| padding: 0 8px; | ||
| } | ||
| .tcw-toolbar-spacer { | ||
| flex: 1; | ||
| } | ||
| .tcw-btn { | ||
| padding: 4px 8px; | ||
| font-size: 12px; | ||
| font-family: inherit; | ||
| border: none; | ||
| border-radius: 4px; | ||
| background: transparent; | ||
| color: var(--tcw-text-dim); | ||
| cursor: pointer; | ||
| transition: all var(--tcw-transition); | ||
| white-space: nowrap; | ||
| line-height: 1; | ||
| } | ||
| .tcw-btn:hover { | ||
| background: var(--tcw-hover-bg); | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-btn.tcw-active { | ||
| background: var(--tcw-accent); | ||
| color: white; | ||
| } | ||
| .tcw-btn-icon { | ||
| width: 32px; | ||
| height: 32px; | ||
| display: inline-flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| font-family: inherit; | ||
| border: none; | ||
| border-radius: 4px; | ||
| background: transparent; | ||
| color: var(--tcw-text-muted); | ||
| cursor: pointer; | ||
| transition: all var(--tcw-transition); | ||
| line-height: 1; | ||
| position: relative; | ||
| } | ||
| .tcw-btn-icon:hover { | ||
| background: var(--tcw-hover-bg); | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-badge-count { | ||
| font-size: 10px; | ||
| color: var(--tcw-accent); | ||
| background: var(--tcw-accent-dim); | ||
| padding: 0 4px; | ||
| border-radius: 8px; | ||
| font-weight: 600; | ||
| } | ||
| .tcw-indicator-chips { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 4px; | ||
| padding: 0 4px; | ||
| flex-wrap: nowrap; | ||
| overflow: hidden; | ||
| } | ||
| .tcw-indicator-chip { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| gap: 4px; | ||
| padding: 2px 6px 2px 8px; | ||
| font-size: 11px; | ||
| font-weight: 500; | ||
| background: var(--tcw-accent-dim); | ||
| color: var(--tcw-accent); | ||
| border-radius: 4px; | ||
| white-space: nowrap; | ||
| line-height: 1.4; | ||
| } | ||
| .tcw-chip-remove { | ||
| cursor: pointer; | ||
| opacity: 0.6; | ||
| padding: 0 2px; | ||
| transition: opacity var(--tcw-transition); | ||
| border: none; | ||
| background: none; | ||
| color: inherit; | ||
| display: inline-flex; | ||
| align-items: center; | ||
| } | ||
| .tcw-chip-remove:hover { | ||
| opacity: 1; | ||
| } | ||
| /* === Dropdown === */ | ||
| .tcw-dropdown-trigger { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| gap: 4px; | ||
| padding: 4px 8px; | ||
| font-size: 12px; | ||
| font-family: inherit; | ||
| border: none; | ||
| border-radius: 4px; | ||
| background: transparent; | ||
| color: var(--tcw-text-dim); | ||
| cursor: pointer; | ||
| transition: all var(--tcw-transition); | ||
| white-space: nowrap; | ||
| line-height: 1; | ||
| } | ||
| .tcw-dropdown-trigger:hover { | ||
| background: var(--tcw-hover-bg); | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-dropdown { | ||
| position: absolute; | ||
| top: 100%; | ||
| margin-top: 4px; | ||
| background: var(--tcw-bg-elevated); | ||
| border: 1px solid var(--tcw-border); | ||
| border-radius: var(--tcw-radius-lg); | ||
| box-shadow: 0 8px 32px rgba(0,0,0,0.4); | ||
| z-index: 50; | ||
| padding: 4px 0; | ||
| max-height: 400px; | ||
| overflow-y: auto; | ||
| } | ||
| .tcw-dropdown-item { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 6px 12px; | ||
| font-size: 12px; | ||
| color: var(--tcw-text-dim); | ||
| cursor: pointer; | ||
| transition: background var(--tcw-transition), color var(--tcw-transition); | ||
| width: 100%; | ||
| border: none; | ||
| background: none; | ||
| font-family: inherit; | ||
| text-align: left; | ||
| } | ||
| .tcw-dropdown-item:hover { | ||
| background: var(--tcw-hover-bg); | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-dropdown-item.tcw-active { | ||
| color: var(--tcw-accent); | ||
| } | ||
| .tcw-dropdown-label { | ||
| text-transform: uppercase; | ||
| font-size: 10px; | ||
| color: var(--tcw-text-muted); | ||
| letter-spacing: 0.05em; | ||
| padding: 6px 12px; | ||
| font-weight: 600; | ||
| } | ||
| .tcw-dropdown-divider { | ||
| border-top: 1px solid var(--tcw-border); | ||
| margin: 4px 0; | ||
| } | ||
| .tcw-tag { | ||
| font-size: 10px; | ||
| color: var(--tcw-text-muted); | ||
| padding: 1px 5px; | ||
| border-radius: 3px; | ||
| background: var(--tcw-hover-bg); | ||
| } | ||
| /* === Body === */ | ||
| .tcw-body { | ||
| display: flex; | ||
| flex: 1; | ||
| min-height: 0; | ||
| } | ||
| .tcw-chart-container { | ||
| flex: 1; | ||
| min-width: 0; | ||
| min-height: 0; | ||
| width: 100%; | ||
| height: 100%; | ||
| } | ||
| /* === Sidebar === */ | ||
| .tcw-sidebar { | ||
| width: 36px; | ||
| flex-shrink: 0; | ||
| background: var(--tcw-bg-elevated); | ||
| border-right: 1px solid var(--tcw-border); | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| padding: 4px 0; | ||
| overflow: visible; | ||
| } | ||
| .tcw-tool-group-wrap { | ||
| position: relative; | ||
| } | ||
| .tcw-sidebar-btn { | ||
| width: 36px; | ||
| height: 32px; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| border: none; | ||
| background: transparent; | ||
| color: var(--tcw-text-muted); | ||
| cursor: pointer; | ||
| font-family: inherit; | ||
| transition: all var(--tcw-transition); | ||
| position: relative; | ||
| flex-shrink: 0; | ||
| line-height: 1; | ||
| } | ||
| .tcw-sidebar-btn:hover { | ||
| color: var(--tcw-text); | ||
| background: var(--tcw-hover-bg); | ||
| } | ||
| .tcw-sidebar-btn.tcw-active { | ||
| color: var(--tcw-accent); | ||
| background: var(--tcw-accent-glow); | ||
| } | ||
| .tcw-sidebar-btn.tcw-danger:hover { | ||
| color: var(--tcw-red); | ||
| background: rgba(239,68,68,0.1); | ||
| } | ||
| .tcw-multi-dot { | ||
| position: absolute; | ||
| bottom: 2px; | ||
| right: 2px; | ||
| width: 4px; | ||
| height: 4px; | ||
| border-radius: 50%; | ||
| background: var(--tcw-text-muted); | ||
| } | ||
| .tcw-sidebar-divider { | ||
| width: 20px; | ||
| height: 1px; | ||
| background: var(--tcw-border); | ||
| margin: 4px 0; | ||
| flex-shrink: 0; | ||
| } | ||
| .tcw-sidebar-spacer { | ||
| flex: 1; | ||
| } | ||
| /* === Flyout === */ | ||
| .tcw-flyout { | ||
| position: absolute; | ||
| left: 100%; | ||
| top: 0; | ||
| margin-left: 2px; | ||
| min-width: 160px; | ||
| background: var(--tcw-bg-elevated); | ||
| border: 1px solid var(--tcw-border); | ||
| border-radius: var(--tcw-radius-lg); | ||
| box-shadow: 0 8px 32px rgba(0,0,0,0.4); | ||
| z-index: 30; | ||
| padding: 4px 0; | ||
| } | ||
| .tcw-flyout-header { | ||
| text-transform: uppercase; | ||
| font-size: 10px; | ||
| color: var(--tcw-text-muted); | ||
| letter-spacing: 0.05em; | ||
| padding: 6px 12px; | ||
| font-weight: 600; | ||
| } | ||
| .tcw-flyout-item { | ||
| padding: 6px 12px; | ||
| font-size: 12px; | ||
| color: var(--tcw-text-dim); | ||
| cursor: pointer; | ||
| width: 100%; | ||
| display: block; | ||
| border: none; | ||
| background: none; | ||
| text-align: left; | ||
| font-family: inherit; | ||
| transition: background var(--tcw-transition), color var(--tcw-transition); | ||
| } | ||
| .tcw-flyout-item:hover { | ||
| background: var(--tcw-hover-bg); | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-flyout-item.tcw-active { | ||
| color: var(--tcw-accent); | ||
| } | ||
| /* === Modal === */ | ||
| .tcw-modal-backdrop { | ||
| position: fixed; | ||
| inset: 0; | ||
| background: rgba(0,0,0,0.5); | ||
| backdrop-filter: blur(4px); | ||
| -webkit-backdrop-filter: blur(4px); | ||
| z-index: 100; | ||
| } | ||
| .tcw-modal { | ||
| position: fixed; | ||
| z-index: 101; | ||
| top: 50%; | ||
| left: 50%; | ||
| transform: translate(-50%, -50%); | ||
| background: var(--tcw-bg-elevated); | ||
| border: 1px solid var(--tcw-border); | ||
| border-radius: var(--tcw-radius-lg); | ||
| width: 480px; | ||
| max-width: 90vw; | ||
| max-height: 80vh; | ||
| display: flex; | ||
| flex-direction: column; | ||
| box-shadow: 0 24px 64px rgba(0,0,0,0.5); | ||
| } | ||
| .tcw-modal-header { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-bottom: 1px solid var(--tcw-border); | ||
| } | ||
| .tcw-modal-header h3 { | ||
| font-size: 15px; | ||
| font-weight: 600; | ||
| margin: 0; | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-modal-close { | ||
| width: 28px; | ||
| height: 28px; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| border: none; | ||
| background: transparent; | ||
| color: var(--tcw-text-muted); | ||
| cursor: pointer; | ||
| border-radius: 4px; | ||
| transition: all var(--tcw-transition); | ||
| } | ||
| .tcw-modal-close:hover { | ||
| background: var(--tcw-hover-bg); | ||
| color: var(--tcw-text); | ||
| } | ||
| .tcw-modal-tabs { | ||
| display: flex; | ||
| gap: 0; | ||
| padding: 0 20px; | ||
| border-bottom: 1px solid var(--tcw-border); | ||
| } | ||
| .tcw-modal-tab { | ||
| padding: 10px 16px; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| color: var(--tcw-text-muted); | ||
| border: none; | ||
| background: none; | ||
| cursor: pointer; | ||
| border-bottom: 2px solid transparent; | ||
| margin-bottom: -1px; | ||
| transition: color var(--tcw-transition); | ||
| font-family: inherit; | ||
| text-transform: capitalize; | ||
| } | ||
| .tcw-modal-tab:hover { | ||
| color: var(--tcw-text-dim); | ||
| } | ||
| .tcw-modal-tab.tcw-active { | ||
| color: var(--tcw-accent); | ||
| border-bottom-color: var(--tcw-accent); | ||
| } | ||
| .tcw-modal-body { | ||
| padding: 20px; | ||
| overflow-y: auto; | ||
| flex: 1; | ||
| } | ||
| .tcw-settings-section { | ||
| margin-bottom: 20px; | ||
| } | ||
| .tcw-settings-section:last-child { | ||
| margin-bottom: 0; | ||
| } | ||
| .tcw-settings-section-title { | ||
| font-size: 11px; | ||
| font-weight: 600; | ||
| text-transform: uppercase; | ||
| letter-spacing: 0.05em; | ||
| color: var(--tcw-text-muted); | ||
| margin-bottom: 12px; | ||
| } | ||
| .tcw-settings-row { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 8px 0; | ||
| } | ||
| .tcw-settings-row + .tcw-settings-row { | ||
| border-top: 1px solid rgba(255,255,255,0.03); | ||
| } | ||
| .tcw-root[data-tcw-theme="light"] .tcw-settings-row + .tcw-settings-row { | ||
| border-top: 1px solid rgba(0,0,0,0.04); | ||
| } | ||
| .tcw-settings-label { | ||
| font-size: 13px; | ||
| color: var(--tcw-text-dim); | ||
| } | ||
| .tcw-color-picker-wrap { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 6px; | ||
| } | ||
| .tcw-color-picker-wrap input[type='color'] { | ||
| width: 28px; | ||
| height: 28px; | ||
| border: 1px solid var(--tcw-border); | ||
| border-radius: 4px; | ||
| background: none; | ||
| cursor: pointer; | ||
| padding: 2px; | ||
| } | ||
| .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper { | ||
| padding: 0; | ||
| } | ||
| .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch { | ||
| border: none; | ||
| border-radius: 2px; | ||
| } | ||
| .tcw-color-hex { | ||
| font-size: 11px; | ||
| font-family: var(--tcw-font-mono); | ||
| color: var(--tcw-text-muted); | ||
| min-width: 60px; | ||
| } | ||
| .tcw-toggle { | ||
| width: 36px; | ||
| height: 20px; | ||
| background: rgba(255,255,255,0.1); | ||
| border-radius: 10px; | ||
| position: relative; | ||
| cursor: pointer; | ||
| transition: background var(--tcw-transition); | ||
| border: none; | ||
| padding: 0; | ||
| flex-shrink: 0; | ||
| } | ||
| .tcw-toggle::after { | ||
| content: ''; | ||
| position: absolute; | ||
| top: 2px; | ||
| left: 2px; | ||
| width: 16px; | ||
| height: 16px; | ||
| border-radius: 50%; | ||
| background: var(--tcw-text-muted); | ||
| transition: all var(--tcw-transition); | ||
| } | ||
| .tcw-toggle.tcw-on { | ||
| background: var(--tcw-accent); | ||
| } | ||
| .tcw-toggle.tcw-on::after { | ||
| left: 18px; | ||
| background: white; | ||
| } | ||
| .tcw-root[data-tcw-theme="light"] .tcw-toggle { | ||
| background: rgba(0,0,0,0.1); | ||
| } | ||
| .tcw-root[data-tcw-theme="light"] .tcw-toggle::after { | ||
| background: #888; | ||
| } | ||
| .tcw-root[data-tcw-theme="light"] .tcw-toggle.tcw-on { | ||
| background: var(--tcw-accent); | ||
| } | ||
| .tcw-root[data-tcw-theme="light"] .tcw-toggle.tcw-on::after { | ||
| background: white; | ||
| } | ||
| .tcw-settings-select { | ||
| padding: 4px 8px; | ||
| font-size: 12px; | ||
| font-family: inherit; | ||
| background: var(--tcw-bg); | ||
| border: 1px solid var(--tcw-border); | ||
| border-radius: 4px; | ||
| color: var(--tcw-text); | ||
| cursor: pointer; | ||
| } | ||
| .tcw-modal-footer { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 12px 20px; | ||
| border-top: 1px solid var(--tcw-border); | ||
| } | ||
| .tcw-reset-link { | ||
| font-size: 12px; | ||
| color: var(--tcw-text-muted); | ||
| cursor: pointer; | ||
| border: none; | ||
| background: none; | ||
| font-family: inherit; | ||
| text-decoration: underline; | ||
| text-underline-offset: 2px; | ||
| transition: color var(--tcw-transition); | ||
| } | ||
| .tcw-reset-link:hover { | ||
| color: var(--tcw-text-dim); | ||
| } | ||
| .tcw-done-btn { | ||
| padding: 6px 16px; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| background: var(--tcw-accent); | ||
| color: white; | ||
| border: none; | ||
| border-radius: 4px; | ||
| cursor: pointer; | ||
| font-family: inherit; | ||
| transition: background var(--tcw-transition); | ||
| } | ||
| .tcw-done-btn:hover { | ||
| background: #2563eb; | ||
| } | ||
| /* === Status Bar === */ | ||
| .tcw-statusbar { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 6px 16px; | ||
| border-top: 1px solid var(--tcw-border); | ||
| background: var(--tcw-bg-elevated); | ||
| font-size: 11px; | ||
| color: var(--tcw-text-muted); | ||
| flex-shrink: 0; | ||
| } | ||
| .tcw-status-indicator { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 6px; | ||
| } | ||
| .tcw-status-dot { | ||
| width: 6px; | ||
| height: 6px; | ||
| border-radius: 50%; | ||
| background: var(--tcw-text-muted); | ||
| transition: background 0.3s; | ||
| } | ||
| .tcw-status-dot.tcw-connected { | ||
| background: var(--tcw-green); | ||
| } | ||
| .tcw-status-dot.tcw-error { | ||
| background: var(--tcw-red); | ||
| } | ||
| /* === Responsive === */ | ||
| @media (max-width: 768px) { | ||
| .tcw-toolbar { | ||
| padding: 0 8px; | ||
| height: 36px; | ||
| } | ||
| .tcw-toolbar-sep { | ||
| display: none; | ||
| } | ||
| .tcw-indicator-chips { | ||
| display: none; | ||
| } | ||
| .tcw-sidebar { | ||
| width: 32px; | ||
| } | ||
| .tcw-sidebar-btn { | ||
| width: 32px; | ||
| height: 28px; | ||
| } | ||
| } | ||
| `,u=0,d=`tcw-styles`;function f(){if(u++,u>1||document.getElementById(d))return;let e=document.createElement(`style`);e.id=d,e.textContent=l,document.head.appendChild(e)}function p(){if(u--,u>0)return;let e=document.getElementById(d);e&&e.remove()}var m={cursor:`<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>`,trendingUp:`<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>`,minus:`<path d="M5 12h14"/>`,penLine:`<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,hash:`<line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/>`,square:`<rect width="18" height="18" x="3" y="3" rx="2"/>`,gitBranch:`<line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>`,ruler:`<path d="M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z"/><path d="m14.5 12.5 2-2"/><path d="m11.5 9.5 2-2"/><path d="m8.5 6.5 2-2"/><path d="m17.5 15.5 2-2"/>`,type:`<polyline points="4 7 4 4 20 4 20 7"/><line x1="9" y1="20" x2="15" y2="20"/><line x1="12" y1="4" x2="12" y2="20"/>`,magnet:`<path d="m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15"/><path d="m5 8 4 4"/><path d="m12 15 4 4"/>`,undo:`<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,redo:`<path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/>`,trash:`<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/>`,camera:`<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>`,settings:`<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>`,moon:`<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>`,sun:`<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>`,chevronDown:`<path d="m6 9 6 6 6-6"/>`,chevronUp:`<path d="m18 15-6-6-6 6"/>`,barChart:`<line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/>`,x:`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,play:`<polygon points="6 3 20 12 6 21 6 3"/>`,pause:`<rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/>`,stop:`<rect width="14" height="14" x="5" y="5" rx="1"/>`,receipt:`<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 17.5v-11"/>`};function h(e,t=14){let n=m[e];return n?`<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`:``}var g=class{trigger;panel;_isOpen=!1;onOutsideClick;onEscapeKey;onTriggerClick;constructor(e,t={}){this.trigger=e,this.panel=document.createElement(`div`),this.panel.className=`tcw-dropdown`,this.panel.style.width=t.width??`200px`,t.align===`right`?this.panel.style.right=`0`:this.panel.style.left=`0`,this.panel.style.display=`none`,e.style.position=`relative`,e.appendChild(this.panel),this.onTriggerClick=()=>{this._isOpen?this.close():this.open()},this.onOutsideClick=e=>{this.trigger.contains(e.target)||this.close()},this.onEscapeKey=e=>{e.key===`Escape`&&this.close()},e.addEventListener(`click`,this.onTriggerClick)}setContent(e){this.panel.innerHTML=e}open(){this._isOpen||(this._isOpen=!0,this.panel.style.display=``,document.addEventListener(`mousedown`,this.onOutsideClick),document.addEventListener(`keydown`,this.onEscapeKey))}close(){this._isOpen&&(this._isOpen=!1,this.panel.style.display=`none`,document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey))}isOpen(){return this._isOpen}destroy(){this.trigger.removeEventListener(`click`,this.onTriggerClick),document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey),this.panel.remove()}},_=class{config;callbacks;el;chartTypeDropdown=null;indicatorDropdown=null;tfButtons=[];chipsContainer=null;themeBtn=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-toolbar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this,r=document.createElement(`button`);r.className=`tcw-toolbar-symbol`,r.dataset.role=`symbol`,r.addEventListener(`click`,t.onSymbolClick),n.appendChild(r),n.appendChild(this.sep());let i=document.createElement(`div`);i.className=`tcw-toolbar-group`;for(let n of e.timeframes){let e=document.createElement(`button`);e.className=`tcw-btn`,e.textContent=n.label,e.dataset.tf=n.value,e.addEventListener(`click`,()=>t.onTimeframe(n.value)),i.appendChild(e),this.tfButtons.push(e)}n.appendChild(i),n.appendChild(this.sep());let a=document.createElement(`div`);a.style.position=`relative`,a.style.display=`inline-flex`;let o=document.createElement(`button`);o.className=`tcw-dropdown-trigger`,o.dataset.role=`charttype`,a.appendChild(o),n.appendChild(a),this.chartTypeDropdown=new g(a,{width:`160px`}),this.buildChartTypeMenu(),n.appendChild(this.sep());let s=document.createElement(`div`);s.style.position=`relative`,s.style.display=`inline-flex`;let c=document.createElement(`button`);c.className=`tcw-dropdown-trigger`,c.dataset.role=`indicators`,s.appendChild(c),n.appendChild(s),this.indicatorDropdown=new g(s,{width:`280px`}),this.buildIndicatorMenu(),this.chipsContainer=document.createElement(`div`),this.chipsContainer.className=`tcw-indicator-chips`,n.appendChild(this.chipsContainer),n.appendChild(this.spacer());let l=this.iconBtn(`camera`,`Screenshot`,t.onScreenshot);n.appendChild(l);let u=this.iconBtn(`settings`,`Chart Settings`,t.onSettings);n.appendChild(u),this.themeBtn=this.iconBtn(`moon`,`Toggle theme`,t.onToggleTheme),this.themeBtn.dataset.role=`theme`,n.appendChild(this.themeBtn)}buildChartTypeMenu(){if(!this.chartTypeDropdown)return;let e=this.config.chartTypes.map(e=>`<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(``);this.chartTypeDropdown.setContent(e),this.chartTypeDropdown.panel.querySelectorAll(`.tcw-dropdown-item`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ct;this.callbacks.onChartType(t),this.chartTypeDropdown?.close()})})}buildIndicatorMenu(){if(!this.indicatorDropdown)return;let{indicators:e,popularIndicatorIds:t}=this.config,n=e.filter(e=>t.includes(e.id)),r=e.filter(e=>!t.includes(e.id)),i=`<div class="tcw-dropdown-label">Popular</div>`;for(let e of n)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;i+=`<div class="tcw-dropdown-divider"></div>`,i+=`<div class="tcw-dropdown-label">All</div>`;for(let e of r)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;this.indicatorDropdown.setContent(i),this.indicatorDropdown.panel.querySelectorAll(`.tcw-dropdown-item[data-ind]`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ind;this.callbacks.onAddIndicator(t)})})}update(e){let t=this.el.querySelector(`[data-role="symbol"]`);t&&(t.textContent=e.symbol);for(let t of this.tfButtons)t.classList.toggle(`tcw-active`,t.dataset.tf===e.timeframe);let n=this.el.querySelector(`[data-role="charttype"]`);if(n){let t=this.config.chartTypes.find(t=>t.value===e.chartType)?.label??`Candles`;n.innerHTML=`${h(`barChart`,14)} ${t} ${h(`chevronDown`,12)}`}let r=this.el.querySelector(`[data-role="indicators"]`);if(r){let t=e.activeIndicators.size,n=`${h(`trendingUp`,14)} Indicators`;t>0&&(n+=` <span class="tcw-badge-count">${t}</span>`),r.innerHTML=n}if(this.chipsContainer){let t=this.getActiveIndicatorList(e);this.chipsContainer.innerHTML=``;for(let e of t){let t=document.createElement(`div`);t.className=`tcw-indicator-chip`;let n=document.createElement(`span`);n.textContent=e.label,t.appendChild(n);let r=document.createElement(`button`);r.className=`tcw-chip-remove`,r.innerHTML=h(`x`,10),r.addEventListener(`click`,()=>this.callbacks.onRemoveIndicator(e.instanceId)),t.appendChild(r),this.chipsContainer.appendChild(t)}}this.themeBtn&&(this.themeBtn.innerHTML=e.isDark?h(`moon`,14):h(`sun`,14))}getActiveIndicatorList(e){let t=[];for(let[n,r]of e.activeIndicators.entries())t.push({instanceId:r,id:n,label:n.toUpperCase()});return t}sep(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-sep`,e}spacer(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-spacer`,e}iconBtn(e,t,n){let r=document.createElement(`button`);return r.className=`tcw-btn-icon`,r.title=t,r.innerHTML=h(e,14),r.addEventListener(`click`,n),r}destroy(){this.chartTypeDropdown?.destroy(),this.indicatorDropdown?.destroy(),this.el.remove()}},v=[`trendingUp`,`minus`,`penLine`,`hash`,`square`,`gitBranch`,`ruler`,`type`],y=class{config;callbacks;el;groupWraps=[];groupButtons=[];cursorBtn=null;magnetBtn=null;flyoutEl=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-sidebar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this;this.cursorBtn=document.createElement(`button`),this.cursorBtn.className=`tcw-sidebar-btn`,this.cursorBtn.title=`Cursor`,this.cursorBtn.innerHTML=h(`cursor`,14),this.cursorBtn.addEventListener(`click`,t.onCancelDrawing),n.appendChild(this.cursorBtn),n.appendChild(this.divider()),e.drawingToolGroups.forEach((e,r)=>{let i=document.createElement(`div`);i.className=`tcw-tool-group-wrap`;let a=document.createElement(`button`);if(a.className=`tcw-sidebar-btn`,a.title=e.label,a.innerHTML=h(v[r]??`square`,14),e.tools.length>1){let e=document.createElement(`span`);e.className=`tcw-multi-dot`,a.appendChild(e)}a.addEventListener(`click`,()=>t.onDrawingTool(e.tools[0].value)),i.appendChild(a),i.addEventListener(`mouseenter`,()=>this.showFlyout(r)),i.addEventListener(`mouseleave`,()=>this.hideFlyout()),n.appendChild(i),this.groupWraps.push(i),this.groupButtons.push(a)});let r=document.createElement(`div`);r.className=`tcw-sidebar-spacer`,n.appendChild(r),n.appendChild(this.divider()),this.magnetBtn=document.createElement(`button`),this.magnetBtn.className=`tcw-sidebar-btn`,this.magnetBtn.title=`Magnet`,this.magnetBtn.innerHTML=h(`magnet`,14),this.magnetBtn.addEventListener(`click`,t.onToggleMagnet),n.appendChild(this.magnetBtn);let i=document.createElement(`button`);i.className=`tcw-sidebar-btn`,i.title=`Undo`,i.innerHTML=h(`undo`,14),i.addEventListener(`click`,t.onUndo),n.appendChild(i);let a=document.createElement(`button`);a.className=`tcw-sidebar-btn`,a.title=`Redo`,a.innerHTML=h(`redo`,14),a.addEventListener(`click`,t.onRedo),n.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-sidebar-btn tcw-danger`,o.title=`Clear all`,o.innerHTML=h(`trash`,14),o.addEventListener(`click`,t.onClearDrawings),n.appendChild(o)}showFlyout(e){let t=this.config.drawingToolGroups[e];if(!t||t.tools.length<=1)return;this.hideFlyout();let n=document.createElement(`div`);n.className=`tcw-flyout`;let r=document.createElement(`div`);r.className=`tcw-flyout-header`,r.textContent=t.label,n.appendChild(r);for(let e of t.tools){let t=document.createElement(`button`);t.className=`tcw-flyout-item`,t.textContent=e.label,t.dataset.toolValue=e.value,t.addEventListener(`click`,()=>{this.callbacks.onDrawingTool(e.value),this.hideFlyout()}),n.appendChild(t)}this.flyoutEl=n,this.groupWraps[e].appendChild(n)}hideFlyout(){this.flyoutEl&&=(this.flyoutEl.remove(),null)}update(e){this.cursorBtn&&this.cursorBtn.classList.toggle(`tcw-active`,e.activeTool===null);let{drawingToolGroups:t}=this.config;for(let n=0;n<t.length;n++){let r=t[n].tools.some(t=>t.value===e.activeTool);this.groupButtons[n].classList.toggle(`tcw-active`,r)}this.flyoutEl&&this.flyoutEl.querySelectorAll(`.tcw-flyout-item`).forEach(t=>{let n=t;n.classList.toggle(`tcw-active`,n.dataset.toolValue===e.activeTool)}),this.magnetBtn&&(this.magnetBtn.classList.toggle(`tcw-active`,e.magnetEnabled),this.magnetBtn.title=e.magnetEnabled?`Magnet ON`:`Magnet OFF`)}divider(){let e=document.createElement(`div`);return e.className=`tcw-sidebar-divider`,e}destroy(){this.hideFlyout(),this.el.remove()}},b=[`style`,`display`,`scale`],x=class{callbacks;backdrop=null;modal=null;currentTab=`style`;currentSettings=null;bodyEl=null;tabButtons=[];constructor(e){this.callbacks=e}open(e){this.currentSettings={...e},this.currentTab=`style`,this.buildModal()}close(){this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.bodyEl=null,this.tabButtons=[]}buildModal(){this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),document.body.appendChild(this.backdrop),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal`;let e=document.createElement(`div`);e.className=`tcw-modal-header`;let t=document.createElement(`h3`);t.textContent=`Chart Settings`,e.appendChild(t);let n=document.createElement(`button`);n.className=`tcw-modal-close`,n.innerHTML=h(`x`,16),n.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),e.appendChild(n),this.modal.appendChild(e);let r=document.createElement(`div`);r.className=`tcw-modal-tabs`,this.tabButtons=[];for(let e of b){let t=document.createElement(`button`);t.className=`tcw-modal-tab`,t.textContent=e,t.dataset.tab=e,e===this.currentTab&&t.classList.add(`tcw-active`),t.addEventListener(`click`,()=>{this.currentTab=e,this.tabButtons.forEach(t=>t.classList.toggle(`tcw-active`,t.dataset.tab===e)),this.renderTabContent()}),r.appendChild(t),this.tabButtons.push(t)}this.modal.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.modal.appendChild(this.bodyEl),this.renderTabContent();let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.callbacks.onReset()),i.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),i.appendChild(o),this.modal.appendChild(i),document.body.appendChild(this.modal);let s=e=>{e.key===`Escape`&&(document.removeEventListener(`keydown`,s),this.callbacks.onClose(),this.close())};document.addEventListener(`keydown`,s)}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.innerHTML=``,this.currentTab){case`style`:this.renderStyleTab();break;case`display`:this.renderDisplayTab();break;case`scale`:this.renderScaleTab();break}}renderStyleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section(`Candle Colors`);t.appendChild(this.colorRow(`Up Body`,e.candleUpColor,e=>this.patch({candleUpColor:e}))),t.appendChild(this.colorRow(`Down Body`,e.candleDownColor,e=>this.patch({candleDownColor:e}))),t.appendChild(this.colorRow(`Up Wick`,e.candleUpWick,e=>this.patch({candleUpWick:e}))),t.appendChild(this.colorRow(`Down Wick`,e.candleDownWick,e=>this.patch({candleDownWick:e}))),this.bodyEl.appendChild(t);let n=this.section(`Background`);n.appendChild(this.colorRow(`Background`,e.backgroundColor,e=>this.patch({backgroundColor:e}))),n.appendChild(this.colorRow(`Grid`,e.gridColor,e=>this.patch({gridColor:e}))),this.bodyEl.appendChild(n)}renderDisplayTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Grid Lines`,e.gridVisible,e=>this.patch({gridVisible:e}))),t.appendChild(this.toggleRow(`Volume`,e.volumeVisible,e=>this.patch({volumeVisible:e}))),t.appendChild(this.toggleRow(`OHLC Legend`,e.legendVisible,e=>this.patch({legendVisible:e}))),t.appendChild(this.toggleRow(`Bar Countdown`,e.barCountdown,e=>this.patch({barCountdown:e}))),t.appendChild(this.selectRow(`Crosshair Mode`,e.crosshairMode,[{label:`Magnet`,value:`magnet`},{label:`Normal`,value:`normal`},{label:`Hidden`,value:`hidden`}],e=>this.patch({crosshairMode:e}))),t.appendChild(this.selectRow(`Number Locale`,e.numberLocale,[{label:`en-US (65,234.00)`,value:`en-US`},{label:`de-DE (65.234,00)`,value:`de-DE`},{label:`fr-FR (65 234,00)`,value:`fr-FR`},{label:`vi-VN (65.234,00)`,value:`vi-VN`},{label:`en-IN (65,234.00)`,value:`en-IN`},{label:`ja-JP (65,234.00)`,value:`ja-JP`}],e=>this.patch({numberLocale:e}))),this.bodyEl.appendChild(t)}renderScaleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Auto Scale`,e.autoScale,e=>this.patch({autoScale:e}))),t.appendChild(this.toggleRow(`Log Scale`,e.logScale,e=>this.patch({logScale:e}))),this.bodyEl.appendChild(t)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}section(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n)}return t}colorRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`div`);a.className=`tcw-color-picker-wrap`;let o=document.createElement(`input`);o.type=`color`,o.value=t;let s=document.createElement(`span`);return s.className=`tcw-color-hex`,s.textContent=t,o.addEventListener(`input`,()=>{s.textContent=o.value,n(o.value)}),a.appendChild(o),a.appendChild(s),r.appendChild(a),r}toggleRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`button`);return a.className=`tcw-toggle${t?` tcw-on`:``}`,a.addEventListener(`click`,()=>{let e=!a.classList.contains(`tcw-on`);a.classList.toggle(`tcw-on`,e),n(e)}),r.appendChild(a),r}selectRow(e,t,n,r){let i=document.createElement(`div`);i.className=`tcw-settings-row`;let a=document.createElement(`span`);a.className=`tcw-settings-label`,a.textContent=e,i.appendChild(a);let o=document.createElement(`select`);o.className=`tcw-settings-select`;for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),o.appendChild(n)}return o.addEventListener(`change`,()=>r(o.value)),i.appendChild(o),i}destroy(){this.close()}},S=class{el;dotEl;messageEl;infoEl;constructor(e){this.el=document.createElement(`div`),this.el.className=`tcw-statusbar`;let t=document.createElement(`div`);t.className=`tcw-status-indicator`,this.dotEl=document.createElement(`span`),this.dotEl.className=`tcw-status-dot`,t.appendChild(this.dotEl),this.messageEl=document.createElement(`span`),t.appendChild(this.messageEl),this.el.appendChild(t),this.infoEl=document.createElement(`span`),this.el.appendChild(this.infoEl),e.appendChild(this.el)}update(e){this.dotEl.className=`tcw-status-dot`,e.connectionState===`connected`?this.dotEl.classList.add(`tcw-connected`):e.connectionState===`error`&&this.dotEl.classList.add(`tcw-error`),this.messageEl.textContent=e.message,this.infoEl.textContent=`${e.symbol} ${e.timeframe}`}destroy(){this.el.remove()}},C=class{chart;state;toolbar=null;sidebar=null;settings=null;statusBar=null;root;chartContainer;destroyed=!1;options;symbolIndex=0;symbols;settingsState;adapter=null;constructor(t,l={}){this.options=l,this.symbols=l.symbols??s,this.settingsState={...c};let u=this.resolveIsDark(l.theme),d=this.resolveTheme(l.theme);this.state={symbol:l.symbol??this.symbols[0]??`BTCUSDT`,timeframe:l.timeframe??`5m`,chartType:l.chartOptions?.chartType??`candlestick`,isDark:u,activeIndicators:new Map,activeTool:null,magnetEnabled:!0,connectionState:`connecting`,connectionMessage:`Connecting...`};let p=this.symbols.indexOf(this.state.symbol);p>=0&&(this.symbolIndex=p),f(),this.root=document.createElement(`div`),this.root.className=`tcw-root`,this.root.dataset.tcwTheme=u?`dark`:`light`,t.appendChild(this.root),l.toolbar!==!1&&(this.toolbar=new _(this.root,{symbols:this.symbols,timeframes:l.timeframes?n.filter(e=>l.timeframes.includes(e.value)):n,chartTypes:l.chartTypes?r.filter(e=>l.chartTypes.includes(e.value)):r,indicators:a,popularIndicatorIds:o},{onSymbolClick:()=>this.handleSymbolClick(),onTimeframe:e=>this.handleTimeframe(e),onChartType:e=>this.handleChartType(e),onAddIndicator:e=>this.handleAddIndicator(e),onRemoveIndicator:e=>this.handleRemoveIndicator(e),onScreenshot:()=>this.chart.screenshot(),onSettings:()=>this.openSettings(),onToggleTheme:()=>this.handleToggleTheme()}));let m=document.createElement(`div`);m.className=`tcw-body`,l.drawingTools!==!1&&(this.sidebar=new y(m,{drawingToolGroups:i},{onDrawingTool:e=>this.handleDrawingTool(e),onCancelDrawing:()=>this.handleCancelDrawing(),onToggleMagnet:()=>this.handleToggleMagnet(),onUndo:()=>this.chart.undo(),onRedo:()=>this.chart.redo(),onClearDrawings:()=>{this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI()}})),this.chartContainer=document.createElement(`div`),this.chartContainer.className=`tcw-chart-container`,m.appendChild(this.chartContainer),this.root.appendChild(m),this.chart=new e.t(this.chartContainer,{chartType:this.state.chartType,theme:d,autoScale:!0,crosshair:{mode:`magnet`},features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:l.trading!==!1,tradingContextMenu:l.trading!==!1,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0},...l.chartOptions}),l.statusBar!==!1&&(this.statusBar=new S(this.root)),l.settings!==!1&&(this.settings=new x({onChange:e=>this.applySettings(e),onReset:()=>this.resetSettings(),onClose:()=>{}})),l.adapter&&(this.adapter=l.adapter,this.connectStream()),this.updateUI(),l.onReady?.(this.chart)}async setSymbol(e){this.state={...this.state,symbol:e};let t=this.symbols.indexOf(e);t>=0&&(this.symbolIndex=t),this.options.onSymbolChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}async setTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}setTheme(e){let t=this.resolveIsDark(e),n=this.resolveTheme(e);this.state={...this.state,isDark:t},this.root.dataset.tcwTheme=t?`dark`:`light`,this.chart.setTheme(n),this.updateUI()}getChart(){return this.chart}destroy(){this.destroyed||(this.destroyed=!0,this.toolbar?.destroy(),this.sidebar?.destroy(),this.settings?.destroy(),this.statusBar?.destroy(),this.chart.destroy(),this.root.remove(),p())}handleSymbolClick(){this.symbolIndex=(this.symbolIndex+1)%this.symbols.length;let e=this.symbols[this.symbolIndex];this.state={...this.state,symbol:e},this.options.onSymbolChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleChartType(e){this.state={...this.state,chartType:e},this.chart.setChartType(e),this.updateUI()}handleAddIndicator(e){if(this.state.activeIndicators.has(e)){let t=this.state.activeIndicators.get(e);this.chart.removeIndicator(t);let n=new Map(this.state.activeIndicators);n.delete(e),this.state={...this.state,activeIndicators:n}}else{let t=this.chart.addIndicator(e);if(t){let n=new Map(this.state.activeIndicators);n.set(e,t),this.state={...this.state,activeIndicators:n}}}this.updateUI()}handleRemoveIndicator(e){this.chart.removeIndicator(e);let t=new Map(this.state.activeIndicators);for(let[n,r]of t.entries())if(r===e){t.delete(n);break}this.state={...this.state,activeIndicators:t},this.updateUI()}handleDrawingTool(e){this.state={...this.state,activeTool:e},this.chart.setDrawingTool(e),this.updateUI()}handleCancelDrawing(){this.state={...this.state,activeTool:null},this.chart.setDrawingTool(null),this.updateUI()}handleToggleMagnet(){let e=!this.state.magnetEnabled;this.state={...this.state,magnetEnabled:e},this.chart.setDrawingMagnet(e),this.updateUI()}handleToggleTheme(){let e=!this.state.isDark;this.state={...this.state,isDark:e},this.root.dataset.tcwTheme=e?`dark`:`light`,this.chart.setTheme(e?t.DARK_THEME:t.LIGHT_THEME),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:e?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.updateUI()}openSettings(){this.settings?.open(this.settingsState)}applySettings(e){this.settingsState={...this.settingsState,...e},e.gridVisible!==void 0&&this.chart.setGridVisible(e.gridVisible),e.volumeVisible!==void 0&&this.chart.setVolumeVisible(e.volumeVisible),e.crosshairMode!==void 0&&this.chart.setCrosshairMode(e.crosshairMode),e.autoScale!==void 0&&this.chart.setAutoScale(e.autoScale),e.logScale!==void 0&&this.chart.setLogScale(e.logScale),e.numberLocale!==void 0&&this.chart.setNumberLocale(e.numberLocale);let t={...this.chart.getTheme()},n=!1;e.candleUpColor!==void 0&&(t.candleUp=e.candleUpColor,n=!0),e.candleDownColor!==void 0&&(t.candleDown=e.candleDownColor,n=!0),e.candleUpWick!==void 0&&(t.candleUpWick=e.candleUpWick,n=!0),e.candleDownWick!==void 0&&(t.candleDownWick=e.candleDownWick,n=!0),e.backgroundColor!==void 0&&(t.background=e.backgroundColor,n=!0),e.gridColor!==void 0&&(t.grid=e.gridColor,n=!0),n&&this.chart.setTheme(t)}resetSettings(){this.settingsState={...c},this.applySettings(this.settingsState)}async connectStream(){if(this.adapter){this.state={...this.state,connectionState:`connecting`,connectionMessage:`Connecting...`},this.updateUI();try{this.chart.disconnectStream(),await this.chart.connect({adapter:this.adapter,symbol:this.state.symbol,timeframe:this.state.timeframe,historyLimit:this.options.historyLimit??500}),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:this.state.isDark?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.state={...this.state,connectionState:`connected`,connectionMessage:`Live`}}catch(e){this.state={...this.state,connectionState:`error`,connectionMessage:e instanceof Error?e.message:`Connection failed`}}this.updateUI()}}updateUI(){this.toolbar?.update(this.state),this.sidebar?.update(this.state),this.statusBar?.update({connectionState:this.state.connectionState,message:this.state.connectionMessage,symbol:this.state.symbol,timeframe:this.state.timeframe})}resolveIsDark(e){return e===void 0||e===`dark`?!0:e===`light`?!1:typeof e==`object`&&e.background?this.isColorDark(e.background):!0}resolveTheme(e){return e===void 0||e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:typeof e==`object`?e:t.DARK_THEME}isColorDark(e){if(e.startsWith(`#`)&&e.length>=7){let t=parseInt(e.slice(1,3),16),n=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return t+n+r<384}return!0}};exports.ChartWidget=C; | ||
| //# sourceMappingURL=index.cjs.map |
Sorry, the diff of this file is too big to display
| export { ChartWidget } from './ChartWidget.js'; | ||
| export type { ChartWidgetOptions } from './types.js'; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/widget/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"} |
+1058
| import { t as e } from "../Chart-CrrTKx3r.js"; | ||
| import { DARK_THEME as t, LIGHT_THEME as n } from "@tradecanvas/commons"; | ||
| //#region src/widget/widgetConfig.ts | ||
| var r = [ | ||
| { | ||
| label: "1m", | ||
| value: "1m" | ||
| }, | ||
| { | ||
| label: "5m", | ||
| value: "5m" | ||
| }, | ||
| { | ||
| label: "15m", | ||
| value: "15m" | ||
| }, | ||
| { | ||
| label: "1H", | ||
| value: "1h" | ||
| }, | ||
| { | ||
| label: "4H", | ||
| value: "4h" | ||
| }, | ||
| { | ||
| label: "1D", | ||
| value: "1d" | ||
| } | ||
| ], i = [ | ||
| { | ||
| label: "Candlestick", | ||
| value: "candlestick" | ||
| }, | ||
| { | ||
| label: "Line", | ||
| value: "line" | ||
| }, | ||
| { | ||
| label: "Area", | ||
| value: "area" | ||
| }, | ||
| { | ||
| label: "Bar", | ||
| value: "bar" | ||
| }, | ||
| { | ||
| label: "Heikin-Ashi", | ||
| value: "heikinAshi" | ||
| }, | ||
| { | ||
| label: "Hollow Candle", | ||
| value: "hollowCandle" | ||
| }, | ||
| { | ||
| label: "Baseline", | ||
| value: "baseline" | ||
| } | ||
| ], a = [ | ||
| { | ||
| label: "Lines", | ||
| tools: [ | ||
| { | ||
| label: "Trend Line", | ||
| value: "trendLine" | ||
| }, | ||
| { | ||
| label: "Ray", | ||
| value: "ray" | ||
| }, | ||
| { | ||
| label: "Extended Line", | ||
| value: "extendedLine" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| label: "Horizontal/Vertical", | ||
| tools: [{ | ||
| label: "Horizontal Line", | ||
| value: "horizontalLine" | ||
| }, { | ||
| label: "Vertical Line", | ||
| value: "verticalLine" | ||
| }] | ||
| }, | ||
| { | ||
| label: "Channels", | ||
| tools: [{ | ||
| label: "Parallel Channel", | ||
| value: "parallelChannel" | ||
| }, { | ||
| label: "Regression Channel", | ||
| value: "regressionChannel" | ||
| }] | ||
| }, | ||
| { | ||
| label: "Fibonacci", | ||
| tools: [{ | ||
| label: "Fib Retracement", | ||
| value: "fibRetracement" | ||
| }, { | ||
| label: "Fib Extension", | ||
| value: "fibExtension" | ||
| }] | ||
| }, | ||
| { | ||
| label: "Shapes", | ||
| tools: [ | ||
| { | ||
| label: "Rectangle", | ||
| value: "rectangle" | ||
| }, | ||
| { | ||
| label: "Ellipse", | ||
| value: "ellipse" | ||
| }, | ||
| { | ||
| label: "Triangle", | ||
| value: "triangle" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| label: "Gann & Advanced", | ||
| tools: [ | ||
| { | ||
| label: "Pitchfork", | ||
| value: "pitchfork" | ||
| }, | ||
| { | ||
| label: "Gann Fan", | ||
| value: "gannFan" | ||
| }, | ||
| { | ||
| label: "Gann Box", | ||
| value: "gannBox" | ||
| }, | ||
| { | ||
| label: "Elliott Wave", | ||
| value: "elliottWave" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| label: "Measure", | ||
| tools: [ | ||
| { | ||
| label: "Price Range", | ||
| value: "priceRange" | ||
| }, | ||
| { | ||
| label: "Date Range", | ||
| value: "dateRange" | ||
| }, | ||
| { | ||
| label: "Measure", | ||
| value: "measure" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| label: "Annotation", | ||
| tools: [{ | ||
| label: "Text", | ||
| value: "text" | ||
| }, { | ||
| label: "Arrow", | ||
| value: "arrow" | ||
| }] | ||
| } | ||
| ], o = [ | ||
| { | ||
| id: "sma", | ||
| name: "SMA", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "ema", | ||
| name: "EMA", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "bb", | ||
| name: "Bollinger Bands", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "vwap", | ||
| name: "VWAP", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "ichimoku", | ||
| name: "Ichimoku Cloud", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "psar", | ||
| name: "Parabolic SAR", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "supertrend", | ||
| name: "Supertrend", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "keltner", | ||
| name: "Keltner Channel", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "donchian", | ||
| name: "Donchian Channel", | ||
| type: "overlay" | ||
| }, | ||
| { | ||
| id: "rsi", | ||
| name: "RSI", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "macd", | ||
| name: "MACD", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "stochastic", | ||
| name: "Stochastic", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "atr", | ||
| name: "ATR", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "adx", | ||
| name: "ADX", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "obv", | ||
| name: "OBV", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "williamsR", | ||
| name: "Williams %R", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "cci", | ||
| name: "CCI", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "mfi", | ||
| name: "MFI", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "roc", | ||
| name: "ROC", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "tsi", | ||
| name: "TSI", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "cmf", | ||
| name: "CMF", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "aroon", | ||
| name: "Aroon", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "stddev", | ||
| name: "Std Deviation", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "vroc", | ||
| name: "Volume ROC", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "ad", | ||
| name: "Acc/Dist", | ||
| type: "panel" | ||
| }, | ||
| { | ||
| id: "volumeProfile", | ||
| name: "Volume Profile", | ||
| type: "panel" | ||
| } | ||
| ], s = [ | ||
| "sma", | ||
| "ema", | ||
| "bb", | ||
| "rsi", | ||
| "macd", | ||
| "stochastic", | ||
| "vwap", | ||
| "atr", | ||
| "obv", | ||
| "ichimoku" | ||
| ], c = [ | ||
| "BTCUSDT", | ||
| "ETHUSDT", | ||
| "SOLUSDT", | ||
| "BNBUSDT" | ||
| ], l = { | ||
| candleUpColor: "#26A69A", | ||
| candleDownColor: "#EF5350", | ||
| candleUpWick: "#26A69A", | ||
| candleDownWick: "#EF5350", | ||
| backgroundColor: "#131722", | ||
| gridColor: "#1E222D", | ||
| gridVisible: !0, | ||
| volumeVisible: !0, | ||
| legendVisible: !0, | ||
| barCountdown: !0, | ||
| logScale: !1, | ||
| autoScale: !0, | ||
| crosshairMode: "magnet", | ||
| numberLocale: "en-US" | ||
| }, u = "/* === TradeCanvas Widget Styles === */\n\n.tcw-root {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 13px;\n color: #d1d4dc;\n background: #131722;\n position: relative;\n overflow: hidden;\n\n /* Dark theme tokens (default) */\n --tcw-bg: #131722;\n --tcw-bg-elevated: #1E222D;\n --tcw-border: #2A2E39;\n --tcw-text: #d1d4dc;\n --tcw-text-dim: #b2b5be;\n --tcw-text-muted: #787b86;\n --tcw-accent: #2962ff;\n --tcw-accent-dim: rgba(41,98,255,0.15);\n --tcw-accent-glow: rgba(41,98,255,0.12);\n --tcw-red: #ef5350;\n --tcw-green: #26a69a;\n --tcw-transition: 0.15s ease;\n --tcw-radius-lg: 8px;\n --tcw-font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;\n --tcw-hover-bg: rgba(255,255,255,0.04);\n}\n\n.tcw-root[data-tcw-theme=\"light\"] {\n color: #131722;\n background: #ffffff;\n\n --tcw-bg: #ffffff;\n --tcw-bg-elevated: #f0f3fa;\n --tcw-border: #e0e3eb;\n --tcw-text: #131722;\n --tcw-text-dim: #434651;\n --tcw-text-muted: #787b86;\n --tcw-accent: #2962ff;\n --tcw-accent-dim: rgba(41,98,255,0.1);\n --tcw-accent-glow: rgba(41,98,255,0.08);\n --tcw-red: #ef5350;\n --tcw-green: #26a69a;\n --tcw-hover-bg: rgba(0,0,0,0.04);\n}\n\n/* === Toolbar === */\n\n.tcw-toolbar {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 12px;\n height: 40px;\n border-bottom: 1px solid var(--tcw-border);\n background: var(--tcw-bg-elevated);\n flex-shrink: 0;\n position: relative;\n z-index: 20;\n}\n\n.tcw-toolbar-symbol {\n font-size: 13px;\n font-weight: 700;\n color: var(--tcw-text);\n padding: 0 10px;\n white-space: nowrap;\n letter-spacing: -0.01em;\n cursor: pointer;\n border: none;\n background: none;\n font-family: inherit;\n}\n\n.tcw-toolbar-sep {\n width: 1px;\n height: 20px;\n background: var(--tcw-border);\n flex-shrink: 0;\n}\n\n.tcw-toolbar-group {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 0 8px;\n}\n\n.tcw-toolbar-spacer {\n flex: 1;\n}\n\n.tcw-btn {\n padding: 4px 8px;\n font-size: 12px;\n font-family: inherit;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: all var(--tcw-transition);\n white-space: nowrap;\n line-height: 1;\n}\n\n.tcw-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-btn.tcw-active {\n background: var(--tcw-accent);\n color: white;\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: 4px;\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition: all var(--tcw-transition);\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-badge-count {\n font-size: 10px;\n color: var(--tcw-accent);\n background: var(--tcw-accent-dim);\n padding: 0 4px;\n border-radius: 8px;\n font-weight: 600;\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: 2px 6px 2px 8px;\n font-size: 11px;\n font-weight: 500;\n background: var(--tcw-accent-dim);\n color: var(--tcw-accent);\n border-radius: 4px;\n white-space: nowrap;\n line-height: 1.4;\n}\n\n.tcw-chip-remove {\n cursor: pointer;\n opacity: 0.6;\n padding: 0 2px;\n transition: opacity var(--tcw-transition);\n border: none;\n background: none;\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: 4px 8px;\n font-size: 12px;\n font-family: inherit;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: all var(--tcw-transition);\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: 4px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg);\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n z-index: 50;\n padding: 4px 0;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.tcw-dropdown-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 12px;\n font-size: 12px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: background var(--tcw-transition), color var(--tcw-transition);\n width: 100%;\n border: none;\n background: none;\n font-family: inherit;\n text-align: left;\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}\n\n.tcw-dropdown-label {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.05em;\n padding: 6px 12px;\n font-weight: 600;\n}\n\n.tcw-dropdown-divider {\n border-top: 1px solid var(--tcw-border);\n margin: 4px 0;\n}\n\n.tcw-tag {\n font-size: 10px;\n color: var(--tcw-text-muted);\n padding: 1px 5px;\n border-radius: 3px;\n background: var(--tcw-hover-bg);\n}\n\n/* === Body === */\n\n.tcw-body {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.tcw-chart-container {\n flex: 1;\n min-width: 0;\n min-height: 0;\n width: 100%;\n height: 100%;\n}\n\n/* === Sidebar === */\n\n.tcw-sidebar {\n width: 36px;\n flex-shrink: 0;\n background: var(--tcw-bg-elevated);\n border-right: 1px solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 4px 0;\n overflow: visible;\n}\n\n.tcw-tool-group-wrap {\n position: relative;\n}\n\n.tcw-sidebar-btn {\n width: 36px;\n height: 32px;\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: all var(--tcw-transition);\n position: relative;\n flex-shrink: 0;\n line-height: 1;\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-glow);\n}\n\n.tcw-sidebar-btn.tcw-danger:hover {\n color: var(--tcw-red);\n background: rgba(239,68,68,0.1);\n}\n\n.tcw-multi-dot {\n position: absolute;\n bottom: 2px;\n right: 2px;\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n}\n\n.tcw-sidebar-divider {\n width: 20px;\n height: 1px;\n background: var(--tcw-border);\n margin: 4px 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: 2px;\n min-width: 160px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg);\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n z-index: 30;\n padding: 4px 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.05em;\n padding: 6px 12px;\n font-weight: 600;\n}\n\n.tcw-flyout-item {\n padding: 6px 12px;\n font-size: 12px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n display: block;\n border: none;\n background: none;\n text-align: left;\n font-family: inherit;\n transition: background var(--tcw-transition), color var(--tcw-transition);\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}\n\n/* === Modal === */\n\n.tcw-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0,0,0,0.5);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n z-index: 100;\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-lg);\n width: 480px;\n max-width: 90vw;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n box-shadow: 0 24px 64px rgba(0,0,0,0.5);\n}\n\n.tcw-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--tcw-border);\n}\n\n.tcw-modal-header h3 {\n font-size: 15px;\n font-weight: 600;\n margin: 0;\n color: var(--tcw-text);\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: 4px;\n transition: all var(--tcw-transition);\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: 0;\n padding: 0 20px;\n border-bottom: 1px solid var(--tcw-border);\n}\n\n.tcw-modal-tab {\n padding: 10px 16px;\n font-size: 12px;\n font-weight: 500;\n color: var(--tcw-text-muted);\n border: none;\n background: none;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n transition: color var(--tcw-transition);\n font-family: inherit;\n text-transform: capitalize;\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}\n\n.tcw-modal-body {\n padding: 20px;\n overflow-y: auto;\n flex: 1;\n}\n\n.tcw-settings-section {\n margin-bottom: 20px;\n}\n\n.tcw-settings-section:last-child {\n margin-bottom: 0;\n}\n\n.tcw-settings-section-title {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\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: 8px 0;\n}\n\n.tcw-settings-row + .tcw-settings-row {\n border-top: 1px solid rgba(255,255,255,0.03);\n}\n\n.tcw-root[data-tcw-theme=\"light\"] .tcw-settings-row + .tcw-settings-row {\n border-top: 1px solid rgba(0,0,0,0.04);\n}\n\n.tcw-settings-label {\n font-size: 13px;\n color: var(--tcw-text-dim);\n}\n\n.tcw-color-picker-wrap {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.tcw-color-picker-wrap input[type='color'] {\n width: 28px;\n height: 28px;\n border: 1px solid var(--tcw-border);\n border-radius: 4px;\n background: none;\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: 60px;\n}\n\n.tcw-toggle {\n width: 36px;\n height: 20px;\n background: rgba(255,255,255,0.1);\n border-radius: 10px;\n position: relative;\n cursor: pointer;\n transition: background var(--tcw-transition);\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: all var(--tcw-transition);\n}\n\n.tcw-toggle.tcw-on {\n background: var(--tcw-accent);\n}\n\n.tcw-toggle.tcw-on::after {\n left: 18px;\n background: white;\n}\n\n.tcw-root[data-tcw-theme=\"light\"] .tcw-toggle {\n background: rgba(0,0,0,0.1);\n}\n\n.tcw-root[data-tcw-theme=\"light\"] .tcw-toggle::after {\n background: #888;\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: white;\n}\n\n.tcw-settings-select {\n padding: 4px 8px;\n font-size: 12px;\n font-family: inherit;\n background: var(--tcw-bg);\n border: 1px solid var(--tcw-border);\n border-radius: 4px;\n color: var(--tcw-text);\n cursor: pointer;\n}\n\n.tcw-modal-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 20px;\n border-top: 1px solid var(--tcw-border);\n}\n\n.tcw-reset-link {\n font-size: 12px;\n color: var(--tcw-text-muted);\n cursor: pointer;\n border: none;\n background: none;\n font-family: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n transition: color var(--tcw-transition);\n}\n\n.tcw-reset-link:hover {\n color: var(--tcw-text-dim);\n}\n\n.tcw-done-btn {\n padding: 6px 16px;\n font-size: 12px;\n font-weight: 500;\n background: var(--tcw-accent);\n color: white;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-family: inherit;\n transition: background var(--tcw-transition);\n}\n\n.tcw-done-btn:hover {\n background: #2563eb;\n}\n\n/* === Status Bar === */\n\n.tcw-statusbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 16px;\n border-top: 1px solid var(--tcw-border);\n background: var(--tcw-bg-elevated);\n font-size: 11px;\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n}\n\n.tcw-status-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.tcw-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n transition: background 0.3s;\n}\n\n.tcw-status-dot.tcw-connected {\n background: var(--tcw-green);\n}\n\n.tcw-status-dot.tcw-error {\n background: var(--tcw-red);\n}\n\n/* === Responsive === */\n\n@media (max-width: 768px) {\n .tcw-toolbar {\n padding: 0 8px;\n height: 36px;\n }\n .tcw-toolbar-sep {\n display: none;\n }\n .tcw-indicator-chips {\n display: none;\n }\n .tcw-sidebar {\n width: 32px;\n }\n .tcw-sidebar-btn {\n width: 32px;\n height: 28px;\n }\n}\n", d = 0, f = "tcw-styles"; | ||
| function p() { | ||
| if (d++, d > 1 || document.getElementById(f)) return; | ||
| let e = document.createElement("style"); | ||
| e.id = f, e.textContent = u, document.head.appendChild(e); | ||
| } | ||
| function m() { | ||
| if (d--, d > 0) return; | ||
| let e = document.getElementById(f); | ||
| e && e.remove(); | ||
| } | ||
| //#endregion | ||
| //#region src/widget/icons.ts | ||
| var h = { | ||
| cursor: "<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>", | ||
| trendingUp: "<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>", | ||
| minus: "<path d=\"M5 12h14\"/>", | ||
| penLine: "<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>", | ||
| hash: "<line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"4\" y1=\"15\" x2=\"20\" y2=\"15\"/><line x1=\"10\" y1=\"3\" x2=\"8\" y2=\"21\"/><line x1=\"16\" y1=\"3\" x2=\"14\" y2=\"21\"/>", | ||
| square: "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>", | ||
| gitBranch: "<line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>", | ||
| ruler: "<path d=\"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z\"/><path d=\"m14.5 12.5 2-2\"/><path d=\"m11.5 9.5 2-2\"/><path d=\"m8.5 6.5 2-2\"/><path d=\"m17.5 15.5 2-2\"/>", | ||
| type: "<polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"9\" y1=\"20\" x2=\"15\" y2=\"20\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/>", | ||
| magnet: "<path d=\"m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15\"/><path d=\"m5 8 4 4\"/><path d=\"m12 15 4 4\"/>", | ||
| undo: "<path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/>", | ||
| redo: "<path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/>", | ||
| trash: "<path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/>", | ||
| camera: "<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/>", | ||
| settings: "<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>", | ||
| moon: "<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>", | ||
| sun: "<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2\"/><path d=\"M12 20v2\"/><path d=\"m4.93 4.93 1.41 1.41\"/><path d=\"m17.66 17.66 1.41 1.41\"/><path d=\"M2 12h2\"/><path d=\"M20 12h2\"/><path d=\"m6.34 17.66-1.41 1.41\"/><path d=\"m19.07 4.93-1.41 1.41\"/>", | ||
| chevronDown: "<path d=\"m6 9 6 6 6-6\"/>", | ||
| chevronUp: "<path d=\"m18 15-6-6-6 6\"/>", | ||
| barChart: "<line x1=\"12\" y1=\"20\" x2=\"12\" y2=\"10\"/><line x1=\"18\" y1=\"20\" x2=\"18\" y2=\"4\"/><line x1=\"6\" y1=\"20\" x2=\"6\" y2=\"16\"/>", | ||
| x: "<path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/>", | ||
| play: "<polygon points=\"6 3 20 12 6 21 6 3\"/>", | ||
| pause: "<rect width=\"4\" height=\"16\" x=\"6\" y=\"4\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"4\"/>", | ||
| stop: "<rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"1\"/>", | ||
| receipt: "<path d=\"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z\"/><path d=\"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\"/><path d=\"M12 17.5v-11\"/>" | ||
| }; | ||
| function g(e, t = 14) { | ||
| let n = h[e]; | ||
| return n ? `<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>` : ""; | ||
| } | ||
| //#endregion | ||
| //#region src/widget/WidgetDropdown.ts | ||
| var _ = class { | ||
| trigger; | ||
| panel; | ||
| _isOpen = !1; | ||
| onOutsideClick; | ||
| onEscapeKey; | ||
| onTriggerClick; | ||
| constructor(e, t = {}) { | ||
| this.trigger = e, this.panel = document.createElement("div"), this.panel.className = "tcw-dropdown", this.panel.style.width = t.width ?? "200px", t.align === "right" ? this.panel.style.right = "0" : this.panel.style.left = "0", this.panel.style.display = "none", e.style.position = "relative", e.appendChild(this.panel), this.onTriggerClick = () => { | ||
| this._isOpen ? this.close() : this.open(); | ||
| }, this.onOutsideClick = (e) => { | ||
| this.trigger.contains(e.target) || this.close(); | ||
| }, this.onEscapeKey = (e) => { | ||
| e.key === "Escape" && this.close(); | ||
| }, e.addEventListener("click", this.onTriggerClick); | ||
| } | ||
| setContent(e) { | ||
| this.panel.innerHTML = e; | ||
| } | ||
| open() { | ||
| this._isOpen || (this._isOpen = !0, this.panel.style.display = "", document.addEventListener("mousedown", this.onOutsideClick), document.addEventListener("keydown", this.onEscapeKey)); | ||
| } | ||
| close() { | ||
| this._isOpen && (this._isOpen = !1, this.panel.style.display = "none", document.removeEventListener("mousedown", this.onOutsideClick), document.removeEventListener("keydown", this.onEscapeKey)); | ||
| } | ||
| isOpen() { | ||
| return this._isOpen; | ||
| } | ||
| destroy() { | ||
| this.trigger.removeEventListener("click", this.onTriggerClick), document.removeEventListener("mousedown", this.onOutsideClick), document.removeEventListener("keydown", this.onEscapeKey), this.panel.remove(); | ||
| } | ||
| }, v = class { | ||
| config; | ||
| callbacks; | ||
| el; | ||
| chartTypeDropdown = null; | ||
| indicatorDropdown = null; | ||
| tfButtons = []; | ||
| chipsContainer = null; | ||
| themeBtn = null; | ||
| constructor(e, t, n) { | ||
| this.config = t, this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-toolbar", this.build(), e.appendChild(this.el); | ||
| } | ||
| build() { | ||
| let { config: e, callbacks: t, el: n } = this, r = document.createElement("button"); | ||
| r.className = "tcw-toolbar-symbol", r.dataset.role = "symbol", r.addEventListener("click", t.onSymbolClick), n.appendChild(r), n.appendChild(this.sep()); | ||
| let i = document.createElement("div"); | ||
| i.className = "tcw-toolbar-group"; | ||
| for (let n of e.timeframes) { | ||
| let e = document.createElement("button"); | ||
| e.className = "tcw-btn", e.textContent = n.label, e.dataset.tf = n.value, e.addEventListener("click", () => t.onTimeframe(n.value)), i.appendChild(e), this.tfButtons.push(e); | ||
| } | ||
| n.appendChild(i), n.appendChild(this.sep()); | ||
| let a = document.createElement("div"); | ||
| a.style.position = "relative", a.style.display = "inline-flex"; | ||
| let o = document.createElement("button"); | ||
| o.className = "tcw-dropdown-trigger", o.dataset.role = "charttype", a.appendChild(o), n.appendChild(a), this.chartTypeDropdown = new _(a, { width: "160px" }), this.buildChartTypeMenu(), n.appendChild(this.sep()); | ||
| let s = document.createElement("div"); | ||
| s.style.position = "relative", s.style.display = "inline-flex"; | ||
| let c = document.createElement("button"); | ||
| c.className = "tcw-dropdown-trigger", c.dataset.role = "indicators", s.appendChild(c), n.appendChild(s), this.indicatorDropdown = new _(s, { width: "280px" }), this.buildIndicatorMenu(), this.chipsContainer = document.createElement("div"), this.chipsContainer.className = "tcw-indicator-chips", n.appendChild(this.chipsContainer), n.appendChild(this.spacer()); | ||
| let l = this.iconBtn("camera", "Screenshot", t.onScreenshot); | ||
| n.appendChild(l); | ||
| let u = this.iconBtn("settings", "Chart Settings", t.onSettings); | ||
| n.appendChild(u), this.themeBtn = this.iconBtn("moon", "Toggle theme", t.onToggleTheme), this.themeBtn.dataset.role = "theme", n.appendChild(this.themeBtn); | ||
| } | ||
| buildChartTypeMenu() { | ||
| if (!this.chartTypeDropdown) return; | ||
| let e = this.config.chartTypes.map((e) => `<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(""); | ||
| this.chartTypeDropdown.setContent(e), this.chartTypeDropdown.panel.querySelectorAll(".tcw-dropdown-item").forEach((e) => { | ||
| e.addEventListener("click", (e) => { | ||
| let t = e.currentTarget.dataset.ct; | ||
| this.callbacks.onChartType(t), this.chartTypeDropdown?.close(); | ||
| }); | ||
| }); | ||
| } | ||
| buildIndicatorMenu() { | ||
| if (!this.indicatorDropdown) return; | ||
| let { indicators: e, popularIndicatorIds: t } = this.config, n = e.filter((e) => t.includes(e.id)), r = e.filter((e) => !t.includes(e.id)), i = "<div class=\"tcw-dropdown-label\">Popular</div>"; | ||
| for (let e of n) i += `<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`; | ||
| i += "<div class=\"tcw-dropdown-divider\"></div>", i += "<div class=\"tcw-dropdown-label\">All</div>"; | ||
| for (let e of r) i += `<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`; | ||
| this.indicatorDropdown.setContent(i), this.indicatorDropdown.panel.querySelectorAll(".tcw-dropdown-item[data-ind]").forEach((e) => { | ||
| e.addEventListener("click", (e) => { | ||
| let t = e.currentTarget.dataset.ind; | ||
| this.callbacks.onAddIndicator(t); | ||
| }); | ||
| }); | ||
| } | ||
| update(e) { | ||
| let t = this.el.querySelector("[data-role=\"symbol\"]"); | ||
| t && (t.textContent = e.symbol); | ||
| for (let t of this.tfButtons) t.classList.toggle("tcw-active", t.dataset.tf === e.timeframe); | ||
| let n = this.el.querySelector("[data-role=\"charttype\"]"); | ||
| if (n) { | ||
| let t = this.config.chartTypes.find((t) => t.value === e.chartType)?.label ?? "Candles"; | ||
| n.innerHTML = `${g("barChart", 14)} ${t} ${g("chevronDown", 12)}`; | ||
| } | ||
| let r = this.el.querySelector("[data-role=\"indicators\"]"); | ||
| if (r) { | ||
| let t = e.activeIndicators.size, n = `${g("trendingUp", 14)} Indicators`; | ||
| t > 0 && (n += ` <span class="tcw-badge-count">${t}</span>`), r.innerHTML = n; | ||
| } | ||
| if (this.chipsContainer) { | ||
| let t = this.getActiveIndicatorList(e); | ||
| this.chipsContainer.innerHTML = ""; | ||
| for (let e of t) { | ||
| let t = document.createElement("div"); | ||
| t.className = "tcw-indicator-chip"; | ||
| let n = document.createElement("span"); | ||
| n.textContent = e.label, t.appendChild(n); | ||
| let r = document.createElement("button"); | ||
| r.className = "tcw-chip-remove", r.innerHTML = g("x", 10), r.addEventListener("click", () => this.callbacks.onRemoveIndicator(e.instanceId)), t.appendChild(r), this.chipsContainer.appendChild(t); | ||
| } | ||
| } | ||
| this.themeBtn && (this.themeBtn.innerHTML = e.isDark ? g("moon", 14) : g("sun", 14)); | ||
| } | ||
| getActiveIndicatorList(e) { | ||
| let t = []; | ||
| for (let [n, r] of e.activeIndicators.entries()) t.push({ | ||
| instanceId: r, | ||
| id: n, | ||
| label: n.toUpperCase() | ||
| }); | ||
| return t; | ||
| } | ||
| sep() { | ||
| let e = document.createElement("span"); | ||
| return e.className = "tcw-toolbar-sep", e; | ||
| } | ||
| spacer() { | ||
| let e = document.createElement("span"); | ||
| return e.className = "tcw-toolbar-spacer", e; | ||
| } | ||
| iconBtn(e, t, n) { | ||
| let r = document.createElement("button"); | ||
| return r.className = "tcw-btn-icon", r.title = t, r.innerHTML = g(e, 14), r.addEventListener("click", n), r; | ||
| } | ||
| destroy() { | ||
| this.chartTypeDropdown?.destroy(), this.indicatorDropdown?.destroy(), this.el.remove(); | ||
| } | ||
| }, y = [ | ||
| "trendingUp", | ||
| "minus", | ||
| "penLine", | ||
| "hash", | ||
| "square", | ||
| "gitBranch", | ||
| "ruler", | ||
| "type" | ||
| ], b = class { | ||
| config; | ||
| callbacks; | ||
| el; | ||
| groupWraps = []; | ||
| groupButtons = []; | ||
| cursorBtn = null; | ||
| magnetBtn = null; | ||
| flyoutEl = null; | ||
| constructor(e, t, n) { | ||
| this.config = t, this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-sidebar", this.build(), e.appendChild(this.el); | ||
| } | ||
| build() { | ||
| let { config: e, callbacks: t, el: n } = this; | ||
| this.cursorBtn = document.createElement("button"), this.cursorBtn.className = "tcw-sidebar-btn", this.cursorBtn.title = "Cursor", this.cursorBtn.innerHTML = g("cursor", 14), this.cursorBtn.addEventListener("click", t.onCancelDrawing), n.appendChild(this.cursorBtn), n.appendChild(this.divider()), e.drawingToolGroups.forEach((e, r) => { | ||
| let i = document.createElement("div"); | ||
| i.className = "tcw-tool-group-wrap"; | ||
| let a = document.createElement("button"); | ||
| if (a.className = "tcw-sidebar-btn", a.title = e.label, a.innerHTML = g(y[r] ?? "square", 14), e.tools.length > 1) { | ||
| let e = document.createElement("span"); | ||
| e.className = "tcw-multi-dot", a.appendChild(e); | ||
| } | ||
| a.addEventListener("click", () => t.onDrawingTool(e.tools[0].value)), i.appendChild(a), i.addEventListener("mouseenter", () => this.showFlyout(r)), i.addEventListener("mouseleave", () => this.hideFlyout()), n.appendChild(i), this.groupWraps.push(i), this.groupButtons.push(a); | ||
| }); | ||
| let r = document.createElement("div"); | ||
| r.className = "tcw-sidebar-spacer", n.appendChild(r), n.appendChild(this.divider()), this.magnetBtn = document.createElement("button"), this.magnetBtn.className = "tcw-sidebar-btn", this.magnetBtn.title = "Magnet", this.magnetBtn.innerHTML = g("magnet", 14), this.magnetBtn.addEventListener("click", t.onToggleMagnet), n.appendChild(this.magnetBtn); | ||
| let i = document.createElement("button"); | ||
| i.className = "tcw-sidebar-btn", i.title = "Undo", i.innerHTML = g("undo", 14), i.addEventListener("click", t.onUndo), n.appendChild(i); | ||
| let a = document.createElement("button"); | ||
| a.className = "tcw-sidebar-btn", a.title = "Redo", a.innerHTML = g("redo", 14), a.addEventListener("click", t.onRedo), n.appendChild(a); | ||
| let o = document.createElement("button"); | ||
| o.className = "tcw-sidebar-btn tcw-danger", o.title = "Clear all", o.innerHTML = g("trash", 14), o.addEventListener("click", t.onClearDrawings), n.appendChild(o); | ||
| } | ||
| showFlyout(e) { | ||
| let t = this.config.drawingToolGroups[e]; | ||
| if (!t || t.tools.length <= 1) return; | ||
| this.hideFlyout(); | ||
| let n = document.createElement("div"); | ||
| n.className = "tcw-flyout"; | ||
| let r = document.createElement("div"); | ||
| r.className = "tcw-flyout-header", r.textContent = t.label, n.appendChild(r); | ||
| for (let e of t.tools) { | ||
| let t = document.createElement("button"); | ||
| t.className = "tcw-flyout-item", t.textContent = e.label, t.dataset.toolValue = e.value, t.addEventListener("click", () => { | ||
| this.callbacks.onDrawingTool(e.value), this.hideFlyout(); | ||
| }), n.appendChild(t); | ||
| } | ||
| this.flyoutEl = n, this.groupWraps[e].appendChild(n); | ||
| } | ||
| hideFlyout() { | ||
| this.flyoutEl &&= (this.flyoutEl.remove(), null); | ||
| } | ||
| update(e) { | ||
| this.cursorBtn && this.cursorBtn.classList.toggle("tcw-active", e.activeTool === null); | ||
| let { drawingToolGroups: t } = this.config; | ||
| for (let n = 0; n < t.length; n++) { | ||
| let r = t[n].tools.some((t) => t.value === e.activeTool); | ||
| this.groupButtons[n].classList.toggle("tcw-active", r); | ||
| } | ||
| this.flyoutEl && this.flyoutEl.querySelectorAll(".tcw-flyout-item").forEach((t) => { | ||
| let n = t; | ||
| n.classList.toggle("tcw-active", n.dataset.toolValue === e.activeTool); | ||
| }), this.magnetBtn && (this.magnetBtn.classList.toggle("tcw-active", e.magnetEnabled), this.magnetBtn.title = e.magnetEnabled ? "Magnet ON" : "Magnet OFF"); | ||
| } | ||
| divider() { | ||
| let e = document.createElement("div"); | ||
| return e.className = "tcw-sidebar-divider", e; | ||
| } | ||
| destroy() { | ||
| this.hideFlyout(), this.el.remove(); | ||
| } | ||
| }, x = [ | ||
| "style", | ||
| "display", | ||
| "scale" | ||
| ], S = class { | ||
| callbacks; | ||
| backdrop = null; | ||
| modal = null; | ||
| currentTab = "style"; | ||
| currentSettings = null; | ||
| bodyEl = null; | ||
| tabButtons = []; | ||
| constructor(e) { | ||
| this.callbacks = e; | ||
| } | ||
| open(e) { | ||
| this.currentSettings = { ...e }, this.currentTab = "style", this.buildModal(); | ||
| } | ||
| close() { | ||
| this.backdrop?.remove(), this.modal?.remove(), this.backdrop = null, this.modal = null, this.bodyEl = null, this.tabButtons = []; | ||
| } | ||
| buildModal() { | ||
| this.backdrop = document.createElement("div"), this.backdrop.className = "tcw-modal-backdrop", this.backdrop.addEventListener("click", () => { | ||
| this.callbacks.onClose(), this.close(); | ||
| }), document.body.appendChild(this.backdrop), this.modal = document.createElement("div"), this.modal.className = "tcw-modal"; | ||
| let e = document.createElement("div"); | ||
| e.className = "tcw-modal-header"; | ||
| let t = document.createElement("h3"); | ||
| t.textContent = "Chart Settings", e.appendChild(t); | ||
| let n = document.createElement("button"); | ||
| n.className = "tcw-modal-close", n.innerHTML = g("x", 16), n.addEventListener("click", () => { | ||
| this.callbacks.onClose(), this.close(); | ||
| }), e.appendChild(n), this.modal.appendChild(e); | ||
| let r = document.createElement("div"); | ||
| r.className = "tcw-modal-tabs", this.tabButtons = []; | ||
| for (let e of x) { | ||
| let t = document.createElement("button"); | ||
| t.className = "tcw-modal-tab", t.textContent = e, t.dataset.tab = e, e === this.currentTab && t.classList.add("tcw-active"), t.addEventListener("click", () => { | ||
| this.currentTab = e, this.tabButtons.forEach((t) => t.classList.toggle("tcw-active", t.dataset.tab === e)), this.renderTabContent(); | ||
| }), r.appendChild(t), this.tabButtons.push(t); | ||
| } | ||
| this.modal.appendChild(r), this.bodyEl = document.createElement("div"), this.bodyEl.className = "tcw-modal-body", this.modal.appendChild(this.bodyEl), this.renderTabContent(); | ||
| let i = document.createElement("div"); | ||
| i.className = "tcw-modal-footer"; | ||
| let a = document.createElement("button"); | ||
| a.className = "tcw-reset-link", a.textContent = "Reset to defaults", a.addEventListener("click", () => this.callbacks.onReset()), i.appendChild(a); | ||
| let o = document.createElement("button"); | ||
| o.className = "tcw-done-btn", o.textContent = "Done", o.addEventListener("click", () => { | ||
| this.callbacks.onClose(), this.close(); | ||
| }), i.appendChild(o), this.modal.appendChild(i), document.body.appendChild(this.modal); | ||
| let s = (e) => { | ||
| e.key === "Escape" && (document.removeEventListener("keydown", s), this.callbacks.onClose(), this.close()); | ||
| }; | ||
| document.addEventListener("keydown", s); | ||
| } | ||
| renderTabContent() { | ||
| if (!(!this.bodyEl || !this.currentSettings)) switch (this.bodyEl.innerHTML = "", this.currentTab) { | ||
| case "style": | ||
| this.renderStyleTab(); | ||
| break; | ||
| case "display": | ||
| this.renderDisplayTab(); | ||
| break; | ||
| case "scale": | ||
| this.renderScaleTab(); | ||
| break; | ||
| } | ||
| } | ||
| renderStyleTab() { | ||
| if (!this.bodyEl || !this.currentSettings) return; | ||
| let e = this.currentSettings, t = this.section("Candle Colors"); | ||
| t.appendChild(this.colorRow("Up Body", e.candleUpColor, (e) => this.patch({ candleUpColor: e }))), t.appendChild(this.colorRow("Down Body", e.candleDownColor, (e) => this.patch({ candleDownColor: e }))), t.appendChild(this.colorRow("Up Wick", e.candleUpWick, (e) => this.patch({ candleUpWick: e }))), t.appendChild(this.colorRow("Down Wick", e.candleDownWick, (e) => this.patch({ candleDownWick: e }))), this.bodyEl.appendChild(t); | ||
| let n = this.section("Background"); | ||
| n.appendChild(this.colorRow("Background", e.backgroundColor, (e) => this.patch({ backgroundColor: e }))), n.appendChild(this.colorRow("Grid", e.gridColor, (e) => this.patch({ gridColor: e }))), this.bodyEl.appendChild(n); | ||
| } | ||
| renderDisplayTab() { | ||
| if (!this.bodyEl || !this.currentSettings) return; | ||
| let e = this.currentSettings, t = this.section(); | ||
| t.appendChild(this.toggleRow("Grid Lines", e.gridVisible, (e) => this.patch({ gridVisible: e }))), t.appendChild(this.toggleRow("Volume", e.volumeVisible, (e) => this.patch({ volumeVisible: e }))), t.appendChild(this.toggleRow("OHLC Legend", e.legendVisible, (e) => this.patch({ legendVisible: e }))), t.appendChild(this.toggleRow("Bar Countdown", e.barCountdown, (e) => this.patch({ barCountdown: e }))), t.appendChild(this.selectRow("Crosshair Mode", e.crosshairMode, [ | ||
| { | ||
| label: "Magnet", | ||
| value: "magnet" | ||
| }, | ||
| { | ||
| label: "Normal", | ||
| value: "normal" | ||
| }, | ||
| { | ||
| label: "Hidden", | ||
| value: "hidden" | ||
| } | ||
| ], (e) => this.patch({ crosshairMode: e }))), t.appendChild(this.selectRow("Number Locale", e.numberLocale, [ | ||
| { | ||
| label: "en-US (65,234.00)", | ||
| value: "en-US" | ||
| }, | ||
| { | ||
| label: "de-DE (65.234,00)", | ||
| value: "de-DE" | ||
| }, | ||
| { | ||
| label: "fr-FR (65 234,00)", | ||
| value: "fr-FR" | ||
| }, | ||
| { | ||
| label: "vi-VN (65.234,00)", | ||
| value: "vi-VN" | ||
| }, | ||
| { | ||
| label: "en-IN (65,234.00)", | ||
| value: "en-IN" | ||
| }, | ||
| { | ||
| label: "ja-JP (65,234.00)", | ||
| value: "ja-JP" | ||
| } | ||
| ], (e) => this.patch({ numberLocale: e }))), this.bodyEl.appendChild(t); | ||
| } | ||
| renderScaleTab() { | ||
| if (!this.bodyEl || !this.currentSettings) return; | ||
| let e = this.currentSettings, t = this.section(); | ||
| t.appendChild(this.toggleRow("Auto Scale", e.autoScale, (e) => this.patch({ autoScale: e }))), t.appendChild(this.toggleRow("Log Scale", e.logScale, (e) => this.patch({ logScale: e }))), this.bodyEl.appendChild(t); | ||
| } | ||
| patch(e) { | ||
| this.currentSettings && Object.assign(this.currentSettings, e), this.callbacks.onChange(e); | ||
| } | ||
| section(e) { | ||
| let t = document.createElement("div"); | ||
| if (t.className = "tcw-settings-section", e) { | ||
| let n = document.createElement("div"); | ||
| n.className = "tcw-settings-section-title", n.textContent = e, t.appendChild(n); | ||
| } | ||
| return t; | ||
| } | ||
| colorRow(e, t, n) { | ||
| let r = document.createElement("div"); | ||
| r.className = "tcw-settings-row"; | ||
| let i = document.createElement("span"); | ||
| i.className = "tcw-settings-label", i.textContent = e, r.appendChild(i); | ||
| let a = document.createElement("div"); | ||
| a.className = "tcw-color-picker-wrap"; | ||
| let o = document.createElement("input"); | ||
| o.type = "color", o.value = t; | ||
| let s = document.createElement("span"); | ||
| return s.className = "tcw-color-hex", s.textContent = t, o.addEventListener("input", () => { | ||
| s.textContent = o.value, n(o.value); | ||
| }), a.appendChild(o), a.appendChild(s), r.appendChild(a), r; | ||
| } | ||
| toggleRow(e, t, n) { | ||
| let r = document.createElement("div"); | ||
| r.className = "tcw-settings-row"; | ||
| let i = document.createElement("span"); | ||
| i.className = "tcw-settings-label", i.textContent = e, r.appendChild(i); | ||
| let a = document.createElement("button"); | ||
| return a.className = `tcw-toggle${t ? " tcw-on" : ""}`, a.addEventListener("click", () => { | ||
| let e = !a.classList.contains("tcw-on"); | ||
| a.classList.toggle("tcw-on", e), n(e); | ||
| }), r.appendChild(a), r; | ||
| } | ||
| selectRow(e, t, n, r) { | ||
| let i = document.createElement("div"); | ||
| i.className = "tcw-settings-row"; | ||
| let a = document.createElement("span"); | ||
| a.className = "tcw-settings-label", a.textContent = e, i.appendChild(a); | ||
| let o = document.createElement("select"); | ||
| o.className = "tcw-settings-select"; | ||
| for (let e of n) { | ||
| let n = document.createElement("option"); | ||
| n.value = e.value, n.textContent = e.label, e.value === t && (n.selected = !0), o.appendChild(n); | ||
| } | ||
| return o.addEventListener("change", () => r(o.value)), i.appendChild(o), i; | ||
| } | ||
| destroy() { | ||
| this.close(); | ||
| } | ||
| }, C = class { | ||
| el; | ||
| dotEl; | ||
| messageEl; | ||
| infoEl; | ||
| constructor(e) { | ||
| this.el = document.createElement("div"), this.el.className = "tcw-statusbar"; | ||
| let t = document.createElement("div"); | ||
| t.className = "tcw-status-indicator", this.dotEl = document.createElement("span"), this.dotEl.className = "tcw-status-dot", t.appendChild(this.dotEl), this.messageEl = document.createElement("span"), t.appendChild(this.messageEl), this.el.appendChild(t), this.infoEl = document.createElement("span"), this.el.appendChild(this.infoEl), e.appendChild(this.el); | ||
| } | ||
| update(e) { | ||
| this.dotEl.className = "tcw-status-dot", e.connectionState === "connected" ? this.dotEl.classList.add("tcw-connected") : e.connectionState === "error" && this.dotEl.classList.add("tcw-error"), this.messageEl.textContent = e.message, this.infoEl.textContent = `${e.symbol} ${e.timeframe}`; | ||
| } | ||
| destroy() { | ||
| this.el.remove(); | ||
| } | ||
| }, w = class { | ||
| chart; | ||
| state; | ||
| toolbar = null; | ||
| sidebar = null; | ||
| settings = null; | ||
| statusBar = null; | ||
| root; | ||
| chartContainer; | ||
| destroyed = !1; | ||
| options; | ||
| symbolIndex = 0; | ||
| symbols; | ||
| settingsState; | ||
| adapter = null; | ||
| constructor(t, n = {}) { | ||
| this.options = n, this.symbols = n.symbols ?? c, this.settingsState = { ...l }; | ||
| let u = this.resolveIsDark(n.theme), d = this.resolveTheme(n.theme); | ||
| this.state = { | ||
| symbol: n.symbol ?? this.symbols[0] ?? "BTCUSDT", | ||
| timeframe: n.timeframe ?? "5m", | ||
| chartType: n.chartOptions?.chartType ?? "candlestick", | ||
| isDark: u, | ||
| activeIndicators: /* @__PURE__ */ new Map(), | ||
| activeTool: null, | ||
| magnetEnabled: !0, | ||
| connectionState: "connecting", | ||
| connectionMessage: "Connecting..." | ||
| }; | ||
| let f = this.symbols.indexOf(this.state.symbol); | ||
| 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, { | ||
| symbols: this.symbols, | ||
| timeframes: n.timeframes ? r.filter((e) => n.timeframes.includes(e.value)) : r, | ||
| chartTypes: n.chartTypes ? i.filter((e) => n.chartTypes.includes(e.value)) : i, | ||
| indicators: o, | ||
| popularIndicatorIds: s | ||
| }, { | ||
| onSymbolClick: () => this.handleSymbolClick(), | ||
| onTimeframe: (e) => this.handleTimeframe(e), | ||
| onChartType: (e) => this.handleChartType(e), | ||
| onAddIndicator: (e) => this.handleAddIndicator(e), | ||
| onRemoveIndicator: (e) => this.handleRemoveIndicator(e), | ||
| onScreenshot: () => this.chart.screenshot(), | ||
| onSettings: () => this.openSettings(), | ||
| onToggleTheme: () => this.handleToggleTheme() | ||
| })); | ||
| let m = document.createElement("div"); | ||
| m.className = "tcw-body", n.drawingTools !== !1 && (this.sidebar = new b(m, { drawingToolGroups: a }, { | ||
| onDrawingTool: (e) => this.handleDrawingTool(e), | ||
| onCancelDrawing: () => this.handleCancelDrawing(), | ||
| onToggleMagnet: () => this.handleToggleMagnet(), | ||
| onUndo: () => this.chart.undo(), | ||
| onRedo: () => this.chart.redo(), | ||
| onClearDrawings: () => { | ||
| this.chart.clearDrawings(), this.state = { | ||
| ...this.state, | ||
| activeTool: null | ||
| }, this.updateUI(); | ||
| } | ||
| })), this.chartContainer = document.createElement("div"), this.chartContainer.className = "tcw-chart-container", m.appendChild(this.chartContainer), this.root.appendChild(m), this.chart = new e(this.chartContainer, { | ||
| chartType: this.state.chartType, | ||
| theme: d, | ||
| autoScale: !0, | ||
| crosshair: { mode: "magnet" }, | ||
| features: { | ||
| drawings: !0, | ||
| drawingMagnet: !0, | ||
| drawingUndoRedo: !0, | ||
| indicators: !0, | ||
| trading: n.trading !== !1, | ||
| tradingContextMenu: n.trading !== !1, | ||
| volume: !0, | ||
| legend: !0, | ||
| crosshair: !0, | ||
| keyboard: !0, | ||
| screenshot: !0, | ||
| alerts: !0, | ||
| barCountdown: !0, | ||
| logScale: !0, | ||
| watermark: !0 | ||
| }, | ||
| ...n.chartOptions | ||
| }), n.statusBar !== !1 && (this.statusBar = new C(this.root)), n.settings !== !1 && (this.settings = new S({ | ||
| onChange: (e) => this.applySettings(e), | ||
| onReset: () => this.resetSettings(), | ||
| onClose: () => {} | ||
| })), n.adapter && (this.adapter = n.adapter, this.connectStream()), this.updateUI(), n.onReady?.(this.chart); | ||
| } | ||
| async setSymbol(e) { | ||
| this.state = { | ||
| ...this.state, | ||
| symbol: e | ||
| }; | ||
| let t = this.symbols.indexOf(e); | ||
| t >= 0 && (this.symbolIndex = t), this.options.onSymbolChange?.(e), this.updateUI(), this.adapter && await this.connectStream(); | ||
| } | ||
| async setTimeframe(e) { | ||
| this.state = { | ||
| ...this.state, | ||
| timeframe: e | ||
| }, this.options.onTimeframeChange?.(e), this.updateUI(), this.adapter && await this.connectStream(); | ||
| } | ||
| setTheme(e) { | ||
| let t = this.resolveIsDark(e), n = this.resolveTheme(e); | ||
| this.state = { | ||
| ...this.state, | ||
| isDark: t | ||
| }, this.root.dataset.tcwTheme = t ? "dark" : "light", this.chart.setTheme(n), this.updateUI(); | ||
| } | ||
| getChart() { | ||
| return this.chart; | ||
| } | ||
| destroy() { | ||
| this.destroyed || (this.destroyed = !0, this.toolbar?.destroy(), this.sidebar?.destroy(), this.settings?.destroy(), this.statusBar?.destroy(), this.chart.destroy(), this.root.remove(), m()); | ||
| } | ||
| handleSymbolClick() { | ||
| this.symbolIndex = (this.symbolIndex + 1) % this.symbols.length; | ||
| let e = this.symbols[this.symbolIndex]; | ||
| this.state = { | ||
| ...this.state, | ||
| symbol: e | ||
| }, this.options.onSymbolChange?.(e), this.updateUI(), this.adapter && this.connectStream(); | ||
| } | ||
| handleTimeframe(e) { | ||
| this.state = { | ||
| ...this.state, | ||
| timeframe: e | ||
| }, this.options.onTimeframeChange?.(e), this.updateUI(), this.adapter && this.connectStream(); | ||
| } | ||
| handleChartType(e) { | ||
| this.state = { | ||
| ...this.state, | ||
| chartType: e | ||
| }, this.chart.setChartType(e), this.updateUI(); | ||
| } | ||
| handleAddIndicator(e) { | ||
| if (this.state.activeIndicators.has(e)) { | ||
| let t = this.state.activeIndicators.get(e); | ||
| this.chart.removeIndicator(t); | ||
| let n = new Map(this.state.activeIndicators); | ||
| n.delete(e), this.state = { | ||
| ...this.state, | ||
| activeIndicators: n | ||
| }; | ||
| } else { | ||
| let t = this.chart.addIndicator(e); | ||
| if (t) { | ||
| let n = new Map(this.state.activeIndicators); | ||
| n.set(e, t), this.state = { | ||
| ...this.state, | ||
| activeIndicators: n | ||
| }; | ||
| } | ||
| } | ||
| this.updateUI(); | ||
| } | ||
| handleRemoveIndicator(e) { | ||
| this.chart.removeIndicator(e); | ||
| let t = new Map(this.state.activeIndicators); | ||
| for (let [n, r] of t.entries()) if (r === e) { | ||
| t.delete(n); | ||
| break; | ||
| } | ||
| this.state = { | ||
| ...this.state, | ||
| activeIndicators: t | ||
| }, this.updateUI(); | ||
| } | ||
| handleDrawingTool(e) { | ||
| this.state = { | ||
| ...this.state, | ||
| activeTool: e | ||
| }, this.chart.setDrawingTool(e), this.updateUI(); | ||
| } | ||
| handleCancelDrawing() { | ||
| this.state = { | ||
| ...this.state, | ||
| activeTool: null | ||
| }, this.chart.setDrawingTool(null), this.updateUI(); | ||
| } | ||
| handleToggleMagnet() { | ||
| let e = !this.state.magnetEnabled; | ||
| this.state = { | ||
| ...this.state, | ||
| magnetEnabled: e | ||
| }, this.chart.setDrawingMagnet(e), this.updateUI(); | ||
| } | ||
| handleToggleTheme() { | ||
| let e = !this.state.isDark; | ||
| this.state = { | ||
| ...this.state, | ||
| isDark: e | ||
| }, this.root.dataset.tcwTheme = e ? "dark" : "light", this.chart.setTheme(e ? t : n), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), { | ||
| fontSize: 48, | ||
| color: e ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)" | ||
| }), this.updateUI(); | ||
| } | ||
| openSettings() { | ||
| this.settings?.open(this.settingsState); | ||
| } | ||
| applySettings(e) { | ||
| this.settingsState = { | ||
| ...this.settingsState, | ||
| ...e | ||
| }, e.gridVisible !== void 0 && this.chart.setGridVisible(e.gridVisible), e.volumeVisible !== void 0 && this.chart.setVolumeVisible(e.volumeVisible), e.crosshairMode !== void 0 && this.chart.setCrosshairMode(e.crosshairMode), e.autoScale !== void 0 && this.chart.setAutoScale(e.autoScale), e.logScale !== void 0 && this.chart.setLogScale(e.logScale), e.numberLocale !== void 0 && this.chart.setNumberLocale(e.numberLocale); | ||
| let t = { ...this.chart.getTheme() }, n = !1; | ||
| e.candleUpColor !== void 0 && (t.candleUp = e.candleUpColor, n = !0), e.candleDownColor !== void 0 && (t.candleDown = e.candleDownColor, n = !0), e.candleUpWick !== void 0 && (t.candleUpWick = e.candleUpWick, n = !0), e.candleDownWick !== void 0 && (t.candleDownWick = e.candleDownWick, n = !0), e.backgroundColor !== void 0 && (t.background = e.backgroundColor, n = !0), e.gridColor !== void 0 && (t.grid = e.gridColor, n = !0), n && this.chart.setTheme(t); | ||
| } | ||
| resetSettings() { | ||
| this.settingsState = { ...l }, this.applySettings(this.settingsState); | ||
| } | ||
| async connectStream() { | ||
| if (this.adapter) { | ||
| this.state = { | ||
| ...this.state, | ||
| connectionState: "connecting", | ||
| connectionMessage: "Connecting..." | ||
| }, this.updateUI(); | ||
| try { | ||
| this.chart.disconnectStream(), await this.chart.connect({ | ||
| adapter: this.adapter, | ||
| symbol: this.state.symbol, | ||
| timeframe: this.state.timeframe, | ||
| historyLimit: this.options.historyLimit ?? 500 | ||
| }), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), { | ||
| fontSize: 48, | ||
| color: this.state.isDark ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)" | ||
| }), this.state = { | ||
| ...this.state, | ||
| connectionState: "connected", | ||
| connectionMessage: "Live" | ||
| }; | ||
| } catch (e) { | ||
| this.state = { | ||
| ...this.state, | ||
| connectionState: "error", | ||
| connectionMessage: e instanceof Error ? e.message : "Connection failed" | ||
| }; | ||
| } | ||
| this.updateUI(); | ||
| } | ||
| } | ||
| updateUI() { | ||
| this.toolbar?.update(this.state), this.sidebar?.update(this.state), this.statusBar?.update({ | ||
| connectionState: this.state.connectionState, | ||
| message: this.state.connectionMessage, | ||
| symbol: this.state.symbol, | ||
| timeframe: this.state.timeframe | ||
| }); | ||
| } | ||
| resolveIsDark(e) { | ||
| return e === void 0 || e === "dark" ? !0 : e === "light" ? !1 : typeof e == "object" && e.background ? this.isColorDark(e.background) : !0; | ||
| } | ||
| resolveTheme(e) { | ||
| return e === void 0 || e === "dark" ? t : e === "light" ? n : typeof e == "object" ? e : t; | ||
| } | ||
| isColorDark(e) { | ||
| if (e.startsWith("#") && e.length >= 7) { | ||
| let t = parseInt(e.slice(1, 3), 16), n = parseInt(e.slice(3, 5), 16), r = parseInt(e.slice(5, 7), 16); | ||
| return t + n + r < 384; | ||
| } | ||
| return !0; | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { w as ChartWidget }; | ||
| //# sourceMappingURL=index.js.map |
Sorry, the diff of this file is too big to display
| import { Theme, ThemeName, ChartType, TimeFrame, DrawingToolType, DataAdapter, ChartOptions } from '@tradecanvas/commons'; | ||
| import { Chart } from '../Chart.js'; | ||
| export interface ChartWidgetOptions { | ||
| symbol?: string; | ||
| timeframe?: TimeFrame; | ||
| theme?: ThemeName | Theme; | ||
| toolbar?: boolean; | ||
| drawingTools?: boolean; | ||
| settings?: boolean; | ||
| trading?: boolean; | ||
| statusBar?: boolean; | ||
| symbols?: string[]; | ||
| timeframes?: TimeFrame[]; | ||
| chartTypes?: ChartType[]; | ||
| adapter?: DataAdapter; | ||
| historyLimit?: number; | ||
| chartOptions?: Partial<ChartOptions>; | ||
| onSymbolChange?: (symbol: string) => void; | ||
| onTimeframeChange?: (tf: TimeFrame) => void; | ||
| onReady?: (chart: Chart) => void; | ||
| } | ||
| export interface WidgetState { | ||
| symbol: string; | ||
| timeframe: TimeFrame; | ||
| chartType: ChartType; | ||
| isDark: boolean; | ||
| activeIndicators: Map<string, string>; | ||
| activeTool: DrawingToolType | null; | ||
| magnetEnabled: boolean; | ||
| connectionState: string; | ||
| connectionMessage: string; | ||
| } | ||
| export interface ToolbarConfig { | ||
| symbols: string[]; | ||
| timeframes: { | ||
| label: string; | ||
| value: TimeFrame; | ||
| }[]; | ||
| chartTypes: { | ||
| label: string; | ||
| value: ChartType; | ||
| }[]; | ||
| indicators: IndicatorDef[]; | ||
| popularIndicatorIds: string[]; | ||
| } | ||
| export interface ToolbarCallbacks { | ||
| onSymbolClick: () => void; | ||
| onTimeframe: (tf: TimeFrame) => void; | ||
| onChartType: (type: ChartType) => void; | ||
| onAddIndicator: (id: string) => void; | ||
| onRemoveIndicator: (instanceId: string) => void; | ||
| onScreenshot: () => void; | ||
| onSettings: () => void; | ||
| onToggleTheme: () => void; | ||
| } | ||
| export interface SidebarConfig { | ||
| drawingToolGroups: DrawingToolGroupDef[]; | ||
| } | ||
| export interface SidebarCallbacks { | ||
| onDrawingTool: (tool: DrawingToolType) => void; | ||
| onCancelDrawing: () => void; | ||
| onToggleMagnet: () => void; | ||
| onUndo: () => void; | ||
| onRedo: () => void; | ||
| onClearDrawings: () => void; | ||
| } | ||
| export interface SettingsCallbacks { | ||
| onChange: (patch: Partial<ChartSettingsState>) => void; | ||
| onReset: () => void; | ||
| onClose: () => void; | ||
| } | ||
| export interface ChartSettingsState { | ||
| candleUpColor: string; | ||
| candleDownColor: string; | ||
| candleUpWick: string; | ||
| candleDownWick: string; | ||
| backgroundColor: string; | ||
| gridColor: string; | ||
| gridVisible: boolean; | ||
| volumeVisible: boolean; | ||
| legendVisible: boolean; | ||
| barCountdown: boolean; | ||
| logScale: boolean; | ||
| autoScale: boolean; | ||
| crosshairMode: 'normal' | 'magnet' | 'hidden'; | ||
| numberLocale: string; | ||
| } | ||
| export interface IndicatorDef { | ||
| id: string; | ||
| name: string; | ||
| type: 'overlay' | 'panel'; | ||
| } | ||
| export interface DrawingToolGroupDef { | ||
| label: string; | ||
| tools: { | ||
| label: string; | ||
| value: DrawingToolType; | ||
| }[]; | ||
| } | ||
| export interface ActiveIndicator { | ||
| instanceId: string; | ||
| id: string; | ||
| label: string; | ||
| } | ||
| //# sourceMappingURL=types.d.ts.map |
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/widget/types.ts"],"names":[],"mappings":"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"} |
| import { ChartType, TimeFrame } from '@tradecanvas/commons'; | ||
| import { IndicatorDef, DrawingToolGroupDef, ChartSettingsState } from './types.js'; | ||
| export declare const TIMEFRAMES: { | ||
| label: string; | ||
| value: TimeFrame; | ||
| }[]; | ||
| export declare const CHART_TYPES: { | ||
| label: string; | ||
| value: ChartType; | ||
| }[]; | ||
| export declare const DRAWING_TOOL_GROUPS: DrawingToolGroupDef[]; | ||
| export declare const INDICATORS: IndicatorDef[]; | ||
| export declare const POPULAR_INDICATORS: string[]; | ||
| export declare const DEFAULT_SYMBOLS: string[]; | ||
| export declare const DEFAULT_SETTINGS: ChartSettingsState; | ||
| //# sourceMappingURL=widgetConfig.d.ts.map |
| {"version":3,"file":"widgetConfig.d.ts","sourceRoot":"","sources":["../../src/widget/widgetConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAmB,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAExF,eAAO,MAAM,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,EAO3D,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,EAQ5D,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,mBAAmB,EA8DpD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,YAAY,EA2BpC,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAG9B,CAAC;AAEF,eAAO,MAAM,eAAe,UAE3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,kBAe9B,CAAC"} |
| import { SidebarConfig, SidebarCallbacks, WidgetState } from './types.js'; | ||
| export declare class WidgetDrawingSidebar { | ||
| private config; | ||
| private callbacks; | ||
| private el; | ||
| private groupWraps; | ||
| private groupButtons; | ||
| private cursorBtn; | ||
| private magnetBtn; | ||
| private flyoutEl; | ||
| constructor(host: HTMLElement, config: SidebarConfig, callbacks: SidebarCallbacks); | ||
| private build; | ||
| private showFlyout; | ||
| private hideFlyout; | ||
| update(state: WidgetState): void; | ||
| private divider; | ||
| destroy(): void; | ||
| } | ||
| //# sourceMappingURL=WidgetDrawingSidebar.d.ts.map |
| {"version":3,"file":"WidgetDrawingSidebar.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetDrawingSidebar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAO/E,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,QAAQ,CAA+B;gBAEnC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB;IASjF,OAAO,CAAC,KAAK;IA8Eb,OAAO,CAAC,UAAU;IA8BlB,OAAO,CAAC,UAAU;IAOlB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IA4BhC,OAAO,CAAC,OAAO;IAMf,OAAO,IAAI,IAAI;CAIhB"} |
| export declare class WidgetDropdown { | ||
| private trigger; | ||
| private panel; | ||
| private _isOpen; | ||
| private onOutsideClick; | ||
| private onEscapeKey; | ||
| private onTriggerClick; | ||
| constructor(trigger: HTMLElement, config?: { | ||
| width?: string; | ||
| align?: 'left' | 'right'; | ||
| }); | ||
| setContent(html: string): void; | ||
| open(): void; | ||
| close(): void; | ||
| isOpen(): boolean; | ||
| destroy(): void; | ||
| } | ||
| //# sourceMappingURL=WidgetDropdown.d.ts.map |
| {"version":3,"file":"WidgetDropdown.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetDropdown.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,cAAc,CAAa;gBAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAO;IAwC3F,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,MAAM,IAAI,OAAO;IAIjB,OAAO,IAAI,IAAI;CAMhB"} |
| import { ChartSettingsState, SettingsCallbacks } from './types.js'; | ||
| export declare class WidgetSettings { | ||
| private callbacks; | ||
| private backdrop; | ||
| private modal; | ||
| private currentTab; | ||
| private currentSettings; | ||
| private bodyEl; | ||
| private tabButtons; | ||
| constructor(callbacks: SettingsCallbacks); | ||
| open(currentSettings: ChartSettingsState): void; | ||
| close(): void; | ||
| private buildModal; | ||
| private renderTabContent; | ||
| private renderStyleTab; | ||
| private renderDisplayTab; | ||
| private renderScaleTab; | ||
| private patch; | ||
| private section; | ||
| private colorRow; | ||
| private toggleRow; | ||
| private selectRow; | ||
| destroy(): void; | ||
| } | ||
| //# sourceMappingURL=WidgetSettings.d.ts.map |
| {"version":3,"file":"WidgetSettings.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetSettings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMxE,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAA2B;gBAEjC,SAAS,EAAE,iBAAiB;IAIxC,IAAI,CAAC,eAAe,EAAE,kBAAkB,GAAG,IAAI;IAM/C,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,UAAU;IAuFlB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;IA8BxB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,QAAQ;IA+BhB,OAAO,CAAC,SAAS;IAoBjB,OAAO,CAAC,SAAS;IA4BjB,OAAO,IAAI,IAAI;CAGhB"} |
| export declare class WidgetStatusBar { | ||
| private el; | ||
| private dotEl; | ||
| private messageEl; | ||
| private infoEl; | ||
| constructor(host: HTMLElement); | ||
| update(state: { | ||
| connectionState: string; | ||
| message: string; | ||
| symbol: string; | ||
| timeframe: string; | ||
| }): void; | ||
| destroy(): void; | ||
| } | ||
| //# sourceMappingURL=WidgetStatusBar.d.ts.map |
| {"version":3,"file":"WidgetStatusBar.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetStatusBar.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAe;IAC1B,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAkB;gBAEpB,IAAI,EAAE,WAAW;IAsB7B,MAAM,CAAC,KAAK,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYpG,OAAO,IAAI,IAAI;CAGhB"} |
| /** | ||
| * Inject the widget stylesheet into `document.head`. Reference-counted so | ||
| * multiple `ChartWidget` instances share the same `<style>` tag and the last | ||
| * to detach removes it. CSS lives in a sibling `.css` file and is inlined at | ||
| * build time via Vite's `?raw` query — consumers see a plain string at runtime. | ||
| */ | ||
| export declare function injectWidgetStyles(): void; | ||
| export declare function removeWidgetStyles(): void; | ||
| //# sourceMappingURL=WidgetStyles.d.ts.map |
| {"version":3,"file":"WidgetStyles.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetStyles.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAQzC"} |
| import { ToolbarConfig, ToolbarCallbacks, WidgetState } from './types.js'; | ||
| export declare class WidgetToolbar { | ||
| private config; | ||
| private callbacks; | ||
| private el; | ||
| private chartTypeDropdown; | ||
| private indicatorDropdown; | ||
| private tfButtons; | ||
| private chipsContainer; | ||
| private themeBtn; | ||
| constructor(host: HTMLElement, config: ToolbarConfig, callbacks: ToolbarCallbacks); | ||
| private build; | ||
| private buildChartTypeMenu; | ||
| private buildIndicatorMenu; | ||
| update(state: WidgetState): void; | ||
| private getActiveIndicatorList; | ||
| private sep; | ||
| private spacer; | ||
| private iconBtn; | ||
| destroy(): void; | ||
| } | ||
| //# sourceMappingURL=WidgetToolbar.d.ts.map |
| {"version":3,"file":"WidgetToolbar.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetToolbar.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAC;AAIhG,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAkC;gBAEtC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB;IASjF,OAAO,CAAC,KAAK;IA4Eb,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,kBAAkB;IA4B1B,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAwDhC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,OAAO;IASf,OAAO,IAAI,IAAI;CAKhB"} |
+1
-4
@@ -34,5 +34,3 @@ import { ChartOptions, ChartType, OHLCBar, DataSeries, Theme, ThemeName, ChartEventType, ChartEvent, ChartEventMap, TauriBridgeOptions, IndicatorPlugin, IndicatorDescriptor, IndicatorOutput, DrawingToolType, DrawingState, DrawingStyle, DrawingPlugin, PanelPosition, TradingOrder, TradingPosition, DepthData, TradingConfig, MarketConfig, Locale, StreamConfig, ConnectionState, ConnectionInfo, TimeFrame, FeaturesConfig } from '@tradecanvas/commons'; | ||
| private undoRedoManager; | ||
| private autoSaveTimer; | ||
| private autoSaveDelay; | ||
| private autoSaveKey; | ||
| private autoSaveScheduler; | ||
| private animator; | ||
@@ -263,5 +261,4 @@ private crosshairTooltip; | ||
| private syncRenderContext; | ||
| private timeframeToMs; | ||
| private buildPriceLimits; | ||
| } | ||
| //# sourceMappingURL=Chart.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../src/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,OAAO,EACP,UAAU,EACV,KAAK,EACL,SAAS,EACT,cAAc,EACd,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,eAAe,EACf,cAAc,EACd,SAAS,EACT,cAAc,EACf,MAAM,sBAAsB,CAAC;AA0D9B,qBAAa,KAAK;IAChB,MAAM,CAAC,OAAO,SAAW;IAEzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,mBAAmB,CAA8D;IACzF,OAAO,CAAC,cAAc,CAA8D;IACpF,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAkD;IAC5E,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,gBAAgB,CAA+C;IACvE,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,eAAe,CAA6C;IACpE,OAAO,CAAC,aAAa,CAAc;gBAGvB,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY;IAwSzD,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAc/B,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAS7B;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAWjC,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAiBjC,gFAAgF;IAChF,qBAAqB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAcnF,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAUnC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,MAAM,GAAG,IAAI;IAgBnI,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI;IAK5F,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAYzC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAI9D,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAIhD,MAAM,CAAC,UAAU,IAAI,mBAAmB,EAAE;IAQ1C,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAKnE,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAOpD,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI;IAOlD,cAAc,IAAI,eAAe,GAAG,IAAI;IAIxC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAInD,WAAW,IAAI,YAAY,EAAE;IAI7B,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAI3C,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI/B,aAAa,IAAI,IAAI;IAIrB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAMhD,IAAI,IAAI,OAAO;IAKf,IAAI,IAAI,OAAO;IAKf,gBAAgB,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAM1D,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIxC,gBAAgB,IAAI,OAAO;IAM3B,eAAe,IAAI,IAAI;IAIvB,iBAAiB,IAAI,IAAI;IAIzB,eAAe,IAAI,IAAI;IAIvB,eAAe,IAAI,IAAI;IAMvB,gBAAgB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQ5C,iBAAiB,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAgB1E,aAAa,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAatE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAO,GAAG,IAAI;IAK9C,eAAe,IAAI,IAAI;IASvB,OAAO,CAAC,gBAAgB;IAaxB,sBAAsB,IAAI,mBAAmB,EAAE;IAI/C,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,IAAI;IAOtF,mEAAmE;IACnE,mBAAmB,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,UAAU,EAAE,mBAAmB,CAAA;KAAE,EAAE;IAI7H,2DAA2D;IAC3D,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,IAAI;IAM9F,qDAAqD;IACrD,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOrH,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI;IAKvC,YAAY,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,IAAI;IAKhD,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAK3C,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ1D,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAOtD;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DlD;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE;;;OAGG;IACG,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvD;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAOxB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAK9C,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAO/C,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKlF,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKrC,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAKrD,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,IAAI;IAKlD,mBAAmB,IAAI,IAAI;IAO3B,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKnC,UAAU,IAAI,OAAO;IAIrB,sBAAsB,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKvH,kBAAkB,IAAI,eAAe;IAIrC,iBAAiB,IAAI,cAAc;IAInC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMrC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAYjC,WAAW,IAAI,IAAI;IAKnB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAuBjE,MAAM,IAAI,IAAI;IAMd,OAAO,IAAI,IAAI;IAMf,UAAU,IAAI,IAAI;IAQlB,EAAE,CAAC,CAAC,SAAS,cAAc,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,SAAS,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI;IAI7I,GAAG,CAAC,CAAC,SAAS,cAAc,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,SAAS,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI;IAI9I,iBAAiB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI;IAI9D,kBAAkB,IAAI,IAAI;IAM1B,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI;IAQ9C,QAAQ,IAAI,KAAK;IAMjB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAO9E,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKpC,WAAW,IAAI,OAAO;IAMtB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI;IAK5D,gBAAgB,IAAI,MAAM;IAM1B,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKtC,aAAa,IAAI,OAAO;IAMxB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOxC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMzC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,GAAG,IAAI;IAK1E,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKnC;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAOxC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAKnC,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAK5B,cAAc,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAO5C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,mBAAmB,EAAE,cAA2B,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO5H,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK7B,SAAS,IAAI,OAAO,mBAAmB,EAAE,UAAU,EAAE;IAIrD,WAAW,IAAI,IAAI;IAKnB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO7B,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,GAAG,IAAI;IAcxE,WAAW,IAAI,IAAI;IACnB,YAAY,IAAI,IAAI;IACpB,UAAU,IAAI,IAAI;IAClB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC/B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IACnC,cAAc,IAAI,SAAS,GAAG,QAAQ,GAAG,SAAS;IAClD,iBAAiB,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAIxE,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAetC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAc7B,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQ1C,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAShC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQxC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQrC,eAAe,IAAI,MAAM;IAMzB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IA8BrC,SAAS,IAAI,YAAY,GAAG,IAAI;IAIhC,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAc5C,6CAA6C;IAC7C,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAIjD,uEAAuE;IACvE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IA8BjD,MAAM,IAAI,IAAI;IAgBd,OAAO,IAAI,IAAI;IAsBf,OAAO,CAAC,mBAAmB;IAiB3B,4EAA4E;IAC5E,OAAO,CAAC,cAAc;IAuBtB,wFAAwF;IACxF,OAAO,CAAC,cAAc;IAYtB,kFAAkF;IAClF,OAAO,CAAC,uBAAuB;IAuC/B,OAAO,CAAC,iBAAiB;IAOzB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,qBAAqB;IAyD7B,OAAO,CAAC,iBAAiB;IAoCzB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,gBAAgB;CAazB"} | ||
| {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../src/Chart.ts"],"names":[],"mappings":"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"} |
+1
-1
@@ -1,2 +0,2 @@ | ||
| Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@tradecanvas/commons`),t=require(`@tradecanvas/core`);function n(e){if(!e||typeof e.time!=`number`)return!1;let{open:t,high:n,low:r,close:i}=e;return!(!isFinite(t)||!isFinite(n)||!isFinite(r)||!isFinite(i)||t<0||n<0||r<0||i<0||n<r||e.volume!==void 0&&(!isFinite(e.volume)||e.volume<0))}function r(e){return{...e,high:Math.max(e.open,e.high,e.low,e.close),low:Math.min(e.open,e.high,e.low,e.close),volume:e.volume===void 0?0:Math.max(0,e.volume)}}var i=class{data=[];getData(){return this.data}setData(e){this.data=e.filter(n).map(r)}appendBar(e){n(e)&&this.data.push(r(e))}updateLastBar(e){if(!n(e))return;let t=r(e);if(this.data.length===0){this.data.push(t);return}this.data[this.data.length-1]=t}updateLastBarFromTick(t){this.data.length!==0&&(!isFinite(t.price)||t.price<0||t.volume!==void 0&&(!isFinite(t.volume)||t.volume<0)||(this.data[this.data.length-1]=(0,e.mergeBar)(this.data[this.data.length-1],t)))}getLength(){return this.data.length}clear(){this.data=[]}},a=class{theme;constructor(t){!t||t===`dark`?this.theme={...e.DARK_THEME}:t===`light`?this.theme={...e.LIGHT_THEME}:this.theme={...t}}getTheme(){return this.theme}setTheme(t){t===`dark`?this.theme={...e.DARK_THEME}:t===`light`?this.theme={...e.LIGHT_THEME}:this.theme={...t}}},o=200,s=80,c=class{panels=[];containerWidth=0;containerHeight=0;resize(e,t){this.containerWidth=e,this.containerHeight=t}addPanel(t,n=`bottom`,r){let i=n===`left`||n===`right`;this.panels.push({id:t,position:n,size:r??(i?o:e.DEFAULT_PANEL_HEIGHT),minSize:i?s:e.MIN_PANEL_HEIGHT,content:{type:`indicator`,indicatorInstanceId:t}})}removePanel(e){this.panels=this.panels.filter(t=>t.id!==e)}setPanelPosition(t,n){let r=this.panels.find(e=>e.id===t);if(r){let t=r.position===`left`||r.position===`right`,i=n===`left`||n===`right`;r.position=n,t!==i&&(r.size=i?o:e.DEFAULT_PANEL_HEIGHT,r.minSize=i?s:e.MIN_PANEL_HEIGHT)}}setPanelSize(e,t){let n=this.panels.find(t=>t.id===e);n&&(n.size=Math.max(n.minSize,t))}getPanels(){return this.panels}resolve(){let t=this.panels.filter(e=>e.position===`left`),n=this.panels.filter(e=>e.position===`right`),r=this.panels.filter(e=>e.position===`top`),i=this.panels.filter(e=>e.position===`bottom`),a=t.reduce((e,t)=>e+t.size,0),o=n.reduce((e,t)=>e+t.size,0),s=r.reduce((e,t)=>e+t.size,0),c=i.reduce((e,t)=>e+t.size,0),l={x:a,y:s,width:Math.max(0,this.containerWidth-a-o-e.PRICE_AXIS_WIDTH),height:Math.max(0,this.containerHeight-s-c-e.TIME_AXIS_HEIGHT)},u=[],d=[],f=0;for(let n of t)u.push({config:n,rect:{x:f,y:0,width:n.size,height:this.containerHeight-e.TIME_AXIS_HEIGHT}}),d.push({panelId:n.id,rect:{x:f+n.size-2,y:0,width:4,height:this.containerHeight},orientation:`vertical`}),f+=n.size;let p=0;for(let e of r)u.push({config:e,rect:{x:a,y:p,width:l.width,height:e.size}}),d.push({panelId:e.id,rect:{x:a,y:p+e.size-2,width:l.width,height:4},orientation:`horizontal`}),p+=e.size;p=l.y+l.height;for(let e of i)u.push({config:e,rect:{x:a,y:p,width:l.width,height:e.size}}),d.push({panelId:e.id,rect:{x:a,y:p-2,width:l.width,height:4},orientation:`horizontal`}),p+=e.size;f=a+l.width+e.PRICE_AXIS_WIDTH;for(let t of n)u.push({config:t,rect:{x:f,y:0,width:t.size,height:this.containerHeight-e.TIME_AXIS_HEIGHT}}),d.push({panelId:t.id,rect:{x:f-2,y:0,width:4,height:this.containerHeight},orientation:`vertical`}),f+=t.size;return{mainChartRect:l,panels:u,dividers:d}}getMainChartRect(){return this.resolve().mainChartRect}},l=class{constructor(e){this.indicatorEngine=e}registerIndicator(e){this.indicatorEngine.register(e)}},u=class{static version=`0.3.0`;engine;viewport;dataManager;themeManager;layoutManager;pluginManager;indicatorEngine;drawingManager;drawingRenderer;tradingManager;tradingRenderer;eventBus;streamManager=null;autoScrollOnNewBar=!0;displayDataCache=null;resolvedLayoutCache=null;panelInfoCache=null;renderScheduled=!1;containerSizeCache=null;containerSizeCacheTime=0;chartLegend;watermark;barCountdown;sessionBreaks;compareRenderer;countdownInterval=null;volumeRenderer;alertManager;replayManager;undoRedoManager;autoSaveTimer=null;autoSaveDelay=0;autoSaveKey=null;animator;crosshairTooltip;interactionManager;crosshairHandler;chartRenderer;gridRenderer;priceAxis;timeAxis;options;features;marketConfig=null;container;currentPriceLine;numberLocale;keyboardHandler=null;onWindowKeyDown=null;currentSymbol=``;constructor(n,r){this.container=n,this.options=r,this.numberLocale=r.numberLocale??`en-US`;let o=r.features??{};this.features={drawings:o.drawings??!0,drawingTools:o.drawingTools??[],drawingMagnet:o.drawingMagnet??!0,drawingUndoRedo:o.drawingUndoRedo??!0,trading:o.trading??!0,tradingContextMenu:o.tradingContextMenu??!0,indicators:o.indicators??!0,indicatorIds:o.indicatorIds??[],panning:o.panning??!0,zooming:o.zooming??!0,crosshair:o.crosshair??!0,keyboard:o.keyboard??!0,priceAxis:o.priceAxis??!0,timeAxis:o.timeAxis??!0,grid:o.grid??r.grid?.visible??!0,legend:o.legend??!0,volume:o.volume??!0,watermark:o.watermark??!0,saveLoad:o.saveLoad??!0,screenshot:o.screenshot??!0,alerts:o.alerts??!0,replay:o.replay??!0,sessionBreaks:o.sessionBreaks??!0,barCountdown:o.barCountdown??!0,compareSymbols:o.compareSymbols??!0,dataExport:o.dataExport??!0,logScale:o.logScale??!0,timeframes:o.timeframes??[],defaultTimeframeFavorites:o.defaultTimeframeFavorites??[]},n.style.position=`relative`,n.style.overflow=`hidden`,n.tabIndex=0,n.style.outline=`none`,this.dataManager=new i,this.themeManager=new a(r.theme),this.layoutManager=new c,this.indicatorEngine=new t.IndicatorEngine,this.pluginManager=new l(this.indicatorEngine),this.eventBus=new t.EventBus,(0,t.registerBuiltInIndicators)(this.indicatorEngine),this.drawingManager=new t.DrawingManager,(0,t.registerBuiltInDrawingTools)(this.drawingManager),this.drawingRenderer=new t.DrawingRenderer(this.drawingManager),this.drawingManager.setRequestRender(()=>{this.syncRenderContext(),this.engine.requestRender(e.LayerType.Overlay),this.scheduleAutoSave()}),this.drawingManager.setEventCallback((e,t)=>{this.eventBus.emit(e,t)}),this.undoRedoManager=new t.UndoRedoManager,this.drawingManager.setUndoRedoManager(this.undoRedoManager),this.drawingManager.setDataGetter(()=>this.dataManager.getData()),this.drawingManager.setDisplayDataGetter(()=>this.getDisplayData()),r.crosshair?.mode===`magnet`&&this.drawingManager.setMagnetMode(`magnet`),this.tradingManager=new t.TradingManager,this.tradingRenderer=new t.TradingRenderer(this.tradingManager),this.tradingManager.setContainer(n),this.tradingManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.tradingManager.setEventCallback((e,t)=>{this.eventBus.emit(e,t)}),this.engine=new t.RenderEngine(n);let s=this.engine.dprManager.getContainerSize();this.viewport=new t.Viewport(s.width,s.height,r.minBarSpacing??2,r.maxBarSpacing??30,r.rightMargin??5),this.layoutManager.resize(s.width,s.height),this.engine.onContainerResize=e=>{if(e.width<=0||e.height<=0)return;let t=this.viewport.isAtEnd();this.viewport.resize(e.width,e.height),this.layoutManager.resize(e.width,e.height),this.updateViewportAndRender(t)},this.chartRenderer=this.createChartRenderer(r.chartType),this.gridRenderer=new t.GridRenderer,r.grid?.visible===!1&&this.gridRenderer.setVisible(!1),this.priceAxis=new t.PriceAxis,this.priceAxis.setLocale(this.numberLocale),this.timeAxis=new t.TimeAxis,this.crosshairHandler=new t.CrosshairHandler,this.crosshairHandler.setLocale(this.numberLocale),r.crosshair?.mode&&this.crosshairHandler.setMode(r.crosshair.mode),this.crosshairHandler.setCallback((e,t)=>{if(e!==null&&t){let n=this.dataManager.getData(),r=e<n.length?n[e]:void 0;this.chartLegend.setHoverBar(r??null),r&&this.crosshairTooltip.show(t,r,this.themeManager.getTheme(),this.cachedContainerSize()),this.eventBus.emit(`crosshairMove`,{point:t,bar:r,barIndex:e})}else this.crosshairTooltip.hide(),this.chartLegend.setHoverBar(null)}),this.chartLegend=new t.ChartLegend,this.chartLegend.setChartType(r.chartType),this.watermark=new t.Watermark,r.watermark&&this.watermark.setConfig(r.watermark),this.volumeRenderer=new t.VolumeRenderer,this.barCountdown=new t.BarCountdown,this.sessionBreaks=new t.SessionBreaks,this.compareRenderer=new t.CompareRenderer,r.sessionBreaks?this.sessionBreaks.setConfig({visible:r.sessionBreaks.visible??!0,color:r.sessionBreaks.color,lineStyle:r.sessionBreaks.lineStyle,lineWidth:r.sessionBreaks.lineWidth}):r.features?.sessionBreaks!==!1&&this.sessionBreaks.setVisible(!0),r.logScale&&this.viewport.setLogScale(!0),this.animator=new t.Animator,this.crosshairTooltip=new t.CrosshairTooltip,this.crosshairTooltip.create(n),this.keyboardHandler=new t.KeyboardHandler({scrollBars:e=>{let t=this.viewport.getState().barWidth+this.viewport.getState().barSpacing;this.viewport.scrollBy(e*t),this.updateViewportAndRender()},zoom:e=>{let t=this.viewport.getState().chartRect.width;this.viewport.zoom(e,t/2),this.updateViewportAndRender()},goToStart:()=>{this.viewport.scrollBy(-1/0),this.updateViewportAndRender()},goToEnd:()=>{this.viewport.scrollToEnd(),this.updateViewportAndRender()},fitContent:()=>this.fitContent()}),this.keyboardHandler.setEnabled(this.features.keyboard),this.onWindowKeyDown=e=>{if(!this.keyboardHandler)return;let t=document.activeElement;t&&t!==this.container&&!this.container.contains(t)||t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.isContentEditable)||this.keyboardHandler.handleKey(e)&&e.preventDefault()},window.addEventListener(`keydown`,this.onWindowKeyDown),this.currentPriceLine=new t.CurrentPriceLine,this.alertManager=new t.AlertManager,this.alertManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.alertManager.on(`triggered`,e=>{this.eventBus.emit(`dataUpdate`,{alert:`triggered`,alertId:e.id,price:e.price,message:e.message})}),this.replayManager=new t.ReplayManager,this.interactionManager=new t.InteractionManager(n),this.features.panning&&this.interactionManager.setPanHandler(new t.PanHandler(e=>{this.viewport.scrollBy(e),this.updateViewportAndRender()})),this.features.zooming&&this.interactionManager.setZoomHandler(new t.ZoomHandler((e,t)=>{this.viewport.zoom(e,t),this.updateViewportAndRender()})),this.features.crosshair&&this.interactionManager.setCrosshairHandler(this.crosshairHandler),this.features.drawings&&this.interactionManager.setDrawingManager(this.drawingManager,()=>this.viewport.getState()),this.features.trading&&this.interactionManager.setTradingManager(this.tradingManager,()=>this.viewport.getState()),this.interactionManager.setOverlayDirtyCallback(()=>{this.engine.requestRender(e.LayerType.Overlay),this.layoutManager.getPanels().length>0&&this.engine.requestRender(e.LayerType.UI)}),this.interactionManager.attach(),this.syncRenderContext(),this.engine.start()}setData(e){this.dataManager.setData(e),this.crosshairHandler.setData(this.dataManager.getData()),this.displayDataCache=null,this.sessionBreaks.invalidateCache(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),e.length>0&&this.currentPriceLine.setPrice(e[e.length-1].close),this.updateViewportAndRender(!0),this.eventBus.emit(`dataUpdate`,{length:e.length})}appendBar(e){this.dataManager.appendBar(e),this.crosshairHandler.setData(this.dataManager.getData()),this.displayDataCache=null,this.autoScrollOnNewBar&&this.viewport.scrollToEnd(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.updateViewportAndRender()}appendBars(e){if(e.length!==0){for(let t of e)this.dataManager.appendBar(t);this.displayDataCache=null,this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.crosshairHandler.setData(this.dataManager.getData()),this.updateViewportAndRender(this.viewport.isAtEnd())}}updateLastBar(e){this.dataManager.updateLastBar(e),this.currentPriceLine.setPrice(e.close),this.options.chartType!==`candlestick`&&this.options.chartType!==`line`&&this.options.chartType!==`area`&&this.options.chartType!==`bar`&&this.options.chartType!==`hollowCandle`&&(this.displayDataCache=null),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.scheduleRender()}updateLastBarFromTick(e){this.dataManager.updateLastBarFromTick(e),this.currentPriceLine.setPrice(e.price),this.options.chartType!==`candlestick`&&this.options.chartType!==`line`&&this.options.chartType!==`area`&&this.options.chartType!==`bar`&&this.options.chartType!==`hollowCandle`&&(this.displayDataCache=null),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.scheduleRender()}setChartType(e){this.options.chartType=e,this.chartRenderer=this.createChartRenderer(e),this.chartLegend.setChartType(e),this.displayDataCache=null,this.updateViewportAndRender(!0)}addIndicator(e,t={},n=`bottom`){if(!this.features.indicators||this.features.indicatorIds.length>0&&!this.features.indicatorIds.includes(e))return null;let r=this.indicatorEngine.addIndicator(e,t,this.dataManager.getData());return this.indicatorEngine.getAvailableIndicators().find(t=>t.id===e)?.placement===`panel`?(this.layoutManager.addPanel(r,n),this.updateViewportAndRender()):this.engine.requestRender(),this.eventBus.emit(`indicatorAdd`,{instanceId:r,id:e}),r}updateIndicator(e,t){this.indicatorEngine.updateIndicator(e,t,this.dataManager.getData()),this.engine.requestRender()}removeIndicator(e){let t=this.layoutManager.getPanels().some(t=>t.id===e);this.indicatorEngine.removeIndicator(e),this.layoutManager.removePanel(e),this.eventBus.emit(`indicatorRemove`,{instanceId:e}),t?this.updateViewportAndRender():this.engine.requestRender()}getIndicatorOutput(e){return this.indicatorEngine.getOutput(e)}registerIndicator(e){this.pluginManager.registerIndicator(e)}static indicators(){let e=new t.IndicatorEngine;return(0,t.registerBuiltInIndicators)(e),e.getAvailableIndicators()}setPanelPosition(e,t){this.layoutManager.setPanelPosition(e,t),this.engine.requestRender()}setPanelSize(e,t){this.layoutManager.setPanelSize(e,t),this.engine.requestRender()}setDrawingTool(e){this.features.drawings&&(e&&this.features.drawingTools.length>0&&!this.features.drawingTools.includes(e)||this.drawingManager.setActiveTool(e))}getDrawingTool(){return this.drawingManager.getActiveTool()}setDrawingStyle(e){this.drawingManager.setStyle(e)}getDrawings(){return this.drawingManager.getDrawings()}setDrawings(e){this.drawingManager.setDrawings(e)}removeDrawing(e){this.drawingManager.removeDrawing(e)}clearDrawings(){this.drawingManager.clearDrawings()}registerDrawingTool(e){this.drawingManager.register(e)}undo(){return this.features.drawingUndoRedo?this.drawingManager.undo():!1}redo(){return this.features.drawingUndoRedo?this.drawingManager.redo():!1}getUndoRedoState(){return this.undoRedoManager.getState()}setDrawingMagnet(e){this.drawingManager.setMagnetMode(e?`magnet`:`none`)}getDrawingMagnet(){return this.drawingManager.getMagnetMode()===`magnet`}lockAllDrawings(){this.drawingManager.lockAllDrawings()}unlockAllDrawings(){this.drawingManager.unlockAllDrawings()}hideAllDrawings(){this.drawingManager.hideAllDrawings()}showAllDrawings(){this.drawingManager.showAllDrawings()}duplicateDrawing(e){let t=e??this.drawingManager.getSelectedDrawingId();return t?this.drawingManager.duplicateDrawing(t):null}exportVisibleData(e=`csv`,n){let r=this.viewport.getState(),i=this.dataManager.getData(),a=Math.max(0,r.visibleRange.from),o=Math.min(i.length-1,r.visibleRange.to),s=i.slice(a,o+1);if(e===`json`){let e=t.DataExporter.toJSON(s);t.DataExporter.download(e,n??`chart-data.json`,`application/json`)}else{let e=t.DataExporter.toCSV(s);t.DataExporter.download(e,n??`chart-data.csv`,`text/csv`)}}exportAllData(e=`csv`,n){let r=this.dataManager.getData();if(e===`json`){let e=t.DataExporter.toJSON(r);t.DataExporter.download(e,n??`chart-data.json`,`application/json`)}else{let e=t.DataExporter.toCSV(r);t.DataExporter.download(e,n??`chart-data.csv`,`text/csv`)}}setAutoSave(e,t=5e3){this.autoSaveKey=e,this.autoSaveDelay=t}disableAutoSave(){this.autoSaveDelay=0,this.autoSaveKey=null,this.autoSaveTimer&&=(clearTimeout(this.autoSaveTimer),null)}scheduleAutoSave(){this.autoSaveDelay<=0||!this.autoSaveKey||(this.autoSaveTimer&&clearTimeout(this.autoSaveTimer),this.autoSaveTimer=setTimeout(()=>{this.autoSaveTimer=null,this.autoSaveKey&&this.saveState(this.autoSaveKey)},this.autoSaveDelay))}getAvailableIndicators(){return this.indicatorEngine.getAvailableIndicators()}getIndicatorInputs(e){let t=this.indicatorEngine.getAvailableIndicators().find(t=>t.id===e);return t?{id:t.id,params:t.defaultConfig}:null}getActiveIndicators(){return this.indicatorEngine.getActiveIndicators()}getIndicatorConfig(e){let t=this.indicatorEngine.getIndicatorConfig(e);return t?{id:t.id,params:{...t.params}}:null}updateIndicatorStyle(e,t){this.indicatorEngine.updateIndicatorStyle(e,t),this.engine.requestRender()}setOrders(e){this.features.trading&&this.tradingManager.setOrders(e)}setPositions(e){this.features.trading&&this.tradingManager.setPositions(e)}setDepthData(e){this.features.trading&&this.tradingManager.setDepthData(e)}setCurrentPrice(e,t){this.tradingManager.setCurrentPrice(e),this.currentPriceLine.setPrice(e),this.scheduleRender(),this.features.alerts&&this.alertManager.checkPrice(e)}setTradingConfig(e){this.features.trading&&this.tradingManager.setConfig(e)}async connect(n){this.disconnectStream(),this.streamManager=new t.StreamManager,this.streamManager.on(`snapshot`,e=>{this.setData(e)}),this.streamManager.on(`barClose`,e=>{this.dataManager.appendBar(e),this.crosshairHandler.setData(this.dataManager.getData()),this.autoScrollOnNewBar&&this.viewport.scrollToEnd(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.updateViewportAndRender()}),this.streamManager.on(`barUpdate`,e=>{this.dataManager.updateLastBar(e),this.currentPriceLine.setPrice(e.close),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.scheduleRender()}),this.streamManager.on(`priceChange`,({price:t})=>{this.tradingManager.setCurrentPrice(t),this.currentPriceLine.setPrice(t),this.engine.requestRender(e.LayerType.Overlay),this.engine.requestRender(e.LayerType.UI)}),this.streamManager.on(`connectionChange`,e=>{this.eventBus.emit(`dataUpdate`,{connection:e})}),this.streamManager.on(`error`,e=>{this.eventBus.emit(`dataUpdate`,{error:e.message})}),this.autoScrollOnNewBar=n.autoScroll!==!1,this.currentSymbol=n.symbol,await this.streamManager.connect(n);let r=this.timeframeToMs(n.timeframe);this.barCountdown.setTimeframeMs(r),this.countdownInterval&&clearInterval(this.countdownInterval),this.countdownInterval=setInterval(()=>{this.barCountdown.isVisible()&&this.engine.requestRender(e.LayerType.UI)},1e3)}async switchStream(e,t){this.streamManager&&(this.currentSymbol=e,await this.streamManager.switchTo(e,t))}async setTimeframe(e){if(!this.streamManager)throw Error(`No active stream. Call connect() first.`);await this.switchStream(this.currentSymbol,e)}disconnectStream(){this.streamManager&&=(this.streamManager.dispose(),null)}setBarCountdownVisible(t){this.barCountdown.setVisible(t),this.engine.requestRender(e.LayerType.UI)}setSessionBreaksVisible(t){this.sessionBreaks.setVisible(t),this.engine.requestRender(e.LayerType.Background)}addCompareSymbol(t,n,r,i){this.compareRenderer.addSymbol({id:t,label:n,data:r,color:i,visible:!0}),this.engine.requestRender(e.LayerType.Main)}removeCompareSymbol(t){this.compareRenderer.removeSymbol(t),this.engine.requestRender(e.LayerType.Main)}updateCompareData(t,n){this.compareRenderer.setSymbolData(t,n),this.engine.requestRender(e.LayerType.Main)}setCompareMode(t){this.compareRenderer.setMode(t),this.engine.requestRender(e.LayerType.Main)}clearCompareSymbols(){this.compareRenderer.clear(),this.engine.requestRender(e.LayerType.Main)}setLogScale(e){this.viewport.setLogScale(e),this.updateViewportAndRender()}isLogScale(){return this.viewport.isLogScale()}setSessionBreaksConfig(t){this.sessionBreaks.setConfig(t),this.engine.requestRender(e.LayerType.Background)}getConnectionState(){return this.streamManager?.getConnectionState()??`disconnected`}getConnectionInfo(){return this.streamManager?.getConnectionInfo()??{state:`disconnected`}}setAutoScroll(e){this.autoScrollOnNewBar=e}scrollTo(e){let t=this.dataManager.getData();for(let n=0;n<t.length;n++)if(t[n].time>=e){let e=this.viewport.getState().barWidth+this.viewport.getState().barSpacing;this.viewport.scrollBy(n*e-this.viewport.getState().offset),this.updateViewportAndRender();return}}scrollToEnd(){this.viewport.scrollToEnd(),this.updateViewportAndRender()}setVisibleRange(e,t){let n=this.dataManager.getData(),r=0,i=n.length-1;for(let t=0;t<n.length;t++)if(n[t].time>=e){r=t;break}for(let e=n.length-1;e>=0;e--)if(n[e].time<=t){i=e;break}let a=i-r+1;if(a>0){let e=this.viewport.getState().chartRect.width,t=e/a,n=Math.max(2,t-this.viewport.getState().barSpacing);this.viewport.zoom((n-this.viewport.getState().barWidth)/this.viewport.getState().barWidth,e/2)}this.updateViewportAndRender()}zoomIn(){let e=this.viewport.getState().chartRect.width;this.viewport.zoom(.2,e/2),this.updateViewportAndRender()}zoomOut(){let e=this.viewport.getState().chartRect.width;this.viewport.zoom(-.2,e/2),this.updateViewportAndRender()}fitContent(){let e=this.dataManager.getData();e.length!==0&&this.setVisibleRange(e[0].time,e[e.length-1].time)}on(e,t){this.eventBus.on(e,t)}off(e,t){this.eventBus.off(e,t)}enableTauriBridge(e){this.eventBus.enableTauriBridge({enabled:!0,...e})}disableTauriBridge(){this.eventBus.disableTauriBridge()}setTheme(e){this.themeManager.setTheme(e),this.syncRenderContext(),this.container.style.backgroundColor=this.themeManager.getTheme().background,this.engine.requestRender(),this.eventBus.emit(`themeChange`,{theme:e})}getTheme(){return this.themeManager.getTheme()}setWatermark(t,n){this.watermark.setConfig({text:t,...n}),this.engine.requestRender(e.LayerType.Background)}setAutoScale(e){this.options.autoScale=e,this.updateViewportAndRender()}isAutoScale(){return this.options.autoScale!==!1}setCrosshairMode(t){this.crosshairHandler.setMode(t),this.engine.requestRender(e.LayerType.Overlay)}getCrosshairMode(){return this.crosshairHandler.getMode()}setGridVisible(t){this.gridRenderer.setVisible(t),this.engine.requestRender(e.LayerType.Background)}isGridVisible(){return this.gridRenderer.isVisible()}setVolumeVisible(t){this.volumeRenderer.setVisible(t),this.engine.requestRender(e.LayerType.Main)}setTooltipVisible(e){e||this.crosshairTooltip.hide()}setLegend(t){this.chartLegend.setConfig(t),this.engine.requestRender(e.LayerType.UI)}setSymbolName(t){this.chartLegend.setSymbol(t),this.engine.requestRender(e.LayerType.UI)}setStatusText(t){this.chartLegend.setStatusText(t),this.engine.requestRender(e.LayerType.UI)}screenshot(e){this.features.screenshot&&t.Screenshot.download(this.container,e,this.themeManager.getTheme().background)}screenshotDataURL(){return this.features.screenshot?t.Screenshot.toDataURL(this.container,this.themeManager.getTheme().background):null}async screenshotBlob(){return this.features.screenshot?t.Screenshot.toBlob(this.container,this.themeManager.getTheme().background):null}addAlert(e,t=`crossing`,n){if(!this.features.alerts)return null;let r=this.alertManager.addAlert(e,t,n);return this.scheduleAutoSave(),r}removeAlert(e){this.alertManager.removeAlert(e),this.scheduleAutoSave()}getAlerts(){return this.alertManager.getAlerts()}clearAlerts(){this.alertManager.clearAlerts(),this.scheduleAutoSave()}saveAlerts(e){this.alertManager.saveToStorage(e)}loadAlerts(t){this.alertManager.loadFromStorage(t),this.engine.requestRender(e.LayerType.Overlay)}replay(e){if(!this.features.replay)return;let t=this.dataManager.getData();this.replayManager.load(t),this.replayManager.on(`bar`,({bar:e,index:n})=>{let r=t.slice(0,n+1);this.dataManager.setData(r),this.crosshairHandler.setData(r),this.indicatorEngine.recalculateAll(r),this.updateViewportAndRender()}),this.replayManager.play(e)}replayPause(){this.replayManager.pause()}replayResume(){this.replayManager.resume()}replayStop(){this.replayManager.stop()}replaySeek(e){this.replayManager.seekTo(e)}setReplaySpeed(e){this.replayManager.setSpeed(e)}getReplayState(){return this.replayManager.getState()}getReplayProgress(){return this.replayManager.getProgress()}saveState(e){if(!this.features.saveLoad)return null;let n=t.ChartStateManager.capture({getDrawings:()=>this.getDrawings(),getTheme:()=>this.getTheme(),getAlerts:()=>this.getAlerts()},{chartType:this.options.chartType}),r=t.ChartStateManager.serialize(n);return e&&t.ChartStateManager.saveToStorage(e,n),r}loadState(e){if(!this.features.saveLoad)return;let n=t.ChartStateManager.deserialize(e);if(n.chartType&&this.setChartType(n.chartType),n.drawings&&this.setDrawings(n.drawings),n.theme&&this.setTheme(n.theme),n.alerts){this.clearAlerts();for(let e of n.alerts)this.addAlert(e.price,e.condition,e.message)}}loadStateFromStorage(e){if(!this.features.saveLoad)return!1;let n=t.ChartStateManager.loadFromStorage(e);return n?(this.loadState(t.ChartStateManager.serialize(n)),!0):!1}downloadState(e){if(!this.features.saveLoad)return;let n=t.ChartStateManager.capture({getDrawings:()=>this.getDrawings(),getTheme:()=>this.getTheme(),getAlerts:()=>this.getAlerts()},{chartType:this.options.chartType});t.ChartStateManager.downloadFile(n,e)}async loadStateFromFile(){if(!this.features.saveLoad)return;let e=await t.ChartStateManager.loadFromFile();this.loadState(t.ChartStateManager.serialize(e))}setLocale(t){(0,e.setLocale)(t),this.engine.requestRender()}setNumberLocale(e){this.numberLocale=e,this.priceAxis.setLocale(e),this.crosshairHandler.setLocale(e),this.syncRenderContext(),this.engine.requestRender()}getNumberLocale(){return this.numberLocale}setMarket(e){if(this.marketConfig=e,e.colorScheme){let t={...this.themeManager.getTheme(),candleUp:e.colorScheme.up,candleDown:e.colorScheme.down,candleUpWick:e.colorScheme.up,candleDownWick:e.colorScheme.down,volumeUp:e.colorScheme.up.replace(`)`,`, 0.3)`).replace(`rgb(`,`rgba(`)||`${e.colorScheme.up}4D`,volumeDown:e.colorScheme.down.replace(`)`,`, 0.3)`).replace(`rgb(`,`rgba(`)||`${e.colorScheme.down}4D`};this.themeManager.setTheme(t)}e.pricePrecision!==void 0&&(this.tradingManager.setConfig({pricePrecision:e.pricePrecision}),this.alertManager.setPricePrecision(e.pricePrecision),this.streamManager?.priceLine.setPricePrecision(e.pricePrecision),this.crosshairHandler.setPricePrecision(e.pricePrecision)),this.syncRenderContext(),this.engine.requestRender()}getMarket(){return this.marketConfig}setPriceLimits(t){this.marketConfig&&((0,e.computePriceLimits)(t,this.marketConfig)&&(this.marketConfig.priceLimits={...this.marketConfig.priceLimits,referencePrice:t}),this.engine.requestRender())}getFeatures(){return this.features}setFeatures(t){Object.assign(this.features,t),t.crosshair===!1&&this.crosshairTooltip.hide(),t.grid!==void 0&&this.engine.requestRender(e.LayerType.Background),t.volume!==void 0&&(this.volumeRenderer.setVisible(t.volume),this.engine.requestRender(e.LayerType.Main)),t.drawings===!1&&this.drawingManager.setActiveTool(null),t.trading===!1&&(this.tradingManager.setOrders([]),this.tradingManager.setPositions([])),t.keyboard!==void 0&&this.keyboardHandler?.setEnabled(t.keyboard),this.engine.requestRender()}resize(){let e=this.engine.dprManager.readContainerSize();if(e.width<=0||e.height<=0)return;this.containerSizeCache=e,this.containerSizeCacheTime=Date.now();let t=this.engine.dprManager.getDpr();this.engine.layerManager.resize(e,t);let n=this.viewport.isAtEnd();this.viewport.resize(e.width,e.height),this.layoutManager.resize(e.width,e.height),this.updateViewportAndRender(n),this.eventBus.emit(`resize`,e)}destroy(){this.countdownInterval&&clearInterval(this.countdownInterval),this.disableAutoSave(),this.disconnectStream(),this.onWindowKeyDown&&=(window.removeEventListener(`keydown`,this.onWindowKeyDown),null),this.keyboardHandler=null,this.interactionManager.detach(),this.tradingManager.destroy(),this.animator.dispose(),this.crosshairTooltip.destroy(),this.replayManager.dispose(),this.undoRedoManager.clear(),this.engine.destroy(),this.eventBus.destroy(),this.container.innerHTML=``}createChartRenderer(e){switch(e){case`candlestick`:return new t.CandlestickRenderer;case`heikinAshi`:return new t.CandlestickRenderer;case`line`:return new t.LineRenderer;case`area`:return new t.AreaRenderer;case`bar`:return new t.BarRenderer;case`hollowCandle`:return new t.HollowCandleRenderer;case`baseline`:return new t.BaselineRenderer;case`renko`:return new t.RenkoRenderer;case`lineBreak`:return new t.CandlestickRenderer;case`kagi`:return new t.KagiRenderer;case`pointAndFigure`:return new t.PointAndFigureRenderer;default:return new t.CandlestickRenderer}}getDisplayData(){if(this.displayDataCache)return this.displayDataCache;let e=this.dataManager.getData();if(e.length===0)return e;let n;switch(this.options.chartType){case`heikinAshi`:n=(0,t.toHeikinAshi)(e);break;case`renko`:n=(0,t.toRenko)(e,{brickSize:0,useATR:!0,atrPeriod:14});break;case`lineBreak`:n=(0,t.toLineBreak)(e,3);break;case`kagi`:n=(0,t.toKagi)(e,4);break;case`pointAndFigure`:n=(0,t.toPointAndFigure)(e,e.reduce((e,t)=>e+t.close,0)/e.length*.01,3);break;default:n=e}return this.displayDataCache=n,n}scheduleRender(){this.renderScheduled||(this.renderScheduled=!0,requestAnimationFrame(()=>{this.renderScheduled=!1;let e=this.getDisplayData();this.viewport.updateData(e,this.options.autoScale!==!1),this.syncRenderContext(),this.engine.requestRender()}))}updateViewportAndRender(e=!1){this.resolvedLayoutCache=null,this.panelInfoCache=null;let t=this.getResolvedLayout();this.viewport.setChartRect(t.mainChartRect);let n=this.getDisplayData();if(this.viewport.updateData(n,this.options.autoScale!==!1),this.options.autoScale!==!1){let e=this.viewport.getState(),t=this.indicatorEngine.getOverlayPriceRange(e.visibleRange.from,Math.min(e.visibleRange.to,n.length-1));if(t){let n=e.priceRange,r=Math.min(n.min,t.min),i=Math.max(n.max,t.max);if(r<n.min||i>n.max){let e=i-r||1;this.viewport.setPriceRange(r-e*.02,i+e*.02)}}}e&&this.viewport.scrollToEnd(),this.syncRenderContext(),this.engine.requestRender()}getResolvedLayout(){return this.resolvedLayoutCache||=this.layoutManager.resolve(),this.resolvedLayoutCache}cachedContainerSize(){let e=Date.now();return(!this.containerSizeCache||e-this.containerSizeCacheTime>500)&&(this.containerSizeCache=this.engine.dprManager.getContainerSize(),this.containerSizeCacheTime=e),this.containerSizeCache}buildPanelRenderInfos(){if(this.panelInfoCache)return this.panelInfoCache;let e=this.getResolvedLayout(),t=this.viewport.getState(),n=e.panels.map(e=>{let n=this.indicatorEngine.getOutput(e.config.id),r=0,i=100;if(n){let e=1/0,a=-1/0,{from:o,to:s}=t.visibleRange,c=0;for(let[,t]of n.values){if(c>=o&&c<=s)for(let n in t){let r=t[n];r!==void 0&&(r<e&&(e=r),r>a&&(a=r))}c++}if(e!==1/0){let t=a-e||1;r=e-t*.1,i=a+t*.1}}let a={x:e.rect.x,y:e.rect.y+20,width:e.rect.width,height:Math.max(0,e.rect.height-20)};return{instanceId:e.config.id,rect:e.rect,viewport:{...t,chartRect:a,priceRange:{min:r,max:i}}}});return this.panelInfoCache=n,n}syncRenderContext(){let e=this.getResolvedLayout(),t=this.features.indicators?this.buildPanelRenderInfos():[],n=e.panels.filter(e=>e.config.position===`bottom`).reduce((e,t)=>e+t.rect.height,0),r=e.mainChartRect.y+e.mainChartRect.height+n;this.engine.setRenderContext({chartRenderer:this.chartRenderer,gridRenderer:this.features.grid?this.gridRenderer:null,priceAxis:this.features.priceAxis?this.priceAxis:null,timeAxis:this.features.timeAxis?this.timeAxis:null,crosshairHandler:this.features.crosshair?this.crosshairHandler:null,indicatorEngine:this.features.indicators?this.indicatorEngine:null,drawingRenderer:this.features.drawings?this.drawingRenderer:null,tradingRenderer:this.features.trading?this.tradingRenderer:null,currentPriceLine:this.streamManager?.priceLine??this.currentPriceLine,chartLegend:this.features.legend?this.chartLegend:null,volumeRenderer:this.features.volume?this.volumeRenderer:null,watermark:this.features.watermark?this.watermark:null,barCountdown:this.barCountdown,sessionBreaks:this.sessionBreaks,compareRenderer:this.compareRenderer,panels:t,priceLimits:this.buildPriceLimits(),timeAxisY:r,viewport:this.viewport.getState(),theme:this.themeManager.getTheme(),data:this.getDisplayData(),numberLocale:this.numberLocale})}timeframeToMs(e){let t=e.match(/^(\d+)([smhdwMy])$/);if(!t)return 0;let n=parseInt(t[1],10);switch(t[2]){case`s`:return n*1e3;case`m`:return n*6e4;case`h`:return n*36e5;case`d`:return n*864e5;case`w`:return n*6048e5;case`M`:return n*2592e6;default:return 0}}buildPriceLimits(){if(!this.marketConfig?.priceLimits?.enabled||!this.marketConfig.priceLimits.referencePrice)return null;let t=(0,e.computePriceLimits)(this.marketConfig.priceLimits.referencePrice,this.marketConfig);return t?{...t,colors:this.marketConfig.colorScheme?{ceiling:this.marketConfig.colorScheme.ceiling,floor:this.marketConfig.colorScheme.floor,reference:this.marketConfig.colorScheme.reference}:void 0}:null}},d=class extends t.BaseFinanceChart{options;constructor(e,t){super(e,t.theme),this.options=t,this.requestRender()}renderChart(e,n,r,i){(0,t.renderSparkline)(e,n,r,this.options,i)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}},f=class extends t.BaseFinanceChart{options;crosshair=null;constructor(e,n){super(e,n.theme),this.options=n,n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,n,r,i){let a=this.crosshair?.getPosition()??null;(0,t.renderDepthChart)(e,n,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},p=class extends t.BaseFinanceChart{options;crosshair=null;constructor(e,n){super(e,n.theme),this.options=n,n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,n,r,i){let a=this.crosshair?.getPosition()??null;(0,t.renderEquityCurve)(e,n,r,this.options,i,a)}update(e,t){this.options={...this.options,data:e},t!==void 0&&(this.options={...this.options,benchmark:t}),this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},m=class extends t.BaseFinanceChart{options;crosshair=null;cachedRects=[];currentData=[];lastLayoutWidth=0;lastLayoutHeight=0;handleClick=null;constructor(e,n){super(e,n.theme),this.options=n,this.currentData=n.data??[],n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),n.onCellClick&&(this.handleClick=e=>{let t=this.canvas.getBoundingClientRect(),n=e.clientX-t.left,r=e.clientY-t.top;this.onCanvasClick(n,r)},this.canvas.addEventListener(`click`,this.handleClick)),this.recomputeLayout(),this.requestRender()}recomputeLayout(){let e={x:0,y:0,width:this.width,height:this.height},n=this.options.cellPadding??2;this.lastLayoutWidth=this.width,this.lastLayoutHeight=this.height,this.options.weighted?this.cachedRects=(0,t.layoutSquarifiedTreemap)(this.currentData.map(e=>({id:e.id,weight:e.weight??(Math.abs(e.value)||1)})),e,n):this.cachedRects=(0,t.layoutUniformGrid)(this.currentData.map(e=>({id:e.id})),e,n)}onCanvasClick(e,t){if(this.options.onCellClick)for(let n of this.cachedRects){let r=n.rect;if(e>=r.x&&e<=r.x+r.width&&t>=r.y&&t<=r.y+r.height){let e=this.currentData.find(e=>e.id===n.id);e&&this.options.onCellClick(e);return}}}renderChart(e,n,r,i){(n!==this.lastLayoutWidth||r!==this.lastLayoutHeight)&&this.recomputeLayout();let a=this.crosshair?.getPosition()??null;(0,t.renderHeatmap)(e,n,r,this.currentData,this.cachedRects,this.options,i,a)}update(e){this.currentData=e,this.options={...this.options,data:e},this.recomputeLayout(),this.requestRender()}setOptions(e){this.options={...this.options,...e},e.data&&(this.currentData=e.data),this.recomputeLayout(),this.requestRender()}destroy(){this.crosshair?.destroy(),this.handleClick&&this.canvas.removeEventListener(`click`,this.handleClick),super.destroy()}},h=class extends t.BaseFinanceChart{options;crosshair=null;constructor(e,n){super(e,n.theme),this.options=n,n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,n,r,i){let a=this.crosshair?.getPosition()??null;(0,t.renderWaterfall)(e,n,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},g=500;function _(e){let t=1-e;return 1-t*t*t}var v=class extends t.BaseFinanceChart{options;currentValue;targetValue;animationStart=null;animationFrom=0;animationFrameId=null;constructor(e,t){super(e,t.theme),this.options=t,this.currentValue=t.value,this.targetValue=t.value,this.requestRender()}renderChart(e,n,r,i){(0,t.renderGauge)(e,n,r,this.options,i,this.currentValue)}setValue(e){if(this.options.animate===!1){this.cancelAnimation(),this.currentValue=e,this.targetValue=e,this.options={...this.options,value:e},this.requestRender();return}this.targetValue=e,this.animationFrom=this.currentValue,this.animationStart=performance.now(),this.options={...this.options,value:e},this.startAnimationLoop()}setOptions(e){let t={...this.options,...e};if(e.value!==void 0&&e.value!==this.targetValue){this.options=t,this.setValue(e.value);return}this.options=t,this.requestRender()}startAnimationLoop(){if(this.animationFrameId!==null)return;let e=()=>{if(this.animationFrameId=null,this.animationStart===null)return;let t=this.options.animationDuration??g,n=performance.now()-this.animationStart,r=Math.min(1,n/Math.max(1,t)),i=_(r);this.currentValue=this.animationFrom+(this.targetValue-this.animationFrom)*i,this.requestRender(),r<1?this.animationFrameId=requestAnimationFrame(e):(this.currentValue=this.targetValue,this.animationStart=null)};this.animationFrameId=requestAnimationFrame(e)}cancelAnimation(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStart=null}destroy(){this.cancelAnimation(),super.destroy()}};Object.defineProperty(exports,`AlertManager`,{enumerable:!0,get:function(){return t.AlertManager}}),Object.defineProperty(exports,`Animator`,{enumerable:!0,get:function(){return t.Animator}}),Object.defineProperty(exports,`BarCountdown`,{enumerable:!0,get:function(){return t.BarCountdown}}),Object.defineProperty(exports,`BinanceAdapter`,{enumerable:!0,get:function(){return t.BinanceAdapter}}),exports.Chart=u,Object.defineProperty(exports,`ChartLegend`,{enumerable:!0,get:function(){return t.ChartLegend}}),Object.defineProperty(exports,`ChartStateManager`,{enumerable:!0,get:function(){return t.ChartStateManager}}),Object.defineProperty(exports,`CompareRenderer`,{enumerable:!0,get:function(){return t.CompareRenderer}}),Object.defineProperty(exports,`CrosshairTooltip`,{enumerable:!0,get:function(){return t.CrosshairTooltip}}),Object.defineProperty(exports,`CurrentPriceLine`,{enumerable:!0,get:function(){return t.CurrentPriceLine}}),Object.defineProperty(exports,`DARK_TERMINAL`,{enumerable:!0,get:function(){return e.DARK_TERMINAL}}),Object.defineProperty(exports,`DARK_THEME`,{enumerable:!0,get:function(){return e.DARK_THEME}}),Object.defineProperty(exports,`DEFAULT_DRAWING_STYLE`,{enumerable:!0,get:function(){return e.DEFAULT_DRAWING_STYLE}}),Object.defineProperty(exports,`DEFAULT_LEGEND_CONFIG`,{enumerable:!0,get:function(){return t.DEFAULT_LEGEND_CONFIG}}),Object.defineProperty(exports,`DEFAULT_RECONNECT`,{enumerable:!0,get:function(){return e.DEFAULT_RECONNECT}}),Object.defineProperty(exports,`DEFAULT_STREAM_CONFIG`,{enumerable:!0,get:function(){return e.DEFAULT_STREAM_CONFIG}}),Object.defineProperty(exports,`DEFAULT_TIMEFRAME_FAVORITES`,{enumerable:!0,get:function(){return e.DEFAULT_TIMEFRAME_FAVORITES}}),Object.defineProperty(exports,`DEFAULT_TRADING_CONFIG`,{enumerable:!0,get:function(){return e.DEFAULT_TRADING_CONFIG}}),Object.defineProperty(exports,`DataExporter`,{enumerable:!0,get:function(){return t.DataExporter}}),exports.DataManager=i,exports.DepthChart=f,Object.defineProperty(exports,`DrawingBase`,{enumerable:!0,get:function(){return t.DrawingBase}}),Object.defineProperty(exports,`Easing`,{enumerable:!0,get:function(){return t.Easing}}),exports.EquityCurveChart=p,exports.GaugeChart=v,exports.HeatmapChart=m,Object.defineProperty(exports,`IndicatorBase`,{enumerable:!0,get:function(){return t.IndicatorBase}}),Object.defineProperty(exports,`KeyboardHandler`,{enumerable:!0,get:function(){return t.KeyboardHandler}}),Object.defineProperty(exports,`LIGHT_THEME`,{enumerable:!0,get:function(){return e.LIGHT_THEME}}),exports.LayoutManager=c,Object.defineProperty(exports,`MARKET_CRYPTO`,{enumerable:!0,get:function(){return e.MARKET_CRYPTO}}),Object.defineProperty(exports,`MARKET_HNX`,{enumerable:!0,get:function(){return e.MARKET_HNX}}),Object.defineProperty(exports,`MARKET_HOSE`,{enumerable:!0,get:function(){return e.MARKET_HOSE}}),Object.defineProperty(exports,`MARKET_NYSE`,{enumerable:!0,get:function(){return e.MARKET_NYSE}}),Object.defineProperty(exports,`MARKET_UPCOM`,{enumerable:!0,get:function(){return e.MARKET_UPCOM}}),Object.defineProperty(exports,`MockAdapter`,{enumerable:!0,get:function(){return t.MockAdapter}}),exports.PluginManager=l,Object.defineProperty(exports,`ReplayManager`,{enumerable:!0,get:function(){return t.ReplayManager}}),Object.defineProperty(exports,`Screenshot`,{enumerable:!0,get:function(){return t.Screenshot}}),Object.defineProperty(exports,`SessionBreaks`,{enumerable:!0,get:function(){return t.SessionBreaks}}),exports.SparklineChart=d,Object.defineProperty(exports,`StreamManager`,{enumerable:!0,get:function(){return t.StreamManager}}),Object.defineProperty(exports,`TIMEFRAMES_CRYPTO`,{enumerable:!0,get:function(){return e.TIMEFRAMES_CRYPTO}}),Object.defineProperty(exports,`TIMEFRAMES_FOREX`,{enumerable:!0,get:function(){return e.TIMEFRAMES_FOREX}}),Object.defineProperty(exports,`TIMEFRAMES_STOCK`,{enumerable:!0,get:function(){return e.TIMEFRAMES_STOCK}}),exports.ThemeManager=a,Object.defineProperty(exports,`TickAggregator`,{enumerable:!0,get:function(){return t.TickAggregator}}),Object.defineProperty(exports,`UndoRedoManager`,{enumerable:!0,get:function(){return t.UndoRedoManager}}),Object.defineProperty(exports,`VN_COLORS`,{enumerable:!0,get:function(){return e.VN_COLORS}}),Object.defineProperty(exports,`VolumeRenderer`,{enumerable:!0,get:function(){return t.VolumeRenderer}}),exports.WaterfallChart=h,Object.defineProperty(exports,`Watermark`,{enumerable:!0,get:function(){return t.Watermark}}),Object.defineProperty(exports,`computePriceLimits`,{enumerable:!0,get:function(){return e.computePriceLimits}}),Object.defineProperty(exports,`createVNTheme`,{enumerable:!0,get:function(){return e.createVNTheme}}),Object.defineProperty(exports,`formatNumber`,{enumerable:!0,get:function(){return e.formatNumber}}),Object.defineProperty(exports,`formatVND`,{enumerable:!0,get:function(){return e.formatVND}}),Object.defineProperty(exports,`formatVolumeLoc`,{enumerable:!0,get:function(){return e.formatVolumeLoc}}),Object.defineProperty(exports,`getCurrentSession`,{enumerable:!0,get:function(){return e.getCurrentSession}}),Object.defineProperty(exports,`getLocale`,{enumerable:!0,get:function(){return e.getLocale}}),Object.defineProperty(exports,`normalizeBar`,{enumerable:!0,get:function(){return e.normalizeBar}}),Object.defineProperty(exports,`normalizeBarTime`,{enumerable:!0,get:function(){return e.normalizeBarTime}}),Object.defineProperty(exports,`registerLocale`,{enumerable:!0,get:function(){return e.registerLocale}}),Object.defineProperty(exports,`setLocale`,{enumerable:!0,get:function(){return e.setLocale}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return e.t}}),Object.defineProperty(exports,`toHeikinAshi`,{enumerable:!0,get:function(){return t.toHeikinAshi}}),Object.defineProperty(exports,`toKagi`,{enumerable:!0,get:function(){return t.toKagi}}),Object.defineProperty(exports,`toLineBreak`,{enumerable:!0,get:function(){return t.toLineBreak}}),Object.defineProperty(exports,`toPointAndFigure`,{enumerable:!0,get:function(){return t.toPointAndFigure}}),Object.defineProperty(exports,`toRenko`,{enumerable:!0,get:function(){return t.toRenko}}); | ||
| Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./Chart-DoR8L8Uk.cjs`);let t=require(`@tradecanvas/commons`),n=require(`@tradecanvas/core`);var r=class extends n.BaseFinanceChart{options;constructor(e,t){super(e,t.theme),this.options=t,this.requestRender()}renderChart(e,t,r,i){(0,n.renderSparkline)(e,t,r,this.options,i)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}},i=class extends n.BaseFinanceChart{options;crosshair=null;constructor(e,t){super(e,t.theme),this.options=t,t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,t,r,i){let a=this.crosshair?.getPosition()??null;(0,n.renderDepthChart)(e,t,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},a=class extends n.BaseFinanceChart{options;crosshair=null;constructor(e,t){super(e,t.theme),this.options=t,t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,t,r,i){let a=this.crosshair?.getPosition()??null;(0,n.renderEquityCurve)(e,t,r,this.options,i,a)}update(e,t){this.options={...this.options,data:e},t!==void 0&&(this.options={...this.options,benchmark:t}),this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},o=class extends n.BaseFinanceChart{options;crosshair=null;cachedRects=[];currentData=[];lastLayoutWidth=0;lastLayoutHeight=0;handleClick=null;constructor(e,t){super(e,t.theme),this.options=t,this.currentData=t.data??[],t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),t.onCellClick&&(this.handleClick=e=>{let t=this.canvas.getBoundingClientRect(),n=e.clientX-t.left,r=e.clientY-t.top;this.onCanvasClick(n,r)},this.canvas.addEventListener(`click`,this.handleClick)),this.recomputeLayout(),this.requestRender()}recomputeLayout(){let e={x:0,y:0,width:this.width,height:this.height},t=this.options.cellPadding??2;if(this.lastLayoutWidth=this.width,this.lastLayoutHeight=this.height,this.options.weighted){let r=this.currentData.map(e=>({id:e.id,weight:e.weight??(Math.abs(e.value)||1)}));this.cachedRects=(0,n.layoutSquarifiedTreemap)(r,e,t)}else this.cachedRects=(0,n.layoutUniformGrid)(this.currentData.map(e=>({id:e.id})),e,t)}onCanvasClick(e,t){if(this.options.onCellClick)for(let n of this.cachedRects){let r=n.rect;if(e>=r.x&&e<=r.x+r.width&&t>=r.y&&t<=r.y+r.height){let e=this.currentData.find(e=>e.id===n.id);e&&this.options.onCellClick(e);return}}}renderChart(e,t,r,i){(t!==this.lastLayoutWidth||r!==this.lastLayoutHeight)&&this.recomputeLayout();let a=this.crosshair?.getPosition()??null;(0,n.renderHeatmap)(e,t,r,this.currentData,this.cachedRects,this.options,i,a)}update(e){this.currentData=e,this.options={...this.options,data:e},this.recomputeLayout(),this.requestRender()}setOptions(e){this.options={...this.options,...e},e.data&&(this.currentData=e.data),this.recomputeLayout(),this.requestRender()}destroy(){this.crosshair?.destroy(),this.handleClick&&this.canvas.removeEventListener(`click`,this.handleClick),super.destroy()}},s=class extends n.BaseFinanceChart{options;crosshair=null;constructor(e,t){super(e,t.theme),this.options=t,t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,t,r,i){let a=this.crosshair?.getPosition()??null;(0,n.renderWaterfall)(e,t,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},c=500;function l(e){let t=1-e;return 1-t*t*t}var u=class extends n.BaseFinanceChart{options;currentValue;targetValue;animationStart=null;animationFrom=0;animationFrameId=null;constructor(e,t){super(e,t.theme),this.options=t,this.currentValue=t.value,this.targetValue=t.value,this.requestRender()}renderChart(e,t,r,i){(0,n.renderGauge)(e,t,r,this.options,i,this.currentValue)}setValue(e){if(this.options.animate===!1){this.cancelAnimation(),this.currentValue=e,this.targetValue=e,this.options={...this.options,value:e},this.requestRender();return}this.targetValue=e,this.animationFrom=this.currentValue,this.animationStart=performance.now(),this.options={...this.options,value:e},this.startAnimationLoop()}setOptions(e){let t={...this.options,...e};if(e.value!==void 0&&e.value!==this.targetValue){this.options=t,this.setValue(e.value);return}this.options=t,this.requestRender()}startAnimationLoop(){if(this.animationFrameId!==null)return;let e=()=>{if(this.animationFrameId=null,this.animationStart===null)return;let t=this.options.animationDuration??c,n=performance.now()-this.animationStart,r=Math.min(1,n/Math.max(1,t)),i=l(r);this.currentValue=this.animationFrom+(this.targetValue-this.animationFrom)*i,this.requestRender(),r<1?this.animationFrameId=requestAnimationFrame(e):(this.currentValue=this.targetValue,this.animationStart=null)};this.animationFrameId=requestAnimationFrame(e)}cancelAnimation(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStart=null}destroy(){this.cancelAnimation(),super.destroy()}};Object.defineProperty(exports,`AlertManager`,{enumerable:!0,get:function(){return n.AlertManager}}),Object.defineProperty(exports,`Animator`,{enumerable:!0,get:function(){return n.Animator}}),Object.defineProperty(exports,`BarCountdown`,{enumerable:!0,get:function(){return n.BarCountdown}}),Object.defineProperty(exports,`BinanceAdapter`,{enumerable:!0,get:function(){return n.BinanceAdapter}}),exports.Chart=e.t,Object.defineProperty(exports,`ChartLegend`,{enumerable:!0,get:function(){return n.ChartLegend}}),Object.defineProperty(exports,`ChartStateManager`,{enumerable:!0,get:function(){return n.ChartStateManager}}),Object.defineProperty(exports,`CompareRenderer`,{enumerable:!0,get:function(){return n.CompareRenderer}}),Object.defineProperty(exports,`CrosshairTooltip`,{enumerable:!0,get:function(){return n.CrosshairTooltip}}),Object.defineProperty(exports,`CurrentPriceLine`,{enumerable:!0,get:function(){return n.CurrentPriceLine}}),Object.defineProperty(exports,`DARK_TERMINAL`,{enumerable:!0,get:function(){return t.DARK_TERMINAL}}),Object.defineProperty(exports,`DARK_THEME`,{enumerable:!0,get:function(){return t.DARK_THEME}}),Object.defineProperty(exports,`DEFAULT_DRAWING_STYLE`,{enumerable:!0,get:function(){return t.DEFAULT_DRAWING_STYLE}}),Object.defineProperty(exports,`DEFAULT_LEGEND_CONFIG`,{enumerable:!0,get:function(){return n.DEFAULT_LEGEND_CONFIG}}),Object.defineProperty(exports,`DEFAULT_RECONNECT`,{enumerable:!0,get:function(){return t.DEFAULT_RECONNECT}}),Object.defineProperty(exports,`DEFAULT_STREAM_CONFIG`,{enumerable:!0,get:function(){return t.DEFAULT_STREAM_CONFIG}}),Object.defineProperty(exports,`DEFAULT_TIMEFRAME_FAVORITES`,{enumerable:!0,get:function(){return t.DEFAULT_TIMEFRAME_FAVORITES}}),Object.defineProperty(exports,`DEFAULT_TRADING_CONFIG`,{enumerable:!0,get:function(){return t.DEFAULT_TRADING_CONFIG}}),Object.defineProperty(exports,`DataExporter`,{enumerable:!0,get:function(){return n.DataExporter}}),exports.DataManager=e.a,exports.DepthChart=i,Object.defineProperty(exports,`DrawingBase`,{enumerable:!0,get:function(){return n.DrawingBase}}),Object.defineProperty(exports,`Easing`,{enumerable:!0,get:function(){return n.Easing}}),exports.EquityCurveChart=a,exports.GaugeChart=u,exports.HeatmapChart=o,Object.defineProperty(exports,`IndicatorBase`,{enumerable:!0,get:function(){return n.IndicatorBase}}),Object.defineProperty(exports,`KeyboardHandler`,{enumerable:!0,get:function(){return n.KeyboardHandler}}),Object.defineProperty(exports,`LIGHT_THEME`,{enumerable:!0,get:function(){return t.LIGHT_THEME}}),exports.LayoutManager=e.r,Object.defineProperty(exports,`MARKET_CRYPTO`,{enumerable:!0,get:function(){return t.MARKET_CRYPTO}}),Object.defineProperty(exports,`MARKET_HNX`,{enumerable:!0,get:function(){return t.MARKET_HNX}}),Object.defineProperty(exports,`MARKET_HOSE`,{enumerable:!0,get:function(){return t.MARKET_HOSE}}),Object.defineProperty(exports,`MARKET_NYSE`,{enumerable:!0,get:function(){return t.MARKET_NYSE}}),Object.defineProperty(exports,`MARKET_UPCOM`,{enumerable:!0,get:function(){return t.MARKET_UPCOM}}),Object.defineProperty(exports,`MockAdapter`,{enumerable:!0,get:function(){return n.MockAdapter}}),exports.PluginManager=e.n,Object.defineProperty(exports,`ReplayManager`,{enumerable:!0,get:function(){return n.ReplayManager}}),Object.defineProperty(exports,`Screenshot`,{enumerable:!0,get:function(){return n.Screenshot}}),Object.defineProperty(exports,`SessionBreaks`,{enumerable:!0,get:function(){return n.SessionBreaks}}),exports.SparklineChart=r,Object.defineProperty(exports,`StreamManager`,{enumerable:!0,get:function(){return n.StreamManager}}),Object.defineProperty(exports,`TIMEFRAMES_CRYPTO`,{enumerable:!0,get:function(){return t.TIMEFRAMES_CRYPTO}}),Object.defineProperty(exports,`TIMEFRAMES_FOREX`,{enumerable:!0,get:function(){return t.TIMEFRAMES_FOREX}}),Object.defineProperty(exports,`TIMEFRAMES_STOCK`,{enumerable:!0,get:function(){return t.TIMEFRAMES_STOCK}}),exports.ThemeManager=e.i,Object.defineProperty(exports,`TickAggregator`,{enumerable:!0,get:function(){return n.TickAggregator}}),Object.defineProperty(exports,`UndoRedoManager`,{enumerable:!0,get:function(){return n.UndoRedoManager}}),Object.defineProperty(exports,`VN_COLORS`,{enumerable:!0,get:function(){return t.VN_COLORS}}),Object.defineProperty(exports,`VolumeRenderer`,{enumerable:!0,get:function(){return n.VolumeRenderer}}),exports.WaterfallChart=s,Object.defineProperty(exports,`Watermark`,{enumerable:!0,get:function(){return n.Watermark}}),Object.defineProperty(exports,`computePriceLimits`,{enumerable:!0,get:function(){return t.computePriceLimits}}),Object.defineProperty(exports,`createVNTheme`,{enumerable:!0,get:function(){return t.createVNTheme}}),Object.defineProperty(exports,`formatNumber`,{enumerable:!0,get:function(){return t.formatNumber}}),Object.defineProperty(exports,`formatVND`,{enumerable:!0,get:function(){return t.formatVND}}),Object.defineProperty(exports,`formatVolumeLoc`,{enumerable:!0,get:function(){return t.formatVolumeLoc}}),Object.defineProperty(exports,`getCurrentSession`,{enumerable:!0,get:function(){return t.getCurrentSession}}),Object.defineProperty(exports,`getLocale`,{enumerable:!0,get:function(){return t.getLocale}}),Object.defineProperty(exports,`normalizeBar`,{enumerable:!0,get:function(){return t.normalizeBar}}),Object.defineProperty(exports,`normalizeBarTime`,{enumerable:!0,get:function(){return t.normalizeBarTime}}),Object.defineProperty(exports,`registerLocale`,{enumerable:!0,get:function(){return t.registerLocale}}),Object.defineProperty(exports,`setLocale`,{enumerable:!0,get:function(){return t.setLocale}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return t.t}}),Object.defineProperty(exports,`toHeikinAshi`,{enumerable:!0,get:function(){return n.toHeikinAshi}}),Object.defineProperty(exports,`toKagi`,{enumerable:!0,get:function(){return n.toKagi}}),Object.defineProperty(exports,`toLineBreak`,{enumerable:!0,get:function(){return n.toLineBreak}}),Object.defineProperty(exports,`toPointAndFigure`,{enumerable:!0,get:function(){return n.toPointAndFigure}}),Object.defineProperty(exports,`toRangeBars`,{enumerable:!0,get:function(){return n.toRangeBars}}),Object.defineProperty(exports,`toRenko`,{enumerable:!0,get:function(){return n.toRenko}}); | ||
| //# sourceMappingURL=index.cjs.map |
+1
-1
@@ -18,3 +18,3 @@ export { Chart } from './Chart.js'; | ||
| export type { CompareSymbol } from '@tradecanvas/core'; | ||
| export { toHeikinAshi, toRenko, toLineBreak, toKagi, toPointAndFigure } from '@tradecanvas/core'; | ||
| export { toHeikinAshi, toRenko, toLineBreak, toKagi, toPointAndFigure, toRangeBars } from '@tradecanvas/core'; | ||
| export { DataExporter } from '@tradecanvas/core'; | ||
@@ -21,0 +21,0 @@ export { AlertManager, ReplayManager, ChartStateManager, UndoRedoManager } from '@tradecanvas/core'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} |
+31
-1024
@@ -1,1008 +0,12 @@ | ||
| import { DARK_TERMINAL as e, DARK_THEME as t, DARK_THEME as n, DEFAULT_DRAWING_STYLE as r, DEFAULT_PANEL_HEIGHT as i, DEFAULT_RECONNECT as a, DEFAULT_STREAM_CONFIG as o, DEFAULT_TIMEFRAME_FAVORITES as s, DEFAULT_TRADING_CONFIG as c, LIGHT_THEME as l, LIGHT_THEME as u, LayerType as d, MARKET_CRYPTO as f, MARKET_HNX as ee, MARKET_HOSE as p, MARKET_NYSE as m, MARKET_UPCOM as h, MIN_PANEL_HEIGHT as g, PRICE_AXIS_WIDTH as _, TIMEFRAMES_CRYPTO as te, TIMEFRAMES_FOREX as ne, TIMEFRAMES_STOCK as re, TIME_AXIS_HEIGHT as v, VN_COLORS as ie, computePriceLimits as ae, computePriceLimits as y, createVNTheme as oe, formatNumber as se, formatVND as ce, formatVolumeLoc as le, getCurrentSession as ue, getLocale as de, mergeBar as fe, normalizeBar as pe, normalizeBarTime as me, registerLocale as b, setLocale as x, setLocale as S, t as C } from "@tradecanvas/commons"; | ||
| import { AlertManager as w, AlertManager as T, Animator as E, Animator as D, AreaRenderer as O, BarCountdown as k, BarCountdown as A, BarRenderer as j, BaseFinanceChart as M, BaselineRenderer as N, BinanceAdapter as P, CandlestickRenderer as F, ChartLegend as I, ChartLegend as L, ChartStateManager as R, ChartStateManager as z, CompareRenderer as he, CompareRenderer as ge, CrosshairHandler as _e, CrosshairTooltip as ve, CrosshairTooltip as ye, CurrentPriceLine as be, CurrentPriceLine as xe, DEFAULT_LEGEND_CONFIG as Se, DataExporter as Ce, DataExporter as B, DrawingBase as we, DrawingManager as Te, DrawingRenderer as Ee, Easing as De, EventBus as Oe, FinanceCrosshair as V, GridRenderer as ke, HollowCandleRenderer as Ae, IndicatorBase as je, IndicatorEngine as H, InteractionManager as Me, KagiRenderer as Ne, KeyboardHandler as Pe, KeyboardHandler as Fe, LineRenderer as Ie, MockAdapter as Le, PanHandler as Re, PointAndFigureRenderer as ze, PriceAxis as Be, RenderEngine as Ve, RenkoRenderer as He, ReplayManager as Ue, ReplayManager as U, Screenshot as We, Screenshot as W, SessionBreaks as Ge, SessionBreaks as Ke, StreamManager as qe, StreamManager as Je, TickAggregator as Ye, TimeAxis as Xe, TradingManager as Ze, TradingRenderer as Qe, UndoRedoManager as $e, UndoRedoManager as et, Viewport as tt, VolumeRenderer as nt, VolumeRenderer as rt, Watermark as it, Watermark as at, ZoomHandler as ot, layoutSquarifiedTreemap as st, layoutUniformGrid as ct, registerBuiltInDrawingTools as lt, registerBuiltInIndicators as G, renderDepthChart as ut, renderEquityCurve as dt, renderGauge as ft, renderHeatmap as pt, renderSparkline as mt, renderWaterfall as ht, toHeikinAshi as gt, toHeikinAshi as _t, toKagi as vt, toKagi as yt, toLineBreak as bt, toLineBreak as xt, toPointAndFigure as St, toPointAndFigure as Ct, toRenko as wt, toRenko as Tt } from "@tradecanvas/core"; | ||
| //#region src/DataManager.ts | ||
| function K(e) { | ||
| if (!e || typeof e.time != "number") return !1; | ||
| let { open: t, high: n, low: r, close: i } = e; | ||
| return !(!isFinite(t) || !isFinite(n) || !isFinite(r) || !isFinite(i) || t < 0 || n < 0 || r < 0 || i < 0 || n < r || e.volume !== void 0 && (!isFinite(e.volume) || e.volume < 0)); | ||
| } | ||
| function q(e) { | ||
| return { | ||
| ...e, | ||
| high: Math.max(e.open, e.high, e.low, e.close), | ||
| low: Math.min(e.open, e.high, e.low, e.close), | ||
| volume: e.volume === void 0 ? 0 : Math.max(0, e.volume) | ||
| }; | ||
| } | ||
| var J = class { | ||
| data = []; | ||
| getData() { | ||
| return this.data; | ||
| } | ||
| setData(e) { | ||
| this.data = e.filter(K).map(q); | ||
| } | ||
| appendBar(e) { | ||
| K(e) && this.data.push(q(e)); | ||
| } | ||
| updateLastBar(e) { | ||
| if (!K(e)) return; | ||
| let t = q(e); | ||
| if (this.data.length === 0) { | ||
| this.data.push(t); | ||
| return; | ||
| } | ||
| this.data[this.data.length - 1] = t; | ||
| } | ||
| updateLastBarFromTick(e) { | ||
| this.data.length !== 0 && (!isFinite(e.price) || e.price < 0 || e.volume !== void 0 && (!isFinite(e.volume) || e.volume < 0) || (this.data[this.data.length - 1] = fe(this.data[this.data.length - 1], e))); | ||
| } | ||
| getLength() { | ||
| return this.data.length; | ||
| } | ||
| clear() { | ||
| this.data = []; | ||
| } | ||
| }, Y = class { | ||
| theme; | ||
| constructor(e) { | ||
| !e || e === "dark" ? this.theme = { ...n } : e === "light" ? this.theme = { ...u } : this.theme = { ...e }; | ||
| } | ||
| getTheme() { | ||
| return this.theme; | ||
| } | ||
| setTheme(e) { | ||
| e === "dark" ? this.theme = { ...n } : e === "light" ? this.theme = { ...u } : this.theme = { ...e }; | ||
| } | ||
| }, X = 200, Z = 80, Q = class { | ||
| panels = []; | ||
| containerWidth = 0; | ||
| containerHeight = 0; | ||
| resize(e, t) { | ||
| this.containerWidth = e, this.containerHeight = t; | ||
| } | ||
| addPanel(e, t = "bottom", n) { | ||
| let r = t === "left" || t === "right"; | ||
| this.panels.push({ | ||
| id: e, | ||
| position: t, | ||
| size: n ?? (r ? X : i), | ||
| minSize: r ? Z : g, | ||
| content: { | ||
| type: "indicator", | ||
| indicatorInstanceId: e | ||
| } | ||
| }); | ||
| } | ||
| removePanel(e) { | ||
| this.panels = this.panels.filter((t) => t.id !== e); | ||
| } | ||
| setPanelPosition(e, t) { | ||
| let n = this.panels.find((t) => t.id === e); | ||
| if (n) { | ||
| let e = n.position === "left" || n.position === "right", r = t === "left" || t === "right"; | ||
| n.position = t, e !== r && (n.size = r ? X : i, n.minSize = r ? Z : g); | ||
| } | ||
| } | ||
| setPanelSize(e, t) { | ||
| let n = this.panels.find((t) => t.id === e); | ||
| n && (n.size = Math.max(n.minSize, t)); | ||
| } | ||
| getPanels() { | ||
| return this.panels; | ||
| } | ||
| resolve() { | ||
| let e = this.panels.filter((e) => e.position === "left"), t = this.panels.filter((e) => e.position === "right"), n = this.panels.filter((e) => e.position === "top"), r = this.panels.filter((e) => e.position === "bottom"), i = e.reduce((e, t) => e + t.size, 0), a = t.reduce((e, t) => e + t.size, 0), o = n.reduce((e, t) => e + t.size, 0), s = r.reduce((e, t) => e + t.size, 0), c = { | ||
| x: i, | ||
| y: o, | ||
| width: Math.max(0, this.containerWidth - i - a - _), | ||
| height: Math.max(0, this.containerHeight - o - s - v) | ||
| }, l = [], u = [], d = 0; | ||
| for (let t of e) l.push({ | ||
| config: t, | ||
| rect: { | ||
| x: d, | ||
| y: 0, | ||
| width: t.size, | ||
| height: this.containerHeight - v | ||
| } | ||
| }), u.push({ | ||
| panelId: t.id, | ||
| rect: { | ||
| x: d + t.size - 2, | ||
| y: 0, | ||
| width: 4, | ||
| height: this.containerHeight | ||
| }, | ||
| orientation: "vertical" | ||
| }), d += t.size; | ||
| let f = 0; | ||
| for (let e of n) l.push({ | ||
| config: e, | ||
| rect: { | ||
| x: i, | ||
| y: f, | ||
| width: c.width, | ||
| height: e.size | ||
| } | ||
| }), u.push({ | ||
| panelId: e.id, | ||
| rect: { | ||
| x: i, | ||
| y: f + e.size - 2, | ||
| width: c.width, | ||
| height: 4 | ||
| }, | ||
| orientation: "horizontal" | ||
| }), f += e.size; | ||
| f = c.y + c.height; | ||
| for (let e of r) l.push({ | ||
| config: e, | ||
| rect: { | ||
| x: i, | ||
| y: f, | ||
| width: c.width, | ||
| height: e.size | ||
| } | ||
| }), u.push({ | ||
| panelId: e.id, | ||
| rect: { | ||
| x: i, | ||
| y: f - 2, | ||
| width: c.width, | ||
| height: 4 | ||
| }, | ||
| orientation: "horizontal" | ||
| }), f += e.size; | ||
| d = i + c.width + _; | ||
| for (let e of t) l.push({ | ||
| config: e, | ||
| rect: { | ||
| x: d, | ||
| y: 0, | ||
| width: e.size, | ||
| height: this.containerHeight - v | ||
| } | ||
| }), u.push({ | ||
| panelId: e.id, | ||
| rect: { | ||
| x: d - 2, | ||
| y: 0, | ||
| width: 4, | ||
| height: this.containerHeight | ||
| }, | ||
| orientation: "vertical" | ||
| }), d += e.size; | ||
| return { | ||
| mainChartRect: c, | ||
| panels: l, | ||
| dividers: u | ||
| }; | ||
| } | ||
| getMainChartRect() { | ||
| return this.resolve().mainChartRect; | ||
| } | ||
| }, $ = class { | ||
| constructor(e) { | ||
| this.indicatorEngine = e; | ||
| } | ||
| registerIndicator(e) { | ||
| this.indicatorEngine.register(e); | ||
| } | ||
| }, Et = class { | ||
| static version = "0.3.0"; | ||
| engine; | ||
| viewport; | ||
| dataManager; | ||
| themeManager; | ||
| layoutManager; | ||
| pluginManager; | ||
| indicatorEngine; | ||
| drawingManager; | ||
| drawingRenderer; | ||
| tradingManager; | ||
| tradingRenderer; | ||
| eventBus; | ||
| streamManager = null; | ||
| autoScrollOnNewBar = !0; | ||
| displayDataCache = null; | ||
| resolvedLayoutCache = null; | ||
| panelInfoCache = null; | ||
| renderScheduled = !1; | ||
| containerSizeCache = null; | ||
| containerSizeCacheTime = 0; | ||
| chartLegend; | ||
| watermark; | ||
| barCountdown; | ||
| sessionBreaks; | ||
| compareRenderer; | ||
| countdownInterval = null; | ||
| volumeRenderer; | ||
| alertManager; | ||
| replayManager; | ||
| undoRedoManager; | ||
| autoSaveTimer = null; | ||
| autoSaveDelay = 0; | ||
| autoSaveKey = null; | ||
| animator; | ||
| crosshairTooltip; | ||
| interactionManager; | ||
| crosshairHandler; | ||
| chartRenderer; | ||
| gridRenderer; | ||
| priceAxis; | ||
| timeAxis; | ||
| import { a as e, i as t, n, r, t as i } from "./Chart-CrrTKx3r.js"; | ||
| import { DARK_TERMINAL as a, DARK_THEME as ee, DEFAULT_DRAWING_STYLE as te, DEFAULT_RECONNECT as o, DEFAULT_STREAM_CONFIG as s, DEFAULT_TIMEFRAME_FAVORITES as c, DEFAULT_TRADING_CONFIG as l, LIGHT_THEME as u, MARKET_CRYPTO as d, MARKET_HNX as f, MARKET_HOSE as p, MARKET_NYSE as m, MARKET_UPCOM as h, TIMEFRAMES_CRYPTO as g, TIMEFRAMES_FOREX as _, TIMEFRAMES_STOCK as v, VN_COLORS as y, computePriceLimits as b, createVNTheme as x, formatNumber as S, formatVND as C, formatVolumeLoc as w, getCurrentSession as T, getLocale as E, normalizeBar as D, normalizeBarTime as O, registerLocale as k, setLocale as A, t as j } from "@tradecanvas/commons"; | ||
| import { AlertManager as M, Animator as N, BarCountdown as P, BaseFinanceChart as F, BinanceAdapter as I, ChartLegend as L, ChartStateManager as R, CompareRenderer as z, CrosshairTooltip as B, CurrentPriceLine as V, DEFAULT_LEGEND_CONFIG as H, DataExporter as U, DrawingBase as W, Easing as G, FinanceCrosshair as K, IndicatorBase as q, KeyboardHandler as J, MockAdapter as Y, ReplayManager as X, Screenshot as Z, SessionBreaks as Q, StreamManager as ne, TickAggregator as re, UndoRedoManager as ie, VolumeRenderer as ae, Watermark as oe, layoutSquarifiedTreemap as se, layoutUniformGrid as ce, renderDepthChart as le, renderEquityCurve as ue, renderGauge as de, renderHeatmap as fe, renderSparkline as pe, renderWaterfall as me, toHeikinAshi as he, toKagi as ge, toLineBreak as _e, toPointAndFigure as ve, toRangeBars as ye, toRenko as be } from "@tradecanvas/core"; | ||
| //#region src/finance/SparklineChart.ts | ||
| var $ = class extends F { | ||
| options; | ||
| features; | ||
| marketConfig = null; | ||
| container; | ||
| currentPriceLine; | ||
| numberLocale; | ||
| keyboardHandler = null; | ||
| onWindowKeyDown = null; | ||
| currentSymbol = ""; | ||
| constructor(e, t) { | ||
| this.container = e, this.options = t, this.numberLocale = t.numberLocale ?? "en-US"; | ||
| let n = t.features ?? {}; | ||
| this.features = { | ||
| drawings: n.drawings ?? !0, | ||
| drawingTools: n.drawingTools ?? [], | ||
| drawingMagnet: n.drawingMagnet ?? !0, | ||
| drawingUndoRedo: n.drawingUndoRedo ?? !0, | ||
| trading: n.trading ?? !0, | ||
| tradingContextMenu: n.tradingContextMenu ?? !0, | ||
| indicators: n.indicators ?? !0, | ||
| indicatorIds: n.indicatorIds ?? [], | ||
| panning: n.panning ?? !0, | ||
| zooming: n.zooming ?? !0, | ||
| crosshair: n.crosshair ?? !0, | ||
| keyboard: n.keyboard ?? !0, | ||
| priceAxis: n.priceAxis ?? !0, | ||
| timeAxis: n.timeAxis ?? !0, | ||
| grid: n.grid ?? t.grid?.visible ?? !0, | ||
| legend: n.legend ?? !0, | ||
| volume: n.volume ?? !0, | ||
| watermark: n.watermark ?? !0, | ||
| saveLoad: n.saveLoad ?? !0, | ||
| screenshot: n.screenshot ?? !0, | ||
| alerts: n.alerts ?? !0, | ||
| replay: n.replay ?? !0, | ||
| sessionBreaks: n.sessionBreaks ?? !0, | ||
| barCountdown: n.barCountdown ?? !0, | ||
| compareSymbols: n.compareSymbols ?? !0, | ||
| dataExport: n.dataExport ?? !0, | ||
| logScale: n.logScale ?? !0, | ||
| timeframes: n.timeframes ?? [], | ||
| defaultTimeframeFavorites: n.defaultTimeframeFavorites ?? [] | ||
| }, e.style.position = "relative", e.style.overflow = "hidden", e.tabIndex = 0, e.style.outline = "none", this.dataManager = new J(), this.themeManager = new Y(t.theme), this.layoutManager = new Q(), this.indicatorEngine = new H(), this.pluginManager = new $(this.indicatorEngine), this.eventBus = new Oe(), G(this.indicatorEngine), this.drawingManager = new Te(), lt(this.drawingManager), this.drawingRenderer = new Ee(this.drawingManager), this.drawingManager.setRequestRender(() => { | ||
| this.syncRenderContext(), this.engine.requestRender(d.Overlay), this.scheduleAutoSave(); | ||
| }), this.drawingManager.setEventCallback((e, t) => { | ||
| this.eventBus.emit(e, t); | ||
| }), this.undoRedoManager = new et(), this.drawingManager.setUndoRedoManager(this.undoRedoManager), this.drawingManager.setDataGetter(() => this.dataManager.getData()), this.drawingManager.setDisplayDataGetter(() => this.getDisplayData()), t.crosshair?.mode === "magnet" && this.drawingManager.setMagnetMode("magnet"), this.tradingManager = new Ze(), this.tradingRenderer = new Qe(this.tradingManager), this.tradingManager.setContainer(e), this.tradingManager.setRequestRender(() => this.engine.requestRender(d.Overlay)), this.tradingManager.setEventCallback((e, t) => { | ||
| this.eventBus.emit(e, t); | ||
| }), this.engine = new Ve(e); | ||
| let r = this.engine.dprManager.getContainerSize(); | ||
| this.viewport = new tt(r.width, r.height, t.minBarSpacing ?? 2, t.maxBarSpacing ?? 30, t.rightMargin ?? 5), this.layoutManager.resize(r.width, r.height), this.engine.onContainerResize = (e) => { | ||
| if (e.width <= 0 || e.height <= 0) return; | ||
| let t = this.viewport.isAtEnd(); | ||
| this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(t); | ||
| }, this.chartRenderer = this.createChartRenderer(t.chartType), this.gridRenderer = new ke(), t.grid?.visible === !1 && this.gridRenderer.setVisible(!1), this.priceAxis = new Be(), this.priceAxis.setLocale(this.numberLocale), this.timeAxis = new Xe(), this.crosshairHandler = new _e(), this.crosshairHandler.setLocale(this.numberLocale), t.crosshair?.mode && this.crosshairHandler.setMode(t.crosshair.mode), this.crosshairHandler.setCallback((e, t) => { | ||
| if (e !== null && t) { | ||
| let n = this.dataManager.getData(), r = e < n.length ? n[e] : void 0; | ||
| this.chartLegend.setHoverBar(r ?? null), r && this.crosshairTooltip.show(t, r, this.themeManager.getTheme(), this.cachedContainerSize()), this.eventBus.emit("crosshairMove", { | ||
| point: t, | ||
| bar: r, | ||
| barIndex: e | ||
| }); | ||
| } else this.crosshairTooltip.hide(), this.chartLegend.setHoverBar(null); | ||
| }), this.chartLegend = new L(), this.chartLegend.setChartType(t.chartType), this.watermark = new at(), t.watermark && this.watermark.setConfig(t.watermark), this.volumeRenderer = new rt(), this.barCountdown = new A(), this.sessionBreaks = new Ke(), this.compareRenderer = new ge(), t.sessionBreaks ? this.sessionBreaks.setConfig({ | ||
| visible: t.sessionBreaks.visible ?? !0, | ||
| color: t.sessionBreaks.color, | ||
| lineStyle: t.sessionBreaks.lineStyle, | ||
| lineWidth: t.sessionBreaks.lineWidth | ||
| }) : t.features?.sessionBreaks !== !1 && this.sessionBreaks.setVisible(!0), t.logScale && this.viewport.setLogScale(!0), this.animator = new D(), this.crosshairTooltip = new ye(), this.crosshairTooltip.create(e), this.keyboardHandler = new Fe({ | ||
| scrollBars: (e) => { | ||
| let t = this.viewport.getState().barWidth + this.viewport.getState().barSpacing; | ||
| this.viewport.scrollBy(e * t), this.updateViewportAndRender(); | ||
| }, | ||
| zoom: (e) => { | ||
| let t = this.viewport.getState().chartRect.width; | ||
| this.viewport.zoom(e, t / 2), this.updateViewportAndRender(); | ||
| }, | ||
| goToStart: () => { | ||
| this.viewport.scrollBy(-Infinity), this.updateViewportAndRender(); | ||
| }, | ||
| goToEnd: () => { | ||
| this.viewport.scrollToEnd(), this.updateViewportAndRender(); | ||
| }, | ||
| fitContent: () => this.fitContent() | ||
| }), this.keyboardHandler.setEnabled(this.features.keyboard), this.onWindowKeyDown = (e) => { | ||
| if (!this.keyboardHandler) return; | ||
| let t = document.activeElement; | ||
| t && t !== this.container && !this.container.contains(t) || t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) || this.keyboardHandler.handleKey(e) && e.preventDefault(); | ||
| }, window.addEventListener("keydown", this.onWindowKeyDown), this.currentPriceLine = new xe(), this.alertManager = new T(), this.alertManager.setRequestRender(() => this.engine.requestRender(d.Overlay)), this.alertManager.on("triggered", (e) => { | ||
| this.eventBus.emit("dataUpdate", { | ||
| alert: "triggered", | ||
| alertId: e.id, | ||
| price: e.price, | ||
| message: e.message | ||
| }); | ||
| }), this.replayManager = new U(), this.interactionManager = new Me(e), this.features.panning && this.interactionManager.setPanHandler(new Re((e) => { | ||
| this.viewport.scrollBy(e), this.updateViewportAndRender(); | ||
| })), this.features.zooming && this.interactionManager.setZoomHandler(new ot((e, t) => { | ||
| this.viewport.zoom(e, t), this.updateViewportAndRender(); | ||
| })), this.features.crosshair && this.interactionManager.setCrosshairHandler(this.crosshairHandler), this.features.drawings && this.interactionManager.setDrawingManager(this.drawingManager, () => this.viewport.getState()), this.features.trading && this.interactionManager.setTradingManager(this.tradingManager, () => this.viewport.getState()), this.interactionManager.setOverlayDirtyCallback(() => { | ||
| this.engine.requestRender(d.Overlay), this.layoutManager.getPanels().length > 0 && this.engine.requestRender(d.UI); | ||
| }), this.interactionManager.attach(), this.syncRenderContext(), this.engine.start(); | ||
| } | ||
| setData(e) { | ||
| this.dataManager.setData(e), this.crosshairHandler.setData(this.dataManager.getData()), this.displayDataCache = null, this.sessionBreaks.invalidateCache(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), e.length > 0 && this.currentPriceLine.setPrice(e[e.length - 1].close), this.updateViewportAndRender(!0), this.eventBus.emit("dataUpdate", { length: e.length }); | ||
| } | ||
| appendBar(e) { | ||
| this.dataManager.appendBar(e), this.crosshairHandler.setData(this.dataManager.getData()), this.displayDataCache = null, this.autoScrollOnNewBar && this.viewport.scrollToEnd(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.updateViewportAndRender(); | ||
| } | ||
| appendBars(e) { | ||
| if (e.length !== 0) { | ||
| for (let t of e) this.dataManager.appendBar(t); | ||
| this.displayDataCache = null, this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.crosshairHandler.setData(this.dataManager.getData()), this.updateViewportAndRender(this.viewport.isAtEnd()); | ||
| } | ||
| } | ||
| updateLastBar(e) { | ||
| this.dataManager.updateLastBar(e), this.currentPriceLine.setPrice(e.close), this.options.chartType !== "candlestick" && this.options.chartType !== "line" && this.options.chartType !== "area" && this.options.chartType !== "bar" && this.options.chartType !== "hollowCandle" && (this.displayDataCache = null), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.scheduleRender(); | ||
| } | ||
| updateLastBarFromTick(e) { | ||
| this.dataManager.updateLastBarFromTick(e), this.currentPriceLine.setPrice(e.price), this.options.chartType !== "candlestick" && this.options.chartType !== "line" && this.options.chartType !== "area" && this.options.chartType !== "bar" && this.options.chartType !== "hollowCandle" && (this.displayDataCache = null), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.scheduleRender(); | ||
| } | ||
| setChartType(e) { | ||
| this.options.chartType = e, this.chartRenderer = this.createChartRenderer(e), this.chartLegend.setChartType(e), this.displayDataCache = null, this.updateViewportAndRender(!0); | ||
| } | ||
| addIndicator(e, t = {}, n = "bottom") { | ||
| if (!this.features.indicators || this.features.indicatorIds.length > 0 && !this.features.indicatorIds.includes(e)) return null; | ||
| let r = this.indicatorEngine.addIndicator(e, t, this.dataManager.getData()); | ||
| return this.indicatorEngine.getAvailableIndicators().find((t) => t.id === e)?.placement === "panel" ? (this.layoutManager.addPanel(r, n), this.updateViewportAndRender()) : this.engine.requestRender(), this.eventBus.emit("indicatorAdd", { | ||
| instanceId: r, | ||
| id: e | ||
| }), r; | ||
| } | ||
| updateIndicator(e, t) { | ||
| this.indicatorEngine.updateIndicator(e, t, this.dataManager.getData()), this.engine.requestRender(); | ||
| } | ||
| removeIndicator(e) { | ||
| let t = this.layoutManager.getPanels().some((t) => t.id === e); | ||
| this.indicatorEngine.removeIndicator(e), this.layoutManager.removePanel(e), this.eventBus.emit("indicatorRemove", { instanceId: e }), t ? this.updateViewportAndRender() : this.engine.requestRender(); | ||
| } | ||
| getIndicatorOutput(e) { | ||
| return this.indicatorEngine.getOutput(e); | ||
| } | ||
| registerIndicator(e) { | ||
| this.pluginManager.registerIndicator(e); | ||
| } | ||
| static indicators() { | ||
| let e = new H(); | ||
| return G(e), e.getAvailableIndicators(); | ||
| } | ||
| setPanelPosition(e, t) { | ||
| this.layoutManager.setPanelPosition(e, t), this.engine.requestRender(); | ||
| } | ||
| setPanelSize(e, t) { | ||
| this.layoutManager.setPanelSize(e, t), this.engine.requestRender(); | ||
| } | ||
| setDrawingTool(e) { | ||
| this.features.drawings && (e && this.features.drawingTools.length > 0 && !this.features.drawingTools.includes(e) || this.drawingManager.setActiveTool(e)); | ||
| } | ||
| getDrawingTool() { | ||
| return this.drawingManager.getActiveTool(); | ||
| } | ||
| setDrawingStyle(e) { | ||
| this.drawingManager.setStyle(e); | ||
| } | ||
| getDrawings() { | ||
| return this.drawingManager.getDrawings(); | ||
| } | ||
| setDrawings(e) { | ||
| this.drawingManager.setDrawings(e); | ||
| } | ||
| removeDrawing(e) { | ||
| this.drawingManager.removeDrawing(e); | ||
| } | ||
| clearDrawings() { | ||
| this.drawingManager.clearDrawings(); | ||
| } | ||
| registerDrawingTool(e) { | ||
| this.drawingManager.register(e); | ||
| } | ||
| undo() { | ||
| return this.features.drawingUndoRedo ? this.drawingManager.undo() : !1; | ||
| } | ||
| redo() { | ||
| return this.features.drawingUndoRedo ? this.drawingManager.redo() : !1; | ||
| } | ||
| getUndoRedoState() { | ||
| return this.undoRedoManager.getState(); | ||
| } | ||
| setDrawingMagnet(e) { | ||
| this.drawingManager.setMagnetMode(e ? "magnet" : "none"); | ||
| } | ||
| getDrawingMagnet() { | ||
| return this.drawingManager.getMagnetMode() === "magnet"; | ||
| } | ||
| lockAllDrawings() { | ||
| this.drawingManager.lockAllDrawings(); | ||
| } | ||
| unlockAllDrawings() { | ||
| this.drawingManager.unlockAllDrawings(); | ||
| } | ||
| hideAllDrawings() { | ||
| this.drawingManager.hideAllDrawings(); | ||
| } | ||
| showAllDrawings() { | ||
| this.drawingManager.showAllDrawings(); | ||
| } | ||
| duplicateDrawing(e) { | ||
| let t = e ?? this.drawingManager.getSelectedDrawingId(); | ||
| return t ? this.drawingManager.duplicateDrawing(t) : null; | ||
| } | ||
| exportVisibleData(e = "csv", t) { | ||
| let n = this.viewport.getState(), r = this.dataManager.getData(), i = Math.max(0, n.visibleRange.from), a = Math.min(r.length - 1, n.visibleRange.to), o = r.slice(i, a + 1); | ||
| if (e === "json") { | ||
| let e = B.toJSON(o); | ||
| B.download(e, t ?? "chart-data.json", "application/json"); | ||
| } else { | ||
| let e = B.toCSV(o); | ||
| B.download(e, t ?? "chart-data.csv", "text/csv"); | ||
| } | ||
| } | ||
| exportAllData(e = "csv", t) { | ||
| let n = this.dataManager.getData(); | ||
| if (e === "json") { | ||
| let e = B.toJSON(n); | ||
| B.download(e, t ?? "chart-data.json", "application/json"); | ||
| } else { | ||
| let e = B.toCSV(n); | ||
| B.download(e, t ?? "chart-data.csv", "text/csv"); | ||
| } | ||
| } | ||
| setAutoSave(e, t = 5e3) { | ||
| this.autoSaveKey = e, this.autoSaveDelay = t; | ||
| } | ||
| disableAutoSave() { | ||
| this.autoSaveDelay = 0, this.autoSaveKey = null, this.autoSaveTimer &&= (clearTimeout(this.autoSaveTimer), null); | ||
| } | ||
| scheduleAutoSave() { | ||
| this.autoSaveDelay <= 0 || !this.autoSaveKey || (this.autoSaveTimer && clearTimeout(this.autoSaveTimer), this.autoSaveTimer = setTimeout(() => { | ||
| this.autoSaveTimer = null, this.autoSaveKey && this.saveState(this.autoSaveKey); | ||
| }, this.autoSaveDelay)); | ||
| } | ||
| getAvailableIndicators() { | ||
| return this.indicatorEngine.getAvailableIndicators(); | ||
| } | ||
| getIndicatorInputs(e) { | ||
| let t = this.indicatorEngine.getAvailableIndicators().find((t) => t.id === e); | ||
| return t ? { | ||
| id: t.id, | ||
| params: t.defaultConfig | ||
| } : null; | ||
| } | ||
| getActiveIndicators() { | ||
| return this.indicatorEngine.getActiveIndicators(); | ||
| } | ||
| getIndicatorConfig(e) { | ||
| let t = this.indicatorEngine.getIndicatorConfig(e); | ||
| return t ? { | ||
| id: t.id, | ||
| params: { ...t.params } | ||
| } : null; | ||
| } | ||
| updateIndicatorStyle(e, t) { | ||
| this.indicatorEngine.updateIndicatorStyle(e, t), this.engine.requestRender(); | ||
| } | ||
| setOrders(e) { | ||
| this.features.trading && this.tradingManager.setOrders(e); | ||
| } | ||
| setPositions(e) { | ||
| this.features.trading && this.tradingManager.setPositions(e); | ||
| } | ||
| setDepthData(e) { | ||
| this.features.trading && this.tradingManager.setDepthData(e); | ||
| } | ||
| setCurrentPrice(e, t) { | ||
| this.tradingManager.setCurrentPrice(e), this.currentPriceLine.setPrice(e), this.scheduleRender(), this.features.alerts && this.alertManager.checkPrice(e); | ||
| } | ||
| setTradingConfig(e) { | ||
| this.features.trading && this.tradingManager.setConfig(e); | ||
| } | ||
| async connect(e) { | ||
| this.disconnectStream(), this.streamManager = new Je(), this.streamManager.on("snapshot", (e) => { | ||
| this.setData(e); | ||
| }), this.streamManager.on("barClose", (e) => { | ||
| this.dataManager.appendBar(e), this.crosshairHandler.setData(this.dataManager.getData()), this.autoScrollOnNewBar && this.viewport.scrollToEnd(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.updateViewportAndRender(); | ||
| }), this.streamManager.on("barUpdate", (e) => { | ||
| this.dataManager.updateLastBar(e), this.currentPriceLine.setPrice(e.close), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.scheduleRender(); | ||
| }), this.streamManager.on("priceChange", ({ price: e }) => { | ||
| this.tradingManager.setCurrentPrice(e), this.currentPriceLine.setPrice(e), this.engine.requestRender(d.Overlay), this.engine.requestRender(d.UI); | ||
| }), this.streamManager.on("connectionChange", (e) => { | ||
| this.eventBus.emit("dataUpdate", { connection: e }); | ||
| }), this.streamManager.on("error", (e) => { | ||
| this.eventBus.emit("dataUpdate", { error: e.message }); | ||
| }), this.autoScrollOnNewBar = e.autoScroll !== !1, this.currentSymbol = e.symbol, await this.streamManager.connect(e); | ||
| let t = this.timeframeToMs(e.timeframe); | ||
| this.barCountdown.setTimeframeMs(t), this.countdownInterval && clearInterval(this.countdownInterval), this.countdownInterval = setInterval(() => { | ||
| this.barCountdown.isVisible() && this.engine.requestRender(d.UI); | ||
| }, 1e3); | ||
| } | ||
| async switchStream(e, t) { | ||
| this.streamManager && (this.currentSymbol = e, await this.streamManager.switchTo(e, t)); | ||
| } | ||
| async setTimeframe(e) { | ||
| if (!this.streamManager) throw Error("No active stream. Call connect() first."); | ||
| await this.switchStream(this.currentSymbol, e); | ||
| } | ||
| disconnectStream() { | ||
| this.streamManager &&= (this.streamManager.dispose(), null); | ||
| } | ||
| setBarCountdownVisible(e) { | ||
| this.barCountdown.setVisible(e), this.engine.requestRender(d.UI); | ||
| } | ||
| setSessionBreaksVisible(e) { | ||
| this.sessionBreaks.setVisible(e), this.engine.requestRender(d.Background); | ||
| } | ||
| addCompareSymbol(e, t, n, r) { | ||
| this.compareRenderer.addSymbol({ | ||
| id: e, | ||
| label: t, | ||
| data: n, | ||
| color: r, | ||
| visible: !0 | ||
| }), this.engine.requestRender(d.Main); | ||
| } | ||
| removeCompareSymbol(e) { | ||
| this.compareRenderer.removeSymbol(e), this.engine.requestRender(d.Main); | ||
| } | ||
| updateCompareData(e, t) { | ||
| this.compareRenderer.setSymbolData(e, t), this.engine.requestRender(d.Main); | ||
| } | ||
| setCompareMode(e) { | ||
| this.compareRenderer.setMode(e), this.engine.requestRender(d.Main); | ||
| } | ||
| clearCompareSymbols() { | ||
| this.compareRenderer.clear(), this.engine.requestRender(d.Main); | ||
| } | ||
| setLogScale(e) { | ||
| this.viewport.setLogScale(e), this.updateViewportAndRender(); | ||
| } | ||
| isLogScale() { | ||
| return this.viewport.isLogScale(); | ||
| } | ||
| setSessionBreaksConfig(e) { | ||
| this.sessionBreaks.setConfig(e), this.engine.requestRender(d.Background); | ||
| } | ||
| getConnectionState() { | ||
| return this.streamManager?.getConnectionState() ?? "disconnected"; | ||
| } | ||
| getConnectionInfo() { | ||
| return this.streamManager?.getConnectionInfo() ?? { state: "disconnected" }; | ||
| } | ||
| setAutoScroll(e) { | ||
| this.autoScrollOnNewBar = e; | ||
| } | ||
| scrollTo(e) { | ||
| let t = this.dataManager.getData(); | ||
| for (let n = 0; n < t.length; n++) if (t[n].time >= e) { | ||
| let e = this.viewport.getState().barWidth + this.viewport.getState().barSpacing; | ||
| this.viewport.scrollBy(n * e - this.viewport.getState().offset), this.updateViewportAndRender(); | ||
| return; | ||
| } | ||
| } | ||
| scrollToEnd() { | ||
| this.viewport.scrollToEnd(), this.updateViewportAndRender(); | ||
| } | ||
| setVisibleRange(e, t) { | ||
| let n = this.dataManager.getData(), r = 0, i = n.length - 1; | ||
| for (let t = 0; t < n.length; t++) if (n[t].time >= e) { | ||
| r = t; | ||
| break; | ||
| } | ||
| for (let e = n.length - 1; e >= 0; e--) if (n[e].time <= t) { | ||
| i = e; | ||
| break; | ||
| } | ||
| let a = i - r + 1; | ||
| if (a > 0) { | ||
| let e = this.viewport.getState().chartRect.width, t = e / a, n = Math.max(2, t - this.viewport.getState().barSpacing); | ||
| this.viewport.zoom((n - this.viewport.getState().barWidth) / this.viewport.getState().barWidth, e / 2); | ||
| } | ||
| this.updateViewportAndRender(); | ||
| } | ||
| zoomIn() { | ||
| let e = this.viewport.getState().chartRect.width; | ||
| this.viewport.zoom(.2, e / 2), this.updateViewportAndRender(); | ||
| } | ||
| zoomOut() { | ||
| let e = this.viewport.getState().chartRect.width; | ||
| this.viewport.zoom(-.2, e / 2), this.updateViewportAndRender(); | ||
| } | ||
| fitContent() { | ||
| let e = this.dataManager.getData(); | ||
| e.length !== 0 && this.setVisibleRange(e[0].time, e[e.length - 1].time); | ||
| } | ||
| on(e, t) { | ||
| this.eventBus.on(e, t); | ||
| } | ||
| off(e, t) { | ||
| this.eventBus.off(e, t); | ||
| } | ||
| enableTauriBridge(e) { | ||
| this.eventBus.enableTauriBridge({ | ||
| enabled: !0, | ||
| ...e | ||
| }); | ||
| } | ||
| disableTauriBridge() { | ||
| this.eventBus.disableTauriBridge(); | ||
| } | ||
| setTheme(e) { | ||
| this.themeManager.setTheme(e), this.syncRenderContext(), this.container.style.backgroundColor = this.themeManager.getTheme().background, this.engine.requestRender(), this.eventBus.emit("themeChange", { theme: e }); | ||
| } | ||
| getTheme() { | ||
| return this.themeManager.getTheme(); | ||
| } | ||
| setWatermark(e, t) { | ||
| this.watermark.setConfig({ | ||
| text: e, | ||
| ...t | ||
| }), this.engine.requestRender(d.Background); | ||
| } | ||
| setAutoScale(e) { | ||
| this.options.autoScale = e, this.updateViewportAndRender(); | ||
| } | ||
| isAutoScale() { | ||
| return this.options.autoScale !== !1; | ||
| } | ||
| setCrosshairMode(e) { | ||
| this.crosshairHandler.setMode(e), this.engine.requestRender(d.Overlay); | ||
| } | ||
| getCrosshairMode() { | ||
| return this.crosshairHandler.getMode(); | ||
| } | ||
| setGridVisible(e) { | ||
| this.gridRenderer.setVisible(e), this.engine.requestRender(d.Background); | ||
| } | ||
| isGridVisible() { | ||
| return this.gridRenderer.isVisible(); | ||
| } | ||
| setVolumeVisible(e) { | ||
| this.volumeRenderer.setVisible(e), this.engine.requestRender(d.Main); | ||
| } | ||
| setTooltipVisible(e) { | ||
| e || this.crosshairTooltip.hide(); | ||
| } | ||
| setLegend(e) { | ||
| this.chartLegend.setConfig(e), this.engine.requestRender(d.UI); | ||
| } | ||
| setSymbolName(e) { | ||
| this.chartLegend.setSymbol(e), this.engine.requestRender(d.UI); | ||
| } | ||
| setStatusText(e) { | ||
| this.chartLegend.setStatusText(e), this.engine.requestRender(d.UI); | ||
| } | ||
| screenshot(e) { | ||
| this.features.screenshot && W.download(this.container, e, this.themeManager.getTheme().background); | ||
| } | ||
| screenshotDataURL() { | ||
| return this.features.screenshot ? W.toDataURL(this.container, this.themeManager.getTheme().background) : null; | ||
| } | ||
| async screenshotBlob() { | ||
| return this.features.screenshot ? W.toBlob(this.container, this.themeManager.getTheme().background) : null; | ||
| } | ||
| addAlert(e, t = "crossing", n) { | ||
| if (!this.features.alerts) return null; | ||
| let r = this.alertManager.addAlert(e, t, n); | ||
| return this.scheduleAutoSave(), r; | ||
| } | ||
| removeAlert(e) { | ||
| this.alertManager.removeAlert(e), this.scheduleAutoSave(); | ||
| } | ||
| getAlerts() { | ||
| return this.alertManager.getAlerts(); | ||
| } | ||
| clearAlerts() { | ||
| this.alertManager.clearAlerts(), this.scheduleAutoSave(); | ||
| } | ||
| saveAlerts(e) { | ||
| this.alertManager.saveToStorage(e); | ||
| } | ||
| loadAlerts(e) { | ||
| this.alertManager.loadFromStorage(e), this.engine.requestRender(d.Overlay); | ||
| } | ||
| replay(e) { | ||
| if (!this.features.replay) return; | ||
| let t = this.dataManager.getData(); | ||
| this.replayManager.load(t), this.replayManager.on("bar", ({ bar: e, index: n }) => { | ||
| let r = t.slice(0, n + 1); | ||
| this.dataManager.setData(r), this.crosshairHandler.setData(r), this.indicatorEngine.recalculateAll(r), this.updateViewportAndRender(); | ||
| }), this.replayManager.play(e); | ||
| } | ||
| replayPause() { | ||
| this.replayManager.pause(); | ||
| } | ||
| replayResume() { | ||
| this.replayManager.resume(); | ||
| } | ||
| replayStop() { | ||
| this.replayManager.stop(); | ||
| } | ||
| replaySeek(e) { | ||
| this.replayManager.seekTo(e); | ||
| } | ||
| setReplaySpeed(e) { | ||
| this.replayManager.setSpeed(e); | ||
| } | ||
| getReplayState() { | ||
| return this.replayManager.getState(); | ||
| } | ||
| getReplayProgress() { | ||
| return this.replayManager.getProgress(); | ||
| } | ||
| saveState(e) { | ||
| if (!this.features.saveLoad) return null; | ||
| let t = z.capture({ | ||
| getDrawings: () => this.getDrawings(), | ||
| getTheme: () => this.getTheme(), | ||
| getAlerts: () => this.getAlerts() | ||
| }, { chartType: this.options.chartType }), n = z.serialize(t); | ||
| return e && z.saveToStorage(e, t), n; | ||
| } | ||
| loadState(e) { | ||
| if (!this.features.saveLoad) return; | ||
| let t = z.deserialize(e); | ||
| if (t.chartType && this.setChartType(t.chartType), t.drawings && this.setDrawings(t.drawings), t.theme && this.setTheme(t.theme), t.alerts) { | ||
| this.clearAlerts(); | ||
| for (let e of t.alerts) this.addAlert(e.price, e.condition, e.message); | ||
| } | ||
| } | ||
| loadStateFromStorage(e) { | ||
| if (!this.features.saveLoad) return !1; | ||
| let t = z.loadFromStorage(e); | ||
| return t ? (this.loadState(z.serialize(t)), !0) : !1; | ||
| } | ||
| downloadState(e) { | ||
| if (!this.features.saveLoad) return; | ||
| let t = z.capture({ | ||
| getDrawings: () => this.getDrawings(), | ||
| getTheme: () => this.getTheme(), | ||
| getAlerts: () => this.getAlerts() | ||
| }, { chartType: this.options.chartType }); | ||
| z.downloadFile(t, e); | ||
| } | ||
| async loadStateFromFile() { | ||
| if (!this.features.saveLoad) return; | ||
| let e = await z.loadFromFile(); | ||
| this.loadState(z.serialize(e)); | ||
| } | ||
| setLocale(e) { | ||
| S(e), this.engine.requestRender(); | ||
| } | ||
| setNumberLocale(e) { | ||
| this.numberLocale = e, this.priceAxis.setLocale(e), this.crosshairHandler.setLocale(e), this.syncRenderContext(), this.engine.requestRender(); | ||
| } | ||
| getNumberLocale() { | ||
| return this.numberLocale; | ||
| } | ||
| setMarket(e) { | ||
| if (this.marketConfig = e, e.colorScheme) { | ||
| let t = { | ||
| ...this.themeManager.getTheme(), | ||
| candleUp: e.colorScheme.up, | ||
| candleDown: e.colorScheme.down, | ||
| candleUpWick: e.colorScheme.up, | ||
| candleDownWick: e.colorScheme.down, | ||
| volumeUp: e.colorScheme.up.replace(")", ", 0.3)").replace("rgb(", "rgba(") || `${e.colorScheme.up}4D`, | ||
| volumeDown: e.colorScheme.down.replace(")", ", 0.3)").replace("rgb(", "rgba(") || `${e.colorScheme.down}4D` | ||
| }; | ||
| this.themeManager.setTheme(t); | ||
| } | ||
| e.pricePrecision !== void 0 && (this.tradingManager.setConfig({ pricePrecision: e.pricePrecision }), this.alertManager.setPricePrecision(e.pricePrecision), this.streamManager?.priceLine.setPricePrecision(e.pricePrecision), this.crosshairHandler.setPricePrecision(e.pricePrecision)), this.syncRenderContext(), this.engine.requestRender(); | ||
| } | ||
| getMarket() { | ||
| return this.marketConfig; | ||
| } | ||
| setPriceLimits(e) { | ||
| this.marketConfig && (y(e, this.marketConfig) && (this.marketConfig.priceLimits = { | ||
| ...this.marketConfig.priceLimits, | ||
| referencePrice: e | ||
| }), this.engine.requestRender()); | ||
| } | ||
| getFeatures() { | ||
| return this.features; | ||
| } | ||
| setFeatures(e) { | ||
| Object.assign(this.features, e), e.crosshair === !1 && this.crosshairTooltip.hide(), e.grid !== void 0 && this.engine.requestRender(d.Background), e.volume !== void 0 && (this.volumeRenderer.setVisible(e.volume), this.engine.requestRender(d.Main)), e.drawings === !1 && this.drawingManager.setActiveTool(null), e.trading === !1 && (this.tradingManager.setOrders([]), this.tradingManager.setPositions([])), e.keyboard !== void 0 && this.keyboardHandler?.setEnabled(e.keyboard), this.engine.requestRender(); | ||
| } | ||
| resize() { | ||
| let e = this.engine.dprManager.readContainerSize(); | ||
| if (e.width <= 0 || e.height <= 0) return; | ||
| this.containerSizeCache = e, this.containerSizeCacheTime = Date.now(); | ||
| let t = this.engine.dprManager.getDpr(); | ||
| this.engine.layerManager.resize(e, t); | ||
| let n = this.viewport.isAtEnd(); | ||
| this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(n), this.eventBus.emit("resize", e); | ||
| } | ||
| destroy() { | ||
| this.countdownInterval && clearInterval(this.countdownInterval), this.disableAutoSave(), this.disconnectStream(), this.onWindowKeyDown &&= (window.removeEventListener("keydown", this.onWindowKeyDown), null), this.keyboardHandler = null, this.interactionManager.detach(), this.tradingManager.destroy(), this.animator.dispose(), this.crosshairTooltip.destroy(), this.replayManager.dispose(), this.undoRedoManager.clear(), this.engine.destroy(), this.eventBus.destroy(), this.container.innerHTML = ""; | ||
| } | ||
| createChartRenderer(e) { | ||
| switch (e) { | ||
| case "candlestick": return new F(); | ||
| case "heikinAshi": return new F(); | ||
| case "line": return new Ie(); | ||
| case "area": return new O(); | ||
| case "bar": return new j(); | ||
| case "hollowCandle": return new Ae(); | ||
| case "baseline": return new N(); | ||
| case "renko": return new He(); | ||
| case "lineBreak": return new F(); | ||
| case "kagi": return new Ne(); | ||
| case "pointAndFigure": return new ze(); | ||
| default: return new F(); | ||
| } | ||
| } | ||
| getDisplayData() { | ||
| if (this.displayDataCache) return this.displayDataCache; | ||
| let e = this.dataManager.getData(); | ||
| if (e.length === 0) return e; | ||
| let t; | ||
| switch (this.options.chartType) { | ||
| case "heikinAshi": | ||
| t = _t(e); | ||
| break; | ||
| case "renko": | ||
| t = Tt(e, { | ||
| brickSize: 0, | ||
| useATR: !0, | ||
| atrPeriod: 14 | ||
| }); | ||
| break; | ||
| case "lineBreak": | ||
| t = xt(e, 3); | ||
| break; | ||
| case "kagi": | ||
| t = yt(e, 4); | ||
| break; | ||
| case "pointAndFigure": | ||
| t = Ct(e, e.reduce((e, t) => e + t.close, 0) / e.length * .01, 3); | ||
| break; | ||
| default: t = e; | ||
| } | ||
| return this.displayDataCache = t, t; | ||
| } | ||
| scheduleRender() { | ||
| this.renderScheduled || (this.renderScheduled = !0, requestAnimationFrame(() => { | ||
| this.renderScheduled = !1; | ||
| let e = this.getDisplayData(); | ||
| this.viewport.updateData(e, this.options.autoScale !== !1), this.syncRenderContext(), this.engine.requestRender(); | ||
| })); | ||
| } | ||
| updateViewportAndRender(e = !1) { | ||
| this.resolvedLayoutCache = null, this.panelInfoCache = null; | ||
| let t = this.getResolvedLayout(); | ||
| this.viewport.setChartRect(t.mainChartRect); | ||
| let n = this.getDisplayData(); | ||
| if (this.viewport.updateData(n, this.options.autoScale !== !1), this.options.autoScale !== !1) { | ||
| let e = this.viewport.getState(), t = this.indicatorEngine.getOverlayPriceRange(e.visibleRange.from, Math.min(e.visibleRange.to, n.length - 1)); | ||
| if (t) { | ||
| let n = e.priceRange, r = Math.min(n.min, t.min), i = Math.max(n.max, t.max); | ||
| if (r < n.min || i > n.max) { | ||
| let e = i - r || 1; | ||
| this.viewport.setPriceRange(r - e * .02, i + e * .02); | ||
| } | ||
| } | ||
| } | ||
| e && this.viewport.scrollToEnd(), this.syncRenderContext(), this.engine.requestRender(); | ||
| } | ||
| getResolvedLayout() { | ||
| return this.resolvedLayoutCache ||= this.layoutManager.resolve(), this.resolvedLayoutCache; | ||
| } | ||
| cachedContainerSize() { | ||
| let e = Date.now(); | ||
| return (!this.containerSizeCache || e - this.containerSizeCacheTime > 500) && (this.containerSizeCache = this.engine.dprManager.getContainerSize(), this.containerSizeCacheTime = e), this.containerSizeCache; | ||
| } | ||
| buildPanelRenderInfos() { | ||
| if (this.panelInfoCache) return this.panelInfoCache; | ||
| let e = this.getResolvedLayout(), t = this.viewport.getState(), n = e.panels.map((e) => { | ||
| let n = this.indicatorEngine.getOutput(e.config.id), r = 0, i = 100; | ||
| if (n) { | ||
| let e = Infinity, a = -Infinity, { from: o, to: s } = t.visibleRange, c = 0; | ||
| for (let [, t] of n.values) { | ||
| if (c >= o && c <= s) for (let n in t) { | ||
| let r = t[n]; | ||
| r !== void 0 && (r < e && (e = r), r > a && (a = r)); | ||
| } | ||
| c++; | ||
| } | ||
| if (e !== Infinity) { | ||
| let t = a - e || 1; | ||
| r = e - t * .1, i = a + t * .1; | ||
| } | ||
| } | ||
| let a = { | ||
| x: e.rect.x, | ||
| y: e.rect.y + 20, | ||
| width: e.rect.width, | ||
| height: Math.max(0, e.rect.height - 20) | ||
| }; | ||
| return { | ||
| instanceId: e.config.id, | ||
| rect: e.rect, | ||
| viewport: { | ||
| ...t, | ||
| chartRect: a, | ||
| priceRange: { | ||
| min: r, | ||
| max: i | ||
| } | ||
| } | ||
| }; | ||
| }); | ||
| return this.panelInfoCache = n, n; | ||
| } | ||
| syncRenderContext() { | ||
| let e = this.getResolvedLayout(), t = this.features.indicators ? this.buildPanelRenderInfos() : [], n = e.panels.filter((e) => e.config.position === "bottom").reduce((e, t) => e + t.rect.height, 0), r = e.mainChartRect.y + e.mainChartRect.height + n; | ||
| this.engine.setRenderContext({ | ||
| chartRenderer: this.chartRenderer, | ||
| gridRenderer: this.features.grid ? this.gridRenderer : null, | ||
| priceAxis: this.features.priceAxis ? this.priceAxis : null, | ||
| timeAxis: this.features.timeAxis ? this.timeAxis : null, | ||
| crosshairHandler: this.features.crosshair ? this.crosshairHandler : null, | ||
| indicatorEngine: this.features.indicators ? this.indicatorEngine : null, | ||
| drawingRenderer: this.features.drawings ? this.drawingRenderer : null, | ||
| tradingRenderer: this.features.trading ? this.tradingRenderer : null, | ||
| currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine, | ||
| chartLegend: this.features.legend ? this.chartLegend : null, | ||
| volumeRenderer: this.features.volume ? this.volumeRenderer : null, | ||
| watermark: this.features.watermark ? this.watermark : null, | ||
| barCountdown: this.barCountdown, | ||
| sessionBreaks: this.sessionBreaks, | ||
| compareRenderer: this.compareRenderer, | ||
| panels: t, | ||
| priceLimits: this.buildPriceLimits(), | ||
| timeAxisY: r, | ||
| viewport: this.viewport.getState(), | ||
| theme: this.themeManager.getTheme(), | ||
| data: this.getDisplayData(), | ||
| numberLocale: this.numberLocale | ||
| }); | ||
| } | ||
| timeframeToMs(e) { | ||
| let t = e.match(/^(\d+)([smhdwMy])$/); | ||
| if (!t) return 0; | ||
| let n = parseInt(t[1], 10); | ||
| switch (t[2]) { | ||
| case "s": return n * 1e3; | ||
| case "m": return n * 6e4; | ||
| case "h": return n * 36e5; | ||
| case "d": return n * 864e5; | ||
| case "w": return n * 6048e5; | ||
| case "M": return n * 2592e6; | ||
| default: return 0; | ||
| } | ||
| } | ||
| buildPriceLimits() { | ||
| if (!this.marketConfig?.priceLimits?.enabled || !this.marketConfig.priceLimits.referencePrice) return null; | ||
| let e = y(this.marketConfig.priceLimits.referencePrice, this.marketConfig); | ||
| return e ? { | ||
| ...e, | ||
| colors: this.marketConfig.colorScheme ? { | ||
| ceiling: this.marketConfig.colorScheme.ceiling, | ||
| floor: this.marketConfig.colorScheme.floor, | ||
| reference: this.marketConfig.colorScheme.reference | ||
| } : void 0 | ||
| } : null; | ||
| } | ||
| }, Dt = class extends M { | ||
| options; | ||
| constructor(e, t) { | ||
| super(e, t.theme), this.options = t, this.requestRender(); | ||
| } | ||
| renderChart(e, t, n, r) { | ||
| mt(e, t, n, this.options, r); | ||
| pe(e, t, n, this.options, r); | ||
| } | ||
@@ -1021,11 +25,11 @@ update(e) { | ||
| } | ||
| }, Ot = class extends M { | ||
| }, xe = class extends F { | ||
| options; | ||
| crosshair = null; | ||
| constructor(e, t) { | ||
| super(e, t.theme), this.options = t, t.crosshair !== !1 && (this.crosshair = new V(this.canvas, () => this.requestRender())), this.requestRender(); | ||
| super(e, t.theme), this.options = t, t.crosshair !== !1 && (this.crosshair = new K(this.canvas, () => this.requestRender())), this.requestRender(); | ||
| } | ||
| renderChart(e, t, n, r) { | ||
| let i = this.crosshair?.getPosition() ?? null; | ||
| ut(e, t, n, this.options, r, i); | ||
| le(e, t, n, this.options, r, i); | ||
| } | ||
@@ -1047,11 +51,11 @@ update(e) { | ||
| } | ||
| }, kt = class extends M { | ||
| }, Se = class extends F { | ||
| options; | ||
| crosshair = null; | ||
| constructor(e, t) { | ||
| super(e, t.theme), this.options = t, t.crosshair !== !1 && (this.crosshair = new V(this.canvas, () => this.requestRender())), this.requestRender(); | ||
| super(e, t.theme), this.options = t, t.crosshair !== !1 && (this.crosshair = new K(this.canvas, () => this.requestRender())), this.requestRender(); | ||
| } | ||
| renderChart(e, t, n, r) { | ||
| let i = this.crosshair?.getPosition() ?? null; | ||
| dt(e, t, n, this.options, r, i); | ||
| ue(e, t, n, this.options, r, i); | ||
| } | ||
@@ -1076,3 +80,3 @@ update(e, t) { | ||
| } | ||
| }, At = class extends M { | ||
| }, Ce = class extends F { | ||
| options; | ||
@@ -1086,3 +90,3 @@ crosshair = null; | ||
| constructor(e, t) { | ||
| super(e, t.theme), this.options = t, this.currentData = t.data ?? [], t.crosshair !== !1 && (this.crosshair = new V(this.canvas, () => this.requestRender())), t.onCellClick && (this.handleClick = (e) => { | ||
| super(e, t.theme), this.options = t, this.currentData = t.data ?? [], t.crosshair !== !1 && (this.crosshair = new K(this.canvas, () => this.requestRender())), t.onCellClick && (this.handleClick = (e) => { | ||
| let t = this.canvas.getBoundingClientRect(), n = e.clientX - t.left, r = e.clientY - t.top; | ||
@@ -1099,6 +103,9 @@ this.onCanvasClick(n, r); | ||
| }, t = this.options.cellPadding ?? 2; | ||
| this.lastLayoutWidth = this.width, this.lastLayoutHeight = this.height, this.options.weighted ? this.cachedRects = st(this.currentData.map((e) => ({ | ||
| id: e.id, | ||
| weight: e.weight ?? (Math.abs(e.value) || 1) | ||
| })), e, t) : this.cachedRects = ct(this.currentData.map((e) => ({ id: e.id })), e, t); | ||
| if (this.lastLayoutWidth = this.width, this.lastLayoutHeight = this.height, this.options.weighted) { | ||
| let n = this.currentData.map((e) => ({ | ||
| id: e.id, | ||
| weight: e.weight ?? (Math.abs(e.value) || 1) | ||
| })); | ||
| this.cachedRects = se(n, e, t); | ||
| } else this.cachedRects = ce(this.currentData.map((e) => ({ id: e.id })), e, t); | ||
| } | ||
@@ -1118,3 +125,3 @@ onCanvasClick(e, t) { | ||
| let i = this.crosshair?.getPosition() ?? null; | ||
| pt(e, t, n, this.currentData, this.cachedRects, this.options, r, i); | ||
| fe(e, t, n, this.currentData, this.cachedRects, this.options, r, i); | ||
| } | ||
@@ -1136,11 +143,11 @@ update(e) { | ||
| } | ||
| }, jt = class extends M { | ||
| }, we = class extends F { | ||
| options; | ||
| crosshair = null; | ||
| constructor(e, t) { | ||
| super(e, t.theme), this.options = t, t.crosshair !== !1 && (this.crosshair = new V(this.canvas, () => this.requestRender())), this.requestRender(); | ||
| super(e, t.theme), this.options = t, t.crosshair !== !1 && (this.crosshair = new K(this.canvas, () => this.requestRender())), this.requestRender(); | ||
| } | ||
| renderChart(e, t, n, r) { | ||
| let i = this.crosshair?.getPosition() ?? null; | ||
| ht(e, t, n, this.options, r, i); | ||
| me(e, t, n, this.options, r, i); | ||
| } | ||
@@ -1162,8 +169,8 @@ update(e) { | ||
| } | ||
| }, Mt = 500; | ||
| function Nt(e) { | ||
| }, Te = 500; | ||
| function Ee(e) { | ||
| let t = 1 - e; | ||
| return 1 - t * t * t; | ||
| } | ||
| var Pt = class extends M { | ||
| var De = class extends F { | ||
| options; | ||
@@ -1179,3 +186,3 @@ currentValue; | ||
| renderChart(e, t, n, r) { | ||
| ft(e, t, n, this.options, r, this.currentValue); | ||
| de(e, t, n, this.options, r, this.currentValue); | ||
| } | ||
@@ -1210,3 +217,3 @@ setValue(e) { | ||
| if (this.animationFrameId = null, this.animationStart === null) return; | ||
| let t = this.options.animationDuration ?? Mt, n = performance.now() - this.animationStart, r = Math.min(1, n / Math.max(1, t)), i = Nt(r); | ||
| let t = this.options.animationDuration ?? Te, n = performance.now() - this.animationStart, r = Math.min(1, n / Math.max(1, t)), i = Ee(r); | ||
| this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * i, this.requestRender(), r < 1 ? this.animationFrameId = requestAnimationFrame(e) : (this.currentValue = this.targetValue, this.animationStart = null); | ||
@@ -1224,4 +231,4 @@ }; | ||
| //#endregion | ||
| export { w as AlertManager, E as Animator, k as BarCountdown, P as BinanceAdapter, Et as Chart, I as ChartLegend, R as ChartStateManager, he as CompareRenderer, ve as CrosshairTooltip, be as CurrentPriceLine, e as DARK_TERMINAL, t as DARK_THEME, r as DEFAULT_DRAWING_STYLE, Se as DEFAULT_LEGEND_CONFIG, a as DEFAULT_RECONNECT, o as DEFAULT_STREAM_CONFIG, s as DEFAULT_TIMEFRAME_FAVORITES, c as DEFAULT_TRADING_CONFIG, Ce as DataExporter, J as DataManager, Ot as DepthChart, we as DrawingBase, De as Easing, kt as EquityCurveChart, Pt as GaugeChart, At as HeatmapChart, je as IndicatorBase, Pe as KeyboardHandler, l as LIGHT_THEME, Q as LayoutManager, f as MARKET_CRYPTO, ee as MARKET_HNX, p as MARKET_HOSE, m as MARKET_NYSE, h as MARKET_UPCOM, Le as MockAdapter, $ as PluginManager, Ue as ReplayManager, We as Screenshot, Ge as SessionBreaks, Dt as SparklineChart, qe as StreamManager, te as TIMEFRAMES_CRYPTO, ne as TIMEFRAMES_FOREX, re as TIMEFRAMES_STOCK, Y as ThemeManager, Ye as TickAggregator, $e as UndoRedoManager, ie as VN_COLORS, nt as VolumeRenderer, jt as WaterfallChart, it as Watermark, ae as computePriceLimits, oe as createVNTheme, se as formatNumber, ce as formatVND, le as formatVolumeLoc, ue as getCurrentSession, de as getLocale, pe as normalizeBar, me as normalizeBarTime, b as registerLocale, x as setLocale, C as t, gt as toHeikinAshi, vt as toKagi, bt as toLineBreak, St as toPointAndFigure, wt as toRenko }; | ||
| export { M as AlertManager, N as Animator, P as BarCountdown, I as BinanceAdapter, i as Chart, L as ChartLegend, R as ChartStateManager, z as CompareRenderer, B as CrosshairTooltip, V as CurrentPriceLine, a as DARK_TERMINAL, ee as DARK_THEME, te as DEFAULT_DRAWING_STYLE, H as DEFAULT_LEGEND_CONFIG, o as DEFAULT_RECONNECT, s as DEFAULT_STREAM_CONFIG, c as DEFAULT_TIMEFRAME_FAVORITES, l as DEFAULT_TRADING_CONFIG, U as DataExporter, e as DataManager, xe as DepthChart, W as DrawingBase, G as Easing, Se as EquityCurveChart, De as GaugeChart, Ce as HeatmapChart, q as IndicatorBase, J as KeyboardHandler, u as LIGHT_THEME, r as LayoutManager, d as MARKET_CRYPTO, f as MARKET_HNX, p as MARKET_HOSE, m as MARKET_NYSE, h as MARKET_UPCOM, Y as MockAdapter, n as PluginManager, X as ReplayManager, Z as Screenshot, Q as SessionBreaks, $ as SparklineChart, ne as StreamManager, g as TIMEFRAMES_CRYPTO, _ as TIMEFRAMES_FOREX, v as TIMEFRAMES_STOCK, t as ThemeManager, re as TickAggregator, ie as UndoRedoManager, y as VN_COLORS, ae as VolumeRenderer, we as WaterfallChart, oe as Watermark, b as computePriceLimits, x as createVNTheme, S as formatNumber, C as formatVND, w as formatVolumeLoc, T as getCurrentSession, E as getLocale, D as normalizeBar, O as normalizeBarTime, k as registerLocale, A as setLocale, j as t, he as toHeikinAshi, ge as toKagi, _e as toLineBreak, ve as toPointAndFigure, ye as toRangeBars, be as toRenko }; | ||
| //# sourceMappingURL=index.js.map |
+14
-4
| { | ||
| "name": "@tradecanvas/chart", | ||
| "version": "0.5.0", | ||
| "version": "0.6.0", | ||
| "type": "module", | ||
@@ -38,2 +38,7 @@ "description": "High-performance canvas trading chart with built-in indicators, drawing tools, and real-time streaming. Zero external dependencies.", | ||
| "require": "./dist/index.cjs" | ||
| }, | ||
| "./widget": { | ||
| "types": "./dist/widget/index.d.ts", | ||
| "import": "./dist/widget/index.js", | ||
| "require": "./dist/widget/index.cjs" | ||
| } | ||
@@ -46,10 +51,15 @@ }, | ||
| "dependencies": { | ||
| "@tradecanvas/commons": "0.5.0", | ||
| "@tradecanvas/core": "0.5.0" | ||
| "@tradecanvas/commons": "0.6.0", | ||
| "@tradecanvas/core": "0.6.0" | ||
| }, | ||
| "devDependencies": { | ||
| "vitest": "^2.1.8" | ||
| }, | ||
| "scripts": { | ||
| "build": "vite build", | ||
| "dev": "vite build --watch", | ||
| "clean": "rm -rf dist" | ||
| "clean": "rm -rf dist", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest" | ||
| } | ||
| } |
+109
-6
@@ -11,3 +11,3 @@ # @tradecanvas/chart | ||
| - **20+ built-in indicators** — MA, EMA, RSI, MACD, Bollinger, Ichimoku, and more. No separate calculation library needed. | ||
| - **33+ built-in indicators** — MA, EMA, Hull MA, RSI, MACD, Bollinger, Ichimoku, Pivot Points, Anchored VWAP, ZigZag, Linear Regression Channel, Awesome / Chaikin Oscillator, and more. No separate calculation library needed. | ||
| - **10+ drawing tools** — Trendlines, Fibonacci retracement, horizontal/vertical lines, rectangles, channels, Elliott waves, Gann fans. With undo/redo. | ||
@@ -59,2 +59,51 @@ - **Trading overlay** — Render open positions with entry line, P&L zone, and SL/TP markers. Orders as dashed lines. Users can drag SL/TP to modify. | ||
| ## Widget (Complete UI) | ||
| For a complete TradingView-like experience with built-in toolbar, drawing tools, and settings — no UI code needed: | ||
| ```typescript | ||
| import { ChartWidget } from '@tradecanvas/chart/widget' | ||
| import { BinanceAdapter } from '@tradecanvas/chart' | ||
| const widget = new ChartWidget(document.getElementById('chart')!, { | ||
| symbol: 'BTCUSDT', | ||
| timeframe: '5m', | ||
| adapter: new BinanceAdapter(), | ||
| theme: 'dark', | ||
| }) | ||
| ``` | ||
| That's it. Full toolbar, drawing sidebar, settings modal, and status bar — all included. | ||
| ### Widget Options | ||
| | Option | Type | Default | Description | | ||
| |---|---|---|---| | ||
| | `symbol` | `string` | `'BTCUSDT'` | Initial trading symbol | | ||
| | `timeframe` | `TimeFrame` | `'5m'` | Initial timeframe | | ||
| | `theme` | `'dark' \| 'light' \| Theme` | `'dark'` | Chart theme | | ||
| | `adapter` | `DataAdapter` | — | Data source adapter | | ||
| | `toolbar` | `boolean` | `true` | Show top toolbar | | ||
| | `drawingTools` | `boolean` | `true` | Show left drawing sidebar | | ||
| | `settings` | `boolean` | `true` | Show settings button | | ||
| | `trading` | `boolean` | `true` | Enable trading overlay | | ||
| | `statusBar` | `boolean` | `true` | Show bottom status bar | | ||
| | `symbols` | `string[]` | BTC/ETH/SOL/BNB | Available symbols | | ||
| | `timeframes` | `TimeFrame[]` | 1m to 1d | Available timeframes | | ||
| | `chartTypes` | `ChartType[]` | 7 types | Available chart types | | ||
| | `onSymbolChange` | `(symbol) => void` | — | Symbol change callback | | ||
| | `onTimeframeChange` | `(tf) => void` | — | Timeframe change callback | | ||
| | `onReady` | `(chart) => void` | — | Fired when chart is ready | | ||
| ### Widget vs Headless | ||
| | | `Chart` (headless) | `ChartWidget` | | ||
| |---|---|---| | ||
| | Import | `@tradecanvas/chart` | `@tradecanvas/chart/widget` | | ||
| | UI included | None — build your own | Complete toolbar, sidebar, settings | | ||
| | Bundle impact | ~50 KB gzip | ~65 KB gzip (includes UI) | | ||
| | Framework | Any (React, Vue, Svelte, vanilla) | Vanilla JS DOM (works everywhere) | | ||
| | Customization | Full control | Toggle sections on/off | | ||
| | Advanced access | Direct API | `widget.getChart()` for direct API | | ||
| ## Features | ||
@@ -77,2 +126,3 @@ | ||
| | Line Break | Three-line break charts | | ||
| | Range Bars | Fixed price-range bars — each bar's high − low equals a configured range | | ||
@@ -132,7 +182,9 @@ ### Finance Charts | ||
| **Overlay** (drawn on the price chart): | ||
| SMA, EMA, Bollinger Bands, Keltner Channel, Donchian Channel, Ichimoku Cloud, Parabolic SAR, Supertrend, VWAP | ||
| SMA, EMA, Hull MA, Bollinger Bands, Keltner Channel, Donchian Channel, Ichimoku Cloud, Parabolic SAR, Supertrend, VWAP, Anchored VWAP, Pivot Points (Classic), ZigZag, Linear Regression Channel | ||
| **Panel** (separate sub-chart): | ||
| RSI, MACD, Stochastic, ATR, ADX, CCI, CMF, MFI, OBV, ROC, TSI, Williams %R, Volume Profile, VROC, Standard Deviation, Accumulation/Distribution, Aroon | ||
| RSI, MACD, Stochastic, ATR, ADX, CCI, CMF, MFI, OBV, ROC, TSI, Williams %R, Awesome Oscillator, Chaikin Oscillator, Volume Profile, VROC, Standard Deviation, Accumulation/Distribution, Aroon | ||
| All indicator parameters are validated at runtime — invalid values (NaN, Infinity, non-numeric strings, missing keys) fall back to documented defaults instead of silently propagating to calculations. | ||
| ### Drawing Tools | ||
@@ -160,2 +212,3 @@ | ||
| quantity: 1.5, | ||
| closedQuantity: 0.5, // partial close — visualized as a left-edge dim band | ||
| stopLoss: 3400, | ||
@@ -175,2 +228,14 @@ takeProfit: 3700, | ||
| // Customize the position zone color via P&L thresholds | ||
| chart.setTradingConfig({ | ||
| pnlThresholds: [ | ||
| { pnl: -Infinity, color: '#b91c1c' }, | ||
| { pnl: 0, color: '#94a3b8' }, | ||
| { pnl: 50, color: '#16a34a' }, | ||
| { pnl: 200, color: '#15803d' }, | ||
| ], | ||
| // Custom label template — tokens: {side} {qty} {openQty} {closedQty} {entry} {price} {pnl} {pnlPct} {pnlSign} | ||
| positionLabel: '{side} {openQty}/{qty} @ {entry} | {pnlSign}{pnl} ({pnlPct})', | ||
| }) | ||
| // Listen for user drag-to-modify | ||
@@ -199,2 +264,39 @@ chart.on('positionModify', (e) => console.log('SL/TP moved:', e.payload)) | ||
| ### Web Worker indicator pipeline | ||
| Heavy charts (1,000+ bars × 10+ indicators) can stutter when `calculate()` runs on the main thread. `IndicatorWorkerHost` offloads calculation to a worker so the render loop stays smooth. | ||
| ```typescript | ||
| import { IndicatorWorkerHost } from '@tradecanvas/core' | ||
| // Bundler-supported worker URL (Vite, webpack 5, esbuild, etc.) | ||
| const worker = new Worker( | ||
| new URL('@tradecanvas/core/dist/indicator.worker.js', import.meta.url), | ||
| { type: 'module' }, | ||
| ) | ||
| const host = new IndicatorWorkerHost(worker, { timeoutMs: 30_000 }) | ||
| const output = await host.calculate( | ||
| 'rsi', | ||
| { id: 'rsi', instanceId: 'rsi-1', params: { period: 14 } }, | ||
| bars, | ||
| ) | ||
| // Health check / cleanup | ||
| await host.ping() | ||
| host.terminate() | ||
| ``` | ||
| No worker available (SSR, tests, or as a safety net)? Pass `null` and register fallback plugins for synchronous calculation: | ||
| ```typescript | ||
| import { IndicatorWorkerHost, RSIIndicator } from '@tradecanvas/core' | ||
| const host = new IndicatorWorkerHost(null) | ||
| host.registerFallbackPlugin(new RSIIndicator()) | ||
| const output = await host.calculate('rsi', config, bars) // runs synchronously | ||
| ``` | ||
| Render still happens on the main thread (it needs `CanvasRenderingContext2D`). Only the heavy compute moves off-thread. | ||
| ### Save / Load | ||
@@ -255,5 +357,5 @@ | ||
| |---|---|---|---|---| | ||
| | Chart types | 11 + 4 finance | 4 | 8 (non-financial) | 10+ | | ||
| | Finance charts | Sparkline, Depth, Equity, Heatmap | None | None | Some | | ||
| | Built-in indicators | 20+ | 0 | 0 | ~30 | | ||
| | Chart types | 12 + 6 finance | 4 | 8 (non-financial) | 10+ | | ||
| | Finance charts | Sparkline, Depth, Equity, Heatmap, Waterfall, Gauge | None | None | Some | | ||
| | Built-in indicators | 33+ | 0 | 0 | ~30 | | ||
| | Drawing tools | 23 | 0 | 0 | Some | | ||
@@ -267,2 +369,3 @@ | Trading overlay | Full (pos + orders + drag) | None | None | None | | ||
| | Dependencies | 0 | 1 | 0 | 0 | | ||
| | Widget (complete UI) | Yes (`ChartWidget`) | No | No | No | | ||
| | License | MIT | Apache 2.0 | MIT | Commercial | | ||
@@ -269,0 +372,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
654760
78.7%73
97.3%4087
120.56%546
23.25%1
Infinity%4
33.33%3
Infinity%1
Infinity%+ Added
+ Added
- Removed
- Removed
Updated
Updated