@tradecanvas/chart 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +570 -545
- package/dist/Chart-BVaoFQh0.cjs +2 -0
- package/dist/Chart-BVaoFQh0.cjs.map +1 -0
- package/dist/{Chart-CrrTKx3r.js → Chart-Cy8K3wHS.js} +129 -51
- package/dist/Chart-Cy8K3wHS.js.map +1 -0
- package/dist/Chart.d.ts +24 -0
- package/dist/Chart.d.ts.map +1 -1
- package/dist/charts/ChartTypeStrategy.d.ts.map +1 -1
- package/dist/grid/ChartGrid.d.ts +39 -0
- package/dist/grid/ChartGrid.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +181 -26
- package/dist/index.js.map +1 -1
- package/dist/widget/ChartWidget.d.ts +5 -0
- package/dist/widget/ChartWidget.d.ts.map +1 -1
- package/dist/widget/WidgetCommandPalette.d.ts +39 -0
- package/dist/widget/WidgetCommandPalette.d.ts.map +1 -0
- package/dist/widget/index.cjs +877 -739
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.js +263 -5
- package/dist/widget/index.js.map +1 -1
- package/dist/widget/widgetConfig.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/Chart-CrrTKx3r.js.map +0 -1
- package/dist/Chart-DoR8L8Uk.cjs +0 -2
- package/dist/Chart-DoR8L8Uk.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
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";
|
|
2
|
-
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
|
|
2
|
+
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 ne, CrosshairTooltip as re, CurrentPriceLine as ie, DataExporter as y, DrawingManager as ae, DrawingRenderer as oe, EventBus as se, GridRenderer as ce, HLCAreaRenderer as le, HollowCandleRenderer as ue, IndicatorEngine as b, InteractionManager as de, KagiRenderer as fe, KeyboardHandler as x, LineRenderer as S, LineWithMarkersRenderer as C, PanHandler as w, PointAndFigureRenderer as T, PriceAxis as E, RenderEngine as D, RenkoRenderer as O, ReplayManager as k, Screenshot as A, SessionBreaks as j, SignalMarkerManager as M, StepLineRenderer as N, StreamManager as P, TimeAxis as F, TradeZoneManager as I, TradingManager as L, TradingRenderer as R, UndoRedoManager as z, Viewport as B, VolumeCandleRenderer as V, VolumeRenderer as pe, Watermark as me, ZoomHandler as he, registerBuiltInDrawingTools as ge, registerBuiltInIndicators as H, toHeikinAshi as _e, toKagi as ve, toLineBreak as ye, toPointAndFigure as be, toRangeBars as xe, toRenko as Se } from "@tradecanvas/core";
|
|
3
3
|
//#region src/charts/ChartTypeStrategy.ts
|
|
4
|
-
function
|
|
4
|
+
function Ce(e) {
|
|
5
5
|
switch (e) {
|
|
6
6
|
case "candlestick":
|
|
7
7
|
case "heikinAshi":
|
|
@@ -10,27 +10,31 @@ function _e(e) {
|
|
|
10
10
|
case "line": return new S();
|
|
11
11
|
case "area": return new p();
|
|
12
12
|
case "bar": return new ee();
|
|
13
|
-
case "hollowCandle": return new
|
|
13
|
+
case "hollowCandle": return new ue();
|
|
14
14
|
case "baseline": return new h();
|
|
15
|
-
case "renko": return new
|
|
16
|
-
case "kagi": return new
|
|
17
|
-
case "pointAndFigure": return new
|
|
15
|
+
case "renko": return new O();
|
|
16
|
+
case "kagi": return new fe();
|
|
17
|
+
case "pointAndFigure": return new T();
|
|
18
|
+
case "volumeCandles": return new V();
|
|
19
|
+
case "hlcArea": return new le();
|
|
20
|
+
case "stepLine": return new N();
|
|
21
|
+
case "lineWithMarkers": return new C();
|
|
18
22
|
default: return new g();
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
|
-
function
|
|
25
|
+
function we(e, t) {
|
|
22
26
|
if (t.length === 0) return t;
|
|
23
27
|
switch (e) {
|
|
24
|
-
case "heikinAshi": return
|
|
25
|
-
case "renko": return
|
|
28
|
+
case "heikinAshi": return _e(t);
|
|
29
|
+
case "renko": return Se(t, {
|
|
26
30
|
brickSize: 0,
|
|
27
31
|
useATR: !0,
|
|
28
32
|
atrPeriod: 14
|
|
29
33
|
});
|
|
30
|
-
case "lineBreak": return
|
|
31
|
-
case "kagi": return
|
|
32
|
-
case "pointAndFigure": return
|
|
33
|
-
case "rangeBars": return
|
|
34
|
+
case "lineBreak": return ye(t, 3);
|
|
35
|
+
case "kagi": return ve(t, 4);
|
|
36
|
+
case "pointAndFigure": return be(t, U(t) * .01, 3);
|
|
37
|
+
case "rangeBars": return xe(t, { rangeSize: U(t) * .005 });
|
|
34
38
|
default: return t;
|
|
35
39
|
}
|
|
36
40
|
}
|
|
@@ -45,7 +49,7 @@ var W = {
|
|
|
45
49
|
min: 0,
|
|
46
50
|
max: 100
|
|
47
51
|
}, G = .1;
|
|
48
|
-
function
|
|
52
|
+
function Te(e, t, n) {
|
|
49
53
|
if (!e) return { ...W };
|
|
50
54
|
let r = Infinity, i = -Infinity, a = 0;
|
|
51
55
|
for (let [, o] of e.values) {
|
|
@@ -64,7 +68,7 @@ function ye(e, t, n) {
|
|
|
64
68
|
}
|
|
65
69
|
//#endregion
|
|
66
70
|
//#region src/state/AutoSaveScheduler.ts
|
|
67
|
-
var
|
|
71
|
+
var Ee = class {
|
|
68
72
|
timer = null;
|
|
69
73
|
delayMs = 0;
|
|
70
74
|
key = null;
|
|
@@ -282,8 +286,8 @@ var J = class {
|
|
|
282
286
|
registerIndicator(e) {
|
|
283
287
|
this.indicatorEngine.register(e);
|
|
284
288
|
}
|
|
285
|
-
},
|
|
286
|
-
static version = "0.
|
|
289
|
+
}, De = class {
|
|
290
|
+
static version = "0.7.0";
|
|
287
291
|
engine;
|
|
288
292
|
viewport;
|
|
289
293
|
dataManager;
|
|
@@ -312,9 +316,11 @@ var J = class {
|
|
|
312
316
|
countdownInterval = null;
|
|
313
317
|
volumeRenderer;
|
|
314
318
|
alertManager;
|
|
319
|
+
signalMarkerManager;
|
|
320
|
+
tradeZoneManager;
|
|
315
321
|
replayManager;
|
|
316
322
|
undoRedoManager;
|
|
317
|
-
autoSaveScheduler = new
|
|
323
|
+
autoSaveScheduler = new Ee((e) => this.saveState(e));
|
|
318
324
|
animator;
|
|
319
325
|
crosshairTooltip;
|
|
320
326
|
interactionManager;
|
|
@@ -365,19 +371,19 @@ var J = class {
|
|
|
365
371
|
logScale: n.logScale ?? !0,
|
|
366
372
|
timeframes: n.timeframes ?? [],
|
|
367
373
|
defaultTimeframeFavorites: n.defaultTimeframeFavorites ?? []
|
|
368
|
-
}, 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
|
|
374
|
+
}, 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 b(), this.pluginManager = new $(this.indicatorEngine), this.eventBus = new se(), H(this.indicatorEngine), this.drawingManager = new ae(), ge(this.drawingManager), this.drawingRenderer = new oe(this.drawingManager), this.drawingManager.setRequestRender(() => {
|
|
369
375
|
this.syncRenderContext(), this.engine.requestRender(r.Overlay), this.scheduleAutoSave();
|
|
370
376
|
}), this.drawingManager.setEventCallback((e, t) => {
|
|
371
377
|
this.eventBus.emit(e, t);
|
|
372
|
-
}), this.undoRedoManager = new
|
|
378
|
+
}), this.undoRedoManager = new z(), 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 L(), this.tradingRenderer = new R(this.tradingManager), this.tradingManager.setContainer(e), this.tradingManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradingManager.setEventCallback((e, t) => {
|
|
373
379
|
this.eventBus.emit(e, t);
|
|
374
|
-
}), this.engine = new
|
|
380
|
+
}), this.engine = new D(e);
|
|
375
381
|
let i = this.engine.dprManager.getContainerSize();
|
|
376
|
-
this.viewport = new
|
|
382
|
+
this.viewport = new B(i.width, i.height, t.minBarSpacing ?? 2, t.maxBarSpacing ?? 30, t.rightMargin ?? 5), this.layoutManager.resize(i.width, i.height), this.engine.onContainerResize = (e) => {
|
|
377
383
|
if (e.width <= 0 || e.height <= 0) return;
|
|
378
384
|
let t = this.viewport.isAtEnd();
|
|
379
385
|
this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(t);
|
|
380
|
-
}, this.chartRenderer = this.createChartRenderer(t.chartType), this.gridRenderer = new
|
|
386
|
+
}, this.chartRenderer = this.createChartRenderer(t.chartType), this.gridRenderer = new ce(), t.grid?.visible === !1 && this.gridRenderer.setVisible(!1), this.priceAxis = new E(), this.priceAxis.setLocale(this.numberLocale), this.timeAxis = new F(), this.crosshairHandler = new ne(), this.crosshairHandler.setLocale(this.numberLocale), t.crosshair?.mode && this.crosshairHandler.setMode(t.crosshair.mode), this.crosshairHandler.setCallback((e, t) => {
|
|
381
387
|
if (e !== null && t) {
|
|
382
388
|
let n = this.dataManager.getData(), r = e < n.length ? n[e] : void 0;
|
|
383
389
|
this.chartLegend.setHoverBar(r ?? null), r && this.crosshairTooltip.show(t, r, this.themeManager.getTheme(), this.cachedContainerSize()), this.eventBus.emit("crosshairMove", {
|
|
@@ -386,12 +392,12 @@ var J = class {
|
|
|
386
392
|
barIndex: e
|
|
387
393
|
});
|
|
388
394
|
} else this.crosshairTooltip.hide(), this.chartLegend.setHoverBar(null);
|
|
389
|
-
}), this.chartLegend = new te(), this.chartLegend.setChartType(t.chartType), this.watermark = new
|
|
395
|
+
}), this.chartLegend = new te(), this.chartLegend.setChartType(t.chartType), this.watermark = new me(), t.watermark && this.watermark.setConfig(t.watermark), this.volumeRenderer = new pe(), this.barCountdown = new m(), this.sessionBreaks = new j(), this.compareRenderer = new v(), t.sessionBreaks ? this.sessionBreaks.setConfig({
|
|
390
396
|
visible: t.sessionBreaks.visible ?? !0,
|
|
391
397
|
color: t.sessionBreaks.color,
|
|
392
398
|
lineStyle: t.sessionBreaks.lineStyle,
|
|
393
399
|
lineWidth: t.sessionBreaks.lineWidth
|
|
394
|
-
}) : t.features?.sessionBreaks !== !1 && this.sessionBreaks.setVisible(!0), t.logScale && this.viewport.setLogScale(!0), this.animator = new f(), this.crosshairTooltip = new
|
|
400
|
+
}) : t.features?.sessionBreaks !== !1 && this.sessionBreaks.setVisible(!0), t.logScale && this.viewport.setLogScale(!0), this.animator = new f(), this.crosshairTooltip = new re(), this.crosshairTooltip.create(e), this.keyboardHandler = new x({
|
|
395
401
|
scrollBars: (e) => {
|
|
396
402
|
let t = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;
|
|
397
403
|
this.viewport.scrollBy(e * t), this.updateViewportAndRender();
|
|
@@ -411,18 +417,39 @@ var J = class {
|
|
|
411
417
|
if (!this.keyboardHandler) return;
|
|
412
418
|
let t = document.activeElement;
|
|
413
419
|
t && t !== this.container && !this.container.contains(t) || t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) || this.keyboardHandler.handleKey(e) && e.preventDefault();
|
|
414
|
-
}, window.addEventListener("keydown", this.onWindowKeyDown), this.currentPriceLine = new
|
|
420
|
+
}, window.addEventListener("keydown", this.onWindowKeyDown), this.currentPriceLine = new ie(), this.alertManager = new d(), this.alertManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.alertManager.on("triggered", (e) => {
|
|
415
421
|
this.eventBus.emit("dataUpdate", {
|
|
416
422
|
alert: "triggered",
|
|
417
423
|
alertId: e.id,
|
|
418
424
|
price: e.price,
|
|
419
425
|
message: e.message
|
|
420
426
|
});
|
|
421
|
-
}), this.
|
|
427
|
+
}), this.signalMarkerManager = new M(), this.signalMarkerManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.signalMarkerManager.setDataGetter(() => this.dataManager.getData()), this.signalMarkerManager.on("added", (e) => {
|
|
428
|
+
this.eventBus.emit("signalMarkerAdd", {
|
|
429
|
+
id: e.id,
|
|
430
|
+
source: e.source,
|
|
431
|
+
direction: e.direction
|
|
432
|
+
});
|
|
433
|
+
}), this.signalMarkerManager.on("removed", (e) => {
|
|
434
|
+
this.eventBus.emit("signalMarkerRemove", { id: e });
|
|
435
|
+
}), this.tradeZoneManager = new I(), this.tradeZoneManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradeZoneManager.setDataGetter(() => this.dataManager.getData()), this.tradeZoneManager.on("added", (e) => {
|
|
436
|
+
this.eventBus.emit("tradeZoneAdd", {
|
|
437
|
+
id: e.id,
|
|
438
|
+
direction: e.direction
|
|
439
|
+
});
|
|
440
|
+
}), this.tradeZoneManager.on("removed", (e) => {
|
|
441
|
+
this.eventBus.emit("tradeZoneRemove", { id: e });
|
|
442
|
+
}), this.replayManager = new k(), this.interactionManager = new de(e), this.features.panning && this.interactionManager.setPanHandler(new w((e) => {
|
|
422
443
|
this.viewport.scrollBy(e), this.updateViewportAndRender();
|
|
423
|
-
})), this.features.zooming && this.interactionManager.setZoomHandler(new
|
|
444
|
+
})), this.features.zooming && this.interactionManager.setZoomHandler(new he((e, t) => {
|
|
424
445
|
this.viewport.zoom(e, t), this.updateViewportAndRender();
|
|
425
|
-
})), this.features.crosshair && this.interactionManager.setCrosshairHandler(this.crosshairHandler), this.features.drawings && this.interactionManager.setDrawingManager(this.drawingManager, () =>
|
|
446
|
+
})), this.features.crosshair && this.interactionManager.setCrosshairHandler(this.crosshairHandler), this.features.drawings && this.interactionManager.setDrawingManager(this.drawingManager, () => ({
|
|
447
|
+
...this.viewport.getState(),
|
|
448
|
+
data: this.getDisplayData()
|
|
449
|
+
})), this.features.trading && this.interactionManager.setTradingManager(this.tradingManager, () => ({
|
|
450
|
+
...this.viewport.getState(),
|
|
451
|
+
data: this.getDisplayData()
|
|
452
|
+
})), this.interactionManager.setOverlayDirtyCallback(() => {
|
|
426
453
|
this.engine.requestRender(r.Overlay), this.layoutManager.getPanels().length > 0 && this.engine.requestRender(r.UI);
|
|
427
454
|
}), this.interactionManager.attach(), this.syncRenderContext(), this.engine.start();
|
|
428
455
|
}
|
|
@@ -469,8 +496,8 @@ var J = class {
|
|
|
469
496
|
this.pluginManager.registerIndicator(e);
|
|
470
497
|
}
|
|
471
498
|
static indicators() {
|
|
472
|
-
let e = new
|
|
473
|
-
return
|
|
499
|
+
let e = new b();
|
|
500
|
+
return H(e), e.getAvailableIndicators();
|
|
474
501
|
}
|
|
475
502
|
setPanelPosition(e, t) {
|
|
476
503
|
this.layoutManager.setPanelPosition(e, t), this.engine.requestRender();
|
|
@@ -536,21 +563,21 @@ var J = class {
|
|
|
536
563
|
exportVisibleData(e = "csv", t) {
|
|
537
564
|
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);
|
|
538
565
|
if (e === "json") {
|
|
539
|
-
let e =
|
|
540
|
-
|
|
566
|
+
let e = y.toJSON(o);
|
|
567
|
+
y.download(e, t ?? "chart-data.json", "application/json");
|
|
541
568
|
} else {
|
|
542
|
-
let e =
|
|
543
|
-
|
|
569
|
+
let e = y.toCSV(o);
|
|
570
|
+
y.download(e, t ?? "chart-data.csv", "text/csv");
|
|
544
571
|
}
|
|
545
572
|
}
|
|
546
573
|
exportAllData(e = "csv", t) {
|
|
547
574
|
let n = this.dataManager.getData();
|
|
548
575
|
if (e === "json") {
|
|
549
|
-
let e =
|
|
550
|
-
|
|
576
|
+
let e = y.toJSON(n);
|
|
577
|
+
y.download(e, t ?? "chart-data.json", "application/json");
|
|
551
578
|
} else {
|
|
552
|
-
let e =
|
|
553
|
-
|
|
579
|
+
let e = y.toCSV(n);
|
|
580
|
+
y.download(e, t ?? "chart-data.csv", "text/csv");
|
|
554
581
|
}
|
|
555
582
|
}
|
|
556
583
|
setAutoSave(e, t = 5e3) {
|
|
@@ -601,7 +628,7 @@ var J = class {
|
|
|
601
628
|
this.features.trading && this.tradingManager.setConfig(e);
|
|
602
629
|
}
|
|
603
630
|
async connect(e) {
|
|
604
|
-
this.disconnectStream(), this.streamManager = new
|
|
631
|
+
this.disconnectStream(), this.streamManager = new P(), this.streamManager.on("snapshot", (e) => {
|
|
605
632
|
this.setData(e);
|
|
606
633
|
}), this.streamManager.on("barClose", (e) => {
|
|
607
634
|
this.dataManager.appendBar(e), this.crosshairHandler.setData(this.dataManager.getData()), this.autoScrollOnNewBar && this.viewport.scrollToEnd(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.updateViewportAndRender();
|
|
@@ -753,6 +780,12 @@ var J = class {
|
|
|
753
780
|
getCrosshairMode() {
|
|
754
781
|
return this.crosshairHandler.getMode();
|
|
755
782
|
}
|
|
783
|
+
setCrosshairPosition(e) {
|
|
784
|
+
e && this.crosshairHandler.onPointerMove(e), this.engine.requestRender(r.Overlay);
|
|
785
|
+
}
|
|
786
|
+
getData() {
|
|
787
|
+
return this.dataManager.getData();
|
|
788
|
+
}
|
|
756
789
|
setGridVisible(e) {
|
|
757
790
|
this.gridRenderer.setVisible(e), this.engine.requestRender(r.Background);
|
|
758
791
|
}
|
|
@@ -775,13 +808,13 @@ var J = class {
|
|
|
775
808
|
this.chartLegend.setStatusText(e), this.engine.requestRender(r.UI);
|
|
776
809
|
}
|
|
777
810
|
screenshot(e) {
|
|
778
|
-
this.features.screenshot &&
|
|
811
|
+
this.features.screenshot && A.download(this.container, e, this.themeManager.getTheme().background);
|
|
779
812
|
}
|
|
780
813
|
screenshotDataURL() {
|
|
781
|
-
return this.features.screenshot ?
|
|
814
|
+
return this.features.screenshot ? A.toDataURL(this.container, this.themeManager.getTheme().background) : null;
|
|
782
815
|
}
|
|
783
816
|
async screenshotBlob() {
|
|
784
|
-
return this.features.screenshot ?
|
|
817
|
+
return this.features.screenshot ? A.toBlob(this.container, this.themeManager.getTheme().background) : null;
|
|
785
818
|
}
|
|
786
819
|
addAlert(e, t = "crossing", n) {
|
|
787
820
|
if (!this.features.alerts) return null;
|
|
@@ -803,6 +836,45 @@ var J = class {
|
|
|
803
836
|
loadAlerts(e) {
|
|
804
837
|
this.alertManager.loadFromStorage(e), this.engine.requestRender(r.Overlay);
|
|
805
838
|
}
|
|
839
|
+
addSignalMarker(e) {
|
|
840
|
+
return this.signalMarkerManager.addMarker(e);
|
|
841
|
+
}
|
|
842
|
+
removeSignalMarker(e) {
|
|
843
|
+
this.signalMarkerManager.removeMarker(e);
|
|
844
|
+
}
|
|
845
|
+
getSignalMarkers() {
|
|
846
|
+
return this.signalMarkerManager.getMarkers();
|
|
847
|
+
}
|
|
848
|
+
setSignalMarkers(e) {
|
|
849
|
+
this.signalMarkerManager.setMarkers(e);
|
|
850
|
+
}
|
|
851
|
+
clearSignalMarkers() {
|
|
852
|
+
this.signalMarkerManager.clearMarkers();
|
|
853
|
+
}
|
|
854
|
+
setSignalMarkerStyle(e) {
|
|
855
|
+
this.signalMarkerManager.setStyle(e);
|
|
856
|
+
}
|
|
857
|
+
addTradeZone(e) {
|
|
858
|
+
return this.tradeZoneManager.addZone(e);
|
|
859
|
+
}
|
|
860
|
+
updateTradeZone(e, t) {
|
|
861
|
+
this.tradeZoneManager.updateZone(e, t);
|
|
862
|
+
}
|
|
863
|
+
removeTradeZone(e) {
|
|
864
|
+
this.tradeZoneManager.removeZone(e);
|
|
865
|
+
}
|
|
866
|
+
getTradeZones() {
|
|
867
|
+
return this.tradeZoneManager.getZones();
|
|
868
|
+
}
|
|
869
|
+
setTradeZones(e) {
|
|
870
|
+
this.tradeZoneManager.setZones(e);
|
|
871
|
+
}
|
|
872
|
+
clearTradeZones() {
|
|
873
|
+
this.tradeZoneManager.clearZones();
|
|
874
|
+
}
|
|
875
|
+
setTradeZoneStyle(e) {
|
|
876
|
+
this.tradeZoneManager.setStyle(e);
|
|
877
|
+
}
|
|
806
878
|
replay(e) {
|
|
807
879
|
if (!this.features.replay) return;
|
|
808
880
|
let t = this.dataManager.getData();
|
|
@@ -920,13 +992,13 @@ var J = class {
|
|
|
920
992
|
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 = "";
|
|
921
993
|
}
|
|
922
994
|
createChartRenderer(e) {
|
|
923
|
-
return
|
|
995
|
+
return Ce(e);
|
|
924
996
|
}
|
|
925
997
|
getDisplayData() {
|
|
926
998
|
if (this.displayDataCache) return this.displayDataCache;
|
|
927
999
|
let e = this.dataManager.getData();
|
|
928
1000
|
if (e.length === 0) return e;
|
|
929
|
-
let t =
|
|
1001
|
+
let t = we(this.options.chartType, e);
|
|
930
1002
|
return this.displayDataCache = t, t;
|
|
931
1003
|
}
|
|
932
1004
|
scheduleRender() {
|
|
@@ -963,7 +1035,7 @@ var J = class {
|
|
|
963
1035
|
buildPanelRenderInfos() {
|
|
964
1036
|
if (this.panelInfoCache) return this.panelInfoCache;
|
|
965
1037
|
let e = this.getResolvedLayout(), t = this.viewport.getState(), { from: n, to: r } = t.visibleRange, i = e.panels.map((e) => {
|
|
966
|
-
let i =
|
|
1038
|
+
let i = Te(this.indicatorEngine.getOutput(e.config.id), n, r), a = {
|
|
967
1039
|
x: e.rect.x,
|
|
968
1040
|
y: e.rect.y + 20,
|
|
969
1041
|
width: e.rect.width,
|
|
@@ -982,7 +1054,7 @@ var J = class {
|
|
|
982
1054
|
return this.panelInfoCache = i, i;
|
|
983
1055
|
}
|
|
984
1056
|
syncRenderContext() {
|
|
985
|
-
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;
|
|
1057
|
+
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, i = this.getDisplayData();
|
|
986
1058
|
this.engine.setRenderContext({
|
|
987
1059
|
chartRenderer: this.chartRenderer,
|
|
988
1060
|
gridRenderer: this.features.grid ? this.gridRenderer : null,
|
|
@@ -999,12 +1071,18 @@ var J = class {
|
|
|
999
1071
|
barCountdown: this.barCountdown,
|
|
1000
1072
|
sessionBreaks: this.sessionBreaks,
|
|
1001
1073
|
compareRenderer: this.compareRenderer,
|
|
1074
|
+
alertManager: this.features.alerts ? this.alertManager : null,
|
|
1075
|
+
signalMarkerManager: this.signalMarkerManager,
|
|
1076
|
+
tradeZoneManager: this.tradeZoneManager,
|
|
1002
1077
|
panels: t,
|
|
1003
1078
|
priceLimits: this.buildPriceLimits(),
|
|
1004
1079
|
timeAxisY: r,
|
|
1005
|
-
viewport:
|
|
1080
|
+
viewport: {
|
|
1081
|
+
...this.viewport.getState(),
|
|
1082
|
+
data: i
|
|
1083
|
+
},
|
|
1006
1084
|
theme: this.themeManager.getTheme(),
|
|
1007
|
-
data:
|
|
1085
|
+
data: i,
|
|
1008
1086
|
numberLocale: this.numberLocale
|
|
1009
1087
|
});
|
|
1010
1088
|
}
|
|
@@ -1022,6 +1100,6 @@ var J = class {
|
|
|
1022
1100
|
}
|
|
1023
1101
|
};
|
|
1024
1102
|
//#endregion
|
|
1025
|
-
export { J as a, Y as i, $ as n, Q as r,
|
|
1103
|
+
export { J as a, Y as i, $ as n, Q as r, De as t };
|
|
1026
1104
|
|
|
1027
|
-
//# sourceMappingURL=Chart-
|
|
1105
|
+
//# sourceMappingURL=Chart-Cy8K3wHS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Chart-Cy8K3wHS.js","names":[],"sources":["../src/charts/ChartTypeStrategy.ts","../src/charts/IndicatorPriceRange.ts","../src/state/AutoSaveScheduler.ts","../src/DataManager.ts","../src/ThemeManager.ts","../src/layout/LayoutManager.ts","../src/plugins/PluginManager.ts","../src/Chart.ts"],"sourcesContent":["import type { ChartType, DataSeries } from '@tradecanvas/commons';\r\nimport {\r\n AreaRenderer,\r\n BarRenderer,\r\n BaselineRenderer,\r\n CandlestickRenderer,\r\n HLCAreaRenderer,\r\n HollowCandleRenderer,\r\n KagiRenderer,\r\n LineRenderer,\r\n LineWithMarkersRenderer,\r\n PointAndFigureRenderer,\r\n RenkoRenderer,\r\n StepLineRenderer,\r\n VolumeCandleRenderer,\r\n toHeikinAshi,\r\n toKagi,\r\n toLineBreak,\r\n toPointAndFigure,\r\n toRangeBars,\r\n toRenko,\r\n} from '@tradecanvas/core';\r\nimport type { ChartRendererInterface } from '@tradecanvas/core';\r\n\r\n/**\r\n * Pure mapping from `ChartType` to the renderer class that draws it. Several\r\n * chart types reuse `CandlestickRenderer` against transformed data\r\n * (heikinAshi, lineBreak, rangeBars).\r\n */\r\nexport function createRendererFor(type: ChartType): ChartRendererInterface {\r\n switch (type) {\r\n case 'candlestick':\r\n case 'heikinAshi':\r\n case 'lineBreak':\r\n case 'rangeBars':\r\n return new CandlestickRenderer();\r\n case 'line':\r\n return new LineRenderer();\r\n case 'area':\r\n return new AreaRenderer();\r\n case 'bar':\r\n return new BarRenderer();\r\n case 'hollowCandle':\r\n return new HollowCandleRenderer();\r\n case 'baseline':\r\n return new BaselineRenderer();\r\n case 'renko':\r\n return new RenkoRenderer();\r\n case 'kagi':\r\n return new KagiRenderer();\r\n case 'pointAndFigure':\r\n return new PointAndFigureRenderer();\r\n case 'volumeCandles':\r\n return new VolumeCandleRenderer();\r\n case 'hlcArea':\r\n return new HLCAreaRenderer();\r\n case 'stepLine':\r\n return new StepLineRenderer();\r\n case 'lineWithMarkers':\r\n return new LineWithMarkersRenderer();\r\n default:\r\n return new CandlestickRenderer();\r\n }\r\n}\r\n\r\n/**\r\n * Transform raw OHLC bars into the display series for a given chart type.\r\n * Returns the input unchanged for chart types that render raw OHLC directly.\r\n *\r\n * Centralized so adding a new chart type only requires editing one file.\r\n */\r\nexport function transformDisplayData(type: ChartType, raw: DataSeries): DataSeries {\r\n if (raw.length === 0) return raw;\r\n\r\n switch (type) {\r\n case 'heikinAshi':\r\n return toHeikinAshi(raw);\r\n case 'renko':\r\n return toRenko(raw, { brickSize: 0, useATR: true, atrPeriod: 14 });\r\n case 'lineBreak':\r\n return toLineBreak(raw, 3);\r\n case 'kagi':\r\n return toKagi(raw, 4);\r\n case 'pointAndFigure': {\r\n const avgPrice = averageClose(raw);\r\n return toPointAndFigure(raw, avgPrice * 0.01, 3);\r\n }\r\n case 'rangeBars': {\r\n const avgPrice = averageClose(raw);\r\n return toRangeBars(raw, { rangeSize: avgPrice * 0.005 });\r\n }\r\n default:\r\n return raw;\r\n }\r\n}\r\n\r\n/** Chart types that materially transform raw OHLC into a different series. */\r\nexport function isTransformedChartType(type: ChartType): boolean {\r\n switch (type) {\r\n case 'heikinAshi':\r\n case 'renko':\r\n case 'lineBreak':\r\n case 'kagi':\r\n case 'pointAndFigure':\r\n case 'rangeBars':\r\n return true;\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\nfunction averageClose(raw: DataSeries): number {\r\n let sum = 0;\r\n for (const b of raw) sum += b.close;\r\n return sum / raw.length;\r\n}\r\n","import type { IndicatorOutput } from '@tradecanvas/commons';\r\n\r\nexport interface PriceRange {\r\n min: number;\r\n max: number;\r\n}\r\n\r\nconst DEFAULT_RANGE: PriceRange = { min: 0, max: 100 };\r\nconst PADDING = 0.1;\r\n\r\n/**\r\n * Compute a padded {min, max} price range for an indicator panel from the\r\n * visible slice of its output. Returns a sensible default range when the\r\n * output is empty or has no values inside [from, to].\r\n *\r\n * Pure — no canvas, no viewport object, just the values map and bar bounds.\r\n * Iterates the output's `values` map in insertion order; we treat its index\r\n * (0…N-1) as the bar index, matching how the engine inserts values.\r\n */\r\nexport function computeIndicatorPriceRange(\r\n output: IndicatorOutput | null,\r\n from: number,\r\n to: number,\r\n): PriceRange {\r\n if (!output) return { ...DEFAULT_RANGE };\r\n\r\n let vMin = Infinity;\r\n let vMax = -Infinity;\r\n let idx = 0;\r\n for (const [, val] of output.values) {\r\n if (idx >= from && idx <= to) {\r\n for (const key in val) {\r\n const v = val[key];\r\n if (v !== undefined && Number.isFinite(v)) {\r\n if (v < vMin) vMin = v;\r\n if (v > vMax) vMax = v;\r\n }\r\n }\r\n }\r\n idx++;\r\n }\r\n\r\n if (vMin === Infinity) return { ...DEFAULT_RANGE };\r\n\r\n const range = vMax - vMin || 1;\r\n return {\r\n min: vMin - range * PADDING,\r\n max: vMax + range * PADDING,\r\n };\r\n}\r\n","/**\r\n * Debounced auto-save scheduler. Coalesces a burst of `schedule()` calls into\r\n * a single `save(key)` invocation after `delayMs` of quiet time. Pure state\r\n * machine — owner injects the actual save callback so this stays testable.\r\n */\r\nexport class AutoSaveScheduler {\r\n private timer: ReturnType<typeof setTimeout> | null = null;\r\n private delayMs = 0;\r\n private key: string | null = null;\r\n\r\n constructor(private save: (key: string) => void) {}\r\n\r\n /** Enable auto-save with the given storage key and quiet-time debounce. */\r\n enable(key: string, delayMs: number): void {\r\n this.key = key;\r\n this.delayMs = delayMs;\r\n }\r\n\r\n /** Disable auto-save and cancel any pending fire. */\r\n disable(): void {\r\n this.key = null;\r\n this.delayMs = 0;\r\n this.cancel();\r\n }\r\n\r\n /**\r\n * Reset the quiet-time window. If currently disabled (no key or delay ≤ 0),\r\n * this is a no-op. Subsequent calls within the window restart the timer.\r\n */\r\n schedule(): void {\r\n if (this.delayMs <= 0 || !this.key) return;\r\n if (this.timer) clearTimeout(this.timer);\r\n this.timer = setTimeout(() => {\r\n this.timer = null;\r\n if (this.key) this.save(this.key);\r\n }, this.delayMs);\r\n }\r\n\r\n /** Cancel any pending fire without changing enabled state. */\r\n cancel(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this.delayMs > 0 && this.key !== null;\r\n }\r\n\r\n hasPending(): boolean {\r\n return this.timer !== null;\r\n }\r\n}\r\n","import type { OHLCBar, DataSeries } from '@tradecanvas/commons';\nimport { mergeBar } from '@tradecanvas/commons';\n\n/** Validate a single OHLC bar. Returns true if bar is usable. */\nfunction isValidBar(bar: OHLCBar): boolean {\n if (!bar || typeof bar.time !== 'number') return false;\n const { open, high, low, close } = bar;\n // Reject NaN / Infinity\n if (!isFinite(open) || !isFinite(high) || !isFinite(low) || !isFinite(close)) return false;\n // Reject negative prices\n if (open < 0 || high < 0 || low < 0 || close < 0) return false;\n // High must be >= low\n if (high < low) return false;\n // Volume (optional) must be non-negative if present\n if (bar.volume !== undefined && (!isFinite(bar.volume) || bar.volume < 0)) return false;\n return true;\n}\n\n/** Sanitize a bar: clamp high/low to envelope OHLC values. */\nfunction sanitizeBar(bar: OHLCBar): OHLCBar {\n return {\n ...bar,\n high: Math.max(bar.open, bar.high, bar.low, bar.close),\n low: Math.min(bar.open, bar.high, bar.low, bar.close),\n volume: bar.volume !== undefined ? Math.max(0, bar.volume) : 0,\n };\n}\n\nexport class DataManager {\n private data: DataSeries = [];\n\n getData(): DataSeries {\n return this.data;\n }\n\n setData(data: DataSeries): void {\n // Filter out completely invalid bars, sanitize the rest\n this.data = data\n .filter(isValidBar)\n .map(sanitizeBar);\n }\n\n appendBar(bar: OHLCBar): void {\n if (!isValidBar(bar)) return;\n this.data.push(sanitizeBar(bar));\n }\n\n updateLastBar(bar: OHLCBar): void {\n if (!isValidBar(bar)) return;\n const sanitized = sanitizeBar(bar);\n if (this.data.length === 0) {\n this.data.push(sanitized);\n return;\n }\n this.data[this.data.length - 1] = sanitized;\n }\n\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\n if (this.data.length === 0) return;\n if (!isFinite(tick.price) || tick.price < 0) return;\n if (tick.volume !== undefined && (!isFinite(tick.volume) || tick.volume < 0)) return;\n this.data[this.data.length - 1] = mergeBar(this.data[this.data.length - 1], tick);\n }\n\n getLength(): number {\n return this.data.length;\n }\n\n clear(): void {\n this.data = [];\n }\n}\n","import type { Theme, ThemeName } from '@tradecanvas/commons';\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\n\nexport class ThemeManager {\n private theme: Theme;\n\n constructor(themeOrName?: ThemeName | Theme) {\n if (!themeOrName || themeOrName === 'dark') {\n this.theme = { ...DARK_THEME };\n } else if (themeOrName === 'light') {\n this.theme = { ...LIGHT_THEME };\n } else {\n this.theme = { ...themeOrName };\n }\n }\n\n getTheme(): Theme {\n return this.theme;\n }\n\n setTheme(themeOrName: ThemeName | Theme): void {\n if (themeOrName === 'dark') {\n this.theme = { ...DARK_THEME };\n } else if (themeOrName === 'light') {\n this.theme = { ...LIGHT_THEME };\n } else {\n this.theme = { ...themeOrName };\n }\n }\n}\n","import type { PanelPosition, PanelConfig, ResolvedLayout, ResolvedPanel, DividerRect, Rect } from '@tradecanvas/commons';\nimport { DEFAULT_PANEL_HEIGHT, MIN_PANEL_HEIGHT, PRICE_AXIS_WIDTH, TIME_AXIS_HEIGHT } from '@tradecanvas/commons';\n\nconst DEFAULT_PANEL_WIDTH = 200;\nconst MIN_PANEL_WIDTH = 80;\n\nexport class LayoutManager {\n private panels: PanelConfig[] = [];\n private containerWidth = 0;\n private containerHeight = 0;\n\n resize(width: number, height: number): void {\n this.containerWidth = width;\n this.containerHeight = height;\n }\n\n addPanel(instanceId: string, position: PanelPosition = 'bottom', size?: number): void {\n const isVertical = position === 'left' || position === 'right';\n this.panels.push({\n id: instanceId,\n position,\n size: size ?? (isVertical ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_HEIGHT),\n minSize: isVertical ? MIN_PANEL_WIDTH : MIN_PANEL_HEIGHT,\n content: { type: 'indicator', indicatorInstanceId: instanceId },\n });\n }\n\n removePanel(instanceId: string): void {\n this.panels = this.panels.filter((p) => p.id !== instanceId);\n }\n\n setPanelPosition(instanceId: string, position: PanelPosition): void {\n const panel = this.panels.find((p) => p.id === instanceId);\n if (panel) {\n const wasVertical = panel.position === 'left' || panel.position === 'right';\n const isVertical = position === 'left' || position === 'right';\n panel.position = position;\n if (wasVertical !== isVertical) {\n panel.size = isVertical ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_HEIGHT;\n panel.minSize = isVertical ? MIN_PANEL_WIDTH : MIN_PANEL_HEIGHT;\n }\n }\n }\n\n setPanelSize(instanceId: string, size: number): void {\n const panel = this.panels.find((p) => p.id === instanceId);\n if (panel) {\n panel.size = Math.max(panel.minSize, size);\n }\n }\n\n getPanels(): PanelConfig[] {\n return this.panels;\n }\n\n resolve(): ResolvedLayout {\n const leftPanels = this.panels.filter((p) => p.position === 'left');\n const rightPanels = this.panels.filter((p) => p.position === 'right');\n const topPanels = this.panels.filter((p) => p.position === 'top');\n const bottomPanels = this.panels.filter((p) => p.position === 'bottom');\n\n const leftWidth = leftPanels.reduce((s, p) => s + p.size, 0);\n const rightWidth = rightPanels.reduce((s, p) => s + p.size, 0);\n const topHeight = topPanels.reduce((s, p) => s + p.size, 0);\n const bottomHeight = bottomPanels.reduce((s, p) => s + p.size, 0);\n\n const mainChartRect: Rect = {\n x: leftWidth,\n y: topHeight,\n width: Math.max(0, this.containerWidth - leftWidth - rightWidth - PRICE_AXIS_WIDTH),\n height: Math.max(0, this.containerHeight - topHeight - bottomHeight - TIME_AXIS_HEIGHT),\n };\n\n const resolvedPanels: ResolvedPanel[] = [];\n const dividers: DividerRect[] = [];\n\n // Left panels (stacked vertically)\n let x = 0;\n for (const panel of leftPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x, y: 0, width: panel.size, height: this.containerHeight - TIME_AXIS_HEIGHT },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: x + panel.size - 2, y: 0, width: 4, height: this.containerHeight },\n orientation: 'vertical',\n });\n x += panel.size;\n }\n\n // Top panels (stacked horizontally, full width minus left/right)\n let y = 0;\n for (const panel of topPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x: leftWidth, y, width: mainChartRect.width, height: panel.size },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: leftWidth, y: y + panel.size - 2, width: mainChartRect.width, height: 4 },\n orientation: 'horizontal',\n });\n y += panel.size;\n }\n\n // Bottom panels\n y = mainChartRect.y + mainChartRect.height;\n for (const panel of bottomPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x: leftWidth, y, width: mainChartRect.width, height: panel.size },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: leftWidth, y: y - 2, width: mainChartRect.width, height: 4 },\n orientation: 'horizontal',\n });\n y += panel.size;\n }\n\n // Right panels\n x = leftWidth + mainChartRect.width + PRICE_AXIS_WIDTH;\n for (const panel of rightPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x, y: 0, width: panel.size, height: this.containerHeight - TIME_AXIS_HEIGHT },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: x - 2, y: 0, width: 4, height: this.containerHeight },\n orientation: 'vertical',\n });\n x += panel.size;\n }\n\n return { mainChartRect, panels: resolvedPanels, dividers };\n }\n\n getMainChartRect(): Rect {\n return this.resolve().mainChartRect;\n }\n}\n","import type { IndicatorPlugin } from '@tradecanvas/commons';\nimport type { IndicatorEngine } from '@tradecanvas/core';\n\nexport class PluginManager {\n constructor(private indicatorEngine: IndicatorEngine) {}\n\n registerIndicator(plugin: IndicatorPlugin): void {\n this.indicatorEngine.register(plugin);\n }\n}\n","import type {\r\n ChartOptions,\r\n ChartType,\r\n OHLCBar,\r\n DataSeries,\r\n Theme,\r\n ThemeName,\r\n ChartEventType,\r\n ChartEvent,\r\n ChartEventMap,\r\n TauriBridgeOptions,\r\n IndicatorPlugin,\r\n IndicatorDescriptor,\r\n IndicatorOutput,\r\n DrawingToolType,\r\n DrawingState,\r\n DrawingStyle,\r\n DrawingPlugin,\r\n PanelPosition,\r\n TradingOrder,\r\n TradingPosition,\r\n DepthData,\r\n TradingConfig,\r\n MarketConfig,\r\n Locale,\r\n StreamConfig,\r\n ConnectionState,\r\n ConnectionInfo,\r\n TimeFrame,\r\n FeaturesConfig,\r\n} from '@tradecanvas/commons';\r\nimport { LayerType, setLocale as setGlobalLocale, computePriceLimits } from '@tradecanvas/commons';\r\nimport {\r\n RenderEngine,\r\n Viewport,\r\n GridRenderer,\r\n PriceAxis,\r\n TimeAxis,\r\n InteractionManager,\r\n PanHandler,\r\n ZoomHandler,\r\n CrosshairHandler,\r\n IndicatorEngine,\r\n registerBuiltInIndicators,\r\n EventBus,\r\n DrawingManager,\r\n DrawingRenderer,\r\n registerBuiltInDrawingTools,\r\n TradingManager,\r\n TradingRenderer,\r\n StreamManager,\r\n ChartLegend,\r\n Screenshot,\r\n Watermark,\r\n BarCountdown,\r\n VolumeRenderer,\r\n AlertManager,\r\n SignalMarkerManager,\r\n TradeZoneManager,\r\n ReplayManager,\r\n ChartStateManager,\r\n UndoRedoManager,\r\n Animator,\r\n KeyboardHandler,\r\n CrosshairTooltip,\r\n DataExporter,\r\n SessionBreaks,\r\n CompareRenderer,\r\n CurrentPriceLine,\r\n} from '@tradecanvas/core';\r\nimport type { ChartRendererInterface } from '@tradecanvas/core';\r\nimport { timeframeToMs } from '@tradecanvas/commons';\r\nimport { createRendererFor, transformDisplayData } from './charts/ChartTypeStrategy.js';\r\nimport { computeIndicatorPriceRange } from './charts/IndicatorPriceRange.js';\r\nimport { AutoSaveScheduler } from './state/AutoSaveScheduler.js';\r\nimport { DataManager } from './DataManager.js';\r\nimport { ThemeManager } from './ThemeManager.js';\r\nimport { LayoutManager } from './layout/LayoutManager.js';\r\nimport { PluginManager } from './plugins/PluginManager.js';\r\n\r\nexport class Chart {\r\n static version = '0.7.0';\r\n\r\n private engine: RenderEngine;\r\n private viewport: Viewport;\r\n private dataManager: DataManager;\r\n private themeManager: ThemeManager;\r\n private layoutManager: LayoutManager;\r\n private pluginManager: PluginManager;\r\n private indicatorEngine: IndicatorEngine;\r\n private drawingManager: DrawingManager;\r\n private drawingRenderer: DrawingRenderer;\r\n private tradingManager: TradingManager;\r\n private tradingRenderer: TradingRenderer;\r\n private eventBus: EventBus;\r\n private streamManager: StreamManager | null = null;\r\n private autoScrollOnNewBar = true;\r\n private displayDataCache: DataSeries | null = null;\r\n private resolvedLayoutCache: import('@tradecanvas/commons').ResolvedLayout | null = null;\r\n private panelInfoCache: import('@tradecanvas/core').PanelRenderInfo[] | null = null;\r\n private renderScheduled = false;\r\n private containerSizeCache: { width: number; height: number } | null = null;\r\n private containerSizeCacheTime = 0;\r\n private chartLegend: ChartLegend;\r\n private watermark: Watermark;\r\n private barCountdown: BarCountdown;\r\n private sessionBreaks: SessionBreaks;\r\n private compareRenderer: CompareRenderer;\r\n private countdownInterval: ReturnType<typeof setInterval> | null = null;\r\n private volumeRenderer: VolumeRenderer;\r\n private alertManager: AlertManager;\r\n private signalMarkerManager: SignalMarkerManager;\r\n private tradeZoneManager: TradeZoneManager;\r\n private replayManager: ReplayManager;\r\n private undoRedoManager: UndoRedoManager;\r\n private autoSaveScheduler = new AutoSaveScheduler((key) => this.saveState(key));\r\n private animator: Animator;\r\n private crosshairTooltip: CrosshairTooltip;\r\n private interactionManager: InteractionManager;\r\n private crosshairHandler: CrosshairHandler;\r\n private chartRenderer: ChartRendererInterface;\r\n private gridRenderer: GridRenderer;\r\n private priceAxis: PriceAxis;\r\n private timeAxis: TimeAxis;\r\n private options: ChartOptions;\r\n private features: Required<FeaturesConfig>;\r\n private marketConfig: MarketConfig | null = null;\r\n private container: HTMLElement;\r\n private currentPriceLine: import('@tradecanvas/core').CurrentPriceLine;\r\n private numberLocale: string;\r\n private keyboardHandler: KeyboardHandler | null = null;\r\n private onWindowKeyDown: ((e: KeyboardEvent) => void) | null = null;\r\n private currentSymbol: string = '';\r\n\r\n\r\n constructor(container: HTMLElement, options: ChartOptions) {\r\n this.container = container;\r\n this.options = options;\r\n this.numberLocale = options.numberLocale ?? 'en-US';\r\n\r\n // Resolve feature flags (all default to true)\r\n const f = options.features ?? {};\r\n this.features = {\r\n drawings: f.drawings ?? true,\r\n drawingTools: f.drawingTools ?? [],\r\n drawingMagnet: f.drawingMagnet ?? true,\r\n drawingUndoRedo: f.drawingUndoRedo ?? true,\r\n trading: f.trading ?? true,\r\n tradingContextMenu: f.tradingContextMenu ?? true,\r\n indicators: f.indicators ?? true,\r\n indicatorIds: f.indicatorIds ?? [],\r\n panning: f.panning ?? true,\r\n zooming: f.zooming ?? true,\r\n crosshair: f.crosshair ?? true,\r\n keyboard: f.keyboard ?? true,\r\n priceAxis: f.priceAxis ?? true,\r\n timeAxis: f.timeAxis ?? true,\r\n grid: f.grid ?? (options.grid?.visible ?? true),\r\n legend: f.legend ?? true,\r\n volume: f.volume ?? true,\r\n watermark: f.watermark ?? true,\r\n saveLoad: f.saveLoad ?? true,\r\n screenshot: f.screenshot ?? true,\r\n alerts: f.alerts ?? true,\r\n replay: f.replay ?? true,\r\n sessionBreaks: f.sessionBreaks ?? true,\r\n barCountdown: f.barCountdown ?? true,\r\n compareSymbols: f.compareSymbols ?? true,\r\n dataExport: f.dataExport ?? true,\r\n logScale: f.logScale ?? true,\r\n timeframes: f.timeframes ?? [],\r\n defaultTimeframeFavorites: f.defaultTimeframeFavorites ?? [],\r\n };\r\n\r\n container.style.position = 'relative';\r\n container.style.overflow = 'hidden';\r\n container.tabIndex = 0; // Allow keyboard events\r\n container.style.outline = 'none';\r\n\r\n // Initialize managers\r\n this.dataManager = new DataManager();\r\n this.themeManager = new ThemeManager(options.theme);\r\n this.layoutManager = new LayoutManager();\r\n this.indicatorEngine = new IndicatorEngine();\r\n this.pluginManager = new PluginManager(this.indicatorEngine);\r\n this.eventBus = new EventBus();\r\n\r\n registerBuiltInIndicators(this.indicatorEngine);\r\n\r\n // Drawing tools\r\n this.drawingManager = new DrawingManager();\r\n registerBuiltInDrawingTools(this.drawingManager);\r\n this.drawingRenderer = new DrawingRenderer(this.drawingManager);\r\n this.drawingManager.setRequestRender(() => {\r\n // Sync entire render context so drawings render with same viewport as candles\r\n this.syncRenderContext();\r\n this.engine.requestRender(LayerType.Overlay);\r\n this.scheduleAutoSave();\r\n });\r\n this.drawingManager.setEventCallback((event, data) => {\r\n this.eventBus.emit(event as ChartEventType, data);\r\n });\r\n // Undo/redo\r\n this.undoRedoManager = new UndoRedoManager();\r\n this.drawingManager.setUndoRedoManager(this.undoRedoManager);\r\n this.drawingManager.setDataGetter(() => this.dataManager.getData());\r\n this.drawingManager.setDisplayDataGetter(() => this.getDisplayData());\r\n // Magnet mode\r\n if (options.crosshair?.mode === 'magnet') {\r\n this.drawingManager.setMagnetMode('magnet');\r\n }\r\n\r\n // Trading\r\n this.tradingManager = new TradingManager();\r\n this.tradingRenderer = new TradingRenderer(this.tradingManager);\r\n this.tradingManager.setContainer(container);\r\n this.tradingManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.tradingManager.setEventCallback((event, data) => {\r\n this.eventBus.emit(event as ChartEventType, data);\r\n });\r\n\r\n // Rendering\r\n this.engine = new RenderEngine(container);\r\n const size = this.engine.dprManager.getContainerSize();\r\n this.viewport = new Viewport(\r\n size.width,\r\n size.height,\r\n options.minBarSpacing ?? 2,\r\n options.maxBarSpacing ?? 30,\r\n options.rightMargin ?? 5,\r\n );\r\n this.layoutManager.resize(size.width, size.height);\r\n\r\n // Sync viewport + layout when the container resizes. Without this hook\r\n // the chart's viewport keeps its construction-time chartRect forever\r\n // (which is wrong if the container started at 0 or got resized since),\r\n // and `scrollToEnd` / clampOffset compute against stale dimensions —\r\n // chart sticks at the wrong offset and the user can't scroll to the\r\n // latest bar.\r\n this.engine.onContainerResize = (newSize) => {\r\n if (newSize.width <= 0 || newSize.height <= 0) return;\r\n const wasAtEnd = this.viewport.isAtEnd();\r\n this.viewport.resize(newSize.width, newSize.height);\r\n this.layoutManager.resize(newSize.width, newSize.height);\r\n // wasAtEnd carries the user's intent: if they were tracking the live\r\n // edge before the resize, keep them there afterwards. Otherwise leave\r\n // their scroll position alone.\r\n this.updateViewportAndRender(wasAtEnd);\r\n };\r\n\r\n // Chart renderer\r\n this.chartRenderer = this.createChartRenderer(options.chartType);\r\n this.gridRenderer = new GridRenderer();\r\n if (options.grid?.visible === false) this.gridRenderer.setVisible(false);\r\n this.priceAxis = new PriceAxis();\r\n this.priceAxis.setLocale(this.numberLocale);\r\n this.timeAxis = new TimeAxis();\r\n\r\n // Crosshair\r\n this.crosshairHandler = new CrosshairHandler();\r\n this.crosshairHandler.setLocale(this.numberLocale);\r\n if (options.crosshair?.mode) {\r\n this.crosshairHandler.setMode(options.crosshair.mode);\r\n }\r\n // Crosshair callback — fired via microtask AFTER render, only when bar changes.\r\n // No DOM writes, no layout reads, no extra render requests.\r\n this.crosshairHandler.setCallback((barIndex, point) => {\r\n if (barIndex !== null && point) {\r\n const data = this.dataManager.getData();\r\n const bar = barIndex < data.length ? data[barIndex] : undefined;\r\n\r\n // Update legend (canvas-rendered, will show on next UI paint)\r\n this.chartLegend.setHoverBar(bar ?? null);\r\n\r\n // Update tooltip (DOM, lightweight update only when bar changes)\r\n if (bar) {\r\n this.crosshairTooltip.show(point, bar, this.themeManager.getTheme(), this.cachedContainerSize());\r\n }\r\n\r\n // Emit for external consumers\r\n this.eventBus.emit('crosshairMove', { point, bar, barIndex });\r\n } else {\r\n this.crosshairTooltip.hide();\r\n this.chartLegend.setHoverBar(null);\r\n }\r\n });\r\n\r\n // Chart legend (OHLCV overlay)\r\n this.chartLegend = new ChartLegend();\r\n this.chartLegend.setChartType(options.chartType);\r\n\r\n // Watermark + Volume\r\n this.watermark = new Watermark();\r\n if (options.watermark) this.watermark.setConfig(options.watermark);\r\n this.volumeRenderer = new VolumeRenderer();\r\n\r\n // Bar countdown timer\r\n this.barCountdown = new BarCountdown();\r\n this.sessionBreaks = new SessionBreaks();\r\n this.compareRenderer = new CompareRenderer();\r\n\r\n // Apply session break config from options\r\n if (options.sessionBreaks) {\r\n this.sessionBreaks.setConfig({\r\n visible: options.sessionBreaks.visible ?? true,\r\n color: options.sessionBreaks.color,\r\n lineStyle: options.sessionBreaks.lineStyle,\r\n lineWidth: options.sessionBreaks.lineWidth,\r\n });\r\n } else if (options.features?.sessionBreaks !== false) {\r\n this.sessionBreaks.setVisible(true);\r\n }\r\n\r\n // Apply log scale from options\r\n if (options.logScale) {\r\n this.viewport.setLogScale(true);\r\n }\r\n\r\n // Animation\r\n this.animator = new Animator();\r\n\r\n // Crosshair tooltip (DOM)\r\n this.crosshairTooltip = new CrosshairTooltip();\r\n this.crosshairTooltip.create(container);\r\n\r\n // Keyboard navigation\r\n this.keyboardHandler = new KeyboardHandler({\r\n scrollBars: (count) => {\r\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\r\n this.viewport.scrollBy(count * barUnit);\r\n this.updateViewportAndRender();\r\n },\r\n zoom: (delta) => {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n this.viewport.zoom(delta, chartWidth / 2);\r\n this.updateViewportAndRender();\r\n },\r\n goToStart: () => {\r\n this.viewport.scrollBy(-Infinity);\r\n this.updateViewportAndRender();\r\n },\r\n goToEnd: () => {\r\n this.viewport.scrollToEnd();\r\n this.updateViewportAndRender();\r\n },\r\n fitContent: () => this.fitContent(),\r\n });\r\n this.keyboardHandler.setEnabled(this.features.keyboard);\r\n\r\n // Attach keyboard listener to window. Only consume the event when the\r\n // chart actually handles the key AND the container is the focused element\r\n // (or an ancestor) — this prevents the chart from swallowing keystrokes\r\n // intended for inputs elsewhere on the page.\r\n this.onWindowKeyDown = (e: KeyboardEvent) => {\r\n if (!this.keyboardHandler) return;\r\n const active = document.activeElement as HTMLElement | null;\r\n if (active && active !== this.container && !this.container.contains(active)) {\r\n return;\r\n }\r\n // Ignore when typing in a form field that happens to live inside the chart.\r\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) {\r\n return;\r\n }\r\n if (this.keyboardHandler.handleKey(e)) {\r\n e.preventDefault();\r\n }\r\n };\r\n window.addEventListener('keydown', this.onWindowKeyDown);\r\n\r\n // Current price line (standalone, works without StreamManager)\r\n this.currentPriceLine = new CurrentPriceLine();\r\n\r\n // Alerts\r\n this.alertManager = new AlertManager();\r\n this.alertManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.alertManager.on('triggered', (alert) => {\r\n this.eventBus.emit('dataUpdate', { alert: 'triggered', alertId: alert.id, price: alert.price, message: alert.message });\r\n });\r\n\r\n // Signal markers\r\n this.signalMarkerManager = new SignalMarkerManager();\r\n this.signalMarkerManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.signalMarkerManager.setDataGetter(() => this.dataManager.getData());\r\n this.signalMarkerManager.on('added', (m) => {\r\n this.eventBus.emit('signalMarkerAdd' as ChartEventType, { id: m.id, source: m.source, direction: m.direction });\r\n });\r\n this.signalMarkerManager.on('removed', (id) => {\r\n this.eventBus.emit('signalMarkerRemove' as ChartEventType, { id });\r\n });\r\n\r\n // Trade zones\r\n this.tradeZoneManager = new TradeZoneManager();\r\n this.tradeZoneManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.tradeZoneManager.setDataGetter(() => this.dataManager.getData());\r\n this.tradeZoneManager.on('added', (z) => {\r\n this.eventBus.emit('tradeZoneAdd' as ChartEventType, { id: z.id, direction: z.direction });\r\n });\r\n this.tradeZoneManager.on('removed', (id) => {\r\n this.eventBus.emit('tradeZoneRemove' as ChartEventType, { id });\r\n });\r\n\r\n // Replay\r\n this.replayManager = new ReplayManager();\r\n\r\n // Interaction\r\n this.interactionManager = new InteractionManager(container);\r\n if (this.features.panning) {\r\n this.interactionManager.setPanHandler(\r\n new PanHandler((deltaX) => {\r\n this.viewport.scrollBy(deltaX);\r\n this.updateViewportAndRender();\r\n }),\r\n );\r\n }\r\n if (this.features.zooming) {\r\n this.interactionManager.setZoomHandler(\r\n new ZoomHandler((delta, centerX) => {\r\n this.viewport.zoom(delta, centerX);\r\n this.updateViewportAndRender();\r\n }),\r\n );\r\n }\r\n if (this.features.crosshair) {\r\n this.interactionManager.setCrosshairHandler(this.crosshairHandler);\r\n }\r\n if (this.features.drawings) {\r\n this.interactionManager.setDrawingManager(\r\n this.drawingManager,\r\n // Inject current data so drawing anchors are stored/resolved as real\r\n // timestamps (survives timeframe/symbol switches).\r\n () => ({ ...this.viewport.getState(), data: this.getDisplayData() }),\r\n );\r\n }\r\n if (this.features.trading) {\r\n this.interactionManager.setTradingManager(\r\n this.tradingManager,\r\n () => ({ ...this.viewport.getState(), data: this.getDisplayData() }),\r\n );\r\n }\r\n this.interactionManager.setOverlayDirtyCallback(() => {\r\n this.engine.requestRender(LayerType.Overlay);\r\n // Also refresh UI layer for panel crosshair value labels\r\n if (this.layoutManager.getPanels().length > 0) {\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n });\r\n this.interactionManager.attach();\r\n\r\n // Set render context\r\n this.syncRenderContext();\r\n this.engine.start();\r\n }\r\n\r\n // --- Data ---\r\n\r\n setData(data: DataSeries): void {\r\n this.dataManager.setData(data);\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n this.displayDataCache = null;\r\n this.sessionBreaks.invalidateCache();\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n // Auto-set current price line from last bar's close\r\n if (data.length > 0) {\r\n this.currentPriceLine.setPrice(data[data.length - 1].close);\r\n }\r\n this.updateViewportAndRender(true);\r\n this.eventBus.emit('dataUpdate', { length: data.length });\r\n }\r\n\r\n appendBar(bar: OHLCBar): void {\r\n this.dataManager.appendBar(bar);\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n this.displayDataCache = null;\r\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.updateViewportAndRender();\r\n }\r\n\r\n /**\r\n * Append multiple bars at once (e.g., catch-up after reconnect).\r\n * More efficient than calling appendBar() in a loop — recalculates\r\n * indicators only once at the end.\r\n */\r\n appendBars(bars: OHLCBar[]): void {\r\n if (bars.length === 0) return;\r\n for (const bar of bars) {\r\n this.dataManager.appendBar(bar);\r\n }\r\n this.displayDataCache = null;\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n this.updateViewportAndRender(this.viewport.isAtEnd());\r\n }\r\n\r\n updateLastBar(bar: OHLCBar): void {\r\n this.dataManager.updateLastBar(bar);\r\n this.currentPriceLine.setPrice(bar.close);\r\n // For non-transform chart types, the displayDataCache still points to the\r\n // same raw array (mutated in place), so no need to invalidate.\r\n // Only invalidate for transform types that produce derived arrays.\r\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\r\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\r\n && this.options.chartType !== 'hollowCandle') {\r\n this.displayDataCache = null;\r\n }\r\n // Keep indicator lines in sync with the forming bar. Without this, panel\r\n // + overlay indicators freeze until bar close.\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.scheduleRender();\r\n }\r\n\r\n /** Merge a price tick into the current last bar (convenience for live feeds) */\r\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\r\n this.dataManager.updateLastBarFromTick(tick);\r\n this.currentPriceLine.setPrice(tick.price);\r\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\r\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\r\n && this.options.chartType !== 'hollowCandle') {\r\n this.displayDataCache = null;\r\n }\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.scheduleRender();\r\n }\r\n\r\n // --- Chart type ---\r\n\r\n setChartType(type: ChartType): void {\r\n this.options.chartType = type;\r\n this.chartRenderer = this.createChartRenderer(type);\r\n this.chartLegend.setChartType(type);\r\n this.displayDataCache = null;\r\n this.updateViewportAndRender(true);\r\n }\r\n\r\n // --- Indicators ---\r\n\r\n addIndicator(id: string, params: Record<string, number | string | boolean> = {}, position: PanelPosition = 'bottom'): string | null {\r\n if (!this.features.indicators) return null;\r\n if (this.features.indicatorIds.length > 0 && !this.features.indicatorIds.includes(id)) return null;\r\n const instanceId = this.indicatorEngine.addIndicator(id, params, this.dataManager.getData());\r\n const descriptor = this.indicatorEngine.getAvailableIndicators().find((d) => d.id === id);\r\n if (descriptor?.placement === 'panel') {\r\n this.layoutManager.addPanel(instanceId, position);\r\n // Panel layout changed — must re-resolve layout, update viewport, and sync render context\r\n this.updateViewportAndRender();\r\n } else {\r\n this.engine.requestRender();\r\n }\r\n this.eventBus.emit('indicatorAdd', { instanceId, id });\r\n return instanceId;\r\n }\r\n\r\n updateIndicator(instanceId: string, params: Record<string, number | string | boolean>): void {\r\n this.indicatorEngine.updateIndicator(instanceId, params, this.dataManager.getData());\r\n this.engine.requestRender();\r\n }\r\n\r\n removeIndicator(instanceId: string): void {\r\n const hadPanel = this.layoutManager.getPanels().some(p => p.id === instanceId);\r\n this.indicatorEngine.removeIndicator(instanceId);\r\n this.layoutManager.removePanel(instanceId);\r\n this.eventBus.emit('indicatorRemove', { instanceId });\r\n if (hadPanel) {\r\n this.updateViewportAndRender();\r\n } else {\r\n this.engine.requestRender();\r\n }\r\n }\r\n\r\n getIndicatorOutput(instanceId: string): IndicatorOutput | null {\r\n return this.indicatorEngine.getOutput(instanceId);\r\n }\r\n\r\n registerIndicator(plugin: IndicatorPlugin): void {\r\n this.pluginManager.registerIndicator(plugin);\r\n }\r\n\r\n static indicators(): IndicatorDescriptor[] {\r\n const engine = new IndicatorEngine();\r\n registerBuiltInIndicators(engine);\r\n return engine.getAvailableIndicators();\r\n }\r\n\r\n // --- Panel layout ---\r\n\r\n setPanelPosition(instanceId: string, position: PanelPosition): void {\r\n this.layoutManager.setPanelPosition(instanceId, position);\r\n this.engine.requestRender();\r\n }\r\n\r\n setPanelSize(instanceId: string, size: number): void {\r\n this.layoutManager.setPanelSize(instanceId, size);\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Drawing tools ---\r\n\r\n setDrawingTool(type: DrawingToolType | null): void {\r\n if (!this.features.drawings) return;\r\n // If whitelist is set, check it\r\n if (type && this.features.drawingTools.length > 0 && !this.features.drawingTools.includes(type)) return;\r\n this.drawingManager.setActiveTool(type);\r\n }\r\n\r\n getDrawingTool(): DrawingToolType | null {\r\n return this.drawingManager.getActiveTool();\r\n }\r\n\r\n setDrawingStyle(style: Partial<DrawingStyle>): void {\r\n this.drawingManager.setStyle(style);\r\n }\r\n\r\n getDrawings(): DrawingState[] {\r\n return this.drawingManager.getDrawings();\r\n }\r\n\r\n setDrawings(drawings: DrawingState[]): void {\r\n this.drawingManager.setDrawings(drawings);\r\n }\r\n\r\n removeDrawing(id: string): void {\r\n this.drawingManager.removeDrawing(id);\r\n }\r\n\r\n clearDrawings(): void {\r\n this.drawingManager.clearDrawings();\r\n }\r\n\r\n registerDrawingTool(plugin: DrawingPlugin): void {\r\n this.drawingManager.register(plugin);\r\n }\r\n\r\n // --- Undo/Redo ---\r\n\r\n undo(): boolean {\r\n if (!this.features.drawingUndoRedo) return false;\r\n return this.drawingManager.undo();\r\n }\r\n\r\n redo(): boolean {\r\n if (!this.features.drawingUndoRedo) return false;\r\n return this.drawingManager.redo();\r\n }\r\n\r\n getUndoRedoState(): { canUndo: boolean; canRedo: boolean } {\r\n return this.undoRedoManager.getState();\r\n }\r\n\r\n // --- Drawing magnet ---\r\n\r\n setDrawingMagnet(enabled: boolean): void {\r\n this.drawingManager.setMagnetMode(enabled ? 'magnet' : 'none');\r\n }\r\n\r\n getDrawingMagnet(): boolean {\r\n return this.drawingManager.getMagnetMode() === 'magnet';\r\n }\r\n\r\n // --- Bulk drawing operations ---\r\n\r\n lockAllDrawings(): void {\r\n this.drawingManager.lockAllDrawings();\r\n }\r\n\r\n unlockAllDrawings(): void {\r\n this.drawingManager.unlockAllDrawings();\r\n }\r\n\r\n hideAllDrawings(): void {\r\n this.drawingManager.hideAllDrawings();\r\n }\r\n\r\n showAllDrawings(): void {\r\n this.drawingManager.showAllDrawings();\r\n }\r\n\r\n // --- Drawing duplication ---\r\n\r\n duplicateDrawing(id?: string): string | null {\r\n const targetId = id ?? this.drawingManager.getSelectedDrawingId();\r\n if (!targetId) return null;\r\n return this.drawingManager.duplicateDrawing(targetId);\r\n }\r\n\r\n // --- Data export ---\r\n\r\n exportVisibleData(format: 'csv' | 'json' = 'csv', filename?: string): void {\r\n const vp = this.viewport.getState();\r\n const data = this.dataManager.getData();\r\n const from = Math.max(0, vp.visibleRange.from);\r\n const to = Math.min(data.length - 1, vp.visibleRange.to);\r\n const slice = data.slice(from, to + 1);\r\n\r\n if (format === 'json') {\r\n const content = DataExporter.toJSON(slice);\r\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\r\n } else {\r\n const content = DataExporter.toCSV(slice);\r\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\r\n }\r\n }\r\n\r\n exportAllData(format: 'csv' | 'json' = 'csv', filename?: string): void {\r\n const data = this.dataManager.getData();\r\n if (format === 'json') {\r\n const content = DataExporter.toJSON(data);\r\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\r\n } else {\r\n const content = DataExporter.toCSV(data);\r\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\r\n }\r\n }\r\n\r\n // --- Auto-save ---\r\n\r\n setAutoSave(key: string, delayMs = 5000): void {\r\n this.autoSaveScheduler.enable(key, delayMs);\r\n }\r\n\r\n disableAutoSave(): void {\r\n this.autoSaveScheduler.disable();\r\n }\r\n\r\n private scheduleAutoSave(): void {\r\n this.autoSaveScheduler.schedule();\r\n }\r\n\r\n // --- Indicator introspection ---\r\n\r\n getAvailableIndicators(): IndicatorDescriptor[] {\r\n return this.indicatorEngine.getAvailableIndicators();\r\n }\r\n\r\n getIndicatorInputs(id: string): { id: string; params: Record<string, unknown> } | null {\r\n const indicators = this.indicatorEngine.getAvailableIndicators();\r\n const desc = indicators.find(i => i.id === id);\r\n if (!desc) return null;\r\n return { id: desc.id, params: desc.defaultConfig };\r\n }\r\n\r\n /** Get all active indicator instances with their current params */\r\n getActiveIndicators(): { instanceId: string; id: string; params: Record<string, unknown>; descriptor: IndicatorDescriptor }[] {\r\n return this.indicatorEngine.getActiveIndicators();\r\n }\r\n\r\n /** Get current config for a specific indicator instance */\r\n getIndicatorConfig(instanceId: string): { id: string; params: Record<string, unknown> } | null {\r\n const config = this.indicatorEngine.getIndicatorConfig(instanceId);\r\n if (!config) return null;\r\n return { id: config.id, params: { ...config.params } };\r\n }\r\n\r\n /** Update indicator colors/line widths at runtime */\r\n updateIndicatorStyle(instanceId: string, style: { colors?: string[]; lineWidths?: number[]; opacity?: number }): void {\r\n this.indicatorEngine.updateIndicatorStyle(instanceId, style);\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Trading ---\r\n\r\n setOrders(orders: TradingOrder[]): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setOrders(orders);\r\n }\r\n\r\n setPositions(positions: TradingPosition[]): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setPositions(positions);\r\n }\r\n\r\n setDepthData(depth: DepthData | null): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setDepthData(depth);\r\n }\r\n\r\n setCurrentPrice(price: number, _pulseColor?: string): void {\r\n this.tradingManager.setCurrentPrice(price);\r\n // Also update standalone price line (visible even without trading feature)\r\n this.currentPriceLine.setPrice(price);\r\n this.scheduleRender();\r\n if (this.features.alerts) this.alertManager.checkPrice(price);\r\n }\r\n\r\n setTradingConfig(config: Partial<TradingConfig>): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setConfig(config);\r\n }\r\n\r\n // --- Real-time Streaming ---\r\n\r\n /**\r\n * Connect to a real-time data source.\r\n * Loads history, starts streaming, manages reconnection automatically.\r\n *\r\n * @example\r\n * import { BinanceAdapter } from '@tradecanvas/core';\r\n * chart.connect({\r\n * adapter: new BinanceAdapter(),\r\n * symbol: 'BTCUSDT',\r\n * timeframe: '1m',\r\n * });\r\n */\r\n async connect(config: StreamConfig): Promise<void> {\r\n this.disconnectStream();\r\n\r\n this.streamManager = new StreamManager();\r\n\r\n this.streamManager.on('snapshot', (bars) => {\r\n this.setData(bars);\r\n });\r\n\r\n this.streamManager.on('barClose', (bar) => {\r\n this.dataManager.appendBar(bar);\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.updateViewportAndRender();\r\n });\r\n\r\n this.streamManager.on('barUpdate', (bar) => {\r\n this.dataManager.updateLastBar(bar);\r\n this.currentPriceLine.setPrice(bar.close);\r\n // Recalculate indicators so panel/overlay series track the forming bar\r\n // instead of freezing until bar close.\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.scheduleRender();\r\n });\r\n\r\n this.streamManager.on('priceChange', ({ price }) => {\r\n this.tradingManager.setCurrentPrice(price);\r\n this.currentPriceLine.setPrice(price);\r\n this.engine.requestRender(LayerType.Overlay);\r\n this.engine.requestRender(LayerType.UI);\r\n });\r\n\r\n this.streamManager.on('connectionChange', (info) => {\r\n this.eventBus.emit('dataUpdate', { connection: info });\r\n });\r\n\r\n this.streamManager.on('error', (err) => {\r\n this.eventBus.emit('dataUpdate', { error: err.message });\r\n });\r\n\r\n this.autoScrollOnNewBar = config.autoScroll !== false;\r\n this.currentSymbol = config.symbol;\r\n\r\n await this.streamManager.connect(config);\r\n\r\n // Set up bar countdown timer based on timeframe\r\n const tfMs = timeframeToMs(config.timeframe);\r\n this.barCountdown.setTimeframeMs(tfMs);\r\n\r\n // Start countdown refresh interval\r\n if (this.countdownInterval) clearInterval(this.countdownInterval);\r\n this.countdownInterval = setInterval(() => {\r\n if (this.barCountdown.isVisible()) {\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n }, 1000);\r\n }\r\n\r\n /**\r\n * Switch symbol or timeframe on an active stream without full reconnect.\r\n */\r\n async switchStream(symbol: string, timeframe: TimeFrame): Promise<void> {\r\n if (!this.streamManager) return;\r\n this.currentSymbol = symbol;\r\n await this.streamManager.switchTo(symbol, timeframe);\r\n }\r\n\r\n /**\r\n * Switch to a new timeframe. Requires an active stream connection.\r\n * Internally calls switchStream with the current symbol.\r\n */\r\n async setTimeframe(timeframe: TimeFrame): Promise<void> {\r\n if (!this.streamManager) throw new Error('No active stream. Call connect() first.');\r\n await this.switchStream(this.currentSymbol, timeframe);\r\n }\r\n\r\n /**\r\n * Disconnect the real-time stream.\r\n */\r\n disconnectStream(): void {\r\n if (this.streamManager) {\r\n this.streamManager.dispose();\r\n this.streamManager = null;\r\n }\r\n }\r\n\r\n setBarCountdownVisible(visible: boolean): void {\r\n this.barCountdown.setVisible(visible);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n setSessionBreaksVisible(visible: boolean): void {\r\n this.sessionBreaks.setVisible(visible);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n // --- Compare symbols ---\r\n\r\n addCompareSymbol(id: string, label: string, data: DataSeries, color: string): void {\r\n this.compareRenderer.addSymbol({ id, label, data, color, visible: true });\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n removeCompareSymbol(id: string): void {\r\n this.compareRenderer.removeSymbol(id);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n updateCompareData(id: string, data: DataSeries): void {\r\n this.compareRenderer.setSymbolData(id, data);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n setCompareMode(mode: 'percent' | 'absolute'): void {\r\n this.compareRenderer.setMode(mode);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n clearCompareSymbols(): void {\r\n this.compareRenderer.clear();\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n // --- Log scale ---\r\n\r\n setLogScale(enabled: boolean): void {\r\n this.viewport.setLogScale(enabled);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n isLogScale(): boolean {\r\n return this.viewport.isLogScale();\r\n }\r\n\r\n setSessionBreaksConfig(config: { color?: string; lineStyle?: 'solid' | 'dashed' | 'dotted'; lineWidth?: number }): void {\r\n this.sessionBreaks.setConfig(config);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n getConnectionState(): ConnectionState {\r\n return this.streamManager?.getConnectionState() ?? 'disconnected';\r\n }\r\n\r\n getConnectionInfo(): ConnectionInfo {\r\n return this.streamManager?.getConnectionInfo() ?? { state: 'disconnected' };\r\n }\r\n\r\n setAutoScroll(enabled: boolean): void {\r\n this.autoScrollOnNewBar = enabled;\r\n }\r\n\r\n // --- Viewport ---\r\n\r\n scrollTo(timestamp: number): void {\r\n const data = this.dataManager.getData();\r\n for (let i = 0; i < data.length; i++) {\r\n if (data[i].time >= timestamp) {\r\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\r\n this.viewport.scrollBy(i * barUnit - this.viewport.getState().offset);\r\n this.updateViewportAndRender();\r\n return;\r\n }\r\n }\r\n }\r\n\r\n scrollToEnd(): void {\r\n this.viewport.scrollToEnd();\r\n this.updateViewportAndRender();\r\n }\r\n\r\n setVisibleRange(fromTimestamp: number, toTimestamp: number): void {\r\n const data = this.dataManager.getData();\r\n let fromIdx = 0;\r\n let toIdx = data.length - 1;\r\n for (let i = 0; i < data.length; i++) {\r\n if (data[i].time >= fromTimestamp) { fromIdx = i; break; }\r\n }\r\n for (let i = data.length - 1; i >= 0; i--) {\r\n if (data[i].time <= toTimestamp) { toIdx = i; break; }\r\n }\r\n const barCount = toIdx - fromIdx + 1;\r\n if (barCount > 0) {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n const targetBarUnit = chartWidth / barCount;\r\n const newBarWidth = Math.max(2, targetBarUnit - this.viewport.getState().barSpacing);\r\n this.viewport.zoom(\r\n (newBarWidth - this.viewport.getState().barWidth) / this.viewport.getState().barWidth,\r\n chartWidth / 2,\r\n );\r\n }\r\n this.updateViewportAndRender();\r\n }\r\n\r\n zoomIn(): void {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n this.viewport.zoom(0.2, chartWidth / 2);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n zoomOut(): void {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n this.viewport.zoom(-0.2, chartWidth / 2);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n fitContent(): void {\r\n const data = this.dataManager.getData();\r\n if (data.length === 0) return;\r\n this.setVisibleRange(data[0].time, data[data.length - 1].time);\r\n }\r\n\r\n // --- Events ---\r\n\r\n on<K extends ChartEventType>(type: K, handler: (event: ChartEvent<K extends keyof ChartEventMap ? ChartEventMap[K] : unknown>) => void): void {\r\n this.eventBus.on(type, handler as (event: ChartEvent) => void);\r\n }\r\n\r\n off<K extends ChartEventType>(type: K, handler: (event: ChartEvent<K extends keyof ChartEventMap ? ChartEventMap[K] : unknown>) => void): void {\r\n this.eventBus.off(type, handler as (event: ChartEvent) => void);\r\n }\r\n\r\n enableTauriBridge(options?: Partial<TauriBridgeOptions>): void {\r\n this.eventBus.enableTauriBridge({ enabled: true, ...options });\r\n }\r\n\r\n disableTauriBridge(): void {\r\n this.eventBus.disableTauriBridge();\r\n }\r\n\r\n // --- Theme ---\r\n\r\n setTheme(themeOrName: ThemeName | Theme): void {\r\n this.themeManager.setTheme(themeOrName);\r\n this.syncRenderContext();\r\n this.container.style.backgroundColor = this.themeManager.getTheme().background;\r\n this.engine.requestRender();\r\n this.eventBus.emit('themeChange', { theme: themeOrName });\r\n }\r\n\r\n getTheme(): Theme {\r\n return this.themeManager.getTheme();\r\n }\r\n\r\n // --- Watermark ---\r\n\r\n setWatermark(text: string, opts?: { color?: string; fontSize?: number }): void {\r\n this.watermark.setConfig({ text, ...opts });\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n // --- Auto Scale ---\r\n\r\n setAutoScale(enabled: boolean): void {\r\n this.options.autoScale = enabled;\r\n this.updateViewportAndRender();\r\n }\r\n\r\n isAutoScale(): boolean {\r\n return this.options.autoScale !== false;\r\n }\r\n\r\n // --- Crosshair ---\r\n\r\n setCrosshairMode(mode: 'normal' | 'magnet' | 'hidden'): void {\r\n this.crosshairHandler.setMode(mode);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n getCrosshairMode(): string {\r\n return this.crosshairHandler.getMode();\r\n }\r\n\r\n setCrosshairPosition(point: { x: number; y: number } | null): void {\r\n if (point) {\r\n this.crosshairHandler.onPointerMove(point);\r\n }\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n getData(): DataSeries {\r\n return this.dataManager.getData();\r\n }\r\n\r\n // --- Grid ---\r\n\r\n setGridVisible(visible: boolean): void {\r\n this.gridRenderer.setVisible(visible);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n isGridVisible(): boolean {\r\n return this.gridRenderer.isVisible();\r\n }\r\n\r\n // --- Volume ---\r\n\r\n setVolumeVisible(visible: boolean): void {\r\n this.volumeRenderer.setVisible(visible);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n // --- Tooltip ---\r\n\r\n setTooltipVisible(visible: boolean): void {\r\n if (!visible) this.crosshairTooltip.hide();\r\n }\r\n\r\n // --- Legend ---\r\n\r\n setLegend(config: Partial<import('@tradecanvas/core').LegendConfig>): void {\r\n this.chartLegend.setConfig(config);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n setSymbolName(symbol: string): void {\r\n this.chartLegend.setSymbol(symbol);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n /**\r\n * Set a status text displayed in the chart legend area (e.g., \"LIVE . 8ms\").\r\n * Pass null to clear.\r\n */\r\n setStatusText(text: string | null): void {\r\n this.chartLegend.setStatusText(text);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n // --- Screenshot ---\r\n\r\n screenshot(filename?: string): void {\r\n if (!this.features.screenshot) return;\r\n Screenshot.download(this.container, filename, this.themeManager.getTheme().background);\r\n }\r\n\r\n screenshotDataURL(): string | null {\r\n if (!this.features.screenshot) return null;\r\n return Screenshot.toDataURL(this.container, this.themeManager.getTheme().background);\r\n }\r\n\r\n async screenshotBlob(): Promise<Blob | null> {\r\n if (!this.features.screenshot) return null;\r\n return Screenshot.toBlob(this.container, this.themeManager.getTheme().background);\r\n }\r\n\r\n // --- Alerts ---\r\n\r\n addAlert(price: number, condition: import('@tradecanvas/core').AlertCondition = 'crossing', message?: string): string | null {\r\n if (!this.features.alerts) return null;\r\n const id = this.alertManager.addAlert(price, condition, message);\r\n this.scheduleAutoSave();\r\n return id;\r\n }\r\n\r\n removeAlert(id: string): void {\r\n this.alertManager.removeAlert(id);\r\n this.scheduleAutoSave();\r\n }\r\n\r\n getAlerts(): import('@tradecanvas/core').PriceAlert[] {\r\n return this.alertManager.getAlerts();\r\n }\r\n\r\n clearAlerts(): void {\r\n this.alertManager.clearAlerts();\r\n this.scheduleAutoSave();\r\n }\r\n\r\n saveAlerts(key: string): void {\r\n this.alertManager.saveToStorage(key);\r\n }\r\n\r\n loadAlerts(key: string): void {\r\n this.alertManager.loadFromStorage(key);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n // --- Signal Markers ---\r\n\r\n addSignalMarker(marker: Omit<import('@tradecanvas/commons').SignalMarker, 'id'> & { id?: string }): string {\r\n return this.signalMarkerManager.addMarker(marker);\r\n }\r\n\r\n removeSignalMarker(id: string): void {\r\n this.signalMarkerManager.removeMarker(id);\r\n }\r\n\r\n getSignalMarkers(): import('@tradecanvas/commons').SignalMarker[] {\r\n return this.signalMarkerManager.getMarkers();\r\n }\r\n\r\n setSignalMarkers(markers: import('@tradecanvas/commons').SignalMarker[]): void {\r\n this.signalMarkerManager.setMarkers(markers);\r\n }\r\n\r\n clearSignalMarkers(): void {\r\n this.signalMarkerManager.clearMarkers();\r\n }\r\n\r\n setSignalMarkerStyle(style: Partial<import('@tradecanvas/commons').SignalMarkerStyle>): void {\r\n this.signalMarkerManager.setStyle(style);\r\n }\r\n\r\n // --- Trade Zones ---\r\n\r\n addTradeZone(zone: Omit<import('@tradecanvas/commons').TradeZone, 'id'> & { id?: string }): string {\r\n return this.tradeZoneManager.addZone(zone);\r\n }\r\n\r\n updateTradeZone(id: string, updates: Partial<Omit<import('@tradecanvas/commons').TradeZone, 'id'>>): void {\r\n this.tradeZoneManager.updateZone(id, updates);\r\n }\r\n\r\n removeTradeZone(id: string): void {\r\n this.tradeZoneManager.removeZone(id);\r\n }\r\n\r\n getTradeZones(): import('@tradecanvas/commons').TradeZone[] {\r\n return this.tradeZoneManager.getZones();\r\n }\r\n\r\n setTradeZones(zones: import('@tradecanvas/commons').TradeZone[]): void {\r\n this.tradeZoneManager.setZones(zones);\r\n }\r\n\r\n clearTradeZones(): void {\r\n this.tradeZoneManager.clearZones();\r\n }\r\n\r\n setTradeZoneStyle(style: Partial<import('@tradecanvas/commons').TradeZoneStyle>): void {\r\n this.tradeZoneManager.setStyle(style);\r\n }\r\n\r\n // --- Replay ---\r\n\r\n replay(config?: Partial<import('@tradecanvas/core').ReplayConfig>): void {\r\n if (!this.features.replay) return;\r\n const data = this.dataManager.getData();\r\n this.replayManager.load(data);\r\n this.replayManager.on('bar', ({ bar: _bar, index }) => {\r\n const slice = data.slice(0, index + 1);\r\n this.dataManager.setData(slice);\r\n this.crosshairHandler.setData(slice);\r\n this.indicatorEngine.recalculateAll(slice);\r\n this.updateViewportAndRender();\r\n });\r\n this.replayManager.play(config);\r\n }\r\n\r\n replayPause(): void { this.replayManager.pause(); }\r\n replayResume(): void { this.replayManager.resume(); }\r\n replayStop(): void { this.replayManager.stop(); }\r\n replaySeek(index: number): void { this.replayManager.seekTo(index); }\r\n setReplaySpeed(speed: number): void { this.replayManager.setSpeed(speed); }\r\n getReplayState(): 'playing' | 'paused' | 'stopped' { return this.replayManager.getState(); }\r\n getReplayProgress(): { current: number; total: number; percent: number } { return this.replayManager.getProgress(); }\r\n\r\n // --- Save / Load ---\r\n\r\n saveState(key?: string): string | null {\r\n if (!this.features.saveLoad) return null;\r\n const snapshot = ChartStateManager.capture(\r\n {\r\n getDrawings: () => this.getDrawings(),\r\n getTheme: () => this.getTheme(),\r\n getAlerts: () => this.getAlerts(),\r\n },\r\n { chartType: this.options.chartType },\r\n );\r\n const json = ChartStateManager.serialize(snapshot);\r\n if (key) ChartStateManager.saveToStorage(key, snapshot);\r\n return json;\r\n }\r\n\r\n loadState(json: string): void {\r\n if (!this.features.saveLoad) return;\r\n const snapshot = ChartStateManager.deserialize(json);\r\n if (snapshot.chartType) this.setChartType(snapshot.chartType);\r\n if (snapshot.drawings) this.setDrawings(snapshot.drawings);\r\n if (snapshot.theme) this.setTheme(snapshot.theme as any);\r\n if (snapshot.alerts) {\r\n this.clearAlerts();\r\n for (const a of snapshot.alerts) {\r\n this.addAlert(a.price, a.condition, a.message);\r\n }\r\n }\r\n }\r\n\r\n loadStateFromStorage(key: string): boolean {\r\n if (!this.features.saveLoad) return false;\r\n const snapshot = ChartStateManager.loadFromStorage(key);\r\n if (!snapshot) return false;\r\n this.loadState(ChartStateManager.serialize(snapshot));\r\n return true;\r\n }\r\n\r\n downloadState(filename?: string): void {\r\n if (!this.features.saveLoad) return;\r\n const snapshot = ChartStateManager.capture(\r\n { getDrawings: () => this.getDrawings(), getTheme: () => this.getTheme(), getAlerts: () => this.getAlerts() },\r\n { chartType: this.options.chartType },\r\n );\r\n ChartStateManager.downloadFile(snapshot, filename);\r\n }\r\n\r\n async loadStateFromFile(): Promise<void> {\r\n if (!this.features.saveLoad) return;\r\n const snapshot = await ChartStateManager.loadFromFile();\r\n this.loadState(ChartStateManager.serialize(snapshot));\r\n }\r\n\r\n // --- Locale ---\r\n\r\n setLocale(locale: Locale): void {\r\n setGlobalLocale(locale);\r\n this.engine.requestRender();\r\n }\r\n\r\n /**\r\n * Update the BCP 47 locale used for number formatting\r\n * (e.g. price axis labels, crosshair value badges).\r\n * Defaults to 'en-US'. Example values: 'de-DE', 'vi-VN', 'fr-FR'.\r\n */\r\n setNumberLocale(locale: string): void {\r\n this.numberLocale = locale;\r\n this.priceAxis.setLocale(locale);\r\n this.crosshairHandler.setLocale(locale);\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n }\r\n\r\n getNumberLocale(): string {\r\n return this.numberLocale;\r\n }\r\n\r\n // --- Market ---\r\n\r\n setMarket(config: MarketConfig): void {\r\n this.marketConfig = config;\r\n\r\n // Apply market color scheme to theme\r\n if (config.colorScheme) {\r\n const base = this.themeManager.getTheme();\r\n const marketTheme: Theme = {\r\n ...base,\r\n candleUp: config.colorScheme.up,\r\n candleDown: config.colorScheme.down,\r\n candleUpWick: config.colorScheme.up,\r\n candleDownWick: config.colorScheme.down,\r\n volumeUp: config.colorScheme.up.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.up}4D`,\r\n volumeDown: config.colorScheme.down.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.down}4D`,\r\n };\r\n this.themeManager.setTheme(marketTheme);\r\n }\r\n\r\n // Apply price precision to trading, alerts, and price line\r\n if (config.pricePrecision !== undefined) {\r\n this.tradingManager.setConfig({ pricePrecision: config.pricePrecision });\r\n this.alertManager.setPricePrecision(config.pricePrecision);\r\n this.streamManager?.priceLine.setPricePrecision(config.pricePrecision);\r\n this.crosshairHandler.setPricePrecision(config.pricePrecision);\r\n }\r\n\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n }\r\n\r\n getMarket(): MarketConfig | null {\r\n return this.marketConfig;\r\n }\r\n\r\n setPriceLimits(referencePrice: number): void {\r\n if (!this.marketConfig) return;\r\n const limits = computePriceLimits(referencePrice, this.marketConfig);\r\n if (limits) {\r\n this.marketConfig.priceLimits = {\r\n ...this.marketConfig.priceLimits!,\r\n referencePrice,\r\n };\r\n }\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Features ---\r\n\r\n /** Get the resolved feature configuration */\r\n getFeatures(): Readonly<Required<FeaturesConfig>> {\r\n return this.features;\r\n }\r\n\r\n /** Update feature flags at runtime. Only provided keys are changed. */\r\n setFeatures(patch: Partial<FeaturesConfig>): void {\r\n Object.assign(this.features, patch);\r\n\r\n // Apply immediate side-effects\r\n if (patch.crosshair === false) {\r\n this.crosshairTooltip.hide();\r\n }\r\n if (patch.grid !== undefined) {\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n if (patch.volume !== undefined) {\r\n this.volumeRenderer.setVisible(patch.volume);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n if (patch.drawings === false) {\r\n this.drawingManager.setActiveTool(null);\r\n }\r\n if (patch.trading === false) {\r\n this.tradingManager.setOrders([]);\r\n this.tradingManager.setPositions([]);\r\n }\r\n if (patch.keyboard !== undefined) {\r\n this.keyboardHandler?.setEnabled(patch.keyboard);\r\n }\r\n\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Lifecycle ---\r\n\r\n resize(): void {\r\n const size = this.engine.dprManager.readContainerSize();\r\n if (size.width <= 0 || size.height <= 0) return;\r\n this.containerSizeCache = size;\r\n this.containerSizeCacheTime = Date.now();\r\n // Resize canvas layers immediately (don't wait for DPRManager's debounced callback)\r\n const dpr = this.engine.dprManager.getDpr();\r\n this.engine.layerManager.resize(size, dpr);\r\n // Check if viewport was at the end before resize\r\n const wasAtEnd = this.viewport.isAtEnd();\r\n this.viewport.resize(size.width, size.height);\r\n this.layoutManager.resize(size.width, size.height);\r\n this.updateViewportAndRender(wasAtEnd);\r\n this.eventBus.emit('resize', size);\r\n }\r\n\r\n destroy(): void {\r\n if (this.countdownInterval) clearInterval(this.countdownInterval);\r\n this.disableAutoSave();\r\n this.disconnectStream();\r\n if (this.onWindowKeyDown) {\r\n window.removeEventListener('keydown', this.onWindowKeyDown);\r\n this.onWindowKeyDown = null;\r\n }\r\n this.keyboardHandler = null;\r\n this.interactionManager.detach();\r\n this.tradingManager.destroy();\r\n this.animator.dispose();\r\n this.crosshairTooltip.destroy();\r\n this.replayManager.dispose();\r\n this.undoRedoManager.clear();\r\n this.engine.destroy();\r\n this.eventBus.destroy();\r\n this.container.innerHTML = '';\r\n }\r\n\r\n // --- Internal ---\r\n\r\n private createChartRenderer(type: ChartType): ChartRendererInterface {\r\n return createRendererFor(type);\r\n }\r\n\r\n /** Cached display data. Invalidated when raw data or chart type changes. */\r\n private getDisplayData(): DataSeries {\r\n if (this.displayDataCache) return this.displayDataCache;\r\n const raw = this.dataManager.getData();\r\n if (raw.length === 0) return raw;\r\n const result = transformDisplayData(this.options.chartType, raw);\r\n this.displayDataCache = result;\r\n return result;\r\n }\r\n\r\n /** Lightweight render for streaming updates. No layout resolve, no indicator recalc. */\r\n private scheduleRender(): void {\r\n if (this.renderScheduled) return;\r\n this.renderScheduled = true;\r\n requestAnimationFrame(() => {\r\n this.renderScheduled = false;\r\n const displayData = this.getDisplayData();\r\n this.viewport.updateData(displayData, this.options.autoScale !== false);\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n });\r\n }\r\n\r\n /** Full update: resolve layout, update viewport, sync context, request render. */\r\n private updateViewportAndRender(scrollToEnd = false): void {\r\n // Invalidate layout cache\r\n this.resolvedLayoutCache = null;\r\n this.panelInfoCache = null;\r\n\r\n const resolved = this.getResolvedLayout();\r\n this.viewport.setChartRect(resolved.mainChartRect);\r\n\r\n const displayData = this.getDisplayData();\r\n this.viewport.updateData(displayData, this.options.autoScale !== false);\r\n\r\n // Expand price range to include overlay indicator values (BB, Ichimoku, etc.)\r\n if (this.options.autoScale !== false) {\r\n const vs = this.viewport.getState();\r\n const overlayRange = this.indicatorEngine.getOverlayPriceRange(\r\n vs.visibleRange.from,\r\n Math.min(vs.visibleRange.to, displayData.length - 1),\r\n );\r\n if (overlayRange) {\r\n const current = vs.priceRange;\r\n const expandedMin = Math.min(current.min, overlayRange.min);\r\n const expandedMax = Math.max(current.max, overlayRange.max);\r\n if (expandedMin < current.min || expandedMax > current.max) {\r\n const range = expandedMax - expandedMin || 1;\r\n this.viewport.setPriceRange(\r\n expandedMin - range * 0.02,\r\n expandedMax + range * 0.02,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Scroll to end AFTER updateData so dataLength is current\r\n if (scrollToEnd) this.viewport.scrollToEnd();\r\n\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n }\r\n\r\n private getResolvedLayout() {\r\n if (!this.resolvedLayoutCache) {\r\n this.resolvedLayoutCache = this.layoutManager.resolve();\r\n }\r\n return this.resolvedLayoutCache;\r\n }\r\n\r\n /** Cache container size for 500ms to avoid layout thrashing on rapid calls */\r\n private cachedContainerSize(): { width: number; height: number } {\r\n const now = Date.now();\r\n if (!this.containerSizeCache || now - this.containerSizeCacheTime > 500) {\r\n this.containerSizeCache = this.engine.dprManager.getContainerSize();\r\n this.containerSizeCacheTime = now;\r\n }\r\n return this.containerSizeCache;\r\n }\r\n\r\n private buildPanelRenderInfos(): import('@tradecanvas/core').PanelRenderInfo[] {\r\n if (this.panelInfoCache) return this.panelInfoCache;\r\n\r\n const resolved = this.getResolvedLayout();\r\n const mainVP = this.viewport.getState();\r\n\r\n const { from, to } = mainVP.visibleRange;\r\n const panels = resolved.panels.map((panel) => {\r\n const output = this.indicatorEngine.getOutput(panel.config.id);\r\n const priceRange = computeIndicatorPriceRange(output, from, to);\r\n\r\n // Inset the indicator drawing area below the panel header (title + divider)\r\n const PANEL_HEADER_HEIGHT = 20;\r\n const insetRect = {\r\n x: panel.rect.x,\r\n y: panel.rect.y + PANEL_HEADER_HEIGHT,\r\n width: panel.rect.width,\r\n height: Math.max(0, panel.rect.height - PANEL_HEADER_HEIGHT),\r\n };\r\n\r\n return {\r\n instanceId: panel.config.id,\r\n rect: panel.rect,\r\n viewport: {\r\n ...mainVP,\r\n chartRect: insetRect,\r\n priceRange,\r\n },\r\n };\r\n });\r\n\r\n this.panelInfoCache = panels;\r\n return panels;\r\n }\r\n\r\n private syncRenderContext(): void {\r\n const resolved = this.getResolvedLayout();\r\n const panels = this.features.indicators ? this.buildPanelRenderInfos() : [];\r\n\r\n // Compute where the time axis should render: below main chart + all bottom panels\r\n const bottomPanelHeight = resolved.panels\r\n .filter(p => p.config.position === 'bottom')\r\n .reduce((sum, p) => sum + p.rect.height, 0);\r\n const timeAxisY = resolved.mainChartRect.y + resolved.mainChartRect.height + bottomPanelHeight;\r\n\r\n const displayData = this.getDisplayData();\r\n this.engine.setRenderContext({\r\n chartRenderer: this.chartRenderer,\r\n gridRenderer: this.features.grid ? this.gridRenderer : null,\r\n priceAxis: this.features.priceAxis ? this.priceAxis : null,\r\n timeAxis: this.features.timeAxis ? this.timeAxis : null,\r\n crosshairHandler: this.features.crosshair ? this.crosshairHandler : null,\r\n indicatorEngine: this.features.indicators ? this.indicatorEngine : null,\r\n drawingRenderer: this.features.drawings ? this.drawingRenderer : null,\r\n tradingRenderer: this.features.trading ? this.tradingRenderer : null,\r\n currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine,\r\n chartLegend: this.features.legend ? this.chartLegend : null,\r\n volumeRenderer: this.features.volume ? this.volumeRenderer : null,\r\n watermark: this.features.watermark ? this.watermark : null,\r\n barCountdown: this.barCountdown,\r\n sessionBreaks: this.sessionBreaks,\r\n compareRenderer: this.compareRenderer,\r\n alertManager: this.features.alerts ? this.alertManager : null,\r\n signalMarkerManager: this.signalMarkerManager,\r\n tradeZoneManager: this.tradeZoneManager,\r\n panels,\r\n priceLimits: this.buildPriceLimits(),\r\n timeAxisY,\r\n // Attach data to the viewport so drawings/indicators can treat\r\n // `anchor.time` as a real timestamp and convert via timestampToBarIndex.\r\n viewport: { ...this.viewport.getState(), data: displayData },\r\n theme: this.themeManager.getTheme(),\r\n data: displayData,\r\n numberLocale: this.numberLocale,\r\n });\r\n }\r\n\r\n private buildPriceLimits() {\r\n if (!this.marketConfig?.priceLimits?.enabled || !this.marketConfig.priceLimits.referencePrice) return null;\r\n const limits = computePriceLimits(this.marketConfig.priceLimits.referencePrice, this.marketConfig);\r\n if (!limits) return null;\r\n return {\r\n ...limits,\r\n colors: this.marketConfig.colorScheme ? {\r\n ceiling: this.marketConfig.colorScheme.ceiling,\r\n floor: this.marketConfig.colorScheme.floor,\r\n reference: this.marketConfig.colorScheme.reference,\r\n } : undefined,\r\n };\r\n }\r\n}\r\n"],"mappings":";;;AA6BA,SAAgB,GAAkB,GAAyC;AACzE,SAAQ,GAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,YACH,QAAO,IAAI,GAAqB;EAClC,KAAK,OACH,QAAO,IAAI,GAAc;EAC3B,KAAK,OACH,QAAO,IAAI,GAAc;EAC3B,KAAK,MACH,QAAO,IAAI,IAAa;EAC1B,KAAK,eACH,QAAO,IAAI,IAAsB;EACnC,KAAK,WACH,QAAO,IAAI,GAAkB;EAC/B,KAAK,QACH,QAAO,IAAI,GAAe;EAC5B,KAAK,OACH,QAAO,IAAI,IAAc;EAC3B,KAAK,iBACH,QAAO,IAAI,GAAwB;EACrC,KAAK,gBACH,QAAO,IAAI,GAAsB;EACnC,KAAK,UACH,QAAO,IAAI,IAAiB;EAC9B,KAAK,WACH,QAAO,IAAI,GAAkB;EAC/B,KAAK,kBACH,QAAO,IAAI,GAAyB;EACtC,QACE,QAAO,IAAI,GAAqB;;;AAUtC,SAAgB,GAAqB,GAAiB,GAA6B;AACjF,KAAI,EAAI,WAAW,EAAG,QAAO;AAE7B,SAAQ,GAAR;EACE,KAAK,aACH,QAAO,GAAa,EAAI;EAC1B,KAAK,QACH,QAAO,GAAQ,GAAK;GAAE,WAAW;GAAG,QAAQ;GAAM,WAAW;GAAI,CAAC;EACpE,KAAK,YACH,QAAO,GAAY,GAAK,EAAE;EAC5B,KAAK,OACH,QAAO,GAAO,GAAK,EAAE;EACvB,KAAK,iBAEH,QAAO,GAAiB,GADP,EAAa,EACD,GAAW,KAAM,EAAE;EAElD,KAAK,YAEH,QAAO,GAAY,GAAK,EAAE,WADT,EAAa,EACO,GAAW,MAAO,CAAC;EAE1D,QACE,QAAO;;;AAmBb,SAAS,EAAa,GAAyB;CAC7C,IAAI,IAAM;AACV,MAAK,IAAM,KAAK,EAAK,MAAO,EAAE;AAC9B,QAAO,IAAM,EAAI;;;;AC3GnB,IAAM,IAA4B;CAAE,KAAK;CAAG,KAAK;CAAK,EAChD,IAAU;AAWhB,SAAgB,GACd,GACA,GACA,GACY;AACZ,KAAI,CAAC,EAAQ,QAAO,EAAE,GAAG,GAAe;CAExC,IAAI,IAAO,UACP,IAAO,WACP,IAAM;AACV,MAAK,IAAM,GAAG,MAAQ,EAAO,QAAQ;AACnC,MAAI,KAAO,KAAQ,KAAO,EACxB,MAAK,IAAM,KAAO,GAAK;GACrB,IAAM,IAAI,EAAI;AACd,GAAI,MAAM,KAAA,KAAa,OAAO,SAAS,EAAE,KACnC,IAAI,MAAM,IAAO,IACjB,IAAI,MAAM,IAAO;;AAI3B;;AAGF,KAAI,MAAS,SAAU,QAAO,EAAE,GAAG,GAAe;CAElD,IAAM,IAAQ,IAAO,KAAQ;AAC7B,QAAO;EACL,KAAK,IAAO,IAAQ;EACpB,KAAK,IAAO,IAAQ;EACrB;;;;AC3CH,IAAa,KAAb,MAA+B;CAC7B,QAAsD;CACtD,UAAkB;CAClB,MAA6B;CAE7B,YAAY,GAAqC;AAA7B,OAAA,OAAA;;CAGpB,OAAO,GAAa,GAAuB;AAEzC,EADA,KAAK,MAAM,GACX,KAAK,UAAU;;CAIjB,UAAgB;AAGd,EAFA,KAAK,MAAM,MACX,KAAK,UAAU,GACf,KAAK,QAAQ;;CAOf,WAAiB;AACX,OAAK,WAAW,KAAK,CAAC,KAAK,QAC3B,KAAK,SAAO,aAAa,KAAK,MAAM,EACxC,KAAK,QAAQ,iBAAiB;AAE5B,GADA,KAAK,QAAQ,MACT,KAAK,OAAK,KAAK,KAAK,KAAK,IAAI;KAChC,KAAK,QAAQ;;CAIlB,SAAe;AACb,EAEE,KAAK,WADL,aAAa,KAAK,MAAM,EACX;;CAIjB,YAAqB;AACnB,SAAO,KAAK,UAAU,KAAK,KAAK,QAAQ;;CAG1C,aAAsB;AACpB,SAAO,KAAK,UAAU;;;;;AC/C1B,SAAS,EAAW,GAAuB;AACzC,KAAI,CAAC,KAAO,OAAO,EAAI,QAAS,SAAU,QAAO;CACjD,IAAM,EAAE,SAAM,SAAM,QAAK,aAAU;AASnC,QADA,EANI,CAAC,SAAS,EAAK,IAAI,CAAC,SAAS,EAAK,IAAI,CAAC,SAAS,EAAI,IAAI,CAAC,SAAS,EAAM,IAExE,IAAO,KAAK,IAAO,KAAK,IAAM,KAAK,IAAQ,KAE3C,IAAO,KAEP,EAAI,WAAW,KAAA,MAAc,CAAC,SAAS,EAAI,OAAO,IAAI,EAAI,SAAS;;AAKzE,SAAS,EAAY,GAAuB;AAC1C,QAAO;EACL,GAAG;EACH,MAAM,KAAK,IAAI,EAAI,MAAM,EAAI,MAAM,EAAI,KAAK,EAAI,MAAM;EACtD,KAAK,KAAK,IAAI,EAAI,MAAM,EAAI,MAAM,EAAI,KAAK,EAAI,MAAM;EACrD,QAAQ,EAAI,WAAW,KAAA,IAAsC,IAA1B,KAAK,IAAI,GAAG,EAAI,OAAO;EAC3D;;AAGH,IAAa,IAAb,MAAyB;CACvB,OAA2B,EAAE;CAE7B,UAAsB;AACpB,SAAO,KAAK;;CAGd,QAAQ,GAAwB;AAE9B,OAAK,OAAO,EACT,OAAO,EAAW,CAClB,IAAI,EAAY;;CAGrB,UAAU,GAAoB;AACvB,IAAW,EAAI,IACpB,KAAK,KAAK,KAAK,EAAY,EAAI,CAAC;;CAGlC,cAAc,GAAoB;AAChC,MAAI,CAAC,EAAW,EAAI,CAAE;EACtB,IAAM,IAAY,EAAY,EAAI;AAClC,MAAI,KAAK,KAAK,WAAW,GAAG;AAC1B,QAAK,KAAK,KAAK,EAAU;AACzB;;AAEF,OAAK,KAAK,KAAK,KAAK,SAAS,KAAK;;CAGpC,sBAAsB,GAA8D;AAC9E,OAAK,KAAK,WAAW,MACrB,CAAC,SAAS,EAAK,MAAM,IAAI,EAAK,QAAQ,KACtC,EAAK,WAAW,KAAA,MAAc,CAAC,SAAS,EAAK,OAAO,IAAI,EAAK,SAAS,OAC1E,KAAK,KAAK,KAAK,KAAK,SAAS,KAAK,EAAS,KAAK,KAAK,KAAK,KAAK,SAAS,IAAI,EAAK;;CAGnF,YAAoB;AAClB,SAAO,KAAK,KAAK;;CAGnB,QAAc;AACZ,OAAK,OAAO,EAAE;;GClEL,IAAb,MAA0B;CACxB;CAEA,YAAY,GAAiC;AAC3C,EAAI,CAAC,KAAe,MAAgB,SAClC,KAAK,QAAQ,EAAE,GAAG,GAAY,GACrB,MAAgB,UACzB,KAAK,QAAQ,EAAE,GAAG,GAAa,GAE/B,KAAK,QAAQ,EAAE,GAAG,GAAa;;CAInC,WAAkB;AAChB,SAAO,KAAK;;CAGd,SAAS,GAAsC;AAC7C,EAAI,MAAgB,SAClB,KAAK,QAAQ,EAAE,GAAG,GAAY,GACrB,MAAgB,UACzB,KAAK,QAAQ,EAAE,GAAG,GAAa,GAE/B,KAAK,QAAQ,EAAE,GAAG,GAAa;;GCvB/B,IAAsB,KACtB,IAAkB,IAEX,IAAb,MAA2B;CACzB,SAAgC,EAAE;CAClC,iBAAyB;CACzB,kBAA0B;CAE1B,OAAO,GAAe,GAAsB;AAE1C,EADA,KAAK,iBAAiB,GACtB,KAAK,kBAAkB;;CAGzB,SAAS,GAAoB,IAA0B,UAAU,GAAqB;EACpF,IAAM,IAAa,MAAa,UAAU,MAAa;AACvD,OAAK,OAAO,KAAK;GACf,IAAI;GACJ;GACA,MAAM,MAAS,IAAa,IAAsB;GAClD,SAAS,IAAa,IAAkB;GACxC,SAAS;IAAE,MAAM;IAAa,qBAAqB;IAAY;GAChE,CAAC;;CAGJ,YAAY,GAA0B;AACpC,OAAK,SAAS,KAAK,OAAO,QAAQ,MAAM,EAAE,OAAO,EAAW;;CAG9D,iBAAiB,GAAoB,GAA+B;EAClE,IAAM,IAAQ,KAAK,OAAO,MAAM,MAAM,EAAE,OAAO,EAAW;AAC1D,MAAI,GAAO;GACT,IAAM,IAAc,EAAM,aAAa,UAAU,EAAM,aAAa,SAC9D,IAAa,MAAa,UAAU,MAAa;AAEvD,GADA,EAAM,WAAW,GACb,MAAgB,MAClB,EAAM,OAAO,IAAa,IAAsB,GAChD,EAAM,UAAU,IAAa,IAAkB;;;CAKrD,aAAa,GAAoB,GAAoB;EACnD,IAAM,IAAQ,KAAK,OAAO,MAAM,MAAM,EAAE,OAAO,EAAW;AAC1D,EAAI,MACF,EAAM,OAAO,KAAK,IAAI,EAAM,SAAS,EAAK;;CAI9C,YAA2B;AACzB,SAAO,KAAK;;CAGd,UAA0B;EACxB,IAAM,IAAa,KAAK,OAAO,QAAQ,MAAM,EAAE,aAAa,OAAO,EAC7D,IAAc,KAAK,OAAO,QAAQ,MAAM,EAAE,aAAa,QAAQ,EAC/D,IAAY,KAAK,OAAO,QAAQ,MAAM,EAAE,aAAa,MAAM,EAC3D,IAAe,KAAK,OAAO,QAAQ,MAAM,EAAE,aAAa,SAAS,EAEjE,IAAY,EAAW,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,EAAE,EACtD,IAAa,EAAY,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,EAAE,EACxD,IAAY,EAAU,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,EAAE,EACrD,IAAe,EAAa,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,EAAE,EAE3D,IAAsB;GAC1B,GAAG;GACH,GAAG;GACH,OAAO,KAAK,IAAI,GAAG,KAAK,iBAAiB,IAAY,IAAa,EAAiB;GACnF,QAAQ,KAAK,IAAI,GAAG,KAAK,kBAAkB,IAAY,IAAe,EAAiB;GACxF,EAEK,IAAkC,EAAE,EACpC,IAA0B,EAAE,EAG9B,IAAI;AACR,OAAK,IAAM,KAAS,EAUlB,CATA,EAAe,KAAK;GAClB,QAAQ;GACR,MAAM;IAAE;IAAG,GAAG;IAAG,OAAO,EAAM;IAAM,QAAQ,KAAK,kBAAkB;IAAkB;GACtF,CAAC,EACF,EAAS,KAAK;GACZ,SAAS,EAAM;GACf,MAAM;IAAE,GAAG,IAAI,EAAM,OAAO;IAAG,GAAG;IAAG,OAAO;IAAG,QAAQ,KAAK;IAAiB;GAC7E,aAAa;GACd,CAAC,EACF,KAAK,EAAM;EAIb,IAAI,IAAI;AACR,OAAK,IAAM,KAAS,EAUlB,CATA,EAAe,KAAK;GAClB,QAAQ;GACR,MAAM;IAAE,GAAG;IAAW;IAAG,OAAO,EAAc;IAAO,QAAQ,EAAM;IAAM;GAC1E,CAAC,EACF,EAAS,KAAK;GACZ,SAAS,EAAM;GACf,MAAM;IAAE,GAAG;IAAW,GAAG,IAAI,EAAM,OAAO;IAAG,OAAO,EAAc;IAAO,QAAQ;IAAG;GACpF,aAAa;GACd,CAAC,EACF,KAAK,EAAM;AAIb,MAAI,EAAc,IAAI,EAAc;AACpC,OAAK,IAAM,KAAS,EAUlB,CATA,EAAe,KAAK;GAClB,QAAQ;GACR,MAAM;IAAE,GAAG;IAAW;IAAG,OAAO,EAAc;IAAO,QAAQ,EAAM;IAAM;GAC1E,CAAC,EACF,EAAS,KAAK;GACZ,SAAS,EAAM;GACf,MAAM;IAAE,GAAG;IAAW,GAAG,IAAI;IAAG,OAAO,EAAc;IAAO,QAAQ;IAAG;GACvE,aAAa;GACd,CAAC,EACF,KAAK,EAAM;AAIb,MAAI,IAAY,EAAc,QAAQ;AACtC,OAAK,IAAM,KAAS,EAUlB,CATA,EAAe,KAAK;GAClB,QAAQ;GACR,MAAM;IAAE;IAAG,GAAG;IAAG,OAAO,EAAM;IAAM,QAAQ,KAAK,kBAAkB;IAAkB;GACtF,CAAC,EACF,EAAS,KAAK;GACZ,SAAS,EAAM;GACf,MAAM;IAAE,GAAG,IAAI;IAAG,GAAG;IAAG,OAAO;IAAG,QAAQ,KAAK;IAAiB;GAChE,aAAa;GACd,CAAC,EACF,KAAK,EAAM;AAGb,SAAO;GAAE;GAAe,QAAQ;GAAgB;GAAU;;CAG5D,mBAAyB;AACvB,SAAO,KAAK,SAAS,CAAC;;GCzIb,IAAb,MAA2B;CACzB,YAAY,GAA0C;AAAlC,OAAA,kBAAA;;CAEpB,kBAAkB,GAA+B;AAC/C,OAAK,gBAAgB,SAAS,EAAO;;GCyE5B,KAAb,MAAmB;CACjB,OAAO,UAAU;CAEjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,gBAA8C;CAC9C,qBAA6B;CAC7B,mBAA8C;CAC9C,sBAAoF;CACpF,iBAA+E;CAC/E,kBAA0B;CAC1B,qBAAuE;CACvE,yBAAiC;CACjC;CACA;CACA;CACA;CACA;CACA,oBAAmE;CACnE;CACA;CACA;CACA;CACA;CACA;CACA,oBAA4B,IAAI,IAAmB,MAAQ,KAAK,UAAU,EAAI,CAAC;CAC/E;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,eAA4C;CAC5C;CACA;CACA;CACA,kBAAkD;CAClD,kBAA+D;CAC/D,gBAAgC;CAGhC,YAAY,GAAwB,GAAuB;AAGzD,EAFA,KAAK,YAAY,GACjB,KAAK,UAAU,GACf,KAAK,eAAe,EAAQ,gBAAgB;EAG5C,IAAM,IAAI,EAAQ,YAAY,EAAE;AAiFhC,EAhFA,KAAK,WAAW;GACd,UAAU,EAAE,YAAY;GACxB,cAAc,EAAE,gBAAgB,EAAE;GAClC,eAAe,EAAE,iBAAiB;GAClC,iBAAiB,EAAE,mBAAmB;GACtC,SAAS,EAAE,WAAW;GACtB,oBAAoB,EAAE,sBAAsB;GAC5C,YAAY,EAAE,cAAc;GAC5B,cAAc,EAAE,gBAAgB,EAAE;GAClC,SAAS,EAAE,WAAW;GACtB,SAAS,EAAE,WAAW;GACtB,WAAW,EAAE,aAAa;GAC1B,UAAU,EAAE,YAAY;GACxB,WAAW,EAAE,aAAa;GAC1B,UAAU,EAAE,YAAY;GACxB,MAAM,EAAE,QAAS,EAAQ,MAAM,WAAW;GAC1C,QAAQ,EAAE,UAAU;GACpB,QAAQ,EAAE,UAAU;GACpB,WAAW,EAAE,aAAa;GAC1B,UAAU,EAAE,YAAY;GACxB,YAAY,EAAE,cAAc;GAC5B,QAAQ,EAAE,UAAU;GACpB,QAAQ,EAAE,UAAU;GACpB,eAAe,EAAE,iBAAiB;GAClC,cAAc,EAAE,gBAAgB;GAChC,gBAAgB,EAAE,kBAAkB;GACpC,YAAY,EAAE,cAAc;GAC5B,UAAU,EAAE,YAAY;GACxB,YAAY,EAAE,cAAc,EAAE;GAC9B,2BAA2B,EAAE,6BAA6B,EAAE;GAC7D,EAED,EAAU,MAAM,WAAW,YAC3B,EAAU,MAAM,WAAW,UAC3B,EAAU,WAAW,GACrB,EAAU,MAAM,UAAU,QAG1B,KAAK,cAAc,IAAI,GAAa,EACpC,KAAK,eAAe,IAAI,EAAa,EAAQ,MAAM,EACnD,KAAK,gBAAgB,IAAI,GAAe,EACxC,KAAK,kBAAkB,IAAI,GAAiB,EAC5C,KAAK,gBAAgB,IAAI,EAAc,KAAK,gBAAgB,EAC5D,KAAK,WAAW,IAAI,IAAU,EAE9B,EAA0B,KAAK,gBAAgB,EAG/C,KAAK,iBAAiB,IAAI,IAAgB,EAC1C,GAA4B,KAAK,eAAe,EAChD,KAAK,kBAAkB,IAAI,GAAgB,KAAK,eAAe,EAC/D,KAAK,eAAe,uBAAuB;AAIzC,GAFA,KAAK,mBAAmB,EACxB,KAAK,OAAO,cAAc,EAAU,QAAQ,EAC5C,KAAK,kBAAkB;IACvB,EACF,KAAK,eAAe,kBAAkB,GAAO,MAAS;AACpD,QAAK,SAAS,KAAK,GAAyB,EAAK;IACjD,EAEF,KAAK,kBAAkB,IAAI,GAAiB,EAC5C,KAAK,eAAe,mBAAmB,KAAK,gBAAgB,EAC5D,KAAK,eAAe,oBAAoB,KAAK,YAAY,SAAS,CAAC,EACnE,KAAK,eAAe,2BAA2B,KAAK,gBAAgB,CAAC,EAEjE,EAAQ,WAAW,SAAS,YAC9B,KAAK,eAAe,cAAc,SAAS,EAI7C,KAAK,iBAAiB,IAAI,GAAgB,EAC1C,KAAK,kBAAkB,IAAI,EAAgB,KAAK,eAAe,EAC/D,KAAK,eAAe,aAAa,EAAU,EAC3C,KAAK,eAAe,uBAAuB,KAAK,OAAO,cAAc,EAAU,QAAQ,CAAC,EACxF,KAAK,eAAe,kBAAkB,GAAO,MAAS;AACpD,QAAK,SAAS,KAAK,GAAyB,EAAK;IACjD,EAGF,KAAK,SAAS,IAAI,EAAa,EAAU;EACzC,IAAM,IAAO,KAAK,OAAO,WAAW,kBAAkB;AAmOtD,EAlOA,KAAK,WAAW,IAAI,EAClB,EAAK,OACL,EAAK,QACL,EAAQ,iBAAiB,GACzB,EAAQ,iBAAiB,IACzB,EAAQ,eAAe,EACxB,EACD,KAAK,cAAc,OAAO,EAAK,OAAO,EAAK,OAAO,EAQlD,KAAK,OAAO,qBAAqB,MAAY;AAC3C,OAAI,EAAQ,SAAS,KAAK,EAAQ,UAAU,EAAG;GAC/C,IAAM,IAAW,KAAK,SAAS,SAAS;AAMxC,GALA,KAAK,SAAS,OAAO,EAAQ,OAAO,EAAQ,OAAO,EACnD,KAAK,cAAc,OAAO,EAAQ,OAAO,EAAQ,OAAO,EAIxD,KAAK,wBAAwB,EAAS;KAIxC,KAAK,gBAAgB,KAAK,oBAAoB,EAAQ,UAAU,EAChE,KAAK,eAAe,IAAI,IAAc,EAClC,EAAQ,MAAM,YAAY,MAAO,KAAK,aAAa,WAAW,GAAM,EACxE,KAAK,YAAY,IAAI,GAAW,EAChC,KAAK,UAAU,UAAU,KAAK,aAAa,EAC3C,KAAK,WAAW,IAAI,GAAU,EAG9B,KAAK,mBAAmB,IAAI,IAAkB,EAC9C,KAAK,iBAAiB,UAAU,KAAK,aAAa,EAC9C,EAAQ,WAAW,QACrB,KAAK,iBAAiB,QAAQ,EAAQ,UAAU,KAAK,EAIvD,KAAK,iBAAiB,aAAa,GAAU,MAAU;AACrD,OAAI,MAAa,QAAQ,GAAO;IAC9B,IAAM,IAAO,KAAK,YAAY,SAAS,EACjC,IAAM,IAAW,EAAK,SAAS,EAAK,KAAY,KAAA;AAWtD,IARA,KAAK,YAAY,YAAY,KAAO,KAAK,EAGrC,KACF,KAAK,iBAAiB,KAAK,GAAO,GAAK,KAAK,aAAa,UAAU,EAAE,KAAK,qBAAqB,CAAC,EAIlG,KAAK,SAAS,KAAK,iBAAiB;KAAE;KAAO;KAAK;KAAU,CAAC;SAG7D,CADA,KAAK,iBAAiB,MAAM,EAC5B,KAAK,YAAY,YAAY,KAAK;IAEpC,EAGF,KAAK,cAAc,IAAI,IAAa,EACpC,KAAK,YAAY,aAAa,EAAQ,UAAU,EAGhD,KAAK,YAAY,IAAI,IAAW,EAC5B,EAAQ,aAAW,KAAK,UAAU,UAAU,EAAQ,UAAU,EAClE,KAAK,iBAAiB,IAAI,IAAgB,EAG1C,KAAK,eAAe,IAAI,GAAc,EACtC,KAAK,gBAAgB,IAAI,GAAe,EACxC,KAAK,kBAAkB,IAAI,GAAiB,EAGxC,EAAQ,gBACV,KAAK,cAAc,UAAU;GAC3B,SAAS,EAAQ,cAAc,WAAW;GAC1C,OAAO,EAAQ,cAAc;GAC7B,WAAW,EAAQ,cAAc;GACjC,WAAW,EAAQ,cAAc;GAClC,CAAC,GACO,EAAQ,UAAU,kBAAkB,MAC7C,KAAK,cAAc,WAAW,GAAK,EAIjC,EAAQ,YACV,KAAK,SAAS,YAAY,GAAK,EAIjC,KAAK,WAAW,IAAI,GAAU,EAG9B,KAAK,mBAAmB,IAAI,IAAkB,EAC9C,KAAK,iBAAiB,OAAO,EAAU,EAGvC,KAAK,kBAAkB,IAAI,EAAgB;GACzC,aAAa,MAAU;IACrB,IAAM,IAAU,KAAK,SAAS,UAAU,CAAC,WAAW,KAAK,SAAS,UAAU,CAAC;AAE7E,IADA,KAAK,SAAS,SAAS,IAAQ,EAAQ,EACvC,KAAK,yBAAyB;;GAEhC,OAAO,MAAU;IACf,IAAM,IAAa,KAAK,SAAS,UAAU,CAAC,UAAU;AAEtD,IADA,KAAK,SAAS,KAAK,GAAO,IAAa,EAAE,EACzC,KAAK,yBAAyB;;GAEhC,iBAAiB;AAEf,IADA,KAAK,SAAS,SAAS,UAAU,EACjC,KAAK,yBAAyB;;GAEhC,eAAe;AAEb,IADA,KAAK,SAAS,aAAa,EAC3B,KAAK,yBAAyB;;GAEhC,kBAAkB,KAAK,YAAY;GACpC,CAAC,EACF,KAAK,gBAAgB,WAAW,KAAK,SAAS,SAAS,EAMvD,KAAK,mBAAmB,MAAqB;AAC3C,OAAI,CAAC,KAAK,gBAAiB;GAC3B,IAAM,IAAS,SAAS;AACpB,QAAU,MAAW,KAAK,aAAa,CAAC,KAAK,UAAU,SAAS,EAAO,IAIvE,MAAW,EAAO,YAAY,WAAW,EAAO,YAAY,cAAc,EAAO,sBAGjF,KAAK,gBAAgB,UAAU,EAAE,IACnC,EAAE,gBAAgB;KAGtB,OAAO,iBAAiB,WAAW,KAAK,gBAAgB,EAGxD,KAAK,mBAAmB,IAAI,IAAkB,EAG9C,KAAK,eAAe,IAAI,GAAc,EACtC,KAAK,aAAa,uBAAuB,KAAK,OAAO,cAAc,EAAU,QAAQ,CAAC,EACtF,KAAK,aAAa,GAAG,cAAc,MAAU;AAC3C,QAAK,SAAS,KAAK,cAAc;IAAE,OAAO;IAAa,SAAS,EAAM;IAAI,OAAO,EAAM;IAAO,SAAS,EAAM;IAAS,CAAC;IACvH,EAGF,KAAK,sBAAsB,IAAI,GAAqB,EACpD,KAAK,oBAAoB,uBAAuB,KAAK,OAAO,cAAc,EAAU,QAAQ,CAAC,EAC7F,KAAK,oBAAoB,oBAAoB,KAAK,YAAY,SAAS,CAAC,EACxE,KAAK,oBAAoB,GAAG,UAAU,MAAM;AAC1C,QAAK,SAAS,KAAK,mBAAqC;IAAE,IAAI,EAAE;IAAI,QAAQ,EAAE;IAAQ,WAAW,EAAE;IAAW,CAAC;IAC/G,EACF,KAAK,oBAAoB,GAAG,YAAY,MAAO;AAC7C,QAAK,SAAS,KAAK,sBAAwC,EAAE,OAAI,CAAC;IAClE,EAGF,KAAK,mBAAmB,IAAI,GAAkB,EAC9C,KAAK,iBAAiB,uBAAuB,KAAK,OAAO,cAAc,EAAU,QAAQ,CAAC,EAC1F,KAAK,iBAAiB,oBAAoB,KAAK,YAAY,SAAS,CAAC,EACrE,KAAK,iBAAiB,GAAG,UAAU,MAAM;AACvC,QAAK,SAAS,KAAK,gBAAkC;IAAE,IAAI,EAAE;IAAI,WAAW,EAAE;IAAW,CAAC;IAC1F,EACF,KAAK,iBAAiB,GAAG,YAAY,MAAO;AAC1C,QAAK,SAAS,KAAK,mBAAqC,EAAE,OAAI,CAAC;IAC/D,EAGF,KAAK,gBAAgB,IAAI,GAAe,EAGxC,KAAK,qBAAqB,IAAI,GAAmB,EAAU,EACvD,KAAK,SAAS,WAChB,KAAK,mBAAmB,cACtB,IAAI,GAAY,MAAW;AAEzB,GADA,KAAK,SAAS,SAAS,EAAO,EAC9B,KAAK,yBAAyB;IAC9B,CACH,EAEC,KAAK,SAAS,WAChB,KAAK,mBAAmB,eACtB,IAAI,IAAa,GAAO,MAAY;AAElC,GADA,KAAK,SAAS,KAAK,GAAO,EAAQ,EAClC,KAAK,yBAAyB;IAC9B,CACH,EAEC,KAAK,SAAS,aAChB,KAAK,mBAAmB,oBAAoB,KAAK,iBAAiB,EAEhE,KAAK,SAAS,YAChB,KAAK,mBAAmB,kBACtB,KAAK,uBAGE;GAAE,GAAG,KAAK,SAAS,UAAU;GAAE,MAAM,KAAK,gBAAgB;GAAE,EACpE,EAEC,KAAK,SAAS,WAChB,KAAK,mBAAmB,kBACtB,KAAK,uBACE;GAAE,GAAG,KAAK,SAAS,UAAU;GAAE,MAAM,KAAK,gBAAgB;GAAE,EACpE,EAEH,KAAK,mBAAmB,8BAA8B;AAGpD,GAFA,KAAK,OAAO,cAAc,EAAU,QAAQ,EAExC,KAAK,cAAc,WAAW,CAAC,SAAS,KAC1C,KAAK,OAAO,cAAc,EAAU,GAAG;IAEzC,EACF,KAAK,mBAAmB,QAAQ,EAGhC,KAAK,mBAAmB,EACxB,KAAK,OAAO,OAAO;;CAKrB,QAAQ,GAAwB;AAW9B,EAVA,KAAK,YAAY,QAAQ,EAAK,EAC9B,KAAK,iBAAiB,QAAQ,KAAK,YAAY,SAAS,CAAC,EACzD,KAAK,mBAAmB,MACxB,KAAK,cAAc,iBAAiB,EACpC,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAE3D,EAAK,SAAS,KAChB,KAAK,iBAAiB,SAAS,EAAK,EAAK,SAAS,GAAG,MAAM,EAE7D,KAAK,wBAAwB,GAAK,EAClC,KAAK,SAAS,KAAK,cAAc,EAAE,QAAQ,EAAK,QAAQ,CAAC;;CAG3D,UAAU,GAAoB;AAM5B,EALA,KAAK,YAAY,UAAU,EAAI,EAC/B,KAAK,iBAAiB,QAAQ,KAAK,YAAY,SAAS,CAAC,EACzD,KAAK,mBAAmB,MACpB,KAAK,sBAAoB,KAAK,SAAS,aAAa,EACxD,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAC/D,KAAK,yBAAyB;;CAQhC,WAAW,GAAuB;AAC5B,QAAK,WAAW,GACpB;QAAK,IAAM,KAAO,EAChB,MAAK,YAAY,UAAU,EAAI;AAKjC,GAHA,KAAK,mBAAmB,MACxB,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAC/D,KAAK,iBAAiB,QAAQ,KAAK,YAAY,SAAS,CAAC,EACzD,KAAK,wBAAwB,KAAK,SAAS,SAAS,CAAC;;;CAGvD,cAAc,GAAoB;AAchC,EAbA,KAAK,YAAY,cAAc,EAAI,EACnC,KAAK,iBAAiB,SAAS,EAAI,MAAM,EAIrC,KAAK,QAAQ,cAAc,iBAAiB,KAAK,QAAQ,cAAc,UACpE,KAAK,QAAQ,cAAc,UAAU,KAAK,QAAQ,cAAc,SAChE,KAAK,QAAQ,cAAc,mBAChC,KAAK,mBAAmB,OAI1B,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAC/D,KAAK,gBAAgB;;CAIvB,sBAAsB,GAA8D;AASlF,EARA,KAAK,YAAY,sBAAsB,EAAK,EAC5C,KAAK,iBAAiB,SAAS,EAAK,MAAM,EACtC,KAAK,QAAQ,cAAc,iBAAiB,KAAK,QAAQ,cAAc,UACpE,KAAK,QAAQ,cAAc,UAAU,KAAK,QAAQ,cAAc,SAChE,KAAK,QAAQ,cAAc,mBAChC,KAAK,mBAAmB,OAE1B,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAC/D,KAAK,gBAAgB;;CAKvB,aAAa,GAAuB;AAKlC,EAJA,KAAK,QAAQ,YAAY,GACzB,KAAK,gBAAgB,KAAK,oBAAoB,EAAK,EACnD,KAAK,YAAY,aAAa,EAAK,EACnC,KAAK,mBAAmB,MACxB,KAAK,wBAAwB,GAAK;;CAKpC,aAAa,GAAY,IAAoD,EAAE,EAAE,IAA0B,UAAyB;AAElI,MADI,CAAC,KAAK,SAAS,cACf,KAAK,SAAS,aAAa,SAAS,KAAK,CAAC,KAAK,SAAS,aAAa,SAAS,EAAG,CAAE,QAAO;EAC9F,IAAM,IAAa,KAAK,gBAAgB,aAAa,GAAI,GAAQ,KAAK,YAAY,SAAS,CAAC;AAU5F,SATmB,KAAK,gBAAgB,wBAAwB,CAAC,MAAM,MAAM,EAAE,OAAO,EAClF,EAAY,cAAc,WAC5B,KAAK,cAAc,SAAS,GAAY,EAAS,EAEjD,KAAK,yBAAyB,IAE9B,KAAK,OAAO,eAAe,EAE7B,KAAK,SAAS,KAAK,gBAAgB;GAAE;GAAY;GAAI,CAAC,EAC/C;;CAGT,gBAAgB,GAAoB,GAAyD;AAE3F,EADA,KAAK,gBAAgB,gBAAgB,GAAY,GAAQ,KAAK,YAAY,SAAS,CAAC,EACpF,KAAK,OAAO,eAAe;;CAG7B,gBAAgB,GAA0B;EACxC,IAAM,IAAW,KAAK,cAAc,WAAW,CAAC,MAAK,MAAK,EAAE,OAAO,EAAW;AAI9E,EAHA,KAAK,gBAAgB,gBAAgB,EAAW,EAChD,KAAK,cAAc,YAAY,EAAW,EAC1C,KAAK,SAAS,KAAK,mBAAmB,EAAE,eAAY,CAAC,EACjD,IACF,KAAK,yBAAyB,GAE9B,KAAK,OAAO,eAAe;;CAI/B,mBAAmB,GAA4C;AAC7D,SAAO,KAAK,gBAAgB,UAAU,EAAW;;CAGnD,kBAAkB,GAA+B;AAC/C,OAAK,cAAc,kBAAkB,EAAO;;CAG9C,OAAO,aAAoC;EACzC,IAAM,IAAS,IAAI,GAAiB;AAEpC,SADA,EAA0B,EAAO,EAC1B,EAAO,wBAAwB;;CAKxC,iBAAiB,GAAoB,GAA+B;AAElE,EADA,KAAK,cAAc,iBAAiB,GAAY,EAAS,EACzD,KAAK,OAAO,eAAe;;CAG7B,aAAa,GAAoB,GAAoB;AAEnD,EADA,KAAK,cAAc,aAAa,GAAY,EAAK,EACjD,KAAK,OAAO,eAAe;;CAK7B,eAAe,GAAoC;AAC5C,OAAK,SAAS,aAEf,KAAQ,KAAK,SAAS,aAAa,SAAS,KAAK,CAAC,KAAK,SAAS,aAAa,SAAS,EAAK,IAC/F,KAAK,eAAe,cAAc,EAAK;;CAGzC,iBAAyC;AACvC,SAAO,KAAK,eAAe,eAAe;;CAG5C,gBAAgB,GAAoC;AAClD,OAAK,eAAe,SAAS,EAAM;;CAGrC,cAA8B;AAC5B,SAAO,KAAK,eAAe,aAAa;;CAG1C,YAAY,GAAgC;AAC1C,OAAK,eAAe,YAAY,EAAS;;CAG3C,cAAc,GAAkB;AAC9B,OAAK,eAAe,cAAc,EAAG;;CAGvC,gBAAsB;AACpB,OAAK,eAAe,eAAe;;CAGrC,oBAAoB,GAA6B;AAC/C,OAAK,eAAe,SAAS,EAAO;;CAKtC,OAAgB;AAEd,SADK,KAAK,SAAS,kBACZ,KAAK,eAAe,MAAM,GADU;;CAI7C,OAAgB;AAEd,SADK,KAAK,SAAS,kBACZ,KAAK,eAAe,MAAM,GADU;;CAI7C,mBAA2D;AACzD,SAAO,KAAK,gBAAgB,UAAU;;CAKxC,iBAAiB,GAAwB;AACvC,OAAK,eAAe,cAAc,IAAU,WAAW,OAAO;;CAGhE,mBAA4B;AAC1B,SAAO,KAAK,eAAe,eAAe,KAAK;;CAKjD,kBAAwB;AACtB,OAAK,eAAe,iBAAiB;;CAGvC,oBAA0B;AACxB,OAAK,eAAe,mBAAmB;;CAGzC,kBAAwB;AACtB,OAAK,eAAe,iBAAiB;;CAGvC,kBAAwB;AACtB,OAAK,eAAe,iBAAiB;;CAKvC,iBAAiB,GAA4B;EAC3C,IAAM,IAAW,KAAM,KAAK,eAAe,sBAAsB;AAEjE,SADK,IACE,KAAK,eAAe,iBAAiB,EAAS,GAD/B;;CAMxB,kBAAkB,IAAyB,OAAO,GAAyB;EACzE,IAAM,IAAK,KAAK,SAAS,UAAU,EAC7B,IAAO,KAAK,YAAY,SAAS,EACjC,IAAO,KAAK,IAAI,GAAG,EAAG,aAAa,KAAK,EACxC,IAAK,KAAK,IAAI,EAAK,SAAS,GAAG,EAAG,aAAa,GAAG,EAClD,IAAQ,EAAK,MAAM,GAAM,IAAK,EAAE;AAEtC,MAAI,MAAW,QAAQ;GACrB,IAAM,IAAU,EAAa,OAAO,EAAM;AAC1C,KAAa,SAAS,GAAS,KAAY,mBAAmB,mBAAmB;SAC5E;GACL,IAAM,IAAU,EAAa,MAAM,EAAM;AACzC,KAAa,SAAS,GAAS,KAAY,kBAAkB,WAAW;;;CAI5E,cAAc,IAAyB,OAAO,GAAyB;EACrE,IAAM,IAAO,KAAK,YAAY,SAAS;AACvC,MAAI,MAAW,QAAQ;GACrB,IAAM,IAAU,EAAa,OAAO,EAAK;AACzC,KAAa,SAAS,GAAS,KAAY,mBAAmB,mBAAmB;SAC5E;GACL,IAAM,IAAU,EAAa,MAAM,EAAK;AACxC,KAAa,SAAS,GAAS,KAAY,kBAAkB,WAAW;;;CAM5E,YAAY,GAAa,IAAU,KAAY;AAC7C,OAAK,kBAAkB,OAAO,GAAK,EAAQ;;CAG7C,kBAAwB;AACtB,OAAK,kBAAkB,SAAS;;CAGlC,mBAAiC;AAC/B,OAAK,kBAAkB,UAAU;;CAKnC,yBAAgD;AAC9C,SAAO,KAAK,gBAAgB,wBAAwB;;CAGtD,mBAAmB,GAAoE;EAErF,IAAM,IADa,KAAK,gBAAgB,wBAC3B,CAAW,MAAK,MAAK,EAAE,OAAO,EAAG;AAE9C,SADK,IACE;GAAE,IAAI,EAAK;GAAI,QAAQ,EAAK;GAAe,GADhC;;CAKpB,sBAA8H;AAC5H,SAAO,KAAK,gBAAgB,qBAAqB;;CAInD,mBAAmB,GAA4E;EAC7F,IAAM,IAAS,KAAK,gBAAgB,mBAAmB,EAAW;AAElE,SADK,IACE;GAAE,IAAI,EAAO;GAAI,QAAQ,EAAE,GAAG,EAAO,QAAQ;GAAE,GADlC;;CAKtB,qBAAqB,GAAoB,GAA6E;AAEpH,EADA,KAAK,gBAAgB,qBAAqB,GAAY,EAAM,EAC5D,KAAK,OAAO,eAAe;;CAK7B,UAAU,GAA8B;AACjC,OAAK,SAAS,WACnB,KAAK,eAAe,UAAU,EAAO;;CAGvC,aAAa,GAAoC;AAC1C,OAAK,SAAS,WACnB,KAAK,eAAe,aAAa,EAAU;;CAG7C,aAAa,GAA+B;AACrC,OAAK,SAAS,WACnB,KAAK,eAAe,aAAa,EAAM;;CAGzC,gBAAgB,GAAe,GAA4B;AAKzD,EAJA,KAAK,eAAe,gBAAgB,EAAM,EAE1C,KAAK,iBAAiB,SAAS,EAAM,EACrC,KAAK,gBAAgB,EACjB,KAAK,SAAS,UAAQ,KAAK,aAAa,WAAW,EAAM;;CAG/D,iBAAiB,GAAsC;AAChD,OAAK,SAAS,WACnB,KAAK,eAAe,UAAU,EAAO;;CAiBvC,MAAM,QAAQ,GAAqC;AA4CjD,EA3CA,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,IAAI,GAAe,EAExC,KAAK,cAAc,GAAG,aAAa,MAAS;AAC1C,QAAK,QAAQ,EAAK;IAClB,EAEF,KAAK,cAAc,GAAG,aAAa,MAAQ;AAKzC,GAJA,KAAK,YAAY,UAAU,EAAI,EAC/B,KAAK,iBAAiB,QAAQ,KAAK,YAAY,SAAS,CAAC,EACrD,KAAK,sBAAoB,KAAK,SAAS,aAAa,EACxD,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAC/D,KAAK,yBAAyB;IAC9B,EAEF,KAAK,cAAc,GAAG,cAAc,MAAQ;AAM1C,GALA,KAAK,YAAY,cAAc,EAAI,EACnC,KAAK,iBAAiB,SAAS,EAAI,MAAM,EAGzC,KAAK,gBAAgB,eAAe,KAAK,YAAY,SAAS,CAAC,EAC/D,KAAK,gBAAgB;IACrB,EAEF,KAAK,cAAc,GAAG,gBAAgB,EAAE,eAAY;AAIlD,GAHA,KAAK,eAAe,gBAAgB,EAAM,EAC1C,KAAK,iBAAiB,SAAS,EAAM,EACrC,KAAK,OAAO,cAAc,EAAU,QAAQ,EAC5C,KAAK,OAAO,cAAc,EAAU,GAAG;IACvC,EAEF,KAAK,cAAc,GAAG,qBAAqB,MAAS;AAClD,QAAK,SAAS,KAAK,cAAc,EAAE,YAAY,GAAM,CAAC;IACtD,EAEF,KAAK,cAAc,GAAG,UAAU,MAAQ;AACtC,QAAK,SAAS,KAAK,cAAc,EAAE,OAAO,EAAI,SAAS,CAAC;IACxD,EAEF,KAAK,qBAAqB,EAAO,eAAe,IAChD,KAAK,gBAAgB,EAAO,QAE5B,MAAM,KAAK,cAAc,QAAQ,EAAO;EAGxC,IAAM,IAAO,EAAc,EAAO,UAAU;AAK5C,EAJA,KAAK,aAAa,eAAe,EAAK,EAGlC,KAAK,qBAAmB,cAAc,KAAK,kBAAkB,EACjE,KAAK,oBAAoB,kBAAkB;AACzC,GAAI,KAAK,aAAa,WAAW,IAC/B,KAAK,OAAO,cAAc,EAAU,GAAG;KAExC,IAAK;;CAMV,MAAM,aAAa,GAAgB,GAAqC;AACjE,OAAK,kBACV,KAAK,gBAAgB,GACrB,MAAM,KAAK,cAAc,SAAS,GAAQ,EAAU;;CAOtD,MAAM,aAAa,GAAqC;AACtD,MAAI,CAAC,KAAK,cAAe,OAAU,MAAM,0CAA0C;AACnF,QAAM,KAAK,aAAa,KAAK,eAAe,EAAU;;CAMxD,mBAAyB;AACvB,EAEE,KAAK,mBADL,KAAK,cAAc,SAAS,EACP;;CAIzB,uBAAuB,GAAwB;AAE7C,EADA,KAAK,aAAa,WAAW,EAAQ,EACrC,KAAK,OAAO,cAAc,EAAU,GAAG;;CAGzC,wBAAwB,GAAwB;AAE9C,EADA,KAAK,cAAc,WAAW,EAAQ,EACtC,KAAK,OAAO,cAAc,EAAU,WAAW;;CAKjD,iBAAiB,GAAY,GAAe,GAAkB,GAAqB;AAEjF,EADA,KAAK,gBAAgB,UAAU;GAAE;GAAI;GAAO;GAAM;GAAO,SAAS;GAAM,CAAC,EACzE,KAAK,OAAO,cAAc,EAAU,KAAK;;CAG3C,oBAAoB,GAAkB;AAEpC,EADA,KAAK,gBAAgB,aAAa,EAAG,EACrC,KAAK,OAAO,cAAc,EAAU,KAAK;;CAG3C,kBAAkB,GAAY,GAAwB;AAEpD,EADA,KAAK,gBAAgB,cAAc,GAAI,EAAK,EAC5C,KAAK,OAAO,cAAc,EAAU,KAAK;;CAG3C,eAAe,GAAoC;AAEjD,EADA,KAAK,gBAAgB,QAAQ,EAAK,EAClC,KAAK,OAAO,cAAc,EAAU,KAAK;;CAG3C,sBAA4B;AAE1B,EADA,KAAK,gBAAgB,OAAO,EAC5B,KAAK,OAAO,cAAc,EAAU,KAAK;;CAK3C,YAAY,GAAwB;AAElC,EADA,KAAK,SAAS,YAAY,EAAQ,EAClC,KAAK,yBAAyB;;CAGhC,aAAsB;AACpB,SAAO,KAAK,SAAS,YAAY;;CAGnC,uBAAuB,GAAiG;AAEtH,EADA,KAAK,cAAc,UAAU,EAAO,EACpC,KAAK,OAAO,cAAc,EAAU,WAAW;;CAGjD,qBAAsC;AACpC,SAAO,KAAK,eAAe,oBAAoB,IAAI;;CAGrD,oBAAoC;AAClC,SAAO,KAAK,eAAe,mBAAmB,IAAI,EAAE,OAAO,gBAAgB;;CAG7E,cAAc,GAAwB;AACpC,OAAK,qBAAqB;;CAK5B,SAAS,GAAyB;EAChC,IAAM,IAAO,KAAK,YAAY,SAAS;AACvC,OAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,IAC/B,KAAI,EAAK,GAAG,QAAQ,GAAW;GAC7B,IAAM,IAAU,KAAK,SAAS,UAAU,CAAC,WAAW,KAAK,SAAS,UAAU,CAAC;AAE7E,GADA,KAAK,SAAS,SAAS,IAAI,IAAU,KAAK,SAAS,UAAU,CAAC,OAAO,EACrE,KAAK,yBAAyB;AAC9B;;;CAKN,cAAoB;AAElB,EADA,KAAK,SAAS,aAAa,EAC3B,KAAK,yBAAyB;;CAGhC,gBAAgB,GAAuB,GAA2B;EAChE,IAAM,IAAO,KAAK,YAAY,SAAS,EACnC,IAAU,GACV,IAAQ,EAAK,SAAS;AAC1B,OAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,IAC/B,KAAI,EAAK,GAAG,QAAQ,GAAe;AAAE,OAAU;AAAG;;AAEpD,OAAK,IAAI,IAAI,EAAK,SAAS,GAAG,KAAK,GAAG,IACpC,KAAI,EAAK,GAAG,QAAQ,GAAa;AAAE,OAAQ;AAAG;;EAEhD,IAAM,IAAW,IAAQ,IAAU;AACnC,MAAI,IAAW,GAAG;GAChB,IAAM,IAAa,KAAK,SAAS,UAAU,CAAC,UAAU,OAChD,IAAgB,IAAa,GAC7B,IAAc,KAAK,IAAI,GAAG,IAAgB,KAAK,SAAS,UAAU,CAAC,WAAW;AACpF,QAAK,SAAS,MACX,IAAc,KAAK,SAAS,UAAU,CAAC,YAAY,KAAK,SAAS,UAAU,CAAC,UAC7E,IAAa,EACd;;AAEH,OAAK,yBAAyB;;CAGhC,SAAe;EACb,IAAM,IAAa,KAAK,SAAS,UAAU,CAAC,UAAU;AAEtD,EADA,KAAK,SAAS,KAAK,IAAK,IAAa,EAAE,EACvC,KAAK,yBAAyB;;CAGhC,UAAgB;EACd,IAAM,IAAa,KAAK,SAAS,UAAU,CAAC,UAAU;AAEtD,EADA,KAAK,SAAS,KAAK,KAAM,IAAa,EAAE,EACxC,KAAK,yBAAyB;;CAGhC,aAAmB;EACjB,IAAM,IAAO,KAAK,YAAY,SAAS;AACnC,IAAK,WAAW,KACpB,KAAK,gBAAgB,EAAK,GAAG,MAAM,EAAK,EAAK,SAAS,GAAG,KAAK;;CAKhE,GAA6B,GAAS,GAAwG;AAC5I,OAAK,SAAS,GAAG,GAAM,EAAuC;;CAGhE,IAA8B,GAAS,GAAwG;AAC7I,OAAK,SAAS,IAAI,GAAM,EAAuC;;CAGjE,kBAAkB,GAA6C;AAC7D,OAAK,SAAS,kBAAkB;GAAE,SAAS;GAAM,GAAG;GAAS,CAAC;;CAGhE,qBAA2B;AACzB,OAAK,SAAS,oBAAoB;;CAKpC,SAAS,GAAsC;AAK7C,EAJA,KAAK,aAAa,SAAS,EAAY,EACvC,KAAK,mBAAmB,EACxB,KAAK,UAAU,MAAM,kBAAkB,KAAK,aAAa,UAAU,CAAC,YACpE,KAAK,OAAO,eAAe,EAC3B,KAAK,SAAS,KAAK,eAAe,EAAE,OAAO,GAAa,CAAC;;CAG3D,WAAkB;AAChB,SAAO,KAAK,aAAa,UAAU;;CAKrC,aAAa,GAAc,GAAoD;AAE7E,EADA,KAAK,UAAU,UAAU;GAAE;GAAM,GAAG;GAAM,CAAC,EAC3C,KAAK,OAAO,cAAc,EAAU,WAAW;;CAKjD,aAAa,GAAwB;AAEnC,EADA,KAAK,QAAQ,YAAY,GACzB,KAAK,yBAAyB;;CAGhC,cAAuB;AACrB,SAAO,KAAK,QAAQ,cAAc;;CAKpC,iBAAiB,GAA4C;AAE3D,EADA,KAAK,iBAAiB,QAAQ,EAAK,EACnC,KAAK,OAAO,cAAc,EAAU,QAAQ;;CAG9C,mBAA2B;AACzB,SAAO,KAAK,iBAAiB,SAAS;;CAGxC,qBAAqB,GAA8C;AAIjE,EAHI,KACF,KAAK,iBAAiB,cAAc,EAAM,EAE5C,KAAK,OAAO,cAAc,EAAU,QAAQ;;CAG9C,UAAsB;AACpB,SAAO,KAAK,YAAY,SAAS;;CAKnC,eAAe,GAAwB;AAErC,EADA,KAAK,aAAa,WAAW,EAAQ,EACrC,KAAK,OAAO,cAAc,EAAU,WAAW;;CAGjD,gBAAyB;AACvB,SAAO,KAAK,aAAa,WAAW;;CAKtC,iBAAiB,GAAwB;AAEvC,EADA,KAAK,eAAe,WAAW,EAAQ,EACvC,KAAK,OAAO,cAAc,EAAU,KAAK;;CAK3C,kBAAkB,GAAwB;AACxC,EAAK,KAAS,KAAK,iBAAiB,MAAM;;CAK5C,UAAU,GAAiE;AAEzE,EADA,KAAK,YAAY,UAAU,EAAO,EAClC,KAAK,OAAO,cAAc,EAAU,GAAG;;CAGzC,cAAc,GAAsB;AAElC,EADA,KAAK,YAAY,UAAU,EAAO,EAClC,KAAK,OAAO,cAAc,EAAU,GAAG;;CAOzC,cAAc,GAA2B;AAEvC,EADA,KAAK,YAAY,cAAc,EAAK,EACpC,KAAK,OAAO,cAAc,EAAU,GAAG;;CAKzC,WAAW,GAAyB;AAC7B,OAAK,SAAS,cACnB,EAAW,SAAS,KAAK,WAAW,GAAU,KAAK,aAAa,UAAU,CAAC,WAAW;;CAGxF,oBAAmC;AAEjC,SADK,KAAK,SAAS,aACZ,EAAW,UAAU,KAAK,WAAW,KAAK,aAAa,UAAU,CAAC,WAAW,GAD9C;;CAIxC,MAAM,iBAAuC;AAE3C,SADK,KAAK,SAAS,aACZ,EAAW,OAAO,KAAK,WAAW,KAAK,aAAa,UAAU,CAAC,WAAW,GAD3C;;CAMxC,SAAS,GAAe,IAAwD,YAAY,GAAiC;AAC3H,MAAI,CAAC,KAAK,SAAS,OAAQ,QAAO;EAClC,IAAM,IAAK,KAAK,aAAa,SAAS,GAAO,GAAW,EAAQ;AAEhE,SADA,KAAK,kBAAkB,EAChB;;CAGT,YAAY,GAAkB;AAE5B,EADA,KAAK,aAAa,YAAY,EAAG,EACjC,KAAK,kBAAkB;;CAGzB,YAAsD;AACpD,SAAO,KAAK,aAAa,WAAW;;CAGtC,cAAoB;AAElB,EADA,KAAK,aAAa,aAAa,EAC/B,KAAK,kBAAkB;;CAGzB,WAAW,GAAmB;AAC5B,OAAK,aAAa,cAAc,EAAI;;CAGtC,WAAW,GAAmB;AAE5B,EADA,KAAK,aAAa,gBAAgB,EAAI,EACtC,KAAK,OAAO,cAAc,EAAU,QAAQ;;CAK9C,gBAAgB,GAA2F;AACzG,SAAO,KAAK,oBAAoB,UAAU,EAAO;;CAGnD,mBAAmB,GAAkB;AACnC,OAAK,oBAAoB,aAAa,EAAG;;CAG3C,mBAAkE;AAChE,SAAO,KAAK,oBAAoB,YAAY;;CAG9C,iBAAiB,GAA8D;AAC7E,OAAK,oBAAoB,WAAW,EAAQ;;CAG9C,qBAA2B;AACzB,OAAK,oBAAoB,cAAc;;CAGzC,qBAAqB,GAAwE;AAC3F,OAAK,oBAAoB,SAAS,EAAM;;CAK1C,aAAa,GAAsF;AACjG,SAAO,KAAK,iBAAiB,QAAQ,EAAK;;CAG5C,gBAAgB,GAAY,GAA8E;AACxG,OAAK,iBAAiB,WAAW,GAAI,EAAQ;;CAG/C,gBAAgB,GAAkB;AAChC,OAAK,iBAAiB,WAAW,EAAG;;CAGtC,gBAA4D;AAC1D,SAAO,KAAK,iBAAiB,UAAU;;CAGzC,cAAc,GAAyD;AACrE,OAAK,iBAAiB,SAAS,EAAM;;CAGvC,kBAAwB;AACtB,OAAK,iBAAiB,YAAY;;CAGpC,kBAAkB,GAAqE;AACrF,OAAK,iBAAiB,SAAS,EAAM;;CAKvC,OAAO,GAAkE;AACvE,MAAI,CAAC,KAAK,SAAS,OAAQ;EAC3B,IAAM,IAAO,KAAK,YAAY,SAAS;AASvC,EARA,KAAK,cAAc,KAAK,EAAK,EAC7B,KAAK,cAAc,GAAG,QAAQ,EAAE,KAAK,GAAM,eAAY;GACrD,IAAM,IAAQ,EAAK,MAAM,GAAG,IAAQ,EAAE;AAItC,GAHA,KAAK,YAAY,QAAQ,EAAM,EAC/B,KAAK,iBAAiB,QAAQ,EAAM,EACpC,KAAK,gBAAgB,eAAe,EAAM,EAC1C,KAAK,yBAAyB;IAC9B,EACF,KAAK,cAAc,KAAK,EAAO;;CAGjC,cAAoB;AAAE,OAAK,cAAc,OAAO;;CAChD,eAAqB;AAAE,OAAK,cAAc,QAAQ;;CAClD,aAAmB;AAAE,OAAK,cAAc,MAAM;;CAC9C,WAAW,GAAqB;AAAE,OAAK,cAAc,OAAO,EAAM;;CAClE,eAAe,GAAqB;AAAE,OAAK,cAAc,SAAS,EAAM;;CACxE,iBAAmD;AAAE,SAAO,KAAK,cAAc,UAAU;;CACzF,oBAAyE;AAAE,SAAO,KAAK,cAAc,aAAa;;CAIlH,UAAU,GAA6B;AACrC,MAAI,CAAC,KAAK,SAAS,SAAU,QAAO;EACpC,IAAM,IAAW,EAAkB,QACjC;GACE,mBAAmB,KAAK,aAAa;GACrC,gBAAgB,KAAK,UAAU;GAC/B,iBAAiB,KAAK,WAAW;GAClC,EACD,EAAE,WAAW,KAAK,QAAQ,WAAW,CACtC,EACK,IAAO,EAAkB,UAAU,EAAS;AAElD,SADI,KAAK,EAAkB,cAAc,GAAK,EAAS,EAChD;;CAGT,UAAU,GAAoB;AAC5B,MAAI,CAAC,KAAK,SAAS,SAAU;EAC7B,IAAM,IAAW,EAAkB,YAAY,EAAK;AAIpD,MAHI,EAAS,aAAW,KAAK,aAAa,EAAS,UAAU,EACzD,EAAS,YAAU,KAAK,YAAY,EAAS,SAAS,EACtD,EAAS,SAAO,KAAK,SAAS,EAAS,MAAa,EACpD,EAAS,QAAQ;AACnB,QAAK,aAAa;AAClB,QAAK,IAAM,KAAK,EAAS,OACvB,MAAK,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ;;;CAKpD,qBAAqB,GAAsB;AACzC,MAAI,CAAC,KAAK,SAAS,SAAU,QAAO;EACpC,IAAM,IAAW,EAAkB,gBAAgB,EAAI;AAGvD,SAFK,KACL,KAAK,UAAU,EAAkB,UAAU,EAAS,CAAC,EAC9C,MAFe;;CAKxB,cAAc,GAAyB;AACrC,MAAI,CAAC,KAAK,SAAS,SAAU;EAC7B,IAAM,IAAW,EAAkB,QACjC;GAAE,mBAAmB,KAAK,aAAa;GAAE,gBAAgB,KAAK,UAAU;GAAE,iBAAiB,KAAK,WAAW;GAAE,EAC7G,EAAE,WAAW,KAAK,QAAQ,WAAW,CACtC;AACD,IAAkB,aAAa,GAAU,EAAS;;CAGpD,MAAM,oBAAmC;AACvC,MAAI,CAAC,KAAK,SAAS,SAAU;EAC7B,IAAM,IAAW,MAAM,EAAkB,cAAc;AACvD,OAAK,UAAU,EAAkB,UAAU,EAAS,CAAC;;CAKvD,UAAU,GAAsB;AAE9B,EADA,EAAgB,EAAO,EACvB,KAAK,OAAO,eAAe;;CAQ7B,gBAAgB,GAAsB;AAKpC,EAJA,KAAK,eAAe,GACpB,KAAK,UAAU,UAAU,EAAO,EAChC,KAAK,iBAAiB,UAAU,EAAO,EACvC,KAAK,mBAAmB,EACxB,KAAK,OAAO,eAAe;;CAG7B,kBAA0B;AACxB,SAAO,KAAK;;CAKd,UAAU,GAA4B;AAIpC,MAHA,KAAK,eAAe,GAGhB,EAAO,aAAa;GAEtB,IAAM,IAAqB;IACzB,GAFW,KAAK,aAAa,UAE1B;IACH,UAAU,EAAO,YAAY;IAC7B,YAAY,EAAO,YAAY;IAC/B,cAAc,EAAO,YAAY;IACjC,gBAAgB,EAAO,YAAY;IACnC,UAAU,EAAO,YAAY,GAAG,QAAQ,KAAK,SAAS,CAAC,QAAQ,QAAQ,QAAQ,IAAI,GAAG,EAAO,YAAY,GAAG;IAC5G,YAAY,EAAO,YAAY,KAAK,QAAQ,KAAK,SAAS,CAAC,QAAQ,QAAQ,QAAQ,IAAI,GAAG,EAAO,YAAY,KAAK;IACnH;AACD,QAAK,aAAa,SAAS,EAAY;;AAYzC,EARI,EAAO,mBAAmB,KAAA,MAC5B,KAAK,eAAe,UAAU,EAAE,gBAAgB,EAAO,gBAAgB,CAAC,EACxE,KAAK,aAAa,kBAAkB,EAAO,eAAe,EAC1D,KAAK,eAAe,UAAU,kBAAkB,EAAO,eAAe,EACtE,KAAK,iBAAiB,kBAAkB,EAAO,eAAe,GAGhE,KAAK,mBAAmB,EACxB,KAAK,OAAO,eAAe;;CAG7B,YAAiC;AAC/B,SAAO,KAAK;;CAGd,eAAe,GAA8B;AACtC,OAAK,iBACK,EAAmB,GAAgB,KAAK,aACnD,KACF,KAAK,aAAa,cAAc;GAC9B,GAAG,KAAK,aAAa;GACrB;GACD,GAEH,KAAK,OAAO,eAAe;;CAM7B,cAAkD;AAChD,SAAO,KAAK;;CAId,YAAY,GAAsC;AAyBhD,EAxBA,OAAO,OAAO,KAAK,UAAU,EAAM,EAG/B,EAAM,cAAc,MACtB,KAAK,iBAAiB,MAAM,EAE1B,EAAM,SAAS,KAAA,KACjB,KAAK,OAAO,cAAc,EAAU,WAAW,EAE7C,EAAM,WAAW,KAAA,MACnB,KAAK,eAAe,WAAW,EAAM,OAAO,EAC5C,KAAK,OAAO,cAAc,EAAU,KAAK,GAEvC,EAAM,aAAa,MACrB,KAAK,eAAe,cAAc,KAAK,EAErC,EAAM,YAAY,OACpB,KAAK,eAAe,UAAU,EAAE,CAAC,EACjC,KAAK,eAAe,aAAa,EAAE,CAAC,GAElC,EAAM,aAAa,KAAA,KACrB,KAAK,iBAAiB,WAAW,EAAM,SAAS,EAGlD,KAAK,OAAO,eAAe;;CAK7B,SAAe;EACb,IAAM,IAAO,KAAK,OAAO,WAAW,mBAAmB;AACvD,MAAI,EAAK,SAAS,KAAK,EAAK,UAAU,EAAG;AAEzC,EADA,KAAK,qBAAqB,GAC1B,KAAK,yBAAyB,KAAK,KAAK;EAExC,IAAM,IAAM,KAAK,OAAO,WAAW,QAAQ;AAC3C,OAAK,OAAO,aAAa,OAAO,GAAM,EAAI;EAE1C,IAAM,IAAW,KAAK,SAAS,SAAS;AAIxC,EAHA,KAAK,SAAS,OAAO,EAAK,OAAO,EAAK,OAAO,EAC7C,KAAK,cAAc,OAAO,EAAK,OAAO,EAAK,OAAO,EAClD,KAAK,wBAAwB,EAAS,EACtC,KAAK,SAAS,KAAK,UAAU,EAAK;;CAGpC,UAAgB;AAiBd,EAhBI,KAAK,qBAAmB,cAAc,KAAK,kBAAkB,EACjE,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,AAEE,KAAK,qBADL,OAAO,oBAAoB,WAAW,KAAK,gBAAgB,EACpC,OAEzB,KAAK,kBAAkB,MACvB,KAAK,mBAAmB,QAAQ,EAChC,KAAK,eAAe,SAAS,EAC7B,KAAK,SAAS,SAAS,EACvB,KAAK,iBAAiB,SAAS,EAC/B,KAAK,cAAc,SAAS,EAC5B,KAAK,gBAAgB,OAAO,EAC5B,KAAK,OAAO,SAAS,EACrB,KAAK,SAAS,SAAS,EACvB,KAAK,UAAU,YAAY;;CAK7B,oBAA4B,GAAyC;AACnE,SAAO,GAAkB,EAAK;;CAIhC,iBAAqC;AACnC,MAAI,KAAK,iBAAkB,QAAO,KAAK;EACvC,IAAM,IAAM,KAAK,YAAY,SAAS;AACtC,MAAI,EAAI,WAAW,EAAG,QAAO;EAC7B,IAAM,IAAS,GAAqB,KAAK,QAAQ,WAAW,EAAI;AAEhE,SADA,KAAK,mBAAmB,GACjB;;CAIT,iBAA+B;AACzB,OAAK,oBACT,KAAK,kBAAkB,IACvB,4BAA4B;AAC1B,QAAK,kBAAkB;GACvB,IAAM,IAAc,KAAK,gBAAgB;AAGzC,GAFA,KAAK,SAAS,WAAW,GAAa,KAAK,QAAQ,cAAc,GAAM,EACvE,KAAK,mBAAmB,EACxB,KAAK,OAAO,eAAe;IAC3B;;CAIJ,wBAAgC,IAAc,IAAa;AAGzD,EADA,KAAK,sBAAsB,MAC3B,KAAK,iBAAiB;EAEtB,IAAM,IAAW,KAAK,mBAAmB;AACzC,OAAK,SAAS,aAAa,EAAS,cAAc;EAElD,IAAM,IAAc,KAAK,gBAAgB;AAIzC,MAHA,KAAK,SAAS,WAAW,GAAa,KAAK,QAAQ,cAAc,GAAM,EAGnE,KAAK,QAAQ,cAAc,IAAO;GACpC,IAAM,IAAK,KAAK,SAAS,UAAU,EAC7B,IAAe,KAAK,gBAAgB,qBACxC,EAAG,aAAa,MAChB,KAAK,IAAI,EAAG,aAAa,IAAI,EAAY,SAAS,EAAE,CACrD;AACD,OAAI,GAAc;IAChB,IAAM,IAAU,EAAG,YACb,IAAc,KAAK,IAAI,EAAQ,KAAK,EAAa,IAAI,EACrD,IAAc,KAAK,IAAI,EAAQ,KAAK,EAAa,IAAI;AAC3D,QAAI,IAAc,EAAQ,OAAO,IAAc,EAAQ,KAAK;KAC1D,IAAM,IAAQ,IAAc,KAAe;AAC3C,UAAK,SAAS,cACZ,IAAc,IAAQ,KACtB,IAAc,IAAQ,IACvB;;;;AASP,EAHI,KAAa,KAAK,SAAS,aAAa,EAE5C,KAAK,mBAAmB,EACxB,KAAK,OAAO,eAAe;;CAG7B,oBAA4B;AAI1B,SAHA,AACE,KAAK,wBAAsB,KAAK,cAAc,SAAS,EAElD,KAAK;;CAId,sBAAiE;EAC/D,IAAM,IAAM,KAAK,KAAK;AAKtB,UAJI,CAAC,KAAK,sBAAsB,IAAM,KAAK,yBAAyB,SAClE,KAAK,qBAAqB,KAAK,OAAO,WAAW,kBAAkB,EACnE,KAAK,yBAAyB,IAEzB,KAAK;;CAGd,wBAA+E;AAC7E,MAAI,KAAK,eAAgB,QAAO,KAAK;EAErC,IAAM,IAAW,KAAK,mBAAmB,EACnC,IAAS,KAAK,SAAS,UAAU,EAEjC,EAAE,SAAM,UAAO,EAAO,cACtB,IAAS,EAAS,OAAO,KAAK,MAAU;GAE5C,IAAM,IAAa,GADJ,KAAK,gBAAgB,UAAU,EAAM,OAAO,GACb,EAAQ,GAAM,EAAG,EAIzD,IAAY;IAChB,GAAG,EAAM,KAAK;IACd,GAAG,EAAM,KAAK,IAAI;IAClB,OAAO,EAAM,KAAK;IAClB,QAAQ,KAAK,IAAI,GAAG,EAAM,KAAK,SAAS,GAAoB;IAC7D;AAED,UAAO;IACL,YAAY,EAAM,OAAO;IACzB,MAAM,EAAM;IACZ,UAAU;KACR,GAAG;KACH,WAAW;KACX;KACD;IACF;IACD;AAGF,SADA,KAAK,iBAAiB,GACf;;CAGT,oBAAkC;EAChC,IAAM,IAAW,KAAK,mBAAmB,EACnC,IAAS,KAAK,SAAS,aAAa,KAAK,uBAAuB,GAAG,EAAE,EAGrE,IAAoB,EAAS,OAChC,QAAO,MAAK,EAAE,OAAO,aAAa,SAAS,CAC3C,QAAQ,GAAK,MAAM,IAAM,EAAE,KAAK,QAAQ,EAAE,EACvC,IAAY,EAAS,cAAc,IAAI,EAAS,cAAc,SAAS,GAEvE,IAAc,KAAK,gBAAgB;AACzC,OAAK,OAAO,iBAAiB;GAC3B,eAAe,KAAK;GACpB,cAAc,KAAK,SAAS,OAAO,KAAK,eAAe;GACvD,WAAW,KAAK,SAAS,YAAY,KAAK,YAAY;GACtD,UAAU,KAAK,SAAS,WAAW,KAAK,WAAW;GACnD,kBAAkB,KAAK,SAAS,YAAY,KAAK,mBAAmB;GACpE,iBAAiB,KAAK,SAAS,aAAa,KAAK,kBAAkB;GACnE,iBAAiB,KAAK,SAAS,WAAW,KAAK,kBAAkB;GACjE,iBAAiB,KAAK,SAAS,UAAU,KAAK,kBAAkB;GAChE,kBAAkB,KAAK,eAAe,aAAa,KAAK;GACxD,aAAa,KAAK,SAAS,SAAS,KAAK,cAAc;GACvD,gBAAgB,KAAK,SAAS,SAAS,KAAK,iBAAiB;GAC7D,WAAW,KAAK,SAAS,YAAY,KAAK,YAAY;GACtD,cAAc,KAAK;GACnB,eAAe,KAAK;GACpB,iBAAiB,KAAK;GACtB,cAAc,KAAK,SAAS,SAAS,KAAK,eAAe;GACzD,qBAAqB,KAAK;GAC1B,kBAAkB,KAAK;GACvB;GACA,aAAa,KAAK,kBAAkB;GACpC;GAGA,UAAU;IAAE,GAAG,KAAK,SAAS,UAAU;IAAE,MAAM;IAAa;GAC5D,OAAO,KAAK,aAAa,UAAU;GACnC,MAAM;GACN,cAAc,KAAK;GACpB,CAAC;;CAGJ,mBAA2B;AACzB,MAAI,CAAC,KAAK,cAAc,aAAa,WAAW,CAAC,KAAK,aAAa,YAAY,eAAgB,QAAO;EACtG,IAAM,IAAS,EAAmB,KAAK,aAAa,YAAY,gBAAgB,KAAK,aAAa;AAElG,SADK,IACE;GACL,GAAG;GACH,QAAQ,KAAK,aAAa,cAAc;IACtC,SAAS,KAAK,aAAa,YAAY;IACvC,OAAO,KAAK,aAAa,YAAY;IACrC,WAAW,KAAK,aAAa,YAAY;IAC1C,GAAG,KAAA;GACL,GARmB"}
|