diff --git a/README.md b/README.md index f258731..903de63 100644 --- a/README.md +++ b/README.md @@ -331,6 +331,7 @@ import { HighchartsChartDirective } from 'highcharts-angular'; import('highcharts/esm/modules/exporting'), ]; }, + timeout: 900, // Optional: increase timeout for loading modules }), ], }) @@ -412,6 +413,12 @@ export class StockComponent { } ``` +**Note:** + +- Some Highcharts modules have dependencies and must be loaded in a specific order. +- In such cases, use a promise chain (e.g., `import('highcharts/esm/highcharts-more').then(() => import('highcharts/esm/modules/dumbbell'))`) +- instead of just listing them as array items. This ensures the dependent module loads only after its dependency. + ### To load a wrapper A wrapper is a [custom extension](https://www.highcharts.com/docs/extending-highcharts/extending-highcharts) for Highcharts. To load a wrapper in the same way as a module, save it as a JavaScript file and add the following code to the beginning and end of the file: diff --git a/highcharts-angular/src/lib/highcharts-chart.component.spec.ts b/highcharts-angular/src/lib/highcharts-chart.component.spec.ts new file mode 100644 index 0000000..2893315 --- /dev/null +++ b/highcharts-angular/src/lib/highcharts-chart.component.spec.ts @@ -0,0 +1,167 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import type Highcharts from 'highcharts/esm/highcharts'; +import { HighchartsChartComponent } from './highcharts-chart.component'; +import { HighchartsChartService } from './highcharts-chart.service'; +import { provideHighcharts, providePartialHighcharts } from './highcharts-chart.provider'; +import { ModuleFactoryFunction } from './types'; + +/** + * Minimal host component to attach per-test module providers via TestBed.overrideComponent. + * We keep it simple to focus on DI and async loading behavior. + */ +@Component({ + selector: 'highcharts-test', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [HighchartsChartComponent], + standalone: true, +}) +class TestComponent {} + +describe('TestComponent / HighchartsChartService (load module)', () => { + beforeEach(async () => { + // 1) Register the standalone host + core Highcharts provider. + // - provideHighcharts(): should wire up HIGHCHARTS_LOADER, etc., so the service can load core Highcharts. + await TestBed.configureTestingModule({ + imports: [TestComponent], + providers: [provideHighcharts()], + }).compileComponents(); + }); + + it('resolves HighchartsChartService from the component injector', () => { + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + // 2) Resolve the service from the component’s injector to honor component-level provider overrides. + const service = fixture.debugElement.injector.get(HighchartsChartService); + expect(service).toBeTruthy(); + }); + + // --------------------------------------------------------------------------- + // Parameterized checks for different Highcharts modules. + // + // For each case, we: + // - override the component’s providers to supply the module list + // - create the fixture (activates providers) + // - wait for the microtasks/imports to settle (fixture.whenStable) + // - assert that the Highcharts instance contains the expected augmented APIs + // --------------------------------------------------------------------------- + + type Case = { + title: string; + modules: ModuleFactoryFunction; + assert(hc: any): void; + timeout?: number; + }; + + const CASES: Case[] = [ + { + title: 'map → exposes Highcharts.MapChart', + modules: () => [import('highcharts/esm/modules/map')], + assert: (hc: typeof Highcharts) => { + expect(hc.MapChart).toBeDefined(); + expect(typeof hc.MapChart).toBe('function'); + }, + }, + { + title: 'tilemap → exposes Highcharts.seriesTypes.tilemap', + modules: () => [import('highcharts/esm/modules/tilemap')], + assert: hc => { + expect(hc.seriesTypes?.tilemap).toBeDefined(); + }, + }, + { + title: 'highcharts-more → exposes arearange series + dumbbell → exposes Highcharts.seriesTypes.dumbbell', + modules: () => [import('highcharts/esm/highcharts-more').then(() => import('highcharts/esm/modules/dumbbell'))], + assert: hc => { + expect(hc.seriesTypes?.arearange).toBeDefined(); + expect(hc.seriesTypes?.dumbbell).toBeDefined(); + }, + timeout: 2000, + }, + { + title: 'pattern-fill → adds SVGRenderer.addPattern', + modules: () => [import('highcharts/esm/modules/pattern-fill')], + assert: hc => { + // pattern-fill augments the renderer with addPattern utility + expect(typeof hc.SVGRenderer?.prototype?.addPattern).toBe('function'); + }, + }, + { + title: 'gantt → exposes Highcharts.ganttChart or Highcharts.GanttChart', + modules: () => [import('highcharts/esm/modules/gantt')], + assert: hc => { + // Some versions expose both; at least one must exist. + const ok = typeof hc.ganttChart === 'function' || typeof hc.GanttChart === 'function'; + expect(ok).toBeTrue(); + }, + }, + ]; + + for (const c of CASES) { + it(`attaches expected API when module is provided: ${c.title}`, async () => { + // 3) Provide the module(s) at the component level. This mirrors your real component’s + // `providers: [providePartialHighcharts({ modules: () => [...] })]`. + TestBed.overrideComponent(TestComponent, { + set: { providers: [providePartialHighcharts({ modules: c.modules, timeout: c.timeout })] }, + }); + + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + // 4) Get the service from this component’s injector scope + const service = fixture.debugElement.injector.get(HighchartsChartService); + expect(service).toBeTruthy(); + + // 5) Wait for all async work to stabilize: + // - dynamic imports for modules + // - the service’s microtasks and internal timers (your working test already relies on whenStable) + await fixture.whenStable(); + + // 6) Read the Highcharts instance from the signal + const hc = service.highcharts(); + expect(hc).toBeTruthy(); + + // 7) Case-specific assertions for the module’s side effects + c.assert(hc); + }); + } + + it('can load multiple modules together (map + tilemap + more + dumbbell + pattern-fill + gantt)', async () => { + TestBed.overrideComponent(TestComponent, { + set: { + providers: [ + providePartialHighcharts({ + modules: () => [ + import('highcharts/esm/modules/map'), + import('highcharts/esm/modules/tilemap'), + import('highcharts/esm/modules/gantt'), + import('highcharts/esm/highcharts-more').then(() => import('highcharts/esm/modules/dumbbell')), + import('highcharts/esm/modules/pattern-fill'), + ], + }), + ], + }, + }); + + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const service = fixture.debugElement.injector.get(HighchartsChartService); + expect(service).toBeTruthy(); + + await fixture.whenStable(); + + const hc: any = service.highcharts(); + expect(hc).toBeTruthy(); + + // Consolidated assertions (quick smoke for “all together”) + expect(typeof hc.MapChart).toBe('function'); // map + expect(hc.seriesTypes?.tilemap).toBeDefined(); // tilemap + expect(hc.seriesTypes?.arearange).toBeDefined(); // highcharts-more + expect(hc.seriesTypes?.dumbbell).toBeDefined(); // dumbbell + expect(typeof hc.SVGRenderer?.prototype?.addPattern).toBe('function'); // pattern-fill + expect(typeof hc.ganttChart === 'function' || typeof hc.GanttChart === 'function').toBeTrue(); // gantt + }); +}); diff --git a/highcharts-angular/src/lib/highcharts-chart.directive.ts b/highcharts-angular/src/lib/highcharts-chart.directive.ts index a60d4e4..20041aa 100644 --- a/highcharts-angular/src/lib/highcharts-chart.directive.ts +++ b/highcharts-angular/src/lib/highcharts-chart.directive.ts @@ -14,7 +14,7 @@ import { } from '@angular/core'; import { isPlatformServer } from '@angular/common'; import { HighchartsChartService } from './highcharts-chart.service'; -import { HIGHCHARTS_CONFIG } from './highcharts-chart.token'; +import { HIGHCHARTS_CONFIG, HIGHCHARTS_TIMEOUT } from './highcharts-chart.token'; import { ChartConstructorType, ConstructorChart } from './types'; import type Highcharts from 'highcharts/esm/highcharts'; @@ -58,6 +58,10 @@ export class HighchartsChartDirective { optional: true, }); + private readonly timeout = inject(HIGHCHARTS_TIMEOUT, { + optional: true, + }); + private readonly highchartsChartService = inject(HighchartsChartService); private readonly constructorChart = computed(() => { @@ -68,8 +72,13 @@ export class HighchartsChartDirective { return undefined; }); + private delay(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); + } + // Create the chart as soon as we can - private readonly chart = computed(() => { + private readonly chart = computed(async () => { + await this.delay(this.relativeConfig?.timeout ?? this.timeout ?? 500); return this.constructorChart()?.( this.el.nativeElement, // Use untracked, so we don't re-create new chart everytime options change @@ -82,14 +91,16 @@ export class HighchartsChartDirective { }); private keepChartUpToDate(): void { - effect(() => { + effect(async () => { + // Wait for the chart to be created this.update(); - this.chart()?.update(this.options(), true, this.oneToOne()); + const chart = await this.chart(); + chart?.update(this.options(), true, this.oneToOne()); }); } - private destroyChart(): void { - const chart = this.chart(); + private async destroyChart(): Promise { + const chart = await this.chart(); if (chart) { // #56 chart.destroy(); diff --git a/highcharts-angular/src/lib/highcharts-chart.provider.ts b/highcharts-angular/src/lib/highcharts-chart.provider.ts index 78794cf..017e694 100644 --- a/highcharts-angular/src/lib/highcharts-chart.provider.ts +++ b/highcharts-angular/src/lib/highcharts-chart.provider.ts @@ -4,6 +4,7 @@ import { HIGHCHARTS_CONFIG, HIGHCHARTS_ROOT_MODULES, HIGHCHARTS_OPTIONS, + HIGHCHARTS_TIMEOUT, } from './highcharts-chart.token'; import { ModuleFactoryFunction, HighchartsConfig, PartialHighchartsConfig, InstanceFactoryFunction } from './types'; import type Highcharts from 'highcharts/esm/highcharts'; @@ -34,9 +35,10 @@ export function providePartialHighcharts(config: PartialHighchartsConfig): Provi } export function provideHighcharts(config: HighchartsConfig = {}): EnvironmentProviders { - const providers: EnvironmentProviders[] = [ + const providers: (Provider | EnvironmentProviders)[] = [ provideHighchartsInstance(config.instance), provideHighchartsRootModules(config.modules ?? emptyModuleFactoryFunction), + { provide: HIGHCHARTS_TIMEOUT, useValue: config.timeout }, ]; if (config.options) { providers.push(provideHighchartsOptions(config.options)); diff --git a/highcharts-angular/src/lib/highcharts-chart.service.ts b/highcharts-angular/src/lib/highcharts-chart.service.ts index 3cef6e6..9a9ecf5 100644 --- a/highcharts-angular/src/lib/highcharts-chart.service.ts +++ b/highcharts-angular/src/lib/highcharts-chart.service.ts @@ -5,8 +5,7 @@ import type Highcharts from 'highcharts/esm/highcharts'; @Injectable({ providedIn: 'root' }) export class HighchartsChartService { - private readonly writableHighcharts = signal(null); - public readonly highcharts = this.writableHighcharts.asReadonly(); + public readonly highcharts = signal(null); private readonly loader = inject(HIGHCHARTS_LOADER); private readonly globalOptions = inject(HIGHCHARTS_OPTIONS, { @@ -19,7 +18,7 @@ export class HighchartsChartService { private async loadHighchartsWithModules(partialConfig: PartialHighchartsConfig | null): Promise { const highcharts = await this.loader(); // Ensure Highcharts core is loaded - await Promise.all([...(this.globalModules?.() ?? []), ...(partialConfig?.modules?.() ?? [])]); + await Promise.allSettled([...(this.globalModules?.() ?? []), ...(partialConfig?.modules?.() ?? [])]); // Return the Highcharts instance return highcharts; @@ -30,8 +29,7 @@ export class HighchartsChartService { if (this.globalOptions) { highcharts.setOptions(this.globalOptions); } - // add timeout to make sure the loader has attached all modules - setTimeout(() => this.writableHighcharts.set(highcharts), 100); + this.highcharts.set(highcharts); }); } } diff --git a/highcharts-angular/src/lib/highcharts-chart.token.ts b/highcharts-angular/src/lib/highcharts-chart.token.ts index 1945255..0b0082c 100644 --- a/highcharts-angular/src/lib/highcharts-chart.token.ts +++ b/highcharts-angular/src/lib/highcharts-chart.token.ts @@ -6,3 +6,4 @@ export const HIGHCHARTS_LOADER = new InjectionToken('HI export const HIGHCHARTS_ROOT_MODULES = new InjectionToken('HIGHCHARTS_ROOT_MODULES'); export const HIGHCHARTS_OPTIONS = new InjectionToken('HIGHCHARTS_OPTIONS'); export const HIGHCHARTS_CONFIG = new InjectionToken('HIGHCHARTS_CONFIG'); +export const HIGHCHARTS_TIMEOUT = new InjectionToken('HIGHCHARTS_TIMEOUT'); diff --git a/highcharts-angular/src/lib/types.ts b/highcharts-angular/src/lib/types.ts index a0041dd..df60bb5 100644 --- a/highcharts-angular/src/lib/types.ts +++ b/highcharts-angular/src/lib/types.ts @@ -21,6 +21,11 @@ export type PartialHighchartsConfig = { * Include Highcharts additional modules (e.g., exporting, accessibility) or custom themes */ modules?: ModuleFactoryFunction; + /** + * Timeout in milliseconds to wait for the Highcharts library to load + * Default is 500ms + */ + timeout?: number; }; export type HighchartsConfig = { diff --git a/package.json b/package.json index 5495e83..a46e7a6 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "run:ssr": "node dist/my-ssr-app/server/server.mjs", "test": "ng test my-app", "lint": "ng lint", + "prettier": "prettier . --write", "release": "cd ./highcharts-angular && standard-version && cd ../ && node tasks/build.js && node tasks/release.js", "release-minor": "cd ./highcharts-angular && standard-version --release-as minor && cd ../ && node tasks/build.js && node tasks/release.js", "release-major": "cd ./highcharts-angular && standard-version --release-as major && cd ../ && node tasks/build.js && node tasks/release.js", diff --git a/src/app/app.component.html b/src/app/app.component.html index a22188c..be58e88 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -2,6 +2,8 @@ + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b97868c..5ede2d4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -4,12 +4,22 @@ import { StockChartComponent } from './stock-chart/stock-chart.component'; import { MapChartComponent } from './map-chart/map-chart.component'; import { GanttChartComponent } from './gantt-chart/gantt-chart.component'; import { LazyLoadingChartComponent } from './lazy-loading-chart/lazy-loading-chart.component'; +import { TilemapChartComponent } from './tilemap-chart/tilemap-chart.component'; +import { DumbbellChartComponent } from './dumbbell-chart/dumbbell-chart.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrl: './app.component.css', - imports: [LineChartComponent, StockChartComponent, MapChartComponent, GanttChartComponent, LazyLoadingChartComponent], + imports: [ + LineChartComponent, + StockChartComponent, + MapChartComponent, + GanttChartComponent, + LazyLoadingChartComponent, + TilemapChartComponent, + DumbbellChartComponent, + ], changeDetection: ChangeDetectionStrategy.OnPush, }) export class AppComponent {} diff --git a/src/app/dumbbell-chart/dumbbell-chart.component.css b/src/app/dumbbell-chart/dumbbell-chart.component.css new file mode 100644 index 0000000..6a487ef --- /dev/null +++ b/src/app/dumbbell-chart/dumbbell-chart.component.css @@ -0,0 +1,11 @@ +h2 { + font-family: Arial, Helvetica, sans-serif; + font-size: 1.25rem; + margin: 0 0 1.5rem 0; +} + +.main { + width: 100%; + height: 650px; + display: block; +} diff --git a/src/app/dumbbell-chart/dumbbell-chart.component.html b/src/app/dumbbell-chart/dumbbell-chart.component.html new file mode 100644 index 0000000..f76f5ae --- /dev/null +++ b/src/app/dumbbell-chart/dumbbell-chart.component.html @@ -0,0 +1,4 @@ +
+

Demo #8: Highcharts Dumbbell

+ +
diff --git a/src/app/dumbbell-chart/dumbbell-chart.component.ts b/src/app/dumbbell-chart/dumbbell-chart.component.ts new file mode 100644 index 0000000..5bde675 --- /dev/null +++ b/src/app/dumbbell-chart/dumbbell-chart.component.ts @@ -0,0 +1,197 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { HighchartsChartComponent } from 'highcharts-angular'; +import { providePartialHighcharts } from 'highcharts-angular'; + +@Component({ + selector: 'app-dumbbell-chart', + imports: [HighchartsChartComponent], + templateUrl: './dumbbell-chart.component.html', + styleUrl: './dumbbell-chart.component.css', + providers: [ + providePartialHighcharts({ + modules: () => { + return [ + import('highcharts/esm/highcharts-more'), + import('highcharts/esm/modules/dumbbell'), + import('highcharts/esm/modules/pattern-fill'), + ]; + }, + timeout: 900, + }), + ], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DumbbellChartComponent { + public options: Highcharts.Options = { + chart: { + plotBorderWidth: 1, + zooming: { + type: 'y', + resetButton: { + theme: { style: { display: 'none' } }, + }, + }, + spacingLeft: 1, + spacingRight: 1, + spacingTop: 7, + spacingBottom: 0, + animation: false, + panning: { + enabled: true, + type: 'y', + }, + panKey: 'shift', + }, + plotOptions: { + columnrange: { + grouping: false, + }, + }, + legend: { enabled: false }, + credits: { enabled: false }, + title: { text: '' }, + yAxis: { + reversed: true, + title: { text: '' }, + startOnTick: false, + endOnTick: false, + gridLineWidth: 1, + tickPixelInterval: 72, + minPadding: 0.1, + minRange: 0.1, + crosshair: { + color: 'red', + snap: false, + zIndex: 4, + }, + labels: { + enabled: true, + style: { fontSize: '11px' }, + x: -7, + }, + }, + xAxis: { + startOnTick: false, + endOnTick: false, + lineWidth: 0, + tickWidth: 0, + minRange: 0.1, + gridLineWidth: 1, + labels: { style: { fontSize: '11px' }, y: 14 }, + }, + series: [ + { + data: [['', 2060, 2000]], + type: 'dumbbell', + name: 'Surface_26: Cement', + color: 'lightgray', + groupPadding: 0.7, + connectorWidth: 14, + marker: { + radius: 0, + }, + }, + { + data: [['', 2060, 2000]], + type: 'dumbbell', + name: 'Surface_26: Tubular', + color: 'black', + zIndex: 1, + groupPadding: 0.7, + connectorWidth: 3, + marker: { + radius: 0, + }, + lowMarker: { + radius: 5, + fillColor: 'black', + symbol: 'flag', + }, + }, + { + data: [['', 2791.96, 2000]], + type: 'dumbbell', + name: 'Phase_16: Cement', + color: 'lightgray', + groupPadding: 0.7, + connectorWidth: 14, + marker: { + radius: 0, + }, + }, + { + data: [['', 2791.96, 2000]], + type: 'dumbbell', + name: 'Phase_16: Tubular', + color: 'black', + zIndex: 1, + groupPadding: 0.7, + connectorWidth: 3, + marker: { + radius: 0, + }, + lowMarker: { + radius: 5, + fillColor: 'black', + symbol: 'flag', + }, + }, + { + data: [['', 4500, 4000]], + type: 'dumbbell', + name: 'Phase_13_375: Cement', + color: 'lightgray', + groupPadding: 0.7, + connectorWidth: 14, + marker: { + radius: 0, + }, + }, + { + data: [['', 4500, 2000]], + type: 'dumbbell', + name: 'Phase_13_375: Tubular', + color: 'black', + zIndex: 1, + groupPadding: 0.7, + connectorWidth: 3, + marker: { + radius: 0, + }, + lowMarker: { + radius: 5, + fillColor: 'black', + symbol: 'flag', + }, + }, + { + data: [['', 5250, 4650]], + type: 'dumbbell', + name: 'Phase_10_74: Cement', + color: 'lightgray', + groupPadding: 0.7, + connectorWidth: 14, + marker: { + radius: 0, + }, + }, + { + data: [['', 5250, 4400]], + type: 'dumbbell', + name: 'Phase_10_74: Tubular', + color: 'black', + zIndex: 1, + groupPadding: 0.7, + connectorWidth: 3, + marker: { + radius: 0, + }, + lowMarker: { + radius: 5, + fillColor: 'black', + symbol: 'flag', + }, + }, + ], + }; +} diff --git a/src/app/map-chart/map-chart.component.ts b/src/app/map-chart/map-chart.component.ts index 44bd377..475beb6 100644 --- a/src/app/map-chart/map-chart.component.ts +++ b/src/app/map-chart/map-chart.component.ts @@ -17,7 +17,8 @@ import { HighchartsChartComponent, providePartialHighcharts } from 'highcharts-a changeDetection: ChangeDetectionStrategy.OnPush, }) export class MapChartComponent { - public readonly worldMap = httpResource('/highcharts/world.geo.json'); + // https://code.highcharts.com/mapdata/ + public readonly worldMap = httpResource('https://code.highcharts.com/mapdata/custom/world.topo.json'); public readonly chartMap = computed(() => { return { chart: { diff --git a/src/app/tilemap-chart/tilemap-chart.component.css b/src/app/tilemap-chart/tilemap-chart.component.css new file mode 100644 index 0000000..6a487ef --- /dev/null +++ b/src/app/tilemap-chart/tilemap-chart.component.css @@ -0,0 +1,11 @@ +h2 { + font-family: Arial, Helvetica, sans-serif; + font-size: 1.25rem; + margin: 0 0 1.5rem 0; +} + +.main { + width: 100%; + height: 650px; + display: block; +} diff --git a/src/app/tilemap-chart/tilemap-chart.component.html b/src/app/tilemap-chart/tilemap-chart.component.html new file mode 100644 index 0000000..d976931 --- /dev/null +++ b/src/app/tilemap-chart/tilemap-chart.component.html @@ -0,0 +1,10 @@ +
+

Demo #5: Highcharts Tile Maps

+ +
diff --git a/src/app/tilemap-chart/tilemap-chart.component.ts b/src/app/tilemap-chart/tilemap-chart.component.ts new file mode 100644 index 0000000..14cf508 --- /dev/null +++ b/src/app/tilemap-chart/tilemap-chart.component.ts @@ -0,0 +1,103 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { HighchartsChartComponent, providePartialHighcharts, ChartConstructorType } from 'highcharts-angular'; + +@Component({ + selector: 'app-tilemap-chart', + imports: [HighchartsChartComponent], + templateUrl: './tilemap-chart.component.html', + styleUrl: './tilemap-chart.component.css', + providers: [ + providePartialHighcharts({ + modules: () => [import('highcharts/esm/modules/map'), import('highcharts/esm/modules/tilemap')], + }), + ], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TilemapChartComponent { + public get chartOptions(): Highcharts.Options { + return { + chart: { + type: 'tilemap', + inverted: true, + height: '80%', + }, + title: { + text: 'My Title', + }, + xAxis: { + visible: false, + }, + yAxis: { + visible: false, + }, + colorAxis: { + dataClasses: [ + { + from: 0, + to: 1000000, + color: '#3b528b', + name: '< 1M', + }, + { + from: 1000000, + to: 5000000, + color: '#21918c', + name: '1M - 5M', + }, + { + from: 5000000, + to: 20000000, + color: '#5ec962', + name: '5M - 20M', + }, + { + from: 20000000, + color: '#fde725', + name: '> 20M', + }, + ], + }, + legend: { + enabled: false, + }, + tooltip: { + headerFormat: '', + pointFormat: 'Population de {point.name}: {point.value}', + }, + plotOptions: { + tilemap: { + tileShape: 'hexagon', + dataLabels: { + enabled: true, + format: '{point.hc-a2}', + style: { + textOutline: 'none', + }, + }, + }, + }, + series: [ + { + type: 'tilemap', + name: 'Population', + data: this.getTilemapData(), + }, + ], + }; + } + + private getTilemapData(): any[] { + return [ + { 'hc-a2': 'CA', name: 'California', x: 5, y: 2, value: 38965193 }, + { 'hc-a2': 'TX', name: 'Texas', x: 7, y: 4, value: 30503301 }, + { 'hc-a2': 'FL', name: 'Florida', x: 8, y: 8, value: 22610726 }, + { 'hc-a2': 'NY', name: 'New York', x: 2, y: 9, value: 19571216 }, + { 'hc-a2': 'IL', name: 'Illinois', x: 3, y: 6, value: 12882135 }, + { 'hc-a2': 'PA', name: 'Pennsylvania', x: 3, y: 8, value: 12801989 }, + ]; + } + + public chartConstructor: ChartConstructorType = 'chart'; + public updateFlag = false; + public oneToOneFlag = true; +}