diff --git a/demos/xychart.html b/demos/xychart.html
index 5803de4b8..ea24e4872 100644
--- a/demos/xychart.html
+++ b/demos/xychart.html
@@ -39,11 +39,9 @@
XY Charts demos
- xychart-beta horizontal
- title Basic xychart
- x-axis "this is x axis" [category1, "category 2", category3, category4]
- y-axis yaxisText 10 --> 150
+ xychart-beta
line [23, 46, 75, 43]
+ bar "sample bat" [52, 96, 35, 10]
diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts
index efee023ba..54b7bc004 100644
--- a/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts
+++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts
@@ -4,7 +4,7 @@ export interface ChartComponent {
getDrawableElements(): DrawableElem[];
}
-export type SimplePlotDataType = [string | number, number][];
+export type SimplePlotDataType = [string, number][];
export interface LinePlotData {
type: 'line';
@@ -26,11 +26,13 @@ export function isBarPlot(data: PlotData): data is BarPlotData {
}
export interface BandAxisDataType {
+ type: 'band';
title: string;
categories: string[];
}
export interface LinearAxisDataType {
+ type: 'linear';
title: string;
min: number;
max: number;
@@ -38,8 +40,12 @@ export interface LinearAxisDataType {
export type AxisDataType = LinearAxisDataType | BandAxisDataType;
-export function isBandAxisData(data: any): data is BandAxisDataType {
- return data.categories && Array.isArray(data.categories);
+export function isBandAxisData(data: AxisDataType): data is BandAxisDataType {
+ return data.type === 'band';
+}
+
+export function isLinearAxisData(data: AxisDataType): data is LinearAxisDataType {
+ return data.type === 'linear';
}
export interface XYChartData {
diff --git a/packages/mermaid/src/diagrams/xychart/xychartDb.ts b/packages/mermaid/src/diagrams/xychart/xychartDb.ts
index eb43d6315..a8d6971c8 100644
--- a/packages/mermaid/src/diagrams/xychart/xychartDb.ts
+++ b/packages/mermaid/src/diagrams/xychart/xychartDb.ts
@@ -12,7 +12,13 @@ import {
clear as commonClear,
} from '../../commonDb.js';
import { XYChartBuilder } from './chartBuilder/index.js';
-import { DrawableElem, XYChartData, isBandAxisData } from './chartBuilder/Interfaces.js';
+import {
+ DrawableElem,
+ SimplePlotDataType,
+ XYChartData,
+ isBandAxisData,
+ isLinearAxisData,
+} from './chartBuilder/Interfaces.js';
import { XYChartConfig } from '../../config.type.js';
const config = configApi.getConfig();
@@ -64,12 +70,14 @@ function getChartDefaultConfig(): XYChartConfig {
function getChartDefalutData(): XYChartData {
return {
yAxis: {
- title: 'yAxis1',
- min: 0,
- max: 100,
+ type: 'linear',
+ title: '',
+ min: Infinity,
+ max: -Infinity,
},
xAxis: {
- title: 'xAxis',
+ type: 'band',
+ title: '',
categories: [],
},
title: '',
@@ -79,6 +87,8 @@ function getChartDefalutData(): XYChartData {
let xyChartConfig: XYChartConfig = getChartDefaultConfig();
let xyChartData: XYChartData = getChartDefalutData();
+let hasSetXAxis = false;
+let hasSetYAxis = false;
function textSanitizer(text: string) {
return sanitizeText(text.trim(), config);
@@ -100,41 +110,92 @@ function setXAxisTitle(title: string) {
xyChartData.xAxis.title = textSanitizer(title);
}
function setXAxisRangeData(min: number, max: number) {
- xyChartData.xAxis = { title: xyChartData.xAxis.title, min, max };
+ xyChartData.xAxis = { type: 'linear', title: xyChartData.xAxis.title, min, max };
+ hasSetXAxis = true;
}
function setXAxisBand(categories: string[]) {
xyChartData.xAxis = {
+ type: 'band',
title: xyChartData.xAxis.title,
categories: categories.map((c) => textSanitizer(c)),
};
+ hasSetXAxis = true;
}
function setYAxisTitle(title: string) {
xyChartData.yAxis.title = textSanitizer(title);
}
function setYAxisRangeData(min: number, max: number) {
- xyChartData.yAxis = { title: xyChartData.yAxis.title, min, max };
+ xyChartData.yAxis = { type: 'linear', title: xyChartData.yAxis.title, min, max };
+ hasSetYAxis = true;
+}
+
+// this function does not set `hasSetYAxis` as there can be multiple data so we should calculate the range accordingly
+function setYAxisRangeFromPlotData(data: number[]) {
+ const minValue = Math.min(...data);
+ const maxValue = Math.max(...data);
+ const prevMinValue = isLinearAxisData(xyChartData.yAxis) ? xyChartData.yAxis.min : Infinity;
+ const prevMaxValue = isLinearAxisData(xyChartData.yAxis) ? xyChartData.yAxis.max : -Infinity;
+ xyChartData.yAxis = {
+ type: 'linear',
+ title: xyChartData.yAxis.title,
+ min: Math.min(prevMinValue, minValue),
+ max: Math.max(prevMaxValue, maxValue),
+ };
+}
+
+function transformDataWithOutCategory(data: number[]): SimplePlotDataType {
+ let retData: SimplePlotDataType = [];
+ if (data.length === 0) {
+ return retData;
+ }
+ if (!hasSetXAxis) {
+ const prevMinValue = isLinearAxisData(xyChartData.xAxis) ? xyChartData.xAxis.min : Infinity;
+ const prevMaxValue = isLinearAxisData(xyChartData.xAxis) ? xyChartData.xAxis.max : -Infinity;
+ setXAxisRangeData(Math.min(prevMinValue, 1), Math.max(prevMaxValue, data.length));
+ }
+ if (!hasSetYAxis) {
+ setYAxisRangeFromPlotData(data);
+ }
+
+ if (isBandAxisData(xyChartData.xAxis)) {
+ retData = xyChartData.xAxis.categories.map((c, i) => [c, data[i]]);
+ }
+
+ if (isLinearAxisData(xyChartData.xAxis)) {
+ const min = xyChartData.xAxis.min;
+ const max = xyChartData.xAxis.max;
+ const step = (max - min + 1) / data.length;
+ const categories: string[] = [];
+ for (let i = min; i <= max; i += step) {
+ categories.push(`${i}`);
+ }
+ retData = categories.map((c, i) => [c, data[i]]);
+ }
+
+ return retData;
}
function setLineData(title: string, data: number[]) {
- if (isBandAxisData(xyChartData.xAxis)) {
- xyChartData.plots.push({
- type: 'line',
- strokeFill: '#00ff00',
- strokeWidth: 2,
- data: xyChartData.xAxis.categories.map((c, i) => [c, data[i]]),
- });
- }
+ const plotData = transformDataWithOutCategory(data);
+ xyChartData.plots.push({
+ type: 'line',
+ strokeFill: '#00ff00',
+ strokeWidth: 2,
+ data: plotData,
+ });
}
function setBarData(title: string, data: number[]) {
- if (isBandAxisData(xyChartData.xAxis)) {
- xyChartData.plots.push({
- type: 'bar',
- fill: '#0000bb',
- data: xyChartData.xAxis.categories.map((c, i) => [c, data[i]]),
- });
- }
+ const plotData = transformDataWithOutCategory(data);
+ xyChartData.plots.push({
+ type: 'bar',
+ fill: '#0000bb',
+ data: plotData,
+ });
}
function getDrawableElem(): DrawableElem[] {
+ if (xyChartData.plots.length === 0) {
+ throw Error('No Plot to render, please provide a plot with some data');
+ }
xyChartData.title = getDiagramTitle();
return XYChartBuilder.build(xyChartConfig, xyChartData);
}
@@ -151,6 +212,8 @@ const clear = function () {
commonClear();
xyChartConfig = getChartDefaultConfig();
xyChartData = getChartDefalutData();
+ hasSetXAxis = false;
+ hasSetYAxis = false;
};
export default {