feat(chart-area): replace ApexCharts with Lightweight Charts for area chart rendering

This commit is contained in:
2026-04-03 10:11:38 +00:00
parent 99a531ee74
commit b38bd28360
10 changed files with 502 additions and 579 deletions

View File

@@ -4,7 +4,15 @@ import { CDN_BASE, CDN_VERSIONS } from './versions.js';
import type { Terminal, ITerminalOptions } from 'xterm';
import type { FitAddon } from 'xterm-addon-fit';
import type { HLJSApi } from 'highlight.js';
import type ApexChartsType from 'apexcharts';
import type {
createChart as createChartType,
IChartApi,
ISeriesApi,
UTCTimestamp,
MouseEventParams,
DeepPartial,
TimeChartOptions,
} from 'lightweight-charts';
import type { Editor, EditorOptions } from '@tiptap/core';
import type { StarterKitOptions } from '@tiptap/starter-kit';
import type { UnderlineOptions } from '@tiptap/extension-underline';
@@ -43,6 +51,29 @@ export interface IXtermSearchAddon {
findPrevious(term: string, searchOptions?: { regex?: boolean; wholeWord?: boolean; caseSensitive?: boolean; incremental?: boolean }): boolean;
}
/**
* Bundle type for TradingView Lightweight Charts
*/
export interface ILightweightChartsBundle {
createChart: typeof createChartType;
AreaSeries: any;
LineSeries: any;
ColorType: {
Solid: string;
VerticalGradient: string;
};
LineType: {
Simple: number;
WithSteps: number;
Curved: number;
};
CrosshairMode: {
Normal: number;
Magnet: number;
Hidden: number;
};
}
/**
* Bundle type for Tiptap editor and extensions
*/
@@ -76,7 +107,7 @@ export class DeesServiceLibLoader {
private xtermFitAddonLib: IXtermFitAddonBundle | null = null;
private xtermSearchAddonLib: IXtermSearchAddonBundle | null = null;
private highlightJsLib: HLJSApi | null = null;
private apexChartsLib: typeof ApexChartsType | null = null;
private lightweightChartsLib: ILightweightChartsBundle | null = null;
private tiptapLib: ITiptapBundle | null = null;
// Loading promises to prevent duplicate concurrent loads
@@ -84,7 +115,7 @@ export class DeesServiceLibLoader {
private xtermFitAddonLoadingPromise: Promise<IXtermFitAddonBundle> | null = null;
private xtermSearchAddonLoadingPromise: Promise<IXtermSearchAddonBundle> | null = null;
private highlightJsLoadingPromise: Promise<HLJSApi> | null = null;
private apexChartsLoadingPromise: Promise<typeof ApexChartsType> | null = null;
private lightweightChartsLoadingPromise: Promise<ILightweightChartsBundle> | null = null;
private tiptapLoadingPromise: Promise<ITiptapBundle> | null = null;
private constructor() {}
@@ -235,27 +266,34 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
}
/**
* Load ApexCharts charting library from CDN
* @returns Promise resolving to ApexCharts constructor
* Load TradingView Lightweight Charts from CDN
* @returns Promise resolving to Lightweight Charts bundle
*/
public async loadApexCharts(): Promise<typeof ApexChartsType> {
if (this.apexChartsLib) {
return this.apexChartsLib;
public async loadLightweightCharts(): Promise<ILightweightChartsBundle> {
if (this.lightweightChartsLib) {
return this.lightweightChartsLib;
}
if (this.apexChartsLoadingPromise) {
return this.apexChartsLoadingPromise;
if (this.lightweightChartsLoadingPromise) {
return this.lightweightChartsLoadingPromise;
}
this.apexChartsLoadingPromise = (async () => {
const url = `${CDN_BASE}/apexcharts@${CDN_VERSIONS.apexcharts}/+esm`;
this.lightweightChartsLoadingPromise = (async () => {
const url = `${CDN_BASE}/lightweight-charts@${CDN_VERSIONS.lightweightCharts}/+esm`;
const module = await import(/* @vite-ignore */ url);
this.apexChartsLib = module.default;
return this.apexChartsLib!;
this.lightweightChartsLib = {
createChart: module.createChart,
AreaSeries: module.AreaSeries,
LineSeries: module.LineSeries,
ColorType: module.ColorType,
LineType: module.LineType,
CrosshairMode: module.CrosshairMode,
};
return this.lightweightChartsLib;
})();
return this.apexChartsLoadingPromise;
return this.lightweightChartsLoadingPromise;
}
/**
@@ -316,7 +354,7 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
this.loadXtermFitAddon(),
this.loadXtermSearchAddon(),
this.loadHighlightJs(),
this.loadApexCharts(),
this.loadLightweightCharts(),
this.loadTiptap(),
]);
}
@@ -324,7 +362,7 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
/**
* Check if a specific library is already loaded
*/
public isLoaded(library: 'xterm' | 'xtermFitAddon' | 'xtermSearchAddon' | 'highlightJs' | 'apexCharts' | 'tiptap'): boolean {
public isLoaded(library: 'xterm' | 'xtermFitAddon' | 'xtermSearchAddon' | 'highlightJs' | 'lightweightCharts' | 'tiptap'): boolean {
switch (library) {
case 'xterm':
return this.xtermLib !== null;
@@ -334,8 +372,8 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
return this.xtermSearchAddonLib !== null;
case 'highlightJs':
return this.highlightJsLib !== null;
case 'apexCharts':
return this.apexChartsLib !== null;
case 'lightweightCharts':
return this.lightweightChartsLib !== null;
case 'tiptap':
return this.tiptapLib !== null;
default: