@diagrammo/dgmo 0.8.8 → 0.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -0
- package/dist/cli.cjs +181 -179
- package/dist/index.cjs +1425 -933
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -1
- package/dist/index.d.ts +147 -1
- package/dist/index.js +1421 -933
- package/dist/index.js.map +1 -1
- package/docs/language-reference.md +28 -2
- package/gallery/fixtures/sitemap-full.dgmo +1 -0
- package/package.json +1 -1
- package/src/boxes-and-lines/layout.ts +48 -8
- package/src/boxes-and-lines/parser.ts +59 -13
- package/src/boxes-and-lines/renderer.ts +33 -137
- package/src/c4/renderer.ts +25 -138
- package/src/class/renderer.ts +185 -186
- package/src/d3.ts +114 -191
- package/src/echarts.ts +99 -214
- package/src/er/renderer.ts +52 -245
- package/src/gantt/renderer.ts +140 -182
- package/src/index.ts +21 -1
- package/src/infra/renderer.ts +91 -244
- package/src/kanban/renderer.ts +22 -129
- package/src/org/renderer.ts +103 -170
- package/src/render.ts +39 -9
- package/src/sequence/renderer.ts +31 -151
- package/src/sitemap/layout.ts +180 -38
- package/src/sitemap/parser.ts +64 -23
- package/src/sitemap/renderer.ts +73 -161
- package/src/utils/legend-constants.ts +6 -0
- package/src/utils/legend-d3.ts +400 -0
- package/src/utils/legend-layout.ts +495 -0
- package/src/utils/legend-svg.ts +26 -0
- package/src/utils/legend-types.ts +169 -0
package/src/echarts.ts
CHANGED
|
@@ -113,20 +113,25 @@ import { parseDataRowValues } from './chart';
|
|
|
113
113
|
// Shared Constants
|
|
114
114
|
// ============================================================
|
|
115
115
|
|
|
116
|
-
const EMPHASIS_SELF = {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
itemStyle: {
|
|
121
|
-
borderWidth: 2,
|
|
122
|
-
borderColor: '#fff',
|
|
123
|
-
shadowBlur: 8,
|
|
124
|
-
shadowColor: 'rgba(0,0,0,0.4)',
|
|
125
|
-
},
|
|
116
|
+
const EMPHASIS_SELF = {
|
|
117
|
+
focus: 'self' as const,
|
|
118
|
+
blurScope: 'global' as const,
|
|
119
|
+
itemStyle: { opacity: 1 },
|
|
126
120
|
};
|
|
127
|
-
const
|
|
121
|
+
const EMPHASIS_SERIES = {
|
|
122
|
+
focus: 'series' as const,
|
|
123
|
+
blurScope: 'global' as const,
|
|
124
|
+
itemStyle: { opacity: 1 },
|
|
125
|
+
};
|
|
126
|
+
const BLUR_DIM = { itemStyle: { opacity: 0.15 }, lineStyle: { opacity: 0.15 } };
|
|
127
|
+
const EMPHASIS_LINE = { ...EMPHASIS_SELF };
|
|
128
|
+
const CHART_BASE: Pick<
|
|
129
|
+
EChartsOption,
|
|
130
|
+
'backgroundColor' | 'animation' | 'tooltip'
|
|
131
|
+
> = {
|
|
128
132
|
backgroundColor: 'transparent',
|
|
129
133
|
animation: false,
|
|
134
|
+
tooltip: { show: false },
|
|
130
135
|
};
|
|
131
136
|
const CHART_BORDER_WIDTH = 2;
|
|
132
137
|
|
|
@@ -698,11 +703,6 @@ function buildChartCommons(
|
|
|
698
703
|
},
|
|
699
704
|
}
|
|
700
705
|
: undefined;
|
|
701
|
-
const tooltipTheme = {
|
|
702
|
-
backgroundColor: palette.surface,
|
|
703
|
-
borderColor: palette.border,
|
|
704
|
-
textStyle: { color: palette.text },
|
|
705
|
-
};
|
|
706
706
|
return {
|
|
707
707
|
textColor,
|
|
708
708
|
axisLineColor,
|
|
@@ -710,7 +710,6 @@ function buildChartCommons(
|
|
|
710
710
|
gridOpacity,
|
|
711
711
|
colors,
|
|
712
712
|
titleConfig,
|
|
713
|
-
tooltipTheme,
|
|
714
713
|
};
|
|
715
714
|
}
|
|
716
715
|
|
|
@@ -729,37 +728,18 @@ export function buildExtendedChartOption(
|
|
|
729
728
|
return {};
|
|
730
729
|
}
|
|
731
730
|
|
|
732
|
-
const {
|
|
733
|
-
|
|
734
|
-
axisLineColor,
|
|
735
|
-
gridOpacity,
|
|
736
|
-
colors,
|
|
737
|
-
titleConfig,
|
|
738
|
-
tooltipTheme,
|
|
739
|
-
} = buildChartCommons(parsed, palette, isDark);
|
|
731
|
+
const { textColor, axisLineColor, gridOpacity, colors, titleConfig } =
|
|
732
|
+
buildChartCommons(parsed, palette, isDark);
|
|
740
733
|
|
|
741
734
|
// Sankey chart has different structure
|
|
742
735
|
if (parsed.type === 'sankey') {
|
|
743
|
-
return buildSankeyOption(
|
|
744
|
-
parsed,
|
|
745
|
-
textColor,
|
|
746
|
-
colors,
|
|
747
|
-
titleConfig,
|
|
748
|
-
tooltipTheme
|
|
749
|
-
);
|
|
736
|
+
return buildSankeyOption(parsed, textColor, colors, titleConfig);
|
|
750
737
|
}
|
|
751
738
|
|
|
752
739
|
// Chord diagram
|
|
753
740
|
if (parsed.type === 'chord') {
|
|
754
741
|
const bg = isDark ? palette.surface : palette.bg;
|
|
755
|
-
return buildChordOption(
|
|
756
|
-
parsed,
|
|
757
|
-
textColor,
|
|
758
|
-
colors,
|
|
759
|
-
bg,
|
|
760
|
-
titleConfig,
|
|
761
|
-
tooltipTheme
|
|
762
|
-
);
|
|
742
|
+
return buildChordOption(parsed, textColor, colors, bg, titleConfig);
|
|
763
743
|
}
|
|
764
744
|
|
|
765
745
|
// Function plot
|
|
@@ -771,8 +751,7 @@ export function buildExtendedChartOption(
|
|
|
771
751
|
axisLineColor,
|
|
772
752
|
gridOpacity,
|
|
773
753
|
colors,
|
|
774
|
-
titleConfig
|
|
775
|
-
tooltipTheme
|
|
754
|
+
titleConfig
|
|
776
755
|
);
|
|
777
756
|
}
|
|
778
757
|
|
|
@@ -787,22 +766,14 @@ export function buildExtendedChartOption(
|
|
|
787
766
|
gridOpacity,
|
|
788
767
|
colors,
|
|
789
768
|
bg,
|
|
790
|
-
titleConfig
|
|
791
|
-
tooltipTheme
|
|
769
|
+
titleConfig
|
|
792
770
|
);
|
|
793
771
|
}
|
|
794
772
|
|
|
795
773
|
// Funnel chart
|
|
796
774
|
if (parsed.type === 'funnel') {
|
|
797
775
|
const bg = isDark ? palette.surface : palette.bg;
|
|
798
|
-
return buildFunnelOption(
|
|
799
|
-
parsed,
|
|
800
|
-
textColor,
|
|
801
|
-
colors,
|
|
802
|
-
bg,
|
|
803
|
-
titleConfig,
|
|
804
|
-
tooltipTheme
|
|
805
|
-
);
|
|
776
|
+
return buildFunnelOption(parsed, textColor, colors, bg, titleConfig);
|
|
806
777
|
}
|
|
807
778
|
|
|
808
779
|
// Heatmap
|
|
@@ -812,8 +783,7 @@ export function buildExtendedChartOption(
|
|
|
812
783
|
isDark,
|
|
813
784
|
textColor,
|
|
814
785
|
axisLineColor,
|
|
815
|
-
titleConfig
|
|
816
|
-
tooltipTheme
|
|
786
|
+
titleConfig
|
|
817
787
|
);
|
|
818
788
|
}
|
|
819
789
|
|
|
@@ -824,8 +794,7 @@ function buildSankeyOption(
|
|
|
824
794
|
parsed: ParsedExtendedChart,
|
|
825
795
|
textColor: string,
|
|
826
796
|
colors: string[],
|
|
827
|
-
titleConfig: EChartsOption['title']
|
|
828
|
-
tooltipTheme: Record<string, unknown>
|
|
797
|
+
titleConfig: EChartsOption['title']
|
|
829
798
|
): EChartsOption {
|
|
830
799
|
// Extract unique nodes from links
|
|
831
800
|
const nodeSet = new Set<string>();
|
|
@@ -848,17 +817,15 @@ function buildSankeyOption(
|
|
|
848
817
|
title: titleConfig,
|
|
849
818
|
xAxis: { show: false },
|
|
850
819
|
yAxis: { show: false },
|
|
851
|
-
tooltip: {
|
|
852
|
-
show: false,
|
|
853
|
-
...tooltipTheme,
|
|
854
|
-
},
|
|
855
820
|
series: [
|
|
856
821
|
{
|
|
857
822
|
type: 'sankey',
|
|
858
823
|
emphasis: {
|
|
859
824
|
focus: 'adjacency',
|
|
860
825
|
blurScope: 'global' as const,
|
|
826
|
+
itemStyle: { opacity: 1 },
|
|
861
827
|
},
|
|
828
|
+
blur: BLUR_DIM,
|
|
862
829
|
nodeAlign: 'left',
|
|
863
830
|
nodeGap: 12,
|
|
864
831
|
nodeWidth: 20,
|
|
@@ -890,8 +857,7 @@ function buildChordOption(
|
|
|
890
857
|
textColor: string,
|
|
891
858
|
colors: string[],
|
|
892
859
|
bg: string,
|
|
893
|
-
titleConfig: EChartsOption['title']
|
|
894
|
-
tooltipTheme: Record<string, unknown>
|
|
860
|
+
titleConfig: EChartsOption['title']
|
|
895
861
|
): EChartsOption {
|
|
896
862
|
// Extract unique nodes from links
|
|
897
863
|
const nodeSet = new Set<string>();
|
|
@@ -936,19 +902,6 @@ function buildChordOption(
|
|
|
936
902
|
return {
|
|
937
903
|
...CHART_BASE,
|
|
938
904
|
title: titleConfig,
|
|
939
|
-
tooltip: {
|
|
940
|
-
trigger: 'item',
|
|
941
|
-
...tooltipTheme,
|
|
942
|
-
formatter: (params: unknown) => {
|
|
943
|
-
const p = params as {
|
|
944
|
-
data?: { source: string; target: string; value: number };
|
|
945
|
-
};
|
|
946
|
-
if (p.data && p.data.source && p.data.target) {
|
|
947
|
-
return `${p.data.source} → ${p.data.target}: ${p.data.value}`;
|
|
948
|
-
}
|
|
949
|
-
return '';
|
|
950
|
-
},
|
|
951
|
-
},
|
|
952
905
|
xAxis: { show: false },
|
|
953
906
|
yAxis: { show: false },
|
|
954
907
|
series: [
|
|
@@ -1013,11 +966,13 @@ function buildChordOption(
|
|
|
1013
966
|
},
|
|
1014
967
|
emphasis: {
|
|
1015
968
|
focus: 'adjacency',
|
|
969
|
+
itemStyle: { opacity: 1 },
|
|
1016
970
|
lineStyle: {
|
|
1017
971
|
width: 5,
|
|
1018
972
|
opacity: 1,
|
|
1019
973
|
},
|
|
1020
974
|
},
|
|
975
|
+
blur: BLUR_DIM,
|
|
1021
976
|
},
|
|
1022
977
|
],
|
|
1023
978
|
};
|
|
@@ -1062,8 +1017,7 @@ function buildFunctionOption(
|
|
|
1062
1017
|
axisLineColor: string,
|
|
1063
1018
|
gridOpacity: number,
|
|
1064
1019
|
colors: string[],
|
|
1065
|
-
titleConfig: EChartsOption['title']
|
|
1066
|
-
tooltipTheme: Record<string, unknown>
|
|
1020
|
+
titleConfig: EChartsOption['title']
|
|
1067
1021
|
): EChartsOption {
|
|
1068
1022
|
const xRange = parsed.xRange ?? { min: -10, max: 10 };
|
|
1069
1023
|
const samples = 200;
|
|
@@ -1103,19 +1057,13 @@ function buildFunctionOption(
|
|
|
1103
1057
|
},
|
|
1104
1058
|
}),
|
|
1105
1059
|
emphasis: EMPHASIS_SELF,
|
|
1060
|
+
blur: BLUR_DIM,
|
|
1106
1061
|
};
|
|
1107
1062
|
});
|
|
1108
1063
|
|
|
1109
1064
|
return {
|
|
1110
1065
|
...CHART_BASE,
|
|
1111
1066
|
title: titleConfig,
|
|
1112
|
-
tooltip: {
|
|
1113
|
-
trigger: 'axis',
|
|
1114
|
-
...tooltipTheme,
|
|
1115
|
-
axisPointer: {
|
|
1116
|
-
type: 'cross',
|
|
1117
|
-
},
|
|
1118
|
-
},
|
|
1119
1067
|
legend: {
|
|
1120
1068
|
data: (parsed.functions ?? []).map((fn) => fn.name),
|
|
1121
1069
|
bottom: 10,
|
|
@@ -1499,8 +1447,7 @@ function buildScatterOption(
|
|
|
1499
1447
|
gridOpacity: number,
|
|
1500
1448
|
colors: string[],
|
|
1501
1449
|
bg: string,
|
|
1502
|
-
titleConfig: EChartsOption['title']
|
|
1503
|
-
tooltipTheme: Record<string, unknown>
|
|
1450
|
+
titleConfig: EChartsOption['title']
|
|
1504
1451
|
): EChartsOption {
|
|
1505
1452
|
const points = parsed.scatterPoints ?? [];
|
|
1506
1453
|
const defaultSize = 15;
|
|
@@ -1522,11 +1469,9 @@ function buildScatterOption(
|
|
|
1522
1469
|
|
|
1523
1470
|
const emphasisConfig = {
|
|
1524
1471
|
focus: 'self' as const,
|
|
1525
|
-
itemStyle: {
|
|
1526
|
-
shadowBlur: 10,
|
|
1527
|
-
shadowColor: 'rgba(0, 0, 0, 0.3)',
|
|
1528
|
-
},
|
|
1472
|
+
itemStyle: { opacity: 1 },
|
|
1529
1473
|
};
|
|
1474
|
+
const blurConfig = BLUR_DIM;
|
|
1530
1475
|
|
|
1531
1476
|
// Build series based on whether categories are present
|
|
1532
1477
|
let series;
|
|
@@ -1567,6 +1512,7 @@ function buildScatterOption(
|
|
|
1567
1512
|
},
|
|
1568
1513
|
label: labelConfig,
|
|
1569
1514
|
emphasis: emphasisConfig,
|
|
1515
|
+
blur: blurConfig,
|
|
1570
1516
|
};
|
|
1571
1517
|
});
|
|
1572
1518
|
} else {
|
|
@@ -1593,30 +1539,11 @@ function buildScatterOption(
|
|
|
1593
1539
|
data,
|
|
1594
1540
|
label: labelConfig,
|
|
1595
1541
|
emphasis: emphasisConfig,
|
|
1542
|
+
blur: blurConfig,
|
|
1596
1543
|
},
|
|
1597
1544
|
];
|
|
1598
1545
|
}
|
|
1599
1546
|
|
|
1600
|
-
// Tooltip adapts to available data
|
|
1601
|
-
const tooltip = {
|
|
1602
|
-
trigger: 'item' as const,
|
|
1603
|
-
...tooltipTheme,
|
|
1604
|
-
formatter: (params: unknown) => {
|
|
1605
|
-
const p = params as {
|
|
1606
|
-
seriesName: string;
|
|
1607
|
-
name: string;
|
|
1608
|
-
value: number[];
|
|
1609
|
-
};
|
|
1610
|
-
const xLabel = parsed.xlabel || 'x';
|
|
1611
|
-
const yLabel = parsed.ylabel || 'y';
|
|
1612
|
-
let html = `<strong>${p.name}</strong>`;
|
|
1613
|
-
if (hasCategories) html += `<br/>${p.seriesName}`;
|
|
1614
|
-
html += `<br/>${xLabel}: ${p.value[0]}<br/>${yLabel}: ${p.value[1]}`;
|
|
1615
|
-
if (hasSize) html += `<br/>${parsed.sizelabel || 'size'}: ${p.value[2]}`;
|
|
1616
|
-
return html;
|
|
1617
|
-
},
|
|
1618
|
-
};
|
|
1619
|
-
|
|
1620
1547
|
// Auto-fit axes to data range with ~10% padding
|
|
1621
1548
|
const xValues = points.map((p) => p.x);
|
|
1622
1549
|
const yValues = points.map((p) => p.y);
|
|
@@ -1716,7 +1643,6 @@ function buildScatterOption(
|
|
|
1716
1643
|
...CHART_BASE,
|
|
1717
1644
|
title: titleConfig,
|
|
1718
1645
|
...(legendConfig && { legend: legendConfig }),
|
|
1719
|
-
tooltip,
|
|
1720
1646
|
grid: {
|
|
1721
1647
|
left: `${gridLeft}%`,
|
|
1722
1648
|
right: `${gridRight}%`,
|
|
@@ -1788,8 +1714,7 @@ function buildHeatmapOption(
|
|
|
1788
1714
|
isDark: boolean,
|
|
1789
1715
|
textColor: string,
|
|
1790
1716
|
axisLineColor: string,
|
|
1791
|
-
titleConfig: EChartsOption['title']
|
|
1792
|
-
tooltipTheme: Record<string, unknown>
|
|
1717
|
+
titleConfig: EChartsOption['title']
|
|
1793
1718
|
): EChartsOption {
|
|
1794
1719
|
const bg = isDark ? palette.surface : palette.bg;
|
|
1795
1720
|
const heatmapRows = parsed.heatmapRows ?? [];
|
|
@@ -1812,16 +1737,6 @@ function buildHeatmapOption(
|
|
|
1812
1737
|
return {
|
|
1813
1738
|
...CHART_BASE,
|
|
1814
1739
|
title: titleConfig,
|
|
1815
|
-
tooltip: {
|
|
1816
|
-
trigger: 'item',
|
|
1817
|
-
...tooltipTheme,
|
|
1818
|
-
formatter: (params: unknown) => {
|
|
1819
|
-
const p = params as { data: [number, number, number] };
|
|
1820
|
-
const colName = columns[p.data[0]] ?? p.data[0];
|
|
1821
|
-
const rowName = rowLabels[p.data[1]] ?? p.data[1];
|
|
1822
|
-
return `${rowName} / ${colName}: <strong>${p.data[2]}</strong>`;
|
|
1823
|
-
},
|
|
1824
|
-
},
|
|
1825
1740
|
grid: {
|
|
1826
1741
|
left: '3%',
|
|
1827
1742
|
right: '10%',
|
|
@@ -1892,11 +1807,8 @@ function buildHeatmapOption(
|
|
|
1892
1807
|
},
|
|
1893
1808
|
emphasis: {
|
|
1894
1809
|
...EMPHASIS_SELF,
|
|
1895
|
-
itemStyle: {
|
|
1896
|
-
shadowBlur: 10,
|
|
1897
|
-
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
1898
|
-
},
|
|
1899
1810
|
},
|
|
1811
|
+
blur: BLUR_DIM,
|
|
1900
1812
|
},
|
|
1901
1813
|
],
|
|
1902
1814
|
};
|
|
@@ -1910,12 +1822,10 @@ function buildFunnelOption(
|
|
|
1910
1822
|
textColor: string,
|
|
1911
1823
|
colors: string[],
|
|
1912
1824
|
bg: string,
|
|
1913
|
-
titleConfig: EChartsOption['title']
|
|
1914
|
-
tooltipTheme: Record<string, unknown>
|
|
1825
|
+
titleConfig: EChartsOption['title']
|
|
1915
1826
|
): EChartsOption {
|
|
1916
1827
|
// Sort data descending by value for funnel ordering
|
|
1917
1828
|
const sorted = [...parsed.data].sort((a, b) => b.value - a.value);
|
|
1918
|
-
const topValue = sorted.length > 0 ? sorted[0].value : 1;
|
|
1919
1829
|
|
|
1920
1830
|
const data = sorted.map((d) => {
|
|
1921
1831
|
const stroke = d.color ?? colors[parsed.data.indexOf(d) % colors.length];
|
|
@@ -1955,25 +1865,6 @@ function buildFunnelOption(
|
|
|
1955
1865
|
title: titleConfig,
|
|
1956
1866
|
xAxis: { show: false },
|
|
1957
1867
|
yAxis: { show: false },
|
|
1958
|
-
tooltip: {
|
|
1959
|
-
trigger: 'item',
|
|
1960
|
-
...tooltipTheme,
|
|
1961
|
-
formatter: (params: unknown) => {
|
|
1962
|
-
const p = params as { name: string; value: number; dataIndex: number };
|
|
1963
|
-
const val = p.value;
|
|
1964
|
-
const prev = prevValueMap.get(p.name) ?? val;
|
|
1965
|
-
const isFirst = p.dataIndex === 0;
|
|
1966
|
-
if (isFirst) return '';
|
|
1967
|
-
const parts: string[] = [];
|
|
1968
|
-
const stepDrop = ((1 - val / prev) * 100).toFixed(1);
|
|
1969
|
-
parts.push(`Step drop-off: ${stepDrop}%`);
|
|
1970
|
-
if (topValue > 0) {
|
|
1971
|
-
const totalDrop = ((1 - val / topValue) * 100).toFixed(1);
|
|
1972
|
-
parts.push(`Overall drop-off: ${totalDrop}%`);
|
|
1973
|
-
}
|
|
1974
|
-
return parts.join('<br/>');
|
|
1975
|
-
},
|
|
1976
|
-
},
|
|
1977
1868
|
series: [
|
|
1978
1869
|
{
|
|
1979
1870
|
type: 'funnel',
|
|
@@ -1992,10 +1883,8 @@ function buildFunnelOption(
|
|
|
1992
1883
|
},
|
|
1993
1884
|
emphasis: {
|
|
1994
1885
|
...EMPHASIS_SELF,
|
|
1995
|
-
label: {
|
|
1996
|
-
fontSize: 15,
|
|
1997
|
-
},
|
|
1998
1886
|
},
|
|
1887
|
+
blur: BLUR_DIM,
|
|
1999
1888
|
data,
|
|
2000
1889
|
},
|
|
2001
1890
|
{
|
|
@@ -2144,7 +2033,6 @@ export function buildSimpleChartOption(
|
|
|
2144
2033
|
gridOpacity,
|
|
2145
2034
|
colors,
|
|
2146
2035
|
titleConfig,
|
|
2147
|
-
tooltipTheme,
|
|
2148
2036
|
} = buildChartCommons(parsed, palette, isDark);
|
|
2149
2037
|
const bg = isDark ? palette.surface : palette.bg;
|
|
2150
2038
|
|
|
@@ -2159,7 +2047,6 @@ export function buildSimpleChartOption(
|
|
|
2159
2047
|
colors,
|
|
2160
2048
|
bg,
|
|
2161
2049
|
titleConfig,
|
|
2162
|
-
tooltipTheme,
|
|
2163
2050
|
chartWidth
|
|
2164
2051
|
);
|
|
2165
2052
|
case 'bar-stacked':
|
|
@@ -2172,7 +2059,6 @@ export function buildSimpleChartOption(
|
|
|
2172
2059
|
colors,
|
|
2173
2060
|
bg,
|
|
2174
2061
|
titleConfig,
|
|
2175
|
-
tooltipTheme,
|
|
2176
2062
|
chartWidth
|
|
2177
2063
|
);
|
|
2178
2064
|
case 'line':
|
|
@@ -2186,7 +2072,6 @@ export function buildSimpleChartOption(
|
|
|
2186
2072
|
gridOpacity,
|
|
2187
2073
|
colors,
|
|
2188
2074
|
titleConfig,
|
|
2189
|
-
tooltipTheme,
|
|
2190
2075
|
chartWidth
|
|
2191
2076
|
)
|
|
2192
2077
|
: buildLineOption(
|
|
@@ -2197,7 +2082,6 @@ export function buildSimpleChartOption(
|
|
|
2197
2082
|
splitLineColor,
|
|
2198
2083
|
gridOpacity,
|
|
2199
2084
|
titleConfig,
|
|
2200
|
-
tooltipTheme,
|
|
2201
2085
|
chartWidth
|
|
2202
2086
|
);
|
|
2203
2087
|
case 'area':
|
|
@@ -2209,7 +2093,6 @@ export function buildSimpleChartOption(
|
|
|
2209
2093
|
splitLineColor,
|
|
2210
2094
|
gridOpacity,
|
|
2211
2095
|
titleConfig,
|
|
2212
|
-
tooltipTheme,
|
|
2213
2096
|
chartWidth
|
|
2214
2097
|
);
|
|
2215
2098
|
case 'pie':
|
|
@@ -2219,7 +2102,6 @@ export function buildSimpleChartOption(
|
|
|
2219
2102
|
getSegmentColors(palette, parsed.data.length),
|
|
2220
2103
|
bg,
|
|
2221
2104
|
titleConfig,
|
|
2222
|
-
tooltipTheme,
|
|
2223
2105
|
false
|
|
2224
2106
|
);
|
|
2225
2107
|
case 'doughnut':
|
|
@@ -2229,7 +2111,6 @@ export function buildSimpleChartOption(
|
|
|
2229
2111
|
getSegmentColors(palette, parsed.data.length),
|
|
2230
2112
|
bg,
|
|
2231
2113
|
titleConfig,
|
|
2232
|
-
tooltipTheme,
|
|
2233
2114
|
true
|
|
2234
2115
|
);
|
|
2235
2116
|
case 'radar':
|
|
@@ -2239,8 +2120,7 @@ export function buildSimpleChartOption(
|
|
|
2239
2120
|
isDark,
|
|
2240
2121
|
textColor,
|
|
2241
2122
|
gridOpacity,
|
|
2242
|
-
titleConfig
|
|
2243
|
-
tooltipTheme
|
|
2123
|
+
titleConfig
|
|
2244
2124
|
);
|
|
2245
2125
|
case 'polar-area':
|
|
2246
2126
|
return buildPolarAreaOption(
|
|
@@ -2248,8 +2128,7 @@ export function buildSimpleChartOption(
|
|
|
2248
2128
|
textColor,
|
|
2249
2129
|
getSegmentColors(palette, parsed.data.length),
|
|
2250
2130
|
bg,
|
|
2251
|
-
titleConfig
|
|
2252
|
-
tooltipTheme
|
|
2131
|
+
titleConfig
|
|
2253
2132
|
);
|
|
2254
2133
|
}
|
|
2255
2134
|
}
|
|
@@ -2262,9 +2141,11 @@ function makeChartGrid(options: {
|
|
|
2262
2141
|
yLabel?: string;
|
|
2263
2142
|
hasTitle: boolean;
|
|
2264
2143
|
hasLegend?: boolean;
|
|
2144
|
+
isHorizontal?: boolean;
|
|
2265
2145
|
}): Record<string, unknown> {
|
|
2146
|
+
const left = options.yLabel ? '12%' : '3%';
|
|
2266
2147
|
return {
|
|
2267
|
-
left
|
|
2148
|
+
left,
|
|
2268
2149
|
right: '4%',
|
|
2269
2150
|
bottom: options.hasLegend ? '15%' : options.xLabel ? '10%' : '3%',
|
|
2270
2151
|
top: options.hasTitle ? '15%' : '5%',
|
|
@@ -2272,6 +2153,23 @@ function makeChartGrid(options: {
|
|
|
2272
2153
|
};
|
|
2273
2154
|
}
|
|
2274
2155
|
|
|
2156
|
+
/** Wrap a label string at word boundaries to fit within `maxChars` per line. */
|
|
2157
|
+
function wrapLabel(text: string, maxChars: number): string {
|
|
2158
|
+
const words = text.split(' ');
|
|
2159
|
+
const lines: string[] = [];
|
|
2160
|
+
let current = '';
|
|
2161
|
+
for (const word of words) {
|
|
2162
|
+
if (current && current.length + 1 + word.length > maxChars) {
|
|
2163
|
+
lines.push(current);
|
|
2164
|
+
current = word;
|
|
2165
|
+
} else {
|
|
2166
|
+
current = current ? current + ' ' + word : word;
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
if (current) lines.push(current);
|
|
2170
|
+
return lines.join('\n');
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2275
2173
|
// ── Bar ──────────────────────────────────────────────────────
|
|
2276
2174
|
|
|
2277
2175
|
function buildBarOption(
|
|
@@ -2283,7 +2181,6 @@ function buildBarOption(
|
|
|
2283
2181
|
colors: string[],
|
|
2284
2182
|
bg: string,
|
|
2285
2183
|
titleConfig: EChartsOption['title'],
|
|
2286
|
-
tooltipTheme: Record<string, unknown>,
|
|
2287
2184
|
chartWidth?: number
|
|
2288
2185
|
): EChartsOption {
|
|
2289
2186
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
@@ -2301,12 +2198,16 @@ function buildBarOption(
|
|
|
2301
2198
|
};
|
|
2302
2199
|
});
|
|
2303
2200
|
|
|
2304
|
-
//
|
|
2305
|
-
//
|
|
2201
|
+
// For horizontal bars, wrap long category labels at word boundaries so they
|
|
2202
|
+
// don't consume too much horizontal space on the y-axis.
|
|
2203
|
+
const catLabels = isHorizontal ? labels.map((l) => wrapLabel(l, 12)) : labels;
|
|
2204
|
+
|
|
2205
|
+
// Compute the max visible line width after wrapping for nameGap calculation.
|
|
2206
|
+
const maxVisibleLen = Math.max(
|
|
2207
|
+
...catLabels.map((l) => Math.max(...l.split('\n').map((seg) => seg.length)))
|
|
2208
|
+
);
|
|
2306
2209
|
const hCatGap =
|
|
2307
|
-
isHorizontal && yLabel
|
|
2308
|
-
? Math.max(40, Math.max(...labels.map((l) => l.length)) * 8 + 16)
|
|
2309
|
-
: undefined;
|
|
2210
|
+
isHorizontal && yLabel ? Math.max(40, maxVisibleLen * 8 + 16) : undefined;
|
|
2310
2211
|
const categoryAxis = makeGridAxis(
|
|
2311
2212
|
'category',
|
|
2312
2213
|
textColor,
|
|
@@ -2314,17 +2215,22 @@ function buildBarOption(
|
|
|
2314
2215
|
splitLineColor,
|
|
2315
2216
|
gridOpacity,
|
|
2316
2217
|
isHorizontal ? yLabel : xLabel,
|
|
2317
|
-
|
|
2218
|
+
catLabels,
|
|
2318
2219
|
hCatGap,
|
|
2319
2220
|
!isHorizontal ? chartWidth : undefined
|
|
2320
2221
|
);
|
|
2222
|
+
// For horizontal bars, the xlabel sits on the value axis (bottom).
|
|
2223
|
+
// Use a moderate nameGap so it doesn't drift.
|
|
2224
|
+
const hValueGap = isHorizontal && xLabel ? 40 : undefined;
|
|
2321
2225
|
const valueAxis = makeGridAxis(
|
|
2322
2226
|
'value',
|
|
2323
2227
|
textColor,
|
|
2324
2228
|
axisLineColor,
|
|
2325
2229
|
splitLineColor,
|
|
2326
2230
|
gridOpacity,
|
|
2327
|
-
isHorizontal ? xLabel : yLabel
|
|
2231
|
+
isHorizontal ? xLabel : yLabel,
|
|
2232
|
+
undefined,
|
|
2233
|
+
hValueGap
|
|
2328
2234
|
);
|
|
2329
2235
|
|
|
2330
2236
|
// xAxis is always the bottom axis, yAxis is always the left axis in ECharts
|
|
@@ -2332,14 +2238,20 @@ function buildBarOption(
|
|
|
2332
2238
|
return {
|
|
2333
2239
|
...CHART_BASE,
|
|
2334
2240
|
title: titleConfig,
|
|
2335
|
-
grid: makeChartGrid({
|
|
2241
|
+
grid: makeChartGrid({
|
|
2242
|
+
xLabel,
|
|
2243
|
+
yLabel,
|
|
2244
|
+
hasTitle: !!parsed.title,
|
|
2245
|
+
isHorizontal,
|
|
2246
|
+
}),
|
|
2336
2247
|
xAxis: isHorizontal ? valueAxis : categoryAxis,
|
|
2337
|
-
yAxis: isHorizontal ? categoryAxis : valueAxis,
|
|
2248
|
+
yAxis: isHorizontal ? { ...categoryAxis, inverse: true } : valueAxis,
|
|
2338
2249
|
series: [
|
|
2339
2250
|
{
|
|
2340
2251
|
type: 'bar',
|
|
2341
2252
|
data,
|
|
2342
2253
|
emphasis: EMPHASIS_SELF,
|
|
2254
|
+
blur: BLUR_DIM,
|
|
2343
2255
|
},
|
|
2344
2256
|
],
|
|
2345
2257
|
};
|
|
@@ -2369,7 +2281,7 @@ function buildMarkArea(
|
|
|
2369
2281
|
if (eras.length === 0) return undefined;
|
|
2370
2282
|
return {
|
|
2371
2283
|
silent: false,
|
|
2372
|
-
tooltip: { show:
|
|
2284
|
+
tooltip: { show: false },
|
|
2373
2285
|
data: eras.map((era) => {
|
|
2374
2286
|
const startIdx = labels.indexOf(era.start);
|
|
2375
2287
|
const endIdx = labels.indexOf(era.end);
|
|
@@ -2404,7 +2316,6 @@ function buildLineOption(
|
|
|
2404
2316
|
splitLineColor: string,
|
|
2405
2317
|
gridOpacity: number,
|
|
2406
2318
|
titleConfig: EChartsOption['title'],
|
|
2407
|
-
tooltipTheme: Record<string, unknown>,
|
|
2408
2319
|
chartWidth?: number
|
|
2409
2320
|
): EChartsOption {
|
|
2410
2321
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
@@ -2419,11 +2330,6 @@ function buildLineOption(
|
|
|
2419
2330
|
return {
|
|
2420
2331
|
...CHART_BASE,
|
|
2421
2332
|
title: titleConfig,
|
|
2422
|
-
tooltip: {
|
|
2423
|
-
trigger: 'axis',
|
|
2424
|
-
...tooltipTheme,
|
|
2425
|
-
axisPointer: { type: 'line' },
|
|
2426
|
-
},
|
|
2427
2333
|
grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
|
|
2428
2334
|
xAxis: makeGridAxis(
|
|
2429
2335
|
'category',
|
|
@@ -2454,6 +2360,7 @@ function buildLineOption(
|
|
|
2454
2360
|
lineStyle: { color: lineColor, width: 3 },
|
|
2455
2361
|
itemStyle: { color: lineColor },
|
|
2456
2362
|
emphasis: EMPHASIS_LINE,
|
|
2363
|
+
blur: BLUR_DIM,
|
|
2457
2364
|
...(markArea && { markArea }),
|
|
2458
2365
|
},
|
|
2459
2366
|
],
|
|
@@ -2471,7 +2378,6 @@ function buildMultiLineOption(
|
|
|
2471
2378
|
gridOpacity: number,
|
|
2472
2379
|
colors: string[],
|
|
2473
2380
|
titleConfig: EChartsOption['title'],
|
|
2474
|
-
tooltipTheme: Record<string, unknown>,
|
|
2475
2381
|
chartWidth?: number
|
|
2476
2382
|
): EChartsOption {
|
|
2477
2383
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
@@ -2495,6 +2401,7 @@ function buildMultiLineOption(
|
|
|
2495
2401
|
lineStyle: { color, width: 3 },
|
|
2496
2402
|
itemStyle: { color },
|
|
2497
2403
|
emphasis: EMPHASIS_LINE,
|
|
2404
|
+
blur: BLUR_DIM,
|
|
2498
2405
|
...(idx === 0 && markArea && { markArea }),
|
|
2499
2406
|
};
|
|
2500
2407
|
});
|
|
@@ -2502,11 +2409,6 @@ function buildMultiLineOption(
|
|
|
2502
2409
|
return {
|
|
2503
2410
|
...CHART_BASE,
|
|
2504
2411
|
title: titleConfig,
|
|
2505
|
-
tooltip: {
|
|
2506
|
-
trigger: 'axis',
|
|
2507
|
-
...tooltipTheme,
|
|
2508
|
-
axisPointer: { type: 'line' },
|
|
2509
|
-
},
|
|
2510
2412
|
legend: {
|
|
2511
2413
|
data: seriesNames,
|
|
2512
2414
|
bottom: 10,
|
|
@@ -2552,7 +2454,6 @@ function buildAreaOption(
|
|
|
2552
2454
|
splitLineColor: string,
|
|
2553
2455
|
gridOpacity: number,
|
|
2554
2456
|
titleConfig: EChartsOption['title'],
|
|
2555
|
-
tooltipTheme: Record<string, unknown>,
|
|
2556
2457
|
chartWidth?: number
|
|
2557
2458
|
): EChartsOption {
|
|
2558
2459
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
@@ -2567,11 +2468,6 @@ function buildAreaOption(
|
|
|
2567
2468
|
return {
|
|
2568
2469
|
...CHART_BASE,
|
|
2569
2470
|
title: titleConfig,
|
|
2570
|
-
tooltip: {
|
|
2571
|
-
trigger: 'axis',
|
|
2572
|
-
...tooltipTheme,
|
|
2573
|
-
axisPointer: { type: 'line' },
|
|
2574
|
-
},
|
|
2575
2471
|
grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
|
|
2576
2472
|
xAxis: makeGridAxis(
|
|
2577
2473
|
'category',
|
|
@@ -2603,6 +2499,7 @@ function buildAreaOption(
|
|
|
2603
2499
|
itemStyle: { color: lineColor },
|
|
2604
2500
|
areaStyle: { opacity: 0.25 },
|
|
2605
2501
|
emphasis: EMPHASIS_LINE,
|
|
2502
|
+
blur: BLUR_DIM,
|
|
2606
2503
|
...(markArea && { markArea }),
|
|
2607
2504
|
},
|
|
2608
2505
|
],
|
|
@@ -2665,7 +2562,6 @@ function buildPieOption(
|
|
|
2665
2562
|
colors: string[],
|
|
2666
2563
|
bg: string,
|
|
2667
2564
|
titleConfig: EChartsOption['title'],
|
|
2668
|
-
tooltipTheme: Record<string, unknown>,
|
|
2669
2565
|
isDoughnut: boolean
|
|
2670
2566
|
): EChartsOption {
|
|
2671
2567
|
const HIDE_AXES = { xAxis: { show: false }, yAxis: { show: false } };
|
|
@@ -2688,10 +2584,6 @@ function buildPieOption(
|
|
|
2688
2584
|
...CHART_BASE,
|
|
2689
2585
|
...HIDE_AXES,
|
|
2690
2586
|
title: titleConfig,
|
|
2691
|
-
tooltip: {
|
|
2692
|
-
trigger: 'item',
|
|
2693
|
-
...tooltipTheme,
|
|
2694
|
-
},
|
|
2695
2587
|
series: [
|
|
2696
2588
|
{
|
|
2697
2589
|
type: 'pie',
|
|
@@ -2708,6 +2600,7 @@ function buildPieOption(
|
|
|
2708
2600
|
},
|
|
2709
2601
|
labelLine: { show: true },
|
|
2710
2602
|
emphasis: EMPHASIS_SELF,
|
|
2603
|
+
blur: BLUR_DIM,
|
|
2711
2604
|
},
|
|
2712
2605
|
],
|
|
2713
2606
|
};
|
|
@@ -2721,8 +2614,7 @@ function buildRadarOption(
|
|
|
2721
2614
|
isDark: boolean,
|
|
2722
2615
|
textColor: string,
|
|
2723
2616
|
gridOpacity: number,
|
|
2724
|
-
titleConfig: EChartsOption['title']
|
|
2725
|
-
tooltipTheme: Record<string, unknown>
|
|
2617
|
+
titleConfig: EChartsOption['title']
|
|
2726
2618
|
): EChartsOption {
|
|
2727
2619
|
const bg = isDark ? palette.surface : palette.bg;
|
|
2728
2620
|
const radarColor =
|
|
@@ -2740,10 +2632,6 @@ function buildRadarOption(
|
|
|
2740
2632
|
title: titleConfig,
|
|
2741
2633
|
xAxis: { show: false },
|
|
2742
2634
|
yAxis: { show: false },
|
|
2743
|
-
tooltip: {
|
|
2744
|
-
trigger: 'item',
|
|
2745
|
-
...tooltipTheme,
|
|
2746
|
-
},
|
|
2747
2635
|
radar: {
|
|
2748
2636
|
indicator,
|
|
2749
2637
|
axisName: {
|
|
@@ -2781,6 +2669,7 @@ function buildRadarOption(
|
|
|
2781
2669
|
},
|
|
2782
2670
|
],
|
|
2783
2671
|
emphasis: EMPHASIS_SELF,
|
|
2672
|
+
blur: BLUR_DIM,
|
|
2784
2673
|
},
|
|
2785
2674
|
],
|
|
2786
2675
|
};
|
|
@@ -2793,8 +2682,7 @@ function buildPolarAreaOption(
|
|
|
2793
2682
|
textColor: string,
|
|
2794
2683
|
colors: string[],
|
|
2795
2684
|
bg: string,
|
|
2796
|
-
titleConfig: EChartsOption['title']
|
|
2797
|
-
tooltipTheme: Record<string, unknown>
|
|
2685
|
+
titleConfig: EChartsOption['title']
|
|
2798
2686
|
): EChartsOption {
|
|
2799
2687
|
const data = parsed.data.map((d, i) => {
|
|
2800
2688
|
const stroke = d.color ?? colors[i % colors.length];
|
|
@@ -2814,10 +2702,6 @@ function buildPolarAreaOption(
|
|
|
2814
2702
|
title: titleConfig,
|
|
2815
2703
|
xAxis: { show: false },
|
|
2816
2704
|
yAxis: { show: false },
|
|
2817
|
-
tooltip: {
|
|
2818
|
-
trigger: 'item',
|
|
2819
|
-
...tooltipTheme,
|
|
2820
|
-
},
|
|
2821
2705
|
series: [
|
|
2822
2706
|
{
|
|
2823
2707
|
type: 'pie',
|
|
@@ -2836,6 +2720,7 @@ function buildPolarAreaOption(
|
|
|
2836
2720
|
},
|
|
2837
2721
|
labelLine: { show: true },
|
|
2838
2722
|
emphasis: EMPHASIS_SELF,
|
|
2723
|
+
blur: BLUR_DIM,
|
|
2839
2724
|
},
|
|
2840
2725
|
],
|
|
2841
2726
|
};
|
|
@@ -2852,7 +2737,6 @@ function buildBarStackedOption(
|
|
|
2852
2737
|
colors: string[],
|
|
2853
2738
|
bg: string,
|
|
2854
2739
|
titleConfig: EChartsOption['title'],
|
|
2855
|
-
tooltipTheme: Record<string, unknown>,
|
|
2856
2740
|
chartWidth?: number
|
|
2857
2741
|
): EChartsOption {
|
|
2858
2742
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
@@ -2884,7 +2768,8 @@ function buildBarStackedOption(
|
|
|
2884
2768
|
fontWeight: 'bold' as const,
|
|
2885
2769
|
fontFamily: FONT_FAMILY,
|
|
2886
2770
|
},
|
|
2887
|
-
emphasis:
|
|
2771
|
+
emphasis: EMPHASIS_SERIES,
|
|
2772
|
+
blur: BLUR_DIM,
|
|
2888
2773
|
};
|
|
2889
2774
|
});
|
|
2890
2775
|
|
|
@@ -2932,7 +2817,7 @@ function buildBarStackedOption(
|
|
|
2932
2817
|
hasLegend: true,
|
|
2933
2818
|
}),
|
|
2934
2819
|
xAxis: isHorizontal ? valueAxis : categoryAxis,
|
|
2935
|
-
yAxis: isHorizontal ? categoryAxis : valueAxis,
|
|
2820
|
+
yAxis: isHorizontal ? { ...categoryAxis, inverse: true } : valueAxis,
|
|
2936
2821
|
series,
|
|
2937
2822
|
};
|
|
2938
2823
|
}
|