From 9e2a3fd4b23008271e9d3edcb9e1ba349e52f2c0 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 10 Dec 2024 19:25:37 +0700 Subject: [PATCH] Pure ESM --- README.md | 14 +++++------ highcharts-angular/package.json | 2 +- .../src/lib/highcharts-chart.directive.ts | 13 ++++++----- .../src/lib/highcharts-chart.service.ts | 12 ++++------ highcharts-angular/src/lib/types.ts | 4 ++-- package.json | 2 +- src/app/app.config.ts | 9 ++++---- src/app/gantt-chart/gantt-chart.component.ts | 5 ++-- .../lazy-loading-chart.component.ts | 12 +++++----- src/app/line-chart/line-chart.component.ts | 5 ++-- src/app/map-chart/map-chart.component.ts | 14 ++++------- src/app/stock-chart/stock-chart.component.ts | 23 +++++++++++-------- .../line-test/line-test.component.spec.ts | 9 ++++---- .../tests/line-test/line-test.component.ts | 6 ++--- 14 files changed, 65 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 1561fa2..8aceb10 100644 --- a/README.md +++ b/README.md @@ -77,9 +77,9 @@ export const appConfig: ApplicationConfig = { // Modules for additional functionality modules: () => { return [ - import('highcharts/modules/accessibility'), - import('highcharts/modules/exporting'), - import('highcharts/themes/sunset') + import('highcharts/es-modules/masters/modules/accessibility.src'), + import('highcharts/es-modules/masters/modules/exporting.src'), + import('highcharts/es-modules/masters/themes/sunset.src') ] } }) @@ -326,9 +326,9 @@ import { HighchartsChartDirective } from 'highcharts-angular'; modules: () => { return [ // Load Gantt Chart - import('highcharts/modules/gantt'), + import('highcharts/es-modules/masters/modules/gantt.src'), // Load core module - import('highcharts/modules/exporting'), + import('highcharts/es-modules/masters/modules/exporting.src'), // Load plugins import('highcharts-custom-events'), ] @@ -360,7 +360,7 @@ import { HighchartsChartDirective } from 'highcharts-angular'; `, styles: [`.chart { width: 100%; height: 400px; display: block; }`], imports: [HighchartsChartDirective], - providers: [providePartialHighChart({ modules: () => [import('highcharts/modules/map')] })], + providers: [providePartialHighChart({ modules: () => [import('highcharts/es-modules/masters/modules/map.src')] })], }) export class MapComponent { chartOptions: Highcharts.Options = { @@ -384,7 +384,7 @@ import { HighchartsChartDirective } from 'highcharts-angular'; `, styles: [`.chart { width: 100%; height: 400px; display: block; }`], imports: [HighchartsChartDirective], - providers: [providePartialHighChart({ modules: () => [import('highcharts/modules/stock')] })], + providers: [providePartialHighChart({ modules: () => [import('highcharts/es-modules/masters/modules/stock.src')] })], }) export class StockComponent { chartOptions: Highcharts.Options = { diff --git a/highcharts-angular/package.json b/highcharts-angular/package.json index aba4941..e7d6064 100644 --- a/highcharts-angular/package.json +++ b/highcharts-angular/package.json @@ -21,7 +21,7 @@ "peerDependencies": { "@angular/common": ">=19.0.0", "@angular/core": ">=19.0.0", - "highcharts": ">=9.0.0" + "highcharts": ">=12.0.0" }, "dependencies": { "tslib": "^2.0.0" diff --git a/highcharts-angular/src/lib/highcharts-chart.directive.ts b/highcharts-angular/src/lib/highcharts-chart.directive.ts index ac50851..c980fc6 100644 --- a/highcharts-angular/src/lib/highcharts-chart.directive.ts +++ b/highcharts-angular/src/lib/highcharts-chart.directive.ts @@ -18,6 +18,7 @@ import { toSignal } from '@angular/core/rxjs-interop'; import { HighchartsChartService } from './highcharts-chart.service'; import { HIGHCHARTS_CONFIG } from './highcharts-chart.token'; import type { Chart, ChartConstructorType } from './types'; +import HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; @Directive({ @@ -32,7 +33,7 @@ export class HighchartsChartDirective { /** * Callback function for the chart. */ - callbackFunction = input(null); + callbackFunction = input(null); /** * When enabled, Updates `series`, `xAxis`, `yAxis`, and `annotations` to match new options. @@ -53,7 +54,7 @@ export class HighchartsChartDirective { */ update = model(); - chartInstance: OutputEmitterRef = output(); // #26 + chartInstance: OutputEmitterRef = output(); // #26 private destroyRef = inject(DestroyRef); @@ -76,7 +77,7 @@ export class HighchartsChartDirective { return undefined; }); - private chart = linkedSignal({ + private chart = linkedSignal({ source: () => ({options: this.options(), update: this.update(), constructorChart: this.constructorChart()}), computation: (source, previous) => { return untracked(() => this.createOrUpdateChart(source, previous?.value, this.oneToOne(), this.callbackFunction())); @@ -85,10 +86,10 @@ export class HighchartsChartDirective { private createOrUpdateChart( source: Chart, - chart: Highcharts.Chart, + chart: HighchartsESM.Chart, oneToOne: boolean, - callbackFunction: Highcharts.ChartCallbackFunction - ): Highcharts.Chart | null { + callbackFunction: HighchartsESM.ChartCallbackFunction + ): HighchartsESM.Chart | null { if (chart) { chart.update(source.options, true, oneToOne); return chart; diff --git a/highcharts-angular/src/lib/highcharts-chart.service.ts b/highcharts-angular/src/lib/highcharts-chart.service.ts index 98d109d..3e0b062 100644 --- a/highcharts-angular/src/lib/highcharts-chart.service.ts +++ b/highcharts-angular/src/lib/highcharts-chart.service.ts @@ -1,7 +1,7 @@ import { inject, Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { HIGHCHARTS_ROOT_MODULES, HIGHCHARTS_LOADER, HIGHCHARTS_OPTIONS } from './highcharts-chart.token'; -import { Chart, ModuleFactoryFunction, PartialHighchartsConfig, ModuleFactory, InstanceFactoryFunction } from './types'; +import { Chart, ModuleFactoryFunction, PartialHighchartsConfig, InstanceFactoryFunction } from './types'; @Injectable({providedIn: 'root'}) export class HighchartsChartService { @@ -14,13 +14,9 @@ export class HighchartsChartService { private async loadHighchartsWithModules(partialConfig?: PartialHighchartsConfig): Promise { const Highcharts: Chart['highcharts'] = await this.source(); // Ensure Highcharts core is loaded - const version: number = Number(Highcharts['version'].split('.').map((v: string) => v.padStart(2, '0')).join('')); - const results: ModuleFactory[] = await Promise.all( - partialConfig?.modules ? [...this.globalModules(), ...partialConfig.modules()] : this.globalModules() - ); - if (version < 120000) { - results.forEach(module => module.default(Highcharts)); - } + + await Promise.all([...this.globalModules(), ...(partialConfig?.modules?.() ?? [])]); + // Return the Highcharts instance return Highcharts; } diff --git a/highcharts-angular/src/lib/types.ts b/highcharts-angular/src/lib/types.ts index a3d9ff1..fa46a5f 100644 --- a/highcharts-angular/src/lib/types.ts +++ b/highcharts-angular/src/lib/types.ts @@ -7,11 +7,11 @@ export type InstanceFactoryFunction = () => Promise; export interface ModuleFactory { Highcharts?: Chart['highcharts'], - default?: (highcharts: Chart['highcharts']) => void + default?: unknown, } export interface Chart { - options: Highcharts.Options | HighchartsESM.Options, + options: HighchartsESM.Options, update?: boolean, highcharts?: typeof HighchartsESM constructorChart?: Function; diff --git a/package.json b/package.json index 14f0959..84b5987 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@highcharts/map-collection": "^2.3.0", "core-js": "^3.19.2", "express": "^4.18.2", - "highcharts": "^12.0.2", + "highcharts": "^11.4.8", "highcharts-custom-events": "^3.0.10", "jquery": "^3.6.0", "proj4": "^2.15.0", diff --git a/src/app/app.config.ts b/src/app/app.config.ts index bda5bea..e1d2610 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -10,7 +10,7 @@ export const appConfig: ApplicationConfig = { importProvidersFrom(BrowserModule), provideHttpClient(withInterceptorsFromDi(), withFetch()), provideHighCharts({ - instance: () => import('highcharts').then(m => m.default), + instance: () => import('highcharts/es-modules/masters/highcharts.src').then(m => m.default), options: { title: { style: { @@ -24,9 +24,10 @@ export const appConfig: ApplicationConfig = { // The modules will work for all charts. modules: () => { return [ - import('highcharts/modules/accessibility'), - import('highcharts/modules/exporting'), - import('highcharts/themes/sunset') + import('highcharts/es-modules/masters/highcharts-more.src'), + import('highcharts/es-modules/masters/modules/accessibility.src'), + import('highcharts/es-modules/masters/modules/exporting.src'), + import('highcharts/es-modules/masters/themes/sunset.src') ] } }) diff --git a/src/app/gantt-chart/gantt-chart.component.ts b/src/app/gantt-chart/gantt-chart.component.ts index 8b12d6a..7cc79e7 100644 --- a/src/app/gantt-chart/gantt-chart.component.ts +++ b/src/app/gantt-chart/gantt-chart.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { HighchartsChartComponent, providePartialHighChart } from 'highcharts-angular'; +import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; @Component({ @@ -7,11 +8,11 @@ import { HighchartsChartComponent, providePartialHighChart } from 'highcharts-an templateUrl: './gantt-chart.component.html', styleUrls: ['./gantt-chart.component.css'], imports: [HighchartsChartComponent], - providers: [providePartialHighChart({ modules: () => [import('highcharts/modules/gantt')] })], + providers: [providePartialHighChart({ modules: () => [import('highcharts/es-modules/masters/modules/gantt.src')] })], changeDetection: ChangeDetectionStrategy.OnPush, }) export class GanttChartComponent { - chartGantt: Highcharts.Options = { + chartGantt: HighchartsESM.Options = { title: { text: 'Highcharts Gantt with Progress Indicators' }, diff --git a/src/app/lazy-loading-chart/lazy-loading-chart.component.ts b/src/app/lazy-loading-chart/lazy-loading-chart.component.ts index b19451b..6b4bb1c 100644 --- a/src/app/lazy-loading-chart/lazy-loading-chart.component.ts +++ b/src/app/lazy-loading-chart/lazy-loading-chart.component.ts @@ -1,11 +1,11 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import type Highcharts from 'highcharts'; +import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; import { AppleDataService } from '../apple-data.service' import { Observable } from 'rxjs'; import { HighchartsChartComponent, providePartialHighChart } from 'highcharts-angular'; -interface ExtendedPlotCandlestickDataGroupingOptions extends Highcharts.DataGroupingOptionsObject { +interface ExtendedPlotCandlestickDataGroupingOptions extends HighchartsESM.DataGroupingOptionsObject { enabled: boolean } @@ -14,16 +14,16 @@ interface ExtendedPlotCandlestickDataGroupingOptions extends Highcharts.DataGrou templateUrl: './lazy-loading-chart.component.html', styleUrls: ['./lazy-loading-chart.component.css'], imports: [HighchartsChartComponent], - providers: [providePartialHighChart({ modules: () => [import('highcharts/modules/stock')] })], + providers: [providePartialHighChart({ modules: () => [import('highcharts/es-modules/masters/modules/stock.src')] })], changeDetection: ChangeDetectionStrategy.OnPush, }) export class LazyLoadingChartComponent { constructor(private appleDataService: AppleDataService) { } - chartRef: Highcharts.Chart; + chartRef: HighchartsESM.Chart; - chartCallback: Highcharts.ChartCallbackFunction = (chart) => { + chartCallback: HighchartsESM.ChartCallbackFunction = (chart) => { this.chartRef = chart; }; @@ -35,7 +35,7 @@ export class LazyLoadingChartComponent { return this.appleDataService.fetchSqlData(min, max); } - chartLazyLoading: Highcharts.Options = { + chartLazyLoading: HighchartsESM.Options = { chart: { type: 'candlestick', zooming: { diff --git a/src/app/line-chart/line-chart.component.ts b/src/app/line-chart/line-chart.component.ts index e67483f..980cd1e 100644 --- a/src/app/line-chart/line-chart.component.ts +++ b/src/app/line-chart/line-chart.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HighchartsChartComponent, providePartialHighChart } from 'highcharts-angular'; +import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; @Component({ selector: 'app-line-chart', @@ -30,7 +31,7 @@ export class LineChartComponent { }] } `; - public optFromInput: Highcharts.Options = JSON.parse(this.optFromInputString); + public optFromInput: HighchartsESM.Options = JSON.parse(this.optFromInputString); private seriesTypes = { line: 'column', column: 'scatter', @@ -39,7 +40,7 @@ export class LineChartComponent { }; // Demonstrate chart instance - public logChartInstance(chart: Highcharts.Chart) { + public logChartInstance(chart: HighchartsESM.Chart) { if (chart) { console.log('Chart instance received:', chart); } else { diff --git a/src/app/map-chart/map-chart.component.ts b/src/app/map-chart/map-chart.component.ts index a4baeff..6ed2a1b 100644 --- a/src/app/map-chart/map-chart.component.ts +++ b/src/app/map-chart/map-chart.component.ts @@ -1,26 +1,22 @@ import {HttpClient} from '@angular/common/http'; import {ChangeDetectionStrategy, Component, inject, computed} from '@angular/core'; import {toSignal} from '@angular/core/rxjs-interop'; -import type Highcharts from 'highcharts'; +import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; import { HighchartsChartComponent, providePartialHighChart } from 'highcharts-angular'; -// import proj4 from 'proj4'; - -// Legacy way of map loading - see file at the path for more info. -// require('../../js/worldmap')(Highcharts); @Component({ selector: 'app-map-chart', templateUrl: './map-chart.component.html', styleUrls: ['./map-chart.component.css'], imports: [HighchartsChartComponent], - providers: [providePartialHighChart({ modules: () => [import('highcharts/modules/map')] })], + providers: [providePartialHighChart({ modules: () => [import('highcharts/es-modules/masters/modules/map.src')] })], changeDetection: ChangeDetectionStrategy.OnPush, }) export class MapChartComponent { private http = inject(HttpClient); worldMap = toSignal(this.http.get('/highcharts/world.geo.json')); - chartMap = computed(() => { + chartMap = computed(() => { return { chart: { map: this.worldMap(), @@ -272,7 +268,7 @@ export class MapChartComponent { ['kg', 211], ['np', 212] ] - } as Highcharts.SeriesMapOptions, + } as HighchartsESM.SeriesMapOptions, { // Specify points using lat/lon type: 'mappoint', @@ -298,7 +294,7 @@ export class MapChartComponent { lon: -114.3718 } ] - } as Highcharts.SeriesMappointOptions] + } as HighchartsESM.SeriesMappointOptions] } }) diff --git a/src/app/stock-chart/stock-chart.component.ts b/src/app/stock-chart/stock-chart.component.ts index 9e17a52..cf5e2aa 100644 --- a/src/app/stock-chart/stock-chart.component.ts +++ b/src/app/stock-chart/stock-chart.component.ts @@ -1,19 +1,22 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import type Highcharts from 'highcharts'; +import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; import { FormsModule } from '@angular/forms'; import { HighchartsChartComponent, providePartialHighChart } from 'highcharts-angular'; -// Alternative way of a plugin loading: -// const HC_ce = require('highcharts-custom-events'); -// HC_ce(Highcharts); - @Component({ selector: 'app-stock-chart', templateUrl: './stock-chart.component.html', styleUrls: ['./stock-chart.component.css'], imports: [FormsModule, HighchartsChartComponent], - providers: [providePartialHighChart({ modules: () => [import('highcharts/modules/stock'), import('highcharts-custom-events')] })], + providers: [ + providePartialHighChart({ + modules: () => [ + import('highcharts/es-modules/masters/modules/stock.src'), + import('highcharts-custom-events'), + ] + }) + ], changeDetection: ChangeDetectionStrategy.OnPush, }) export class StockChartComponent { @@ -65,8 +68,8 @@ export class StockChartComponent { [3, 10, -3, 3] ] }] - } as Highcharts.Options, - hcCallback: (chart: Highcharts.Chart) => { + } as HighchartsESM.Options, + hcCallback: (chart: HighchartsESM.Chart) => { console.log('some variables: ', chart, this.charts); } }, { @@ -85,7 +88,7 @@ export class StockChartComponent { [3, 10, -3, 3] ] }] - } as Highcharts.Options, + } as HighchartsESM.Options, hcCallback: () => {} }, { hcOptions: { @@ -104,7 +107,7 @@ export class StockChartComponent { 0 ] }] - } as Highcharts.Options, + } as HighchartsESM.Options, hcCallback: () => {} }]; diff --git a/src/app/tests/line-test/line-test.component.spec.ts b/src/app/tests/line-test/line-test.component.spec.ts index cc7a37a..e5299a2 100644 --- a/src/app/tests/line-test/line-test.component.spec.ts +++ b/src/app/tests/line-test/line-test.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { provideHighCharts } from '../../../../highcharts-angular/src/public_api'; import { LineTestComponent } from './line-test.component'; +import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; describe('LineTestComponent', () => { let component: LineTestComponent; @@ -33,7 +34,7 @@ describe('LineTestComponent', () => { // Simulate the chartInstance being assigned (this happens when the chart is rendered) component.chartInstance = { series: [{yData: [1, 2, 3]}], - } as unknown as Highcharts.Chart; + } as unknown as HighchartsESM.Chart; const series = component.chartInstance.series[0]; expect((series as any).yData).toEqual((chartOptions.series[0] as any).data); @@ -49,11 +50,11 @@ describe('LineTestComponent', () => { it('should be properly updated', () => { // Simulate the chartInstance and a mock series - const mockSeries = { color: 'hotpink' } as unknown as Highcharts.Series; + const mockSeries = { color: 'hotpink' } as unknown as HighchartsESM.Series; component.chartInstance = { series: [mockSeries], - } as unknown as Highcharts.Chart; + } as unknown as HighchartsESM.Chart; // Perform the color update component.updateSeriesColor(); @@ -64,7 +65,7 @@ describe('LineTestComponent', () => { }); it('should bind chart instance when Highcharts chart emits instance', () => { - const mockChartInstance = {} as Highcharts.Chart; + const mockChartInstance = {} as HighchartsESM.Chart; component.chartInstance = mockChartInstance; expect(component.chartInstance).toBe(mockChartInstance); diff --git a/src/app/tests/line-test/line-test.component.ts b/src/app/tests/line-test/line-test.component.ts index a95c2a2..57ecdbf 100644 --- a/src/app/tests/line-test/line-test.component.ts +++ b/src/app/tests/line-test/line-test.component.ts @@ -3,7 +3,7 @@ import type HighchartsESM from 'highcharts/es-modules/masters/highcharts.src'; import { HighchartsChartComponent } from '../../../../highcharts-angular/src/public_api'; interface ExtendedSeriesCandlestickOptions extends HighchartsESM.SeriesCandlestickOptions { - color: Highcharts.ColorType; + color: HighchartsESM.ColorType; } @Component({ @@ -15,8 +15,8 @@ interface ExtendedSeriesCandlestickOptions extends HighchartsESM.SeriesCandlesti }) export class LineTestComponent { updateFlag = false; - chartInstance: Highcharts.Chart; - chartOptions: Highcharts.Options = { + chartInstance: HighchartsESM.Chart; + chartOptions: HighchartsESM.Options = { series: [ { type: 'line',