@visionaris-bruno/vs-echarts 8.1.0 → 8.3.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,6 +1,6 @@
1
1
  import { provideEchartsCore, NgxEchartsDirective } from 'ngx-echarts';
2
2
  import * as echarts from 'echarts/core';
3
- import { BarChart, PieChart, LineChart, ScatterChart, FunnelChart, SunburstChart } from 'echarts/charts';
3
+ import { BarChart, PieChart, LineChart, ScatterChart, FunnelChart, SunburstChart, SankeyChart } from 'echarts/charts';
4
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';
@@ -66,6 +66,7 @@ function initializeEcharts() {
66
66
  ScatterChart,
67
67
  FunnelChart,
68
68
  SunburstChart,
69
+ SankeyChart,
69
70
  TitleComponent,
70
71
  TooltipComponent,
71
72
  GridComponent,
@@ -162,6 +163,9 @@ function defaultOptionsOverrides() {
162
163
  sunburst: {
163
164
  series: {},
164
165
  },
166
+ sankey: {
167
+ series: {}
168
+ },
165
169
  };
166
170
  }
167
171
 
@@ -618,7 +622,7 @@ function getCellValue(val) {
618
622
  */
619
623
  function getItemTooltipFormatter(data, formatCellValue, opts) {
620
624
  return (params) => {
621
- let title = '', subtitle = '', valFormatted = '', auxVal = '';
625
+ let title = '', subtitle = '', valFormatted = '', percentVal = '';
622
626
  const showSerieName = opts?.showSerieName ?? true;
623
627
  const row = params.value;
624
628
  const dimension = data.dimensions[params.seriesIndex + 1];
@@ -628,9 +632,30 @@ function getItemTooltipFormatter(data, formatCellValue, opts) {
628
632
  const rawValue = (row && typeof row === 'object') ? row[dimensionName] : params.value;
629
633
  const serieName = showSerieName ? `${params.marker} ${params.seriesName}<br/ >` : '';
630
634
  title = params.name || (row && typeof row === 'object' ? row.category : '');
631
- subtitle = (params.percent !== undefined && data.dimensions.length <= 2) ? '' : serieName;
635
+ subtitle = serieName;
632
636
  valFormatted = formatCellValue(Number(rawValue ?? 0), dimensionName);
633
- auxVal = params.percent !== undefined ? ` (${params.percent}%)` : '';
637
+ // pie/funnel series
638
+ if (params.percent != undefined) {
639
+ percentVal = ` (${params.percent}%)`;
640
+ if (data.dimensions.length <= 2) {
641
+ subtitle = '';
642
+ }
643
+ }
644
+ // sankey
645
+ if (params.dataType != undefined) {
646
+ const dataType = params.dataType;
647
+ subtitle = `${params.marker}<br/>`;
648
+ if (dataType === 'edge') {
649
+ const sourceName = params.data.source.split('___')[0];
650
+ const targetName = params.data.target.split('___')[0];
651
+ title = `${sourceName} &rarr; ${targetName}`;
652
+ valFormatted = formatCellValue(Number(params.value ?? 0), dimensionName);
653
+ }
654
+ else if (dataType === 'node') {
655
+ title = params.name.split('___')[0];
656
+ valFormatted = formatCellValue(Number(params.value ?? 0), dimensionName);
657
+ }
658
+ }
634
659
  // sunburst treemap
635
660
  if (params.treePathInfo) {
636
661
  const lastLevelIndex = params.treePathInfo.length - 1, parentNodeIndex = lastLevelIndex - 1;
@@ -641,7 +666,7 @@ function getItemTooltipFormatter(data, formatCellValue, opts) {
641
666
  subtitle = `${params.marker} ${oldParentNode.name}<br/ >`;
642
667
  }
643
668
  }
644
- return `<div style="text-align: center;"><b>${title}</b><br/>${subtitle}<b>${valFormatted}</b>${auxVal}</div>`;
669
+ return `<div style="text-align: center;"><b>${title}</b><br/>${subtitle}<b>${valFormatted}</b>${percentVal}</div>`;
645
670
  };
646
671
  }
647
672
  /**
@@ -1063,6 +1088,21 @@ class VSECDirector {
1063
1088
  this.builder.addTooltip(data, overrides.tooltip);
1064
1089
  // this.builder.addLegend();
1065
1090
  }
1091
+ makeSankey(data, overrides, opts = {}) {
1092
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
1093
+ this.builder.reset();
1094
+ // El orden importa, primero callbacks y despues componentes.
1095
+ this.builder.setValueFormatter(valueFormatter);
1096
+ this.builder.setPalette(palette);
1097
+ this.builder.setColorResolver(colorResolver);
1098
+ const product = this.builder.baseProduct;
1099
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1100
+ // chart components
1101
+ this.builder.addCommons();
1102
+ const layoutOpts = {};
1103
+ this.builder.addSeries(data, seriesOverrides, layoutOpts);
1104
+ this.builder.addTooltip(data, overrides.tooltip);
1105
+ }
1066
1106
  }
1067
1107
 
1068
1108
  /**
@@ -2357,6 +2397,203 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2357
2397
  ], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
2358
2398
  }] });
2359
2399
 
2400
+ /**
2401
+ * SankeyBuilder
2402
+ *
2403
+ * Builder concreto para el gráfico Sankey (diagrama de flujos de izquierda a derecha).
2404
+ */
2405
+ class SankeyBuilder {
2406
+ baseProduct;
2407
+ valueFormatter = (value) => value.toLocaleString();
2408
+ palette = [];
2409
+ colorResolver;
2410
+ result = {};
2411
+ constructor(baseProduct) {
2412
+ this.baseProduct = baseProduct;
2413
+ }
2414
+ reset() {
2415
+ this.result = {};
2416
+ }
2417
+ addSeries(data, overrides) {
2418
+ if (!data || !data.source || data.source.length === 0) {
2419
+ return;
2420
+ }
2421
+ // Identificar medidas (todas las dimensiones excepto 'category')
2422
+ const measureKeys = data.dimensions
2423
+ .filter((d) => d.name !== "category")
2424
+ .map((d) => d.name);
2425
+ // Función auxiliar para sumarizar valores de medidas en caso de haber más de una
2426
+ const getNodeValue = (node) => {
2427
+ return measureKeys.reduce((sum, key) => sum + (Number(node[key]) || 0), 0);
2428
+ };
2429
+ const nodesMap = new Map();
2430
+ const linksMap = new Map();
2431
+ // Función recursiva para aplanar datos jerárquicos a nodos y enlaces
2432
+ const traverse = (nodeList, level, parentId) => {
2433
+ for (const node of nodeList) {
2434
+ const category = node.category;
2435
+ const currentId = `${category}___${level}`;
2436
+ const value = getNodeValue(node);
2437
+ nodesMap.set(currentId, (nodesMap.get(currentId) || 0) + value);
2438
+ if (parentId) {
2439
+ const linkKey = `${parentId}--->${currentId}`;
2440
+ if (linksMap.has(linkKey)) {
2441
+ linksMap.get(linkKey).value += value;
2442
+ }
2443
+ else {
2444
+ linksMap.set(linkKey, {
2445
+ source: parentId,
2446
+ target: currentId,
2447
+ value: value,
2448
+ });
2449
+ }
2450
+ }
2451
+ if (node.children && node.children.length > 0) {
2452
+ traverse(node.children, level + 1, currentId);
2453
+ }
2454
+ }
2455
+ };
2456
+ // Comenzar el recorrido en el nivel 0
2457
+ traverse(data.source, 0);
2458
+ // al menos un nivel de links para dibujar.
2459
+ if (linksMap.size === 0)
2460
+ return;
2461
+ // Mapear nodos acumulados a la estructura requerida por ECharts (name y opcionalmente color, sin value redundante)
2462
+ const nodes = Array.from(nodesMap.keys()).map((currentId) => {
2463
+ const category = currentId.split("___")[0];
2464
+ const nodeItem = {
2465
+ name: currentId,
2466
+ };
2467
+ if (this.colorResolver) {
2468
+ const color = this.colorResolver({ name: category, data: nodeItem });
2469
+ if (color) {
2470
+ nodeItem.itemStyle = { color };
2471
+ }
2472
+ }
2473
+ return nodeItem;
2474
+ });
2475
+ const dynamicSerieOptions = {
2476
+ type: "sankey",
2477
+ orient: "horizontal", // De izquierda a derecha
2478
+ draggable: true,
2479
+ emphasis: {
2480
+ focus: "adjacency",
2481
+ },
2482
+ lineStyle: {
2483
+ color: "source",
2484
+ opacity: 0.25,
2485
+ curveness: 0.5,
2486
+ },
2487
+ label: {
2488
+ show: true,
2489
+ position: "right",
2490
+ fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif",
2491
+ fontSize: 10,
2492
+ formatter: (params) => {
2493
+ // Remover el sufijo de nivel de la etiqueta visual
2494
+ return params.name.split("___")[0];
2495
+ },
2496
+ },
2497
+ roam: true,
2498
+ data: nodes,
2499
+ links: Array.from(linksMap.values()),
2500
+ };
2501
+ const serie = merge$1({}, dynamicSerieOptions, overrides);
2502
+ if (this.colorResolver && !serie.itemStyle) {
2503
+ serie.itemStyle = {};
2504
+ }
2505
+ if (this.colorResolver && serie.itemStyle) {
2506
+ serie.itemStyle.color = this.colorResolver;
2507
+ }
2508
+ this.result.series = serie;
2509
+ }
2510
+ addTooltip(data, overrides) {
2511
+ merge$1(overrides, {
2512
+ formatter: getTooltipFormatter(overrides.trigger || 'item', data, this.valueFormatter),
2513
+ });
2514
+ const tooltip = getTooltipOptions(overrides);
2515
+ this.result.tooltip = tooltip;
2516
+ }
2517
+ addPolar() { }
2518
+ addXAxis(data, overrides, type) { }
2519
+ addYAxis(data, overrides, type) { }
2520
+ addRadiusAxis(data, overrides) { }
2521
+ addAngleAxis(data, overrides) { }
2522
+ addLegend() { }
2523
+ addCommons() {
2524
+ const opts = {
2525
+ palette: this.palette,
2526
+ };
2527
+ merge$1(this.result, getCommons(opts));
2528
+ }
2529
+ addGraphic() { }
2530
+ getResult() {
2531
+ return this.result;
2532
+ }
2533
+ setValueFormatter(formatter) {
2534
+ if (formatter) {
2535
+ this.valueFormatter = formatter;
2536
+ }
2537
+ }
2538
+ setPalette(palette) {
2539
+ if (palette) {
2540
+ this.palette = palette;
2541
+ }
2542
+ }
2543
+ setColorResolver(resolver) {
2544
+ if (resolver) {
2545
+ this.colorResolver = resolver;
2546
+ }
2547
+ }
2548
+ }
2549
+
2550
+ class EchartsSankeyComponent extends BaseEchartsComponent {
2551
+ baseSeriesOptions = {
2552
+ type: 'sankey',
2553
+ orient: 'horizontal',
2554
+ draggable: true,
2555
+ emphasis: {
2556
+ focus: 'adjacency'
2557
+ },
2558
+ lineStyle: {
2559
+ color: 'source',
2560
+ opacity: 0.25,
2561
+ curveness: 0.5
2562
+ },
2563
+ label: {
2564
+ show: true,
2565
+ position: 'right',
2566
+ fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif",
2567
+ fontSize: 10
2568
+ }
2569
+ };
2570
+ baseProduct = {
2571
+ chartKey: 'sankey',
2572
+ baseOptions: {
2573
+ series: this.baseSeriesOptions,
2574
+ },
2575
+ };
2576
+ builder = new SankeyBuilder(this.baseProduct);
2577
+ director = new VSECDirector(this.builder);
2578
+ make() {
2579
+ const makeOpts = {
2580
+ palette: this.palette,
2581
+ colorResolver: this.colorResolver,
2582
+ valueFormatter: this.valueFormatter,
2583
+ };
2584
+ this.director.makeSankey(this.data, this.optionsOverrides, makeOpts);
2585
+ }
2586
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsSankeyComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2587
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsSankeyComponent, isStandalone: true, selector: "vs-echarts-sankey", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
2588
+ }
2589
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsSankeyComponent, decorators: [{
2590
+ type: Component,
2591
+ args: [{ selector: 'vs-echarts-sankey', standalone: true, imports: [
2592
+ CommonModule,
2593
+ NgxEchartsDirective,
2594
+ ], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
2595
+ }] });
2596
+
2360
2597
  // Interfaces de Inputs de Base EChart Component //
2361
2598
 
2362
2599
  ;
@@ -2371,5 +2608,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2371
2608
  * Generated bundle index. Do not edit.
2372
2609
  */
2373
2610
 
2374
- export { BaseEchartsComponent, EChartsAreaComponent, EChartsAreaStackComponent, EChartsBarStackedComponent, EChartsBarStackedRadialComponent, EChartsHBarComponent, EChartsHBarStackedComponent, EChartsSunburstComponent, EchartsBarComponent, EchartsFunnelComponent, EchartsLineComponent, EchartsPieComponent, EchartsRingComponent, EchartsScatterComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
2611
+ export { BaseEchartsComponent, EChartsAreaComponent, EChartsAreaStackComponent, EChartsBarStackedComponent, EChartsBarStackedRadialComponent, EChartsHBarComponent, EChartsHBarStackedComponent, EChartsSunburstComponent, EchartsBarComponent, EchartsFunnelComponent, EchartsLineComponent, EchartsPieComponent, EchartsRingComponent, EchartsSankeyComponent, EchartsScatterComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
2375
2612
  //# sourceMappingURL=visionaris-bruno-vs-echarts.mjs.map