ng-apexcharts
Version:
An angular implementation of ApexCharts
463 lines (453 loc) • 29.5 kB
JavaScript
import * as i0 from '@angular/core';
import { input, output, signal, viewChild, inject, NgZone, PLATFORM_ID, Injector, afterNextRender, afterEveryRender, ChangeDetectionStrategy, Component, Injectable, PendingTasks, ElementRef, TransferState, makeStateKey, Inject, runInInjectionContext, NgModule } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
class ChartComponent {
constructor() {
this.chart = input(...(ngDevMode ? [undefined, { debugName: "chart" }] : []));
this.annotations = input(...(ngDevMode ? [undefined, { debugName: "annotations" }] : []));
this.colors = input(...(ngDevMode ? [undefined, { debugName: "colors" }] : []));
this.dataLabels = input(...(ngDevMode ? [undefined, { debugName: "dataLabels" }] : []));
this.series = input(...(ngDevMode ? [undefined, { debugName: "series" }] : []));
this.stroke = input(...(ngDevMode ? [undefined, { debugName: "stroke" }] : []));
this.labels = input(...(ngDevMode ? [undefined, { debugName: "labels" }] : []));
this.legend = input(...(ngDevMode ? [undefined, { debugName: "legend" }] : []));
this.markers = input(...(ngDevMode ? [undefined, { debugName: "markers" }] : []));
this.noData = input(...(ngDevMode ? [undefined, { debugName: "noData" }] : []));
this.parsing = input(...(ngDevMode ? [undefined, { debugName: "parsing" }] : []));
this.fill = input(...(ngDevMode ? [undefined, { debugName: "fill" }] : []));
this.tooltip = input(...(ngDevMode ? [undefined, { debugName: "tooltip" }] : []));
this.plotOptions = input(...(ngDevMode ? [undefined, { debugName: "plotOptions" }] : []));
this.responsive = input(...(ngDevMode ? [undefined, { debugName: "responsive" }] : []));
this.xaxis = input(...(ngDevMode ? [undefined, { debugName: "xaxis" }] : []));
this.yaxis = input(...(ngDevMode ? [undefined, { debugName: "yaxis" }] : []));
this.forecastDataPoints = input(...(ngDevMode ? [undefined, { debugName: "forecastDataPoints" }] : []));
this.grid = input(...(ngDevMode ? [undefined, { debugName: "grid" }] : []));
this.states = input(...(ngDevMode ? [undefined, { debugName: "states" }] : []));
this.title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : []));
this.subtitle = input(...(ngDevMode ? [undefined, { debugName: "subtitle" }] : []));
this.theme = input(...(ngDevMode ? [undefined, { debugName: "theme" }] : []));
this.autoUpdateSeries = input(true, ...(ngDevMode ? [{ debugName: "autoUpdateSeries" }] : []));
this.chartReady = output();
// If consumers need to capture the `chartInstance` for use, consumers
// can access the component instance through `viewChild` and use `computed`
// or `effect` on `component.chartInstance()` to monitor its changes and
// recompute effects or computations whenever `chartInstance` is updated.
this.chartInstance = signal(null, ...(ngDevMode ? [{ debugName: "chartInstance" }] : []));
this.chartElement = viewChild.required("chart");
this.ngZone = inject(NgZone);
this.isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
this._destroyed = false;
this._injector = inject(Injector);
this.waitingForConnectedRef = null;
}
ngOnChanges(changes) {
if (!this.isBrowser)
return;
this.hydrate(changes);
}
ngOnDestroy() {
this.destroy();
this._destroyed = true;
}
/** Determine if the host element is connected to the document */
get isConnected() {
return this.chartElement()?.nativeElement.isConnected;
}
hydrate(changes) {
if (this.waitingForConnectedRef) {
return;
}
const shouldUpdateSeries = this.chartInstance() &&
this.autoUpdateSeries() &&
Object.keys(changes).filter((c) => c !== "series").length === 0;
if (shouldUpdateSeries) {
this.updateSeries(this.series(), true);
return;
}
// Create the chart after the layout is finalized and ready to be measured.
afterNextRender({
read: () => this.createElement(),
}, { injector: this._injector });
}
/** @internal Extracted to allow subclasses and tests to swap the ApexCharts bundle. */
importApexCharts() {
return import('apexcharts/client');
}
async createElement() {
const { default: ApexCharts } = await this.importApexCharts();
window.ApexCharts ||= ApexCharts;
if (this._destroyed)
return;
if (!this.isConnected) {
this.waitForConnected();
return;
}
const options = {};
const properties = [
"annotations",
"chart",
"colors",
"dataLabels",
"series",
"stroke",
"labels",
"legend",
"fill",
"tooltip",
"plotOptions",
"responsive",
"markers",
"noData",
"parsing",
"xaxis",
"yaxis",
"forecastDataPoints",
"grid",
"states",
"title",
"subtitle",
"theme",
];
properties.forEach((property) => {
const value = this[property]();
if (value) {
options[property] = value;
}
});
this.destroy();
const chartInstance = this.ngZone.runOutsideAngular(() => new ApexCharts(this.chartElement().nativeElement, options));
this.chartInstance.set(chartInstance);
this.render();
this.chartReady.emit({ chartObj: chartInstance });
}
render() {
if (this.isConnected) {
return this.ngZone.runOutsideAngular(() => this.chartInstance()?.render());
}
else {
this.waitForConnected();
}
}
updateOptions(options, redrawPaths, animate, updateSyncedCharts) {
return this.ngZone.runOutsideAngular(() => this.chartInstance()?.updateOptions(options, redrawPaths, animate, updateSyncedCharts));
}
updateSeries(newSeries, animate) {
return this.ngZone.runOutsideAngular(() => this.chartInstance()?.updateSeries(newSeries, animate));
}
appendSeries(newSeries, animate) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.appendSeries(newSeries, animate));
}
appendData(newData) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.appendData(newData));
}
highlightSeries(seriesName) {
return this.ngZone.runOutsideAngular(() => this.chartInstance()?.highlightSeries(seriesName));
}
toggleSeries(seriesName) {
return this.ngZone.runOutsideAngular(() => this.chartInstance()?.toggleSeries(seriesName));
}
showSeries(seriesName) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.showSeries(seriesName));
}
hideSeries(seriesName) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.hideSeries(seriesName));
}
resetSeries() {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.resetSeries());
}
zoomX(min, max) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.zoomX(min, max));
}
toggleDataPointSelection(seriesIndex, dataPointIndex) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.toggleDataPointSelection(seriesIndex, dataPointIndex));
}
destroy() {
this.chartInstance()?.destroy();
this.chartInstance.set(null);
}
setLocale(localeName) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.setLocale(localeName));
}
paper() {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.paper());
}
addXaxisAnnotation(options, pushToMemory, context) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.addXaxisAnnotation(options, pushToMemory, context));
}
addYaxisAnnotation(options, pushToMemory, context) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.addYaxisAnnotation(options, pushToMemory, context));
}
addPointAnnotation(options, pushToMemory, context) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.addPointAnnotation(options, pushToMemory, context));
}
removeAnnotation(id, options) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.removeAnnotation(id, options));
}
clearAnnotations(options) {
this.ngZone.runOutsideAngular(() => this.chartInstance()?.clearAnnotations(options));
}
dataURI(options) {
return this.chartInstance()?.dataURI(options);
}
waitForConnected() {
if (this.waitingForConnectedRef) {
return;
}
this.waitingForConnectedRef = afterEveryRender({
read: () => {
if (this.isConnected) {
this.waitingForConnectedRef.destroy();
this.waitingForConnectedRef = null;
this.createElement();
}
},
}, { injector: this._injector });
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.5", type: ChartComponent, isStandalone: true, selector: "apx-chart", inputs: { chart: { classPropertyName: "chart", publicName: "chart", isSignal: true, isRequired: false, transformFunction: null }, annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, dataLabels: { classPropertyName: "dataLabels", publicName: "dataLabels", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, stroke: { classPropertyName: "stroke", publicName: "stroke", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null }, markers: { classPropertyName: "markers", publicName: "markers", isSignal: true, isRequired: false, transformFunction: null }, noData: { classPropertyName: "noData", publicName: "noData", isSignal: true, isRequired: false, transformFunction: null }, parsing: { classPropertyName: "parsing", publicName: "parsing", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, plotOptions: { classPropertyName: "plotOptions", publicName: "plotOptions", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, xaxis: { classPropertyName: "xaxis", publicName: "xaxis", isSignal: true, isRequired: false, transformFunction: null }, yaxis: { classPropertyName: "yaxis", publicName: "yaxis", isSignal: true, isRequired: false, transformFunction: null }, forecastDataPoints: { classPropertyName: "forecastDataPoints", publicName: "forecastDataPoints", isSignal: true, isRequired: false, transformFunction: null }, grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: false, transformFunction: null }, states: { classPropertyName: "states", publicName: "states", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, autoUpdateSeries: { classPropertyName: "autoUpdateSeries", publicName: "autoUpdateSeries", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartReady: "chartReady" }, viewQueries: [{ propertyName: "chartElement", first: true, predicate: ["chart"], descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: `<div #chart></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartComponent, decorators: [{
type: Component,
args: [{
selector: "apx-chart",
template: `<div #chart></div>`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}]
}], propDecorators: { chart: [{ type: i0.Input, args: [{ isSignal: true, alias: "chart", required: false }] }], annotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotations", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], dataLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataLabels", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], stroke: [{ type: i0.Input, args: [{ isSignal: true, alias: "stroke", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], legend: [{ type: i0.Input, args: [{ isSignal: true, alias: "legend", required: false }] }], markers: [{ type: i0.Input, args: [{ isSignal: true, alias: "markers", required: false }] }], noData: [{ type: i0.Input, args: [{ isSignal: true, alias: "noData", required: false }] }], parsing: [{ type: i0.Input, args: [{ isSignal: true, alias: "parsing", required: false }] }], fill: [{ type: i0.Input, args: [{ isSignal: true, alias: "fill", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], plotOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "plotOptions", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], xaxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "xaxis", required: false }] }], yaxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "yaxis", required: false }] }], forecastDataPoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "forecastDataPoints", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: false }] }], states: [{ type: i0.Input, args: [{ isSignal: true, alias: "states", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], autoUpdateSeries: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoUpdateSeries", required: false }] }], chartReady: [{ type: i0.Output, args: ["chartReady"] }], chartElement: [{ type: i0.ViewChild, args: ["chart", { isSignal: true }] }] } });
/**
* Tree-shakeable variant of `<apx-chart>`.
*
* Loads `apexcharts/core` (~611 KB) instead of the full `apexcharts/client`
* bundle (~942 KB). To register chart types and features, add side-effect
* imports **before** this component is rendered — typically in `app.config.ts`
* or at the top of the component that bootstraps the charts:
*
* ```ts
* import "apexcharts/line"; // line, area, scatter, bubble
* import "apexcharts/bar"; // bar, column, rangeBar
* import "apexcharts/features/legend"; // opt-in legend
* import "apexcharts/features/toolbar"; // opt-in toolbar
* ```
*
* All inputs/outputs/methods are identical to `<apx-chart>`.
*/
class ChartCoreComponent extends ChartComponent {
importApexCharts() {
return import('apexcharts/core');
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartCoreComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: ChartCoreComponent, isStandalone: true, selector: "apx-chart-core", usesInheritance: true, ngImport: i0, template: `<div #chart></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartCoreComponent, decorators: [{
type: Component,
args: [{
selector: "apx-chart-core",
template: `<div #chart></div>`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}]
}] });
class ChartSSRService {
constructor() {
/** Per-app-instance counter for stable TransferState keys. Resets on each server bootstrap. */
this.instanceCounter = 0;
}
nextInstanceId() {
return this.instanceCounter++;
}
/** @internal Extracted to allow spying in unit tests without importing actual SSR bundle. */
importSSRModule() {
return import('apexcharts/ssr');
}
async renderToHTML(options, ssrOptions = {}) {
const { default: ApexCharts } = await this.importSSRModule();
return ApexCharts.renderToHTML(options, ssrOptions);
}
async renderToString(options, ssrOptions = {}) {
const { default: ApexCharts } = await this.importSSRModule();
return ApexCharts.renderToString(options, ssrOptions);
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartSSRService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartSSRService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartSSRService, decorators: [{
type: Injectable,
args: [{
providedIn: "root",
}]
}] });
/**
* Server-side rendering component for ApexCharts.
*
* On the server: renders SVG imperatively into the host element, stores HTML in TransferState.
* On the client: ngSkipHydration tells Angular to leave the host DOM alone.
* afterNextRender then injects the HTML from TransferState into the host imperatively
* (as a fallback if ngSkipHydration stripped the content, which it does with empty templates).
* ChartHydrateComponent also uses afterNextRender so it runs after this, guaranteeing
* [data-apexcharts-hydrate] is present when Pattern B calls hydrate().
*
* @example
* <apx-chart-ssr [options]="chartOptions" [width]="500" [height]="300" />
*/
class ChartSSRComponent {
constructor(platformId) {
this.options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
this.width = input(400, ...(ngDevMode ? [{ debugName: "width" }] : []));
this.height = input(300, ...(ngDevMode ? [{ debugName: "height" }] : []));
this.chartSSRService = inject(ChartSSRService);
this.pendingTasks = inject(PendingTasks);
this.el = inject((ElementRef));
this.transferState = inject(TransferState);
this.stateKey = makeStateKey(`apx-chart-ssr-${this.chartSSRService.nextInstanceId()}`);
this.isServer = isPlatformServer(platformId);
if (!this.isServer) {
afterNextRender(() => {
const host = this.el.nativeElement;
const html = this.transferState.get(this.stateKey, "");
this.transferState.remove(this.stateKey);
if (html) {
// html is a JSON string: { svgOuter: "<svg ...>...</svg>", config: "base64..." }
const { svgOuter, config } = JSON.parse(html);
// Parse SVG via XML parser to correctly handle self-closing tags and namespaces.
// Using innerHTML on an HTML element would corrupt the SVG tree (HTML parser mode).
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgOuter, 'image/svg+xml');
const svgEl = document.importNode(svgDoc.documentElement, true);
// Create wrapper div with attributes needed by ApexCharts.hydrate()
const wrapper = document.createElement('div');
wrapper.className = 'apexcharts-ssr-wrapper';
wrapper.setAttribute('data-apexcharts-hydrate', '');
if (config)
wrapper.setAttribute('data-apexcharts-config', config);
wrapper.appendChild(svgEl);
host.innerHTML = '';
host.appendChild(wrapper);
}
});
}
}
async ngOnInit() {
if (!this.isServer)
return;
const done = this.pendingTasks.add();
const ssrOptions = { width: this.width(), height: this.height() };
try {
const [html, svgOuter] = await Promise.all([
this.chartSSRService.renderToHTML(this.options(), ssrOptions),
this.chartSSRService.renderToString(this.options(), ssrOptions),
]);
const configMatch = html.match(/data-apexcharts-config="([^"]*)"/);
const config = configMatch?.[1] ?? '';
this.transferState.set(this.stateKey, JSON.stringify({ svgOuter, config }));
this.el.nativeElement.innerHTML = html;
}
finally {
done();
}
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartSSRComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.5", type: ChartSSRComponent, isStandalone: true, selector: "apx-chart-ssr", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "ngSkipHydration": "true" } }, ngImport: i0, template: ``, isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartSSRComponent, decorators: [{
type: Component,
args: [{
selector: "apx-chart-ssr",
template: ``,
standalone: true,
host: { ngSkipHydration: "true" },
}]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
/**
* Client-side hydration component for ApexCharts SSR output.
*
* Must be placed immediately after `<apx-chart-ssr>` in the DOM. It finds
* the server-rendered `[data-apexcharts-hydrate]` element in the preceding
* `<apx-chart-ssr>` sibling and calls `ApexCharts.hydrate()` on it to
* attach full interactivity (animations, tooltips, zoom, etc.).
*
* Uses afterNextRender so it runs after ChartSSRComponent has injected the
* server HTML into the DOM (which also happens in afterNextRender).
*
* On the server this component does nothing.
*
* @example
* <apx-chart-ssr [options]="chartOptions" />
* <apx-chart-hydrate [clientOptions]="{ chart: { animations: { enabled: true } } }" />
*/
class ChartHydrateComponent {
constructor(platformId) {
this.clientOptions = input({}, ...(ngDevMode ? [{ debugName: "clientOptions" }] : []));
this.el = inject((ElementRef));
this.ngZone = inject(NgZone);
this.injector = inject(Injector);
this.chartObj = null;
this.isBrowser = isPlatformBrowser(platformId);
}
ngOnInit() {
if (!this.isBrowser)
return;
runInInjectionContext(this.injector, () => afterNextRender(async () => {
// By this point ChartSSRComponent's afterNextRender has already run,
// so [data-apexcharts-hydrate] is guaranteed to be in the DOM.
const host = this.el.nativeElement;
const ssrEl = host.parentElement?.querySelector("[data-apexcharts-hydrate]");
if (!ssrEl) {
console.warn("[ng-apexcharts] ChartHydrateComponent: No [data-apexcharts-hydrate] element found. Ensure <apx-chart-ssr> precedes <apx-chart-hydrate> in the same container.");
return;
}
const { default: ApexCharts } = await this.importClientModule();
try {
this.chartObj = this.ngZone.runOutsideAngular(() => ApexCharts.hydrate(ssrEl, this.clientOptions()));
}
catch (error) {
console.error("[ng-apexcharts] ChartHydrateComponent: Failed to hydrate chart.", error);
}
}));
}
/** @internal Extracted to allow spying in unit tests without importing actual SSR/hydrate bundle. */
importClientModule() {
return import('apexcharts/ssr');
}
ngOnDestroy() {
this.chartObj?.destroy();
this.chartObj = null;
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartHydrateComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.5", type: ChartHydrateComponent, isStandalone: true, selector: "apx-chart-hydrate", inputs: { clientOptions: { classPropertyName: "clientOptions", publicName: "clientOptions", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: ``, isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ChartHydrateComponent, decorators: [{
type: Component,
args: [{
selector: "apx-chart-hydrate",
template: ``,
standalone: true,
}]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }], propDecorators: { clientOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "clientOptions", required: false }] }] } });
const declarations = [ChartComponent, ChartCoreComponent, ChartSSRComponent, ChartHydrateComponent];
class NgApexchartsModule {
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgApexchartsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.5", ngImport: i0, type: NgApexchartsModule, imports: [ChartComponent, ChartCoreComponent, ChartSSRComponent, ChartHydrateComponent], exports: [ChartComponent, ChartCoreComponent, ChartSSRComponent, ChartHydrateComponent] }); }
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgApexchartsModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgApexchartsModule, decorators: [{
type: NgModule,
args: [{
imports: [declarations],
exports: [declarations],
}]
}] });
/*
* Public API Surface of ng-apexcharts
*/
/**
* Generated bundle index. Do not edit.
*/
export { ChartComponent, ChartCoreComponent, ChartHydrateComponent, ChartSSRComponent, ChartSSRService, NgApexchartsModule };
//# sourceMappingURL=ng-apexcharts.mjs.map