@visionaris-bruno/vs-echarts 7.2.0 → 8.1.0

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.
@@ -1,7 +1,7 @@
1
1
  import { provideEchartsCore, NgxEchartsDirective } from 'ngx-echarts';
2
2
  import * as echarts from 'echarts/core';
3
3
  import { BarChart, PieChart, LineChart, ScatterChart, FunnelChart, SunburstChart } from 'echarts/charts';
4
- import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GraphicComponent, ToolboxComponent, PolarComponent } from 'echarts/components';
4
+ import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GraphicComponent, ToolboxComponent, PolarComponent, DatasetComponent } from 'echarts/components';
5
5
  import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
6
6
  import * as i0 from '@angular/core';
7
7
  import { EventEmitter, Output, Input, ViewChild, Directive, Component } from '@angular/core';
@@ -75,6 +75,7 @@ function initializeEcharts() {
75
75
  GraphicComponent,
76
76
  ToolboxComponent,
77
77
  PolarComponent,
78
+ DatasetComponent,
78
79
  ]);
79
80
  initialized = true;
80
81
  }
@@ -175,7 +176,7 @@ function defaultOptionsOverrides() {
175
176
  class BaseEchartsComponent {
176
177
  chartContainer;
177
178
  /** Datos normalizados para graficar */
178
- data = { categories: [], series: [] };
179
+ data = { dimensions: [], source: [] };
179
180
  optionsOverrides = defaultOptionsOverrides();
180
181
  /** Paleta de colores básica */
181
182
  palette;
@@ -406,12 +407,12 @@ function getLegendOptions(overrides) {
406
407
  return merge({}, defaults, overrides);
407
408
  }
408
409
  function getCategoryAxisOptions(overrides) {
409
- const categories = resolveCategoryNames(overrides?.data);
410
- const autoRotate = categories.length > 10 ? 45 : 0;
410
+ const categories = overrides?.data ? overrides.data.map(c => typeof c === 'string' ? c : (c?.name || String(c))) : undefined;
411
+ const autoRotate = categories && categories.length > 10 ? 45 : 0;
411
412
  const defaults = {
412
413
  type: 'category',
413
414
  triggerEvent: true,
414
- data: categories,
415
+ ...(categories ? { data: categories } : {}),
415
416
  axisLabel: {
416
417
  rotate: autoRotate,
417
418
  interval: 0,
@@ -429,7 +430,7 @@ function getCategoryAxisOptions(overrides) {
429
430
  }
430
431
  }
431
432
  };
432
- return merge({}, defaults, { ...overrides, data: categories });
433
+ return merge({}, defaults, overrides);
433
434
  }
434
435
  function getValueAxisOptions(overrides) {
435
436
  const defaults = {
@@ -598,12 +599,11 @@ function applyLineSelectionStyle(series, selectedCategoryIndex, selectedSeriesIn
598
599
  /**
599
600
  * Resolves the unique key of a category safely.
600
601
  */
601
- function getCategoryKey(categories, index) {
602
- if (!categories || !categories[index]) {
602
+ function getCategoryKey(dimensions, index) {
603
+ if (!dimensions || !dimensions[index]) {
603
604
  return String(index);
604
605
  }
605
- const node = categories[index];
606
- return node.key || node.name || String(index);
606
+ return dimensions[index].name;
607
607
  }
608
608
  /**
609
609
  * Resolves the numeric value from a series data point.
@@ -613,126 +613,35 @@ function getCellValue(val) {
613
613
  return 0;
614
614
  return val;
615
615
  }
616
- function flattenCategoriesToFirstLevel(categories) {
617
- if (!categories)
618
- return [];
619
- return categories.map(cat => ({
620
- name: cat.name,
621
- key: cat.key
622
- }));
623
- }
624
- function getLeafIndicesMap(categories) {
625
- let leafCount = 0;
626
- const topLevelLeaves = [];
627
- const countLeaves = (node) => {
628
- if (!node.children || node.children.length === 0) {
629
- return 1;
630
- }
631
- let sum = 0;
632
- for (const child of node.children) {
633
- sum += countLeaves(child);
634
- }
635
- return sum;
636
- };
637
- for (const cat of categories) {
638
- const leavesUnderCat = countLeaves(cat);
639
- topLevelLeaves.push({
640
- start: leafCount,
641
- end: leafCount + leavesUnderCat
642
- });
643
- leafCount += leavesUnderCat;
644
- }
645
- return {
646
- topLevelLeaves,
647
- totalLeaves: leafCount
648
- };
649
- }
650
- function collectLeafSeries(nodes, parentNamePath = []) {
651
- const leaves = [];
652
- for (const node of nodes) {
653
- const currentPath = [...parentNamePath, node.name];
654
- if (node.children && node.children.length > 0) {
655
- leaves.push(...collectLeafSeries(node.children, currentPath));
656
- }
657
- else {
658
- const combinedName = currentPath.join(' ');
659
- leaves.push({
660
- ...node,
661
- name: combinedName
662
- });
663
- }
664
- }
665
- return leaves;
666
- }
667
- function flattenEChartData(data) {
668
- if (!data)
669
- return { categories: [], series: [] };
670
- const categories = data.categories || [];
671
- const series = data.series || [];
672
- const topLevelCategories = flattenCategoriesToFirstLevel(categories);
673
- const { topLevelLeaves } = getLeafIndicesMap(categories);
674
- const flatSeries = collectLeafSeries(series).map(s => {
675
- const aggregatedData = [];
676
- for (const range of topLevelLeaves) {
677
- let sum = 0;
678
- for (let j = range.start; j < range.end; j++) {
679
- sum += s.data[j] ?? 0;
680
- }
681
- aggregatedData.push(sum);
682
- }
683
- return {
684
- ...s,
685
- data: aggregatedData
686
- };
687
- });
688
- return {
689
- categories: topLevelCategories,
690
- series: flatSeries
691
- };
692
- }
693
- /**
694
- * Normalizes category nodes into an array of string names for category axes.
695
- */
696
- function resolveCategoryNames(categories) {
697
- if (!categories)
698
- return [];
699
- return categories.map(c => {
700
- if (!c)
701
- return '';
702
- if (typeof c === 'string')
703
- return c;
704
- if (typeof c === 'object' && 'name' in c)
705
- return c.name;
706
- return String(c);
707
- });
708
- }
709
- /**
710
- * Maps categories and series data into a flat array of objects suitable for Pie/Ring/Funnel charts.
711
- */
712
- function mapToChartItems(categories, seriesNode) {
713
- if (!categories || !seriesNode || !seriesNode.data)
714
- return [];
715
- return categories.map((catNode, catIndex) => ({
716
- name: catNode.name,
717
- value: getCellValue(seriesNode.data[catIndex]),
718
- originalMeassureKey: seriesNode.originalKey || getCategoryKey(categories, catIndex)
719
- }));
720
- }
721
616
  /**
722
617
  * Formatter generator for 'item' trigger strategy in tooltips.
723
618
  */
724
619
  function getItemTooltipFormatter(data, formatCellValue, opts) {
725
- const totalSeries = data.series.length;
726
620
  return (params) => {
621
+ let title = '', subtitle = '', valFormatted = '', auxVal = '';
727
622
  const showSerieName = opts?.showSerieName ?? true;
728
- const seriesObj = data.series[params.seriesIndex];
729
- const key = params.data?.originalMeassureKey || seriesObj?.originalKey || getCategoryKey(data.categories, params.dataIndex);
730
- const valFormatted = formatCellValue(params.value, key);
623
+ const row = params.value;
624
+ const dimension = data.dimensions[params.seriesIndex + 1];
625
+ const dimensionName = dimension ? dimension.name : '';
626
+ if (!dimensionName)
627
+ return '';
628
+ const rawValue = (row && typeof row === 'object') ? row[dimensionName] : params.value;
731
629
  const serieName = showSerieName ? `${params.marker} ${params.seriesName}<br/ >` : '';
732
- const title = params.name;
733
- const subtitle = (params.percent !== undefined && totalSeries <= 1) ? '' : serieName;
734
- const percentText = params.percent !== undefined ? ` (${params.percent}%)` : '';
735
- return `<div style="text-align: center;"><b>${title}</b><br/>${subtitle}<b>${valFormatted}</b>${percentText}</div>`;
630
+ title = params.name || (row && typeof row === 'object' ? row.category : '');
631
+ subtitle = (params.percent !== undefined && data.dimensions.length <= 2) ? '' : serieName;
632
+ valFormatted = formatCellValue(Number(rawValue ?? 0), dimensionName);
633
+ auxVal = params.percent !== undefined ? ` (${params.percent}%)` : '';
634
+ // sunburst treemap
635
+ if (params.treePathInfo) {
636
+ const lastLevelIndex = params.treePathInfo.length - 1, parentNodeIndex = lastLevelIndex - 1;
637
+ const parentNode = params.treePathInfo[parentNodeIndex];
638
+ const oldParentNode = params.treePathInfo[1];
639
+ if (parentNode.name) {
640
+ title = `${parentNode.name}->${params.name}`;
641
+ subtitle = `${params.marker} ${oldParentNode.name}<br/ >`;
642
+ }
643
+ }
644
+ return `<div style="text-align: center;"><b>${title}</b><br/>${subtitle}<b>${valFormatted}</b>${auxVal}</div>`;
736
645
  };
737
646
  }
738
647
  /**
@@ -746,13 +655,17 @@ function getAxisTooltipFormatter(data, formatCellValue, opts) {
746
655
  if (items.length === 0)
747
656
  return '';
748
657
  const firstItem = items[0];
749
- let html = `<b>${firstItem.name}</b><br/>`;
658
+ const row = firstItem.value;
659
+ const title = firstItem.name || (row && typeof row === 'object' ? row.category : '');
660
+ let html = `<b>${title}</b><br/>`;
750
661
  for (const item of items) {
751
- const seriesObj = data.series[item.seriesIndex];
752
- if (!seriesObj)
662
+ const dimension = data.dimensions[item.seriesIndex + 1];
663
+ const dimensionName = dimension ? dimension.name : '';
664
+ if (!dimensionName)
753
665
  continue;
754
- const key = seriesObj.originalKey || getCategoryKey(data.categories, item.dataIndex);
755
- const valFormatted = formatCellValue(item.value, key);
666
+ const itemRow = item.value;
667
+ const rawValue = (itemRow && typeof itemRow === 'object') ? itemRow[dimensionName] : item.value;
668
+ const valFormatted = formatCellValue(Number(rawValue ?? 0), dimensionName);
756
669
  html += `${item.marker} ${item.seriesName}: <b>${valFormatted}</b><br/>`;
757
670
  }
758
671
  return html;
@@ -786,63 +699,43 @@ function getCommons(opts) {
786
699
  return common;
787
700
  }
788
701
  /**
789
- * Maps hierarchical category nodes and an array of series into a nested structure
790
- * suitable for Sunburst/Treemap charts.
791
- * The categories form the levels closest to the center, and the series form the leaf level.
702
+ * Maps hierarchical category nodes and their measures into a nested structure
703
+ * suitable for Sunburst/Treemap charts from the IEChartDataNode children.
792
704
  */
793
- function mapHierarchicalData(categories, series) {
794
- if (!categories) {
705
+ function mapHierarchicalData(source, dimensions) {
706
+ if (!source) {
795
707
  return [];
796
708
  }
797
- let leafIndex = 0;
798
- function mapSeriesTree(seriesNodes, index) {
799
- if (!seriesNodes) {
800
- return [];
801
- }
802
- return seriesNodes.map(s => {
803
- const node = {
804
- name: s.name,
805
- };
806
- if (s.children && s.children.length > 0) {
807
- node.children = mapSeriesTree(s.children, index);
808
- }
809
- else {
810
- // Leaf series node: extract value from s.data[index]
811
- const dataVal = s.data?.[index];
812
- if (dataVal !== undefined && dataVal !== null) {
813
- const value = typeof dataVal === 'object' && 'value' in dataVal ? dataVal.value : dataVal;
814
- node.value = getCellValue(value);
815
- }
816
- else {
817
- node.value = 0;
818
- }
819
- node.originalMeassureKey = s.originalKey;
820
- }
821
- return node;
822
- });
823
- }
709
+ const measureDims = dimensions.filter(d => d.name !== 'category');
824
710
  function traverse(nodes) {
825
- return nodes.map(cat => {
826
- const node = {
827
- name: cat.name,
711
+ return nodes.map(node => {
712
+ const item = {
713
+ name: node.category,
828
714
  };
829
- if (cat.children && cat.children.length > 0) {
830
- node.children = traverse(cat.children);
715
+ if (node.children && node.children.length > 0) {
716
+ item.children = traverse(node.children);
831
717
  }
832
718
  else {
833
- // Leaf category node: append the series tree as children
834
- if (series && series.length > 0) {
835
- node.children = mapSeriesTree(series, leafIndex);
719
+ // Leaf category node: append the series (measures) as the final level of children
720
+ if (measureDims.length > 0) {
721
+ item.children = measureDims.map(dim => {
722
+ const rawValue = node[dim.name];
723
+ const value = typeof rawValue === 'object' && rawValue !== null && 'value' in rawValue ? rawValue.value : rawValue;
724
+ return {
725
+ name: dim.displayName || dim.name,
726
+ value: getCellValue(Number(value ?? 0)),
727
+ originalMeassureKey: dim.name
728
+ };
729
+ });
836
730
  }
837
731
  else {
838
- node.value = 0;
732
+ item.value = 0;
839
733
  }
840
- leafIndex++;
841
734
  }
842
- return node;
735
+ return item;
843
736
  });
844
737
  }
845
- return traverse(categories);
738
+ return traverse(source);
846
739
  }
847
740
  /**
848
741
  * Calculates the maximum depth of a tree structure.
@@ -889,10 +782,14 @@ class RingBuilder {
889
782
  merge(this.result, common);
890
783
  }
891
784
  addSeries(data, overrides) {
892
- const flatData = flattenEChartData(data);
893
- if (!flatData || !flatData.series.length)
785
+ if (!data || !data.dimensions || !data.source || data.source.length === 0)
894
786
  return;
895
- const totalRings = flatData.series.length; // Cada serie es un anillo
787
+ this.result.dataset = {
788
+ dimensions: data.dimensions,
789
+ source: data.source
790
+ };
791
+ const measureDims = data.dimensions.filter(d => d.name !== 'category');
792
+ const totalRings = measureDims.length; // Cada serie es un anillo
896
793
  // Configuración dinámica de radios y márgenes
897
794
  const margin = totalRings > 1 ? Math.max(0.5, 2.5 - (totalRings * 0.1)) : 0;
898
795
  const minInnerRadius = totalRings === 1 ? 45 : (totalRings > 5 ? Math.max(15, 40 - (totalRings * 1.2)) : 40);
@@ -901,12 +798,14 @@ class RingBuilder {
901
798
  const thickness = availableSpan / totalRings;
902
799
  const borderRadius = totalRings === 1 ? 10 : Math.max(2, Math.min(10, thickness * 0.8));
903
800
  const borderWidth = totalRings === 1 ? 2 : Math.max(0.5, Math.min(2, thickness * 0.15));
904
- const series = flatData.series.map((s, ringIndex) => {
801
+ const series = measureDims.map((dim, ringIndex) => {
802
+ const dimKey = dim.name;
803
+ const friendlyName = dim.displayName || dim.name;
905
804
  const inner = minInnerRadius + (ringIndex * (thickness + margin));
906
805
  const outer = inner + thickness;
907
- const pieData = mapToChartItems(flatData.categories, s);
908
806
  const dynamicRingSeriesOptions = {
909
- name: s.name,
807
+ name: friendlyName,
808
+ type: 'pie',
910
809
  radius: [`${inner}%`, `${outer}%`],
911
810
  itemStyle: {
912
811
  borderRadius: borderRadius,
@@ -922,7 +821,10 @@ class RingBuilder {
922
821
  borderWidth: borderWidth,
923
822
  },
924
823
  },
925
- data: pieData,
824
+ encode: {
825
+ itemName: 'category',
826
+ value: dimKey
827
+ },
926
828
  id: `ring_${ringIndex}`,
927
829
  };
928
830
  const seriesOption = merge(dynamicRingSeriesOptions, overrides);
@@ -958,9 +860,8 @@ class RingBuilder {
958
860
  }];
959
861
  }
960
862
  addTooltip(data, overrides) {
961
- const flatData = flattenEChartData(data);
962
863
  merge(overrides, {
963
- formatter: getTooltipFormatter(overrides.trigger, flatData, this.formatCellValue.bind(this)),
864
+ formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
964
865
  });
965
866
  const tooltip = getTooltipOptions(overrides);
966
867
  this.result.tooltip = tooltip;
@@ -1022,7 +923,8 @@ class VSECDirector {
1022
923
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1023
924
  // chart components
1024
925
  this.builder.addCommons();
1025
- this.builder.addSeries(data, seriesOverrides);
926
+ const layoutOpts = { axisTypes };
927
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1026
928
  this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1027
929
  this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1028
930
  this.builder.addTooltip(data, overrides.tooltip);
@@ -1044,7 +946,8 @@ class VSECDirector {
1044
946
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1045
947
  // chart components
1046
948
  this.builder.addCommons();
1047
- this.builder.addSeries(data, seriesOverrides);
949
+ const layoutOpts = { axisTypes, coordinateSystem: 'polar' };
950
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1048
951
  this.builder.addPolar();
1049
952
  this.builder.addAngleAxis(data, overrides['axis']);
1050
953
  this.builder.addRadiusAxis(data, overrides['axis']);
@@ -1067,7 +970,8 @@ class VSECDirector {
1067
970
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1068
971
  // chart components
1069
972
  this.builder.addCommons();
1070
- this.builder.addSeries(data, seriesOverrides);
973
+ const layoutOpts = { axisTypes };
974
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1071
975
  this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1072
976
  this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1073
977
  this.builder.addTooltip(data, overrides.tooltip);
@@ -1087,7 +991,8 @@ class VSECDirector {
1087
991
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1088
992
  // chart components
1089
993
  this.builder.addCommons();
1090
- this.builder.addSeries(data, seriesOverrides);
994
+ const layoutOpts = { axisTypes };
995
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1091
996
  this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1092
997
  this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1093
998
  this.builder.addTooltip(data, overrides.tooltip);
@@ -1104,7 +1009,8 @@ class VSECDirector {
1104
1009
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1105
1010
  // chart components
1106
1011
  this.builder.addCommons();
1107
- this.builder.addSeries(data, seriesOverrides);
1012
+ const layoutOpts = {};
1013
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1108
1014
  this.builder.addGraphic();
1109
1015
  this.builder.addTooltip(data, overrides.tooltip);
1110
1016
  this.builder.addLegend();
@@ -1120,7 +1026,8 @@ class VSECDirector {
1120
1026
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1121
1027
  // chart components
1122
1028
  this.builder.addCommons();
1123
- this.builder.addSeries(data, seriesOverrides);
1029
+ const layoutOpts = {};
1030
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1124
1031
  this.builder.addTooltip(data, overrides.tooltip);
1125
1032
  this.builder.addLegend();
1126
1033
  }
@@ -1135,7 +1042,8 @@ class VSECDirector {
1135
1042
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1136
1043
  // chart components
1137
1044
  this.builder.addCommons();
1138
- this.builder.addSeries(data, seriesOverrides);
1045
+ const layoutOpts = {};
1046
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1139
1047
  this.builder.addTooltip(data, overrides.tooltip);
1140
1048
  this.builder.addLegend();
1141
1049
  }
@@ -1150,7 +1058,8 @@ class VSECDirector {
1150
1058
  const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1151
1059
  // chart components
1152
1060
  this.builder.addCommons();
1153
- this.builder.addSeries(data, seriesOverrides);
1061
+ const layoutOpts = {};
1062
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1154
1063
  this.builder.addTooltip(data, overrides.tooltip);
1155
1064
  // this.builder.addLegend();
1156
1065
  }
@@ -1316,18 +1225,26 @@ class PieBuilder {
1316
1225
  merge(this.result, common);
1317
1226
  }
1318
1227
  addSeries(data, overrides) {
1319
- const flatData = flattenEChartData(data);
1320
- if (!flatData || !flatData.series.length)
1228
+ if (!data || !data.dimensions || !data.source || data.source.length === 0)
1321
1229
  return;
1322
- const totalSeries = flatData.series.length;
1230
+ this.result.dataset = {
1231
+ dimensions: data.dimensions,
1232
+ source: data.source
1233
+ };
1234
+ const measureDims = data.dimensions.filter(d => d.name !== 'category');
1235
+ const totalSeries = measureDims.length;
1323
1236
  let series = [];
1324
1237
  if (totalSeries === 1) {
1325
- const s = flatData.series[0];
1326
- const pieData = mapToChartItems(flatData.categories, s);
1238
+ const dim = measureDims[0];
1239
+ const dimKey = dim.name;
1240
+ const friendlyName = dim.displayName || dim.name;
1327
1241
  const dynamicPieSeriesOptions = {
1328
- name: s.name,
1242
+ name: friendlyName,
1329
1243
  type: 'pie',
1330
- data: pieData,
1244
+ encode: {
1245
+ itemName: 'category',
1246
+ value: dimKey
1247
+ },
1331
1248
  id: `pie_0`,
1332
1249
  radius: [0, '50%'],
1333
1250
  label: {
@@ -1352,8 +1269,9 @@ class PieBuilder {
1352
1269
  const numRings = totalSeries - 1;
1353
1270
  const availableSpan = maxOuterRadius - (centerPieRadius + margin) - (margin * (numRings - 1));
1354
1271
  const thickness = availableSpan / numRings;
1355
- series = flatData.series.map((s, idx) => {
1356
- const pieData = mapToChartItems(flatData.categories, s);
1272
+ series = measureDims.map((dim, idx) => {
1273
+ const dimKey = dim.name;
1274
+ const friendlyName = dim.displayName || dim.name;
1357
1275
  let radius;
1358
1276
  let labelPosition;
1359
1277
  let labelLineShow;
@@ -1374,7 +1292,7 @@ class PieBuilder {
1374
1292
  labelLineShow = true;
1375
1293
  }
1376
1294
  const dynamicPieSeriesOptions = {
1377
- name: s.name,
1295
+ name: friendlyName,
1378
1296
  type: 'pie',
1379
1297
  radius: radius,
1380
1298
  label: {
@@ -1384,7 +1302,10 @@ class PieBuilder {
1384
1302
  labelLine: {
1385
1303
  show: labelLineShow
1386
1304
  },
1387
- data: pieData,
1305
+ encode: {
1306
+ itemName: 'category',
1307
+ value: dimKey
1308
+ },
1388
1309
  id: `pie_${idx}`,
1389
1310
  };
1390
1311
  const seriesOption = merge(dynamicPieSeriesOptions, overrides);
@@ -1398,9 +1319,8 @@ class PieBuilder {
1398
1319
  this.result.series = series;
1399
1320
  }
1400
1321
  addTooltip(data, overrides) {
1401
- const flatData = flattenEChartData(data);
1402
1322
  merge(overrides, {
1403
- formatter: getTooltipFormatter(overrides.trigger, flatData, this.formatCellValue.bind(this)),
1323
+ formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
1404
1324
  });
1405
1325
  const tooltip = getTooltipOptions(overrides);
1406
1326
  this.result.tooltip = tooltip;
@@ -1524,39 +1444,45 @@ class FunnelBuilder {
1524
1444
  merge(this.result, common);
1525
1445
  }
1526
1446
  addSeries(data, overrides) {
1527
- const flatData = flattenEChartData(data);
1528
- if (!flatData || !flatData.series.length)
1447
+ if (!data || !data.dimensions || !data.source || data.source.length === 0)
1529
1448
  return;
1530
- const series = flatData.series.map((s, seriesIndex) => {
1531
- const funnelData = mapToChartItems(flatData.categories, s);
1532
- let left = '10%';
1533
- let width = '80%';
1534
- const seriesValues = s.data.filter(val => typeof val === 'number');
1535
- const minVal = seriesValues.length > 0 ? Math.min(...seriesValues) : 0;
1536
- const maxVal = seriesValues.length > 0 ? Math.max(...seriesValues) : 100;
1537
- const dynamicFunnelSeriesOptions = {
1538
- name: s.name,
1539
- type: 'funnel',
1540
- left: left,
1541
- width: width,
1542
- min: minVal,
1543
- max: maxVal,
1544
- data: funnelData,
1545
- id: `funnel_${seriesIndex}`
1546
- };
1547
- const seriesOption = merge({}, overrides, dynamicFunnelSeriesOptions);
1548
- // Inject color resolver if provided
1549
- if (this.colorResolver && seriesOption.itemStyle) {
1550
- seriesOption.itemStyle.color = this.colorResolver;
1551
- }
1552
- return seriesOption;
1553
- });
1554
- this.result.series = series.shift();
1449
+ this.result.dataset = {
1450
+ dimensions: data.dimensions,
1451
+ source: data.source
1452
+ };
1453
+ const measureDims = data.dimensions.filter(d => d.name !== 'category');
1454
+ if (measureDims.length === 0)
1455
+ return;
1456
+ const dim = measureDims[0];
1457
+ const dimKey = dim.name;
1458
+ const friendlyName = dim.displayName || dim.name;
1459
+ // Obtener los valores para min/max
1460
+ const seriesValues = data.source.map(row => Number(row[dimKey] ?? 0));
1461
+ const minVal = seriesValues.length > 0 ? Math.min(...seriesValues) : 0;
1462
+ const maxVal = seriesValues.length > 0 ? Math.max(...seriesValues) : 100;
1463
+ const dynamicFunnelSeriesOptions = {
1464
+ name: friendlyName,
1465
+ type: 'funnel',
1466
+ left: '10%',
1467
+ width: '80%',
1468
+ min: minVal,
1469
+ max: maxVal,
1470
+ encode: {
1471
+ itemName: 'category',
1472
+ value: dimKey
1473
+ },
1474
+ id: `funnel_0`
1475
+ };
1476
+ const seriesOption = merge({}, overrides, dynamicFunnelSeriesOptions);
1477
+ // Inject color resolver if provided
1478
+ if (this.colorResolver && seriesOption.itemStyle) {
1479
+ seriesOption.itemStyle.color = this.colorResolver;
1480
+ }
1481
+ this.result.series = seriesOption;
1555
1482
  }
1556
1483
  addTooltip(data, overrides) {
1557
- const flatData = flattenEChartData(data);
1558
1484
  merge(overrides, {
1559
- formatter: getTooltipFormatter(overrides.trigger, flatData, this.formatCellValue.bind(this)),
1485
+ formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
1560
1486
  });
1561
1487
  const tooltip = getTooltipOptions(overrides);
1562
1488
  this.result.tooltip = tooltip;
@@ -1700,18 +1626,43 @@ class EChartBuilder {
1700
1626
  * @param overrides
1701
1627
  * @returns
1702
1628
  */
1703
- addSeries(data, overrides) {
1704
- const flatData = flattenEChartData(data);
1705
- if (!flatData || !flatData.series.length)
1629
+ addSeries(data, overrides, opts) {
1630
+ if (!data || !data.dimensions || !data.source || data.source.length === 0)
1706
1631
  return;
1707
- const series = flatData.series.map((s) => {
1632
+ this.result.dataset = {
1633
+ dimensions: data.dimensions,
1634
+ source: data.source
1635
+ };
1636
+ const measureDims = data.dimensions.filter(d => d.name !== 'category');
1637
+ const isPolar = opts?.coordinateSystem === 'polar';
1638
+ const isHorizontal = opts?.axisTypes?.x === 'value' && opts?.axisTypes?.y === 'category';
1639
+ const series = measureDims.map((dim) => {
1640
+ const friendlyName = dim.displayName || dim.name;
1641
+ const dimKey = dim.name;
1642
+ let encode = {
1643
+ x: 'category',
1644
+ y: dimKey
1645
+ };
1646
+ if (isPolar) {
1647
+ encode = {
1648
+ angle: 'category',
1649
+ radius: dimKey
1650
+ };
1651
+ }
1652
+ else if (isHorizontal) {
1653
+ encode = {
1654
+ x: dimKey,
1655
+ y: 'category'
1656
+ };
1657
+ }
1708
1658
  const dynamicOverrides = {
1709
- name: s.name,
1710
- data: s.data,
1659
+ name: friendlyName,
1660
+ encode,
1711
1661
  label: {
1712
1662
  formatter: (params) => {
1713
- const key = s.originalKey || getCategoryKey(flatData.categories, params.dataIndex);
1714
- return this.formatCellValue(params.value, key);
1663
+ const row = params.value;
1664
+ const rawValue = (row && typeof row === 'object') ? row[dimKey] : params.value;
1665
+ return this.formatCellValue(Number(rawValue ?? 0), dimKey);
1715
1666
  }
1716
1667
  }
1717
1668
  };
@@ -1731,9 +1682,8 @@ class EChartBuilder {
1731
1682
  */
1732
1683
  addTooltip(data, overrides) {
1733
1684
  // inyecto formateador a overrides de tooltip
1734
- const flatData = flattenEChartData(data);
1735
1685
  merge$1(overrides, {
1736
- formatter: getTooltipFormatter(overrides.trigger, flatData, this.formatCellValue.bind(this)),
1686
+ formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
1737
1687
  });
1738
1688
  const tooltip = getTooltipOptions(overrides);
1739
1689
  this.result.tooltip = tooltip;
@@ -1850,10 +1800,9 @@ class EChartBuilder {
1850
1800
  }
1851
1801
  // Utils
1852
1802
  getCategoryAxisOptions(data, overrides) {
1853
- const flatCategories = flattenCategoriesToFirstLevel(data.categories);
1803
+ // No explicit data needed on category axis when using ECharts dataset
1854
1804
  const categoryAxisOptionsOverrides = {
1855
- ...overrides.categoryAxis[0],
1856
- data: resolveCategoryNames(flatCategories),
1805
+ ...overrides.categoryAxis[0]
1857
1806
  };
1858
1807
  const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
1859
1808
  return categoryAxisOptions;
@@ -2282,10 +2231,10 @@ class SunburstBuilder {
2282
2231
  this.result = {};
2283
2232
  }
2284
2233
  addSeries(data, overrides) {
2285
- if (!data || !data.series || data.series.length === 0) {
2234
+ if (!data || !data.source || data.source.length === 0) {
2286
2235
  return;
2287
2236
  }
2288
- const sunburstData = mapHierarchicalData(data.categories, data.series);
2237
+ const sunburstData = mapHierarchicalData(data.source, data.dimensions);
2289
2238
  const depth = getTreeDepth(sunburstData);
2290
2239
  const levels = [];
2291
2240
  for (let i = 0; i <= depth; i++) {