@visionaris-bruno/vs-echarts 8.4.1 → 8.4.2

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.
@@ -188,11 +188,11 @@ class BaseEchartsComponent {
188
188
  data = { dimensions: [], source: [] };
189
189
  optionsOverrides = defaultOptionsOverrides();
190
190
  /** Paleta de colores básica */
191
- palette;
191
+ palette = getDefaultPalette();
192
192
  /** Resolver de colores dinámico (Callback) */
193
193
  colorResolver;
194
194
  /** Formateador de valores para etiquetas y tooltips */
195
- valueFormatter;
195
+ valueFormatter = (value) => value.toLocaleString();
196
196
  chartClick = new EventEmitter();
197
197
  /** Subject para debouncing de actualizaciones. ReplaySubject asegura no perder el primer renderizado. */
198
198
  updateSubject = new ReplaySubject(1);
@@ -1128,344 +1128,236 @@ class BoxPlotBuilder {
1128
1128
  }
1129
1129
 
1130
1130
  /**
1131
- * Director de Builds.
1131
+ * Builder principal.
1132
+ *
1133
+ * Es muy completo, tiene soporte para ejes y sistema cartesiano polar.
1134
+ *
1135
+ * Puede verse utilizado en graficos como Lineas y Bars. Siempre que se pueda priorizar utilizar este.
1132
1136
  */
1133
- class VSECDirector {
1134
- builder = undefined;
1135
- constructor(builder) {
1136
- this.builder = builder;
1137
- }
1138
- makeBar(data, overrides, opts = {}) {
1139
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1140
- x: 'category',
1141
- y: 'value',
1142
- // TODO agregar radius y angle axis
1143
- } } = opts;
1144
- this.builder.reset();
1145
- // El orden importa, primero callbaks y despues componentes.
1146
- //chart callbacks
1147
- this.builder.setValueFormatter(valueFormatter);
1148
- this.builder.setPalette(palette);
1149
- this.builder.setColorResolver(colorResolver);
1150
- const product = this.builder.baseProduct;
1151
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1152
- // chart components
1153
- this.builder.addCommons();
1154
- const layoutOpts = { axisTypes };
1155
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1156
- this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1157
- this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1158
- this.builder.addTooltip(data, overrides.tooltip);
1159
- this.builder.addLegend();
1160
- }
1161
- makeBarRadial(data, overrides, opts = {}) {
1162
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1163
- x: 'category',
1164
- y: 'value',
1165
- // TODO agregar radius y angle axis
1166
- } } = opts;
1167
- this.builder.reset();
1168
- // El orden importa, primero callbaks y despues componentes.
1169
- //chart callbacks
1170
- this.builder.setValueFormatter(valueFormatter);
1171
- this.builder.setPalette(palette);
1172
- this.builder.setColorResolver(colorResolver);
1173
- const product = this.builder.baseProduct;
1174
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1175
- // chart components
1176
- this.builder.addCommons();
1177
- const layoutOpts = { axisTypes, coordinateSystem: 'polar' };
1178
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1179
- this.builder.addPolar();
1180
- this.builder.addAngleAxis(data, overrides['axis']);
1181
- this.builder.addRadiusAxis(data, overrides['axis']);
1182
- this.builder.addTooltip(data, overrides.tooltip);
1183
- this.builder.addLegend();
1184
- }
1185
- makeLine(data, overrides, opts = {}) {
1186
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1187
- x: 'category',
1188
- y: 'value',
1189
- // TODO agregar radius y angle axis
1190
- } } = opts;
1191
- this.builder.reset();
1192
- // El orden importa, primero callbaks y despues componentes.
1193
- //chart callbacks
1194
- this.builder.setValueFormatter(valueFormatter);
1195
- this.builder.setPalette(palette);
1196
- this.builder.setColorResolver(colorResolver);
1197
- const product = this.builder.baseProduct;
1198
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1199
- // chart components
1200
- this.builder.addCommons();
1201
- const layoutOpts = { axisTypes };
1202
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1203
- this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1204
- this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1205
- this.builder.addTooltip(data, overrides.tooltip);
1206
- this.builder.addLegend();
1137
+ class EChartBuilder {
1138
+ baseProduct = undefined;
1139
+ valueFormatter = (value) => value.toLocaleString();
1140
+ palette = [];
1141
+ // TODO: Hay que implementar un valor por defecto.
1142
+ colorResolver;
1143
+ result = {};
1144
+ constructor(baseProduct) {
1145
+ this.baseProduct = baseProduct;
1207
1146
  }
1208
- makeScatter(data, overrides, opts = {}) {
1209
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1210
- x: 'category',
1211
- y: 'value',
1212
- } } = opts;
1213
- this.builder.reset();
1214
- // El orden importa, primero callbacks y despues componentes.
1215
- this.builder.setValueFormatter(valueFormatter);
1216
- this.builder.setPalette(palette);
1217
- this.builder.setColorResolver(colorResolver);
1218
- const product = this.builder.baseProduct;
1219
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1220
- // chart components
1221
- this.builder.addCommons();
1222
- const layoutOpts = { axisTypes };
1223
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1224
- this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1225
- this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1226
- this.builder.addTooltip(data, overrides.tooltip);
1227
- this.builder.addLegend();
1147
+ reset() {
1148
+ this.result = {};
1228
1149
  }
1229
- makeRing(data, overrides, opts = {}) {
1230
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
1231
- this.builder.reset();
1232
- // El orden importa, primero callbacks y despues componentes.
1233
- this.builder.setValueFormatter(valueFormatter);
1234
- this.builder.setPalette(palette);
1235
- this.builder.setColorResolver(colorResolver);
1236
- const product = this.builder.baseProduct;
1237
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1238
- // chart components
1239
- this.builder.addCommons();
1240
- const layoutOpts = {};
1241
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1242
- this.builder.addGraphic();
1243
- this.builder.addTooltip(data, overrides.tooltip);
1244
- this.builder.addLegend();
1150
+ addCommons() {
1151
+ const opts = {
1152
+ palette: this.palette,
1153
+ };
1154
+ merge$1(this.result, getCommons(opts));
1245
1155
  }
1246
- makePie(data, overrides, opts = {}) {
1247
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
1248
- this.builder.reset();
1249
- // El orden importa, primero callbacks y despues componentes.
1250
- this.builder.setValueFormatter(valueFormatter);
1251
- this.builder.setPalette(palette);
1252
- this.builder.setColorResolver(colorResolver);
1253
- const product = this.builder.baseProduct;
1254
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1255
- // chart components
1256
- this.builder.addCommons();
1257
- const layoutOpts = {};
1258
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1259
- this.builder.addTooltip(data, overrides.tooltip);
1260
- this.builder.addLegend();
1156
+ /**
1157
+ *
1158
+ * @param data
1159
+ * @param overrides
1160
+ * @returns
1161
+ */
1162
+ addSeries(data, overrides, opts) {
1163
+ if (!data || !data.dimensions || !data.source || data.source.length === 0)
1164
+ return;
1165
+ this.result.dataset = {
1166
+ dimensions: data.dimensions,
1167
+ source: data.source
1168
+ };
1169
+ const measureDims = data.dimensions.filter(d => d.name !== 'category');
1170
+ const isPolar = opts?.coordinateSystem === 'polar';
1171
+ const isHorizontal = opts?.axisTypes?.x === 'value' && opts?.axisTypes?.y === 'category';
1172
+ const series = measureDims.map((dim) => {
1173
+ const friendlyName = dim.displayName || dim.name;
1174
+ const dimKey = dim.name;
1175
+ let encode = {
1176
+ x: 'category',
1177
+ y: dimKey
1178
+ };
1179
+ if (isPolar) {
1180
+ encode = {
1181
+ angle: 'category',
1182
+ radius: dimKey
1183
+ };
1184
+ }
1185
+ else if (isHorizontal) {
1186
+ encode = {
1187
+ x: dimKey,
1188
+ y: 'category'
1189
+ };
1190
+ }
1191
+ const dynamicOverrides = {
1192
+ name: friendlyName,
1193
+ encode,
1194
+ label: {
1195
+ formatter: (params) => {
1196
+ const row = params.value;
1197
+ const rawValue = (row && typeof row === 'object') ? row[dimKey] : params.value;
1198
+ return this.formatCellValue(Number(rawValue ?? 0), dimKey);
1199
+ }
1200
+ }
1201
+ };
1202
+ const seriesOption = merge$1(dynamicOverrides, overrides);
1203
+ // Inyectar el resolver de color si existe
1204
+ if (this.colorResolver && seriesOption.itemStyle) {
1205
+ seriesOption.itemStyle.color = this.colorResolver;
1206
+ }
1207
+ return seriesOption;
1208
+ });
1209
+ this.result.series = series;
1261
1210
  }
1262
- makeFunnel(data, overrides, opts = {}) {
1263
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
1264
- this.builder.reset();
1265
- // El orden importa, primero callbacks y despues componentes.
1266
- this.builder.setValueFormatter(valueFormatter);
1267
- this.builder.setPalette(palette);
1268
- this.builder.setColorResolver(colorResolver);
1269
- const product = this.builder.baseProduct;
1270
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1271
- // chart components
1272
- this.builder.addCommons();
1273
- const layoutOpts = {};
1274
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1275
- this.builder.addTooltip(data, overrides.tooltip);
1276
- this.builder.addLegend();
1211
+ /**
1212
+ * TODO: Mejorar funcion, no me convence como se implemento el tooltip formatter.
1213
+ * @param data
1214
+ * @param overrides
1215
+ */
1216
+ addTooltip(data, overrides) {
1217
+ // inyecto formateador a overrides de tooltip
1218
+ merge$1(overrides, {
1219
+ formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
1220
+ });
1221
+ const tooltip = getTooltipOptions(overrides);
1222
+ this.result.tooltip = tooltip;
1277
1223
  }
1278
- makeSunburst(data, overrides, opts = {}) {
1279
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
1280
- this.builder.reset();
1281
- // El orden importa, primero callbacks y despues componentes.
1282
- this.builder.setValueFormatter(valueFormatter);
1283
- this.builder.setPalette(palette);
1284
- this.builder.setColorResolver(colorResolver);
1285
- const product = this.builder.baseProduct;
1286
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1287
- // chart components
1288
- this.builder.addCommons();
1289
- const layoutOpts = {};
1290
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1291
- this.builder.addTooltip(data, overrides.tooltip);
1292
- // this.builder.addLegend();
1224
+ addPolar() {
1225
+ const polar = [];
1226
+ polar.push({
1227
+ radius: '65%',
1228
+ center: ["50%", "44%"],
1229
+ });
1230
+ this.result.polar = polar;
1293
1231
  }
1294
- makeSankey(data, overrides, opts = {}) {
1295
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
1296
- this.builder.reset();
1297
- // El orden importa, primero callbacks y despues componentes.
1298
- this.builder.setValueFormatter(valueFormatter);
1299
- this.builder.setPalette(palette);
1300
- this.builder.setColorResolver(colorResolver);
1301
- const product = this.builder.baseProduct;
1302
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1303
- // chart components
1304
- this.builder.addCommons();
1305
- const layoutOpts = {};
1306
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1307
- this.builder.addTooltip(data, overrides.tooltip);
1232
+ addXAxis(data, overrides, type = 'category') {
1233
+ const xAxis = [];
1234
+ const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1235
+ const valueAxisOptions = this.getValueAxisOptions(data, overrides);
1236
+ if (type == 'category') {
1237
+ xAxis.push(categoryAxisOptions);
1238
+ }
1239
+ else if (type == 'value') {
1240
+ xAxis.push(valueAxisOptions);
1241
+ }
1242
+ this.result.xAxis = xAxis;
1308
1243
  }
1309
- makeBoxplot(data, overrides, opts = {}) {
1310
- if (this.builder instanceof BoxPlotBuilder == false) {
1311
- return;
1244
+ addYAxis(data, overrides, type = 'value') {
1245
+ const yAxis = [];
1246
+ const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1247
+ const valueAxisOptions = this.getValueAxisOptions(data, overrides);
1248
+ if (type == 'category') {
1249
+ yAxis.push(categoryAxisOptions);
1312
1250
  }
1313
- const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1314
- x: 'value',
1315
- y: 'category',
1316
- }, statisticsKeys = undefined, } = opts;
1317
- this.builder.reset();
1318
- // El orden importa, primero callbacks y despues componentes.
1319
- this.builder.setValueFormatter(valueFormatter);
1320
- this.builder.setPalette(palette);
1321
- this.builder.setColorResolver(colorResolver);
1322
- const product = this.builder.baseProduct;
1323
- const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1324
- // chart components
1325
- this.builder.addCommons();
1326
- const layoutOpts = { axisTypes };
1327
- this.builder.addDataset(data, { statisticsKeys });
1328
- this.builder.addSeries(data, seriesOverrides, layoutOpts);
1329
- this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1330
- this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1331
- this.builder.addTooltip(data, overrides.tooltip);
1332
- this.builder.addDataZoom();
1251
+ else if (type == 'value') {
1252
+ yAxis.push(valueAxisOptions);
1253
+ }
1254
+ this.result.yAxis = yAxis;
1333
1255
  }
1334
- }
1335
-
1336
- /**
1337
- * EchartsRingComponent
1338
- *
1339
- * Especialista en visualización de tipo Ring. Soporta multi-medidas y KPI central.
1340
- * @see {@link vs-echarts/docs/charts/ring-patterns.md}
1341
- */
1342
- class EchartsRingComponent extends BaseEchartsComponent {
1343
- baseSeriesOptions = {
1344
- type: 'pie',
1345
- center: ['50%', '50%'],
1346
- avoidLabelOverlap: true,
1347
- minAngle: 3,
1348
- selectedMode: 'single',
1349
- selectedOffset: 4,
1350
- itemStyle: {
1351
- borderColor: '#fff',
1352
- },
1353
- label: { show: false },
1354
- emphasis: {
1355
- scale: true,
1356
- scaleSize: 2,
1357
- },
1358
- select: {
1359
- itemStyle: {
1360
- borderColor: EChartsTokens.sBorderColor,
1361
- shadowColor: EChartsTokens.sShadowColor,
1362
- borderWidth: 1,
1363
- shadowBlur: 4,
1256
+ addRadiusAxis(data, overrides) {
1257
+ const radiusAxis = [];
1258
+ /** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
1259
+ const radiusAxisOverrides = {
1260
+ zlevel: 10,
1261
+ axisTick: {
1262
+ show: false,
1364
1263
  },
1365
- },
1366
- animationType: 'scale',
1367
- animationEasing: 'elasticOut',
1368
- };
1369
- baseProduct = {
1370
- chartKey: 'ring',
1371
- baseOptions: {
1372
- series: this.baseSeriesOptions,
1373
- }
1374
- };
1375
- builder = new RingBuilder(this.baseProduct);
1376
- director = new VSECDirector(this.builder);
1377
- lastSelectedSeriesIndex = null;
1378
- lastSelectedDataIndex = null;
1379
- selectedPercent = null;
1380
- currentGraphicText = '';
1381
- constructor() {
1382
- super();
1383
- }
1384
- make() {
1385
- const makeOpts = {
1386
- valueFormatter: this.valueFormatter,
1387
- palette: this.palette,
1388
- colorResolver: this.colorResolver,
1264
+ axisLabel: {
1265
+ margin: 2,
1266
+ fontSize: 8,
1267
+ align: 'right',
1268
+ rotate: 20,
1269
+ verticalAlign: 'top',
1270
+ },
1271
+ splitLine: {
1272
+ show: true,
1273
+ lineStyle: {
1274
+ opacity: 0.2,
1275
+ type: 'solid',
1276
+ }
1277
+ },
1278
+ axisLine: {
1279
+ lineStyle: {
1280
+ type: 'dashed',
1281
+ },
1282
+ }
1389
1283
  };
1390
- this.director.makeRing(this.data, this.optionsOverrides, makeOpts);
1284
+ const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
1285
+ radiusAxis.push(radialAxisOptions);
1286
+ this.result.radiusAxis = radiusAxis;
1391
1287
  }
1392
- onInputChanges(changes) {
1393
- // Reset selection only if data changed
1394
- if (changes['data']) {
1395
- this.lastSelectedSeriesIndex = null;
1396
- this.lastSelectedDataIndex = null;
1397
- this.selectedPercent = null;
1398
- this.currentGraphicText = '';
1399
- }
1400
- super.onInputChanges(changes);
1288
+ addAngleAxis(data, overrides) {
1289
+ const angleAxis = [];
1290
+ const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1291
+ angleAxis.push(categoryAxisOptions);
1292
+ this.result.angleAxis = angleAxis;
1293
+ }
1294
+ addLegend() {
1295
+ this.result.legend = getLegendOptions();
1296
+ }
1297
+ // No-ops for ring charts
1298
+ addGraphic() { }
1299
+ addDataset(data) { }
1300
+ addDataZoom() {
1301
+ this.result.dataZoom = [
1302
+ {
1303
+ type: 'inside'
1304
+ },
1305
+ {
1306
+ type: 'slider',
1307
+ height: 20,
1308
+ bottom: 60
1309
+ }
1310
+ ];
1311
+ }
1312
+ getResult() {
1313
+ return this.result;
1401
1314
  }
1315
+ ;
1402
1316
  /**
1403
- * Maneja clics en los sectores del ring.
1404
- * Soporta múltiples series (anillos) y actualiza el KPI central.
1317
+ * Formatea un valor utilizando el callback inyectado.
1405
1318
  */
1406
- onChartClick(event) {
1407
- if (this.chartInstance && event && event.dataIndex !== undefined) {
1408
- const isSameSelection = event.seriesIndex === this.lastSelectedSeriesIndex &&
1409
- event.dataIndex === this.lastSelectedDataIndex;
1410
- if (isSameSelection) {
1411
- // Toggle OFF
1412
- this.lastSelectedSeriesIndex = null;
1413
- this.lastSelectedDataIndex = null;
1414
- this.selectedPercent = null;
1415
- this.setGraphicText('');
1416
- }
1417
- else {
1418
- // SELECT
1419
- this.lastSelectedSeriesIndex = event.seriesIndex;
1420
- this.lastSelectedDataIndex = event.dataIndex;
1421
- this.selectedPercent = (event.percent !== undefined) ? event.percent + '%' : '';
1422
- this.setGraphicText(this.selectedPercent);
1423
- }
1424
- this.chartClick.emit({
1425
- type: 'cross-filter',
1426
- data: {
1427
- category: event.name,
1428
- serie: event.seriesName,
1429
- value: event.value
1430
- }
1431
- });
1432
- }
1319
+ formatCellValue(value, key) {
1320
+ return this.valueFormatter(value, key);
1433
1321
  }
1434
- onChartMouseOver(event) {
1435
- if (this.selectedPercent === null && event && event.percent !== undefined) {
1436
- this.setGraphicText(event.percent + '%');
1322
+ // Setters
1323
+ /**
1324
+ * Permite inyectar un formateador de valores externo.
1325
+ */
1326
+ setValueFormatter(formatter) {
1327
+ if (formatter) {
1328
+ this.valueFormatter = formatter;
1437
1329
  }
1438
1330
  }
1439
- onChartMouseOut(event) {
1440
- if (this.selectedPercent === null) {
1441
- this.setGraphicText('');
1331
+ /**
1332
+ * Permite inyectar una paleta de colores básica.
1333
+ */
1334
+ setPalette(palette) {
1335
+ if (palette) {
1336
+ this.palette = palette;
1442
1337
  }
1443
1338
  }
1444
1339
  /**
1445
- * Actualiza el texto del Graphic central y persiste la selección en el modelo de opciones.
1340
+ * Permite inyectar un resolver de colores dinámico.
1446
1341
  */
1447
- setGraphicText(text) {
1448
- this.currentGraphicText = text;
1449
- // Persistencia de GRAPHIC (KPI central)
1450
- this.chartInstance?.setOption({
1451
- graphic: {
1452
- style: {
1453
- text: this.currentGraphicText,
1454
- opacity: this.currentGraphicText ? 1 : 0,
1455
- }
1456
- }
1457
- });
1342
+ setColorResolver(resolver) {
1343
+ if (resolver) {
1344
+ this.colorResolver = resolver;
1345
+ }
1346
+ }
1347
+ // Utils
1348
+ getCategoryAxisOptions(data, overrides) {
1349
+ // No explicit data needed on category axis when using ECharts dataset
1350
+ const categoryAxisOptionsOverrides = {
1351
+ ...overrides.categoryAxis[0]
1352
+ };
1353
+ const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
1354
+ return categoryAxisOptions;
1355
+ }
1356
+ getValueAxisOptions(data, overrides) {
1357
+ const valueAxisOptions = getValueAxisOptions();
1358
+ return valueAxisOptions;
1458
1359
  }
1459
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsRingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1460
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsRingComponent, isStandalone: true, selector: "vs-echarts-ring", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" \n echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartMouseOver)=\"onChartMouseOver($event)\" \n (chartMouseOut)=\"onChartMouseOut($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\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"] }] });
1461
1360
  }
1462
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsRingComponent, decorators: [{
1463
- type: Component,
1464
- args: [{ selector: 'vs-echarts-ring', standalone: true, imports: [
1465
- CommonModule,
1466
- NgxEchartsDirective,
1467
- ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" \n echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartMouseOver)=\"onChartMouseOver($event)\" \n (chartMouseOut)=\"onChartMouseOut($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\n></div>\n ", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1468
- }], ctorParameters: () => [] });
1469
1361
 
1470
1362
  /**
1471
1363
  * PieBuilder
@@ -1630,78 +1522,18 @@ class PieBuilder {
1630
1522
  }
1631
1523
 
1632
1524
  /**
1633
- * EchartsPieComponent
1525
+ * FunnelBuilder
1634
1526
  *
1635
- * Especialista en visualización de tipo Pie (Torta y Anillos concéntricos).
1636
- * La primera serie se dibuja como un gráfico de torta tradicional (lleno) y
1637
- * las subsecuentes como anillos concéntricos alrededor.
1527
+ * Concrete builder for Funnel charts.
1638
1528
  */
1639
- class EchartsPieComponent extends BaseEchartsComponent {
1640
- baseSeriesOptions = {
1641
- type: 'pie',
1642
- center: ['50%', '50%'],
1643
- avoidLabelOverlap: true,
1644
- minAngle: 3,
1645
- selectedMode: 'single',
1646
- selectedOffset: 4,
1647
- emphasis: {
1648
- scale: true,
1649
- scaleSize: 2,
1650
- },
1651
- select: {
1652
- itemStyle: {
1653
- borderColor: EChartsTokens.sBorderColor,
1654
- shadowColor: EChartsTokens.sShadowColor,
1655
- borderWidth: 1,
1656
- shadowBlur: 4,
1657
- },
1658
- },
1659
- animationType: 'scale',
1660
- animationEasing: 'elasticOut',
1661
- };
1662
- baseProduct = {
1663
- chartKey: 'pie',
1664
- baseOptions: {
1665
- series: this.baseSeriesOptions,
1666
- }
1667
- };
1668
- builder = new PieBuilder(this.baseProduct);
1669
- director = new VSECDirector(this.builder);
1670
- constructor() {
1671
- super();
1672
- }
1673
- make() {
1674
- const makeOpts = {
1675
- valueFormatter: this.valueFormatter,
1676
- palette: this.palette,
1677
- colorResolver: this.colorResolver,
1678
- };
1679
- this.director.makePie(this.data, this.optionsOverrides, makeOpts);
1680
- }
1681
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsPieComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1682
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsPieComponent, isStandalone: true, selector: "vs-echarts-pie", 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 (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\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"] }] });
1683
- }
1684
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsPieComponent, decorators: [{
1685
- type: Component,
1686
- args: [{ selector: 'vs-echarts-pie', standalone: true, imports: [
1687
- CommonModule,
1688
- NgxEchartsDirective,
1689
- ], 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 (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1690
- }], ctorParameters: () => [] });
1691
-
1692
- /**
1693
- * FunnelBuilder
1694
- *
1695
- * Concrete builder for Funnel charts.
1696
- */
1697
- class FunnelBuilder {
1698
- baseProduct;
1699
- valueFormatter = (value) => value.toLocaleString();
1700
- palette = [];
1701
- colorResolver;
1702
- result = {};
1703
- constructor(baseProduct) {
1704
- this.baseProduct = baseProduct;
1529
+ class FunnelBuilder {
1530
+ baseProduct;
1531
+ valueFormatter = (value) => value.toLocaleString();
1532
+ palette = [];
1533
+ colorResolver;
1534
+ result = {};
1535
+ constructor(baseProduct) {
1536
+ this.baseProduct = baseProduct;
1705
1537
  }
1706
1538
  reset() {
1707
1539
  this.result = {};
@@ -1793,91 +1625,10 @@ class FunnelBuilder {
1793
1625
  }
1794
1626
  }
1795
1627
 
1796
- /**
1797
- * EchartsFunnelComponent
1798
- *
1799
- * Component for Funnel visualization. Supports single and multiple measures.
1800
- */
1801
- class EchartsFunnelComponent extends BaseEchartsComponent {
1802
- baseSeriesOptions = {
1803
- type: 'funnel',
1804
- left: '10%',
1805
- width: '80%',
1806
- minSize: '0.01%',
1807
- maxSize: '100%',
1808
- sort: 'descending',
1809
- gap: 2,
1810
- label: {
1811
- show: true,
1812
- position: 'inside'
1813
- },
1814
- labelLine: {
1815
- show: false
1816
- },
1817
- itemStyle: {
1818
- borderColor: '#fff',
1819
- borderWidth: 1
1820
- },
1821
- emphasis: {
1822
- label: {
1823
- fontSize: 16
1824
- }
1825
- },
1826
- selectedMode: 'single',
1827
- select: {
1828
- label: {
1829
- fontSize: 16
1830
- },
1831
- itemStyle: {
1832
- borderWidth: 1,
1833
- borderColor: EChartsTokens.sBorderColor,
1834
- shadowColor: EChartsTokens.sShadowColor,
1835
- shadowBlur: 6,
1836
- }
1837
- },
1838
- };
1839
- baseProduct = {
1840
- chartKey: 'funnel',
1841
- baseOptions: {
1842
- series: this.baseSeriesOptions,
1843
- }
1844
- };
1845
- builder = new FunnelBuilder(this.baseProduct);
1846
- director = new VSECDirector(this.builder);
1847
- constructor() {
1848
- super();
1849
- }
1850
- make() {
1851
- const makeOpts = {
1852
- valueFormatter: this.valueFormatter,
1853
- palette: this.palette,
1854
- colorResolver: this.colorResolver,
1855
- };
1856
- this.director.makeFunnel(this.data, this.optionsOverrides, makeOpts);
1857
- }
1858
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsFunnelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1859
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsFunnelComponent, isStandalone: true, selector: "vs-echarts-funnel", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\" \n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\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"] }] });
1860
- }
1861
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsFunnelComponent, decorators: [{
1862
- type: Component,
1863
- args: [{ selector: 'vs-echarts-funnel', standalone: true, imports: [
1864
- CommonModule,
1865
- NgxEchartsDirective,
1866
- ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\" \n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1867
- }], ctorParameters: () => [] });
1868
-
1869
- /**
1870
- * Builder principal.
1871
- *
1872
- * Es muy completo, tiene soporte para ejes y sistema cartesiano polar.
1873
- *
1874
- * Puede verse utilizado en graficos como Lineas y Bars. Siempre que se pueda priorizar utilizar este.
1875
- */
1876
- class EChartBuilder {
1877
- baseProduct = undefined;
1628
+ class SunburstBuilder {
1629
+ baseProduct;
1878
1630
  valueFormatter = (value) => value.toLocaleString();
1879
1631
  palette = [];
1880
- // TODO: Hay que implementar un valor por defecto.
1881
1632
  colorResolver;
1882
1633
  result = {};
1883
1634
  constructor(baseProduct) {
@@ -1886,217 +1637,779 @@ class EChartBuilder {
1886
1637
  reset() {
1887
1638
  this.result = {};
1888
1639
  }
1889
- addCommons() {
1890
- const opts = {
1891
- palette: this.palette,
1892
- };
1893
- merge$1(this.result, getCommons(opts));
1894
- }
1895
- /**
1896
- *
1897
- * @param data
1898
- * @param overrides
1899
- * @returns
1900
- */
1901
- addSeries(data, overrides, opts) {
1902
- if (!data || !data.dimensions || !data.source || data.source.length === 0)
1640
+ addSeries(data, overrides) {
1641
+ if (!data || !data.source || data.source.length === 0) {
1903
1642
  return;
1904
- this.result.dataset = {
1905
- dimensions: data.dimensions,
1906
- source: data.source
1907
- };
1908
- const measureDims = data.dimensions.filter(d => d.name !== 'category');
1909
- const isPolar = opts?.coordinateSystem === 'polar';
1910
- const isHorizontal = opts?.axisTypes?.x === 'value' && opts?.axisTypes?.y === 'category';
1911
- const series = measureDims.map((dim) => {
1912
- const friendlyName = dim.displayName || dim.name;
1913
- const dimKey = dim.name;
1914
- let encode = {
1915
- x: 'category',
1916
- y: dimKey
1917
- };
1918
- if (isPolar) {
1919
- encode = {
1920
- angle: 'category',
1921
- radius: dimKey
1922
- };
1923
- }
1924
- else if (isHorizontal) {
1925
- encode = {
1926
- x: dimKey,
1927
- y: 'category'
1928
- };
1929
- }
1930
- const dynamicOverrides = {
1931
- name: friendlyName,
1932
- encode,
1643
+ }
1644
+ const sunburstData = mapHierarchicalData(data.source, data.dimensions);
1645
+ const depth = getTreeDepth(sunburstData);
1646
+ const levels = [];
1647
+ for (let i = 0; i <= depth; i++) {
1648
+ levels.push({
1933
1649
  label: {
1934
- formatter: (params) => {
1935
- const row = params.value;
1936
- const rawValue = (row && typeof row === 'object') ? row[dimKey] : params.value;
1937
- return this.formatCellValue(Number(rawValue ?? 0), dimKey);
1938
- }
1939
- }
1940
- };
1941
- const seriesOption = merge$1(dynamicOverrides, overrides);
1942
- // Inyectar el resolver de color si existe
1943
- if (this.colorResolver && seriesOption.itemStyle) {
1944
- seriesOption.itemStyle.color = this.colorResolver;
1650
+ show: false,
1651
+ },
1652
+ });
1653
+ }
1654
+ const dynamiSerieOptions = {
1655
+ name: '',
1656
+ data: sunburstData,
1657
+ levels: levels
1658
+ };
1659
+ const serie = merge$1({}, dynamiSerieOptions, overrides);
1660
+ if (this.colorResolver) {
1661
+ if (!serie.itemStyle) {
1662
+ serie.itemStyle = {};
1945
1663
  }
1946
- return seriesOption;
1947
- });
1948
- this.result.series = series;
1664
+ serie.itemStyle.color = this.colorResolver;
1665
+ }
1666
+ this.result.series = serie;
1949
1667
  }
1950
- /**
1951
- * TODO: Mejorar funcion, no me convence como se implemento el tooltip formatter.
1952
- * @param data
1953
- * @param overrides
1954
- */
1955
1668
  addTooltip(data, overrides) {
1956
- // inyecto formateador a overrides de tooltip
1957
1669
  merge$1(overrides, {
1958
- formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
1670
+ formatter: getTooltipFormatter(overrides.trigger || 'item', data, this.valueFormatter),
1959
1671
  });
1960
1672
  const tooltip = getTooltipOptions(overrides);
1961
1673
  this.result.tooltip = tooltip;
1962
1674
  }
1963
- addPolar() {
1964
- const polar = [];
1965
- polar.push({
1966
- radius: '65%',
1967
- center: ["50%", "44%"],
1968
- });
1969
- this.result.polar = polar;
1675
+ addCommons() {
1676
+ const opts = {
1677
+ palette: this.palette,
1678
+ };
1679
+ merge$1(this.result, getCommons(opts));
1970
1680
  }
1971
- addXAxis(data, overrides, type = 'category') {
1972
- const xAxis = [];
1973
- const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1974
- const valueAxisOptions = this.getValueAxisOptions(data, overrides);
1975
- if (type == 'category') {
1976
- xAxis.push(categoryAxisOptions);
1977
- }
1978
- else if (type == 'value') {
1979
- xAxis.push(valueAxisOptions);
1980
- }
1981
- this.result.xAxis = xAxis;
1681
+ getResult() {
1682
+ return this.result;
1982
1683
  }
1983
- addYAxis(data, overrides, type = 'value') {
1984
- const yAxis = [];
1985
- const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1986
- const valueAxisOptions = this.getValueAxisOptions(data, overrides);
1987
- if (type == 'category') {
1988
- yAxis.push(categoryAxisOptions);
1989
- }
1990
- else if (type == 'value') {
1991
- yAxis.push(valueAxisOptions);
1684
+ ;
1685
+ // No-ops
1686
+ addPolar() { }
1687
+ addXAxis(data, overrides, type) { }
1688
+ addYAxis(data, overrides, type) { }
1689
+ addRadiusAxis(data, overrides) { }
1690
+ addAngleAxis(data, overrides) { }
1691
+ addLegend() { }
1692
+ addDataZoom() { }
1693
+ addDataset(data, opts) { }
1694
+ addGraphic() { }
1695
+ // Setters
1696
+ /**
1697
+ * Permite inyectar un formateador de valores externo.
1698
+ */
1699
+ setValueFormatter(formatter) {
1700
+ if (formatter) {
1701
+ this.valueFormatter = formatter;
1992
1702
  }
1993
- this.result.yAxis = yAxis;
1994
1703
  }
1995
- addRadiusAxis(data, overrides) {
1996
- const radiusAxis = [];
1997
- /** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
1998
- const radiusAxisOverrides = {
1999
- zlevel: 10,
2000
- axisTick: {
2001
- show: false,
1704
+ /**
1705
+ * Permite inyectar una paleta de colores básica.
1706
+ */
1707
+ setPalette(palette) {
1708
+ if (palette) {
1709
+ this.palette = palette;
1710
+ }
1711
+ }
1712
+ /**
1713
+ * Permite inyectar un resolver de colores dinámico.
1714
+ */
1715
+ setColorResolver(resolver) {
1716
+ if (resolver) {
1717
+ this.colorResolver = resolver;
1718
+ }
1719
+ }
1720
+ }
1721
+
1722
+ /**
1723
+ * SankeyBuilder
1724
+ *
1725
+ * Builder concreto para el gráfico Sankey (diagrama de flujos de izquierda a derecha).
1726
+ */
1727
+ class SankeyBuilder {
1728
+ baseProduct;
1729
+ valueFormatter = (value) => value.toLocaleString();
1730
+ palette = [];
1731
+ colorResolver;
1732
+ result = {};
1733
+ constructor(baseProduct) {
1734
+ this.baseProduct = baseProduct;
1735
+ }
1736
+ reset() {
1737
+ this.result = {};
1738
+ }
1739
+ addSeries(data, overrides) {
1740
+ if (!data || !data.source || data.source.length === 0) {
1741
+ return;
1742
+ }
1743
+ // Identificar medidas (todas las dimensiones excepto 'category')
1744
+ const measureKeys = data.dimensions
1745
+ .filter((d) => d.name !== "category")
1746
+ .map((d) => d.name);
1747
+ // Función auxiliar para sumarizar valores de medidas en caso de haber más de una
1748
+ const getNodeValue = (node) => {
1749
+ return measureKeys.reduce((sum, key) => sum + (Number(node[key]) || 0), 0);
1750
+ };
1751
+ const nodesMap = new Map();
1752
+ const linksMap = new Map();
1753
+ // Función recursiva para aplanar datos jerárquicos a nodos y enlaces
1754
+ const traverse = (nodeList, level, parentId) => {
1755
+ for (const node of nodeList) {
1756
+ const category = node.category;
1757
+ const currentId = `${category}___${level}`;
1758
+ const value = getNodeValue(node);
1759
+ nodesMap.set(currentId, (nodesMap.get(currentId) || 0) + value);
1760
+ if (parentId) {
1761
+ const linkKey = `${parentId}--->${currentId}`;
1762
+ if (linksMap.has(linkKey)) {
1763
+ linksMap.get(linkKey).value += value;
1764
+ }
1765
+ else {
1766
+ linksMap.set(linkKey, {
1767
+ source: parentId,
1768
+ target: currentId,
1769
+ value: value,
1770
+ });
1771
+ }
1772
+ }
1773
+ if (node.children && node.children.length > 0) {
1774
+ traverse(node.children, level + 1, currentId);
1775
+ }
1776
+ }
1777
+ };
1778
+ // Comenzar el recorrido en el nivel 0
1779
+ traverse(data.source, 0);
1780
+ // al menos un nivel de links para dibujar.
1781
+ if (linksMap.size === 0)
1782
+ return;
1783
+ // Mapear nodos acumulados a la estructura requerida por ECharts (name y opcionalmente color, sin value redundante)
1784
+ const nodes = Array.from(nodesMap.keys()).map((currentId) => {
1785
+ const category = currentId.split("___")[0];
1786
+ const nodeItem = {
1787
+ name: currentId,
1788
+ };
1789
+ if (this.colorResolver) {
1790
+ const color = this.colorResolver({ name: category, data: nodeItem });
1791
+ if (color) {
1792
+ nodeItem.itemStyle = { color };
1793
+ }
1794
+ }
1795
+ return nodeItem;
1796
+ });
1797
+ const dynamicSerieOptions = {
1798
+ type: "sankey",
1799
+ orient: "horizontal", // De izquierda a derecha
1800
+ draggable: true,
1801
+ emphasis: {
1802
+ focus: "adjacency",
2002
1803
  },
2003
- axisLabel: {
2004
- margin: 2,
2005
- fontSize: 8,
2006
- align: 'right',
2007
- rotate: 20,
2008
- verticalAlign: 'top',
1804
+ lineStyle: {
1805
+ color: "source",
1806
+ opacity: 0.25,
1807
+ curveness: 0.5,
2009
1808
  },
2010
- splitLine: {
1809
+ label: {
2011
1810
  show: true,
2012
- lineStyle: {
2013
- opacity: 0.2,
2014
- type: 'solid',
2015
- }
2016
- },
2017
- axisLine: {
2018
- lineStyle: {
2019
- type: 'dashed',
1811
+ position: "right",
1812
+ fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif",
1813
+ fontSize: 10,
1814
+ formatter: (params) => {
1815
+ // Remover el sufijo de nivel de la etiqueta visual
1816
+ return params.name.split("___")[0];
2020
1817
  },
2021
- }
1818
+ },
1819
+ roam: true,
1820
+ data: nodes,
1821
+ links: Array.from(linksMap.values()),
2022
1822
  };
2023
- const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
2024
- radiusAxis.push(radialAxisOptions);
2025
- this.result.radiusAxis = radiusAxis;
2026
- }
2027
- addAngleAxis(data, overrides) {
2028
- const angleAxis = [];
2029
- const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
2030
- angleAxis.push(categoryAxisOptions);
2031
- this.result.angleAxis = angleAxis;
1823
+ const serie = merge$1({}, dynamicSerieOptions, overrides);
1824
+ if (this.colorResolver && !serie.itemStyle) {
1825
+ serie.itemStyle = {};
1826
+ }
1827
+ if (this.colorResolver && serie.itemStyle) {
1828
+ serie.itemStyle.color = this.colorResolver;
1829
+ }
1830
+ this.result.series = serie;
2032
1831
  }
2033
- addLegend() {
2034
- this.result.legend = getLegendOptions();
1832
+ addTooltip(data, overrides) {
1833
+ merge$1(overrides, {
1834
+ formatter: getTooltipFormatter(overrides.trigger || 'item', data, this.valueFormatter),
1835
+ });
1836
+ const tooltip = getTooltipOptions(overrides);
1837
+ this.result.tooltip = tooltip;
2035
1838
  }
2036
- // No-ops for ring charts
2037
- addGraphic() { }
1839
+ addPolar() { }
1840
+ addXAxis(data, overrides, type) { }
1841
+ addYAxis(data, overrides, type) { }
1842
+ addRadiusAxis(data, overrides) { }
1843
+ addAngleAxis(data, overrides) { }
1844
+ addLegend() { }
1845
+ addDataZoom() { }
2038
1846
  addDataset(data, opts) { }
2039
- addDataZoom() {
2040
- this.result.dataZoom = [
2041
- {
2042
- type: 'inside'
2043
- },
2044
- {
2045
- type: 'slider',
2046
- height: 20,
2047
- bottom: 60
2048
- }
2049
- ];
1847
+ addCommons() {
1848
+ const opts = {
1849
+ palette: this.palette,
1850
+ };
1851
+ merge$1(this.result, getCommons(opts));
2050
1852
  }
1853
+ addGraphic() { }
2051
1854
  getResult() {
2052
1855
  return this.result;
2053
1856
  }
2054
- ;
2055
- /**
2056
- * Formatea un valor utilizando el callback inyectado.
2057
- */
2058
- formatCellValue(value, key) {
2059
- return this.valueFormatter(value, key);
2060
- }
2061
- // Setters
2062
- /**
2063
- * Permite inyectar un formateador de valores externo.
2064
- */
2065
1857
  setValueFormatter(formatter) {
2066
1858
  if (formatter) {
2067
1859
  this.valueFormatter = formatter;
2068
1860
  }
2069
1861
  }
2070
- /**
2071
- * Permite inyectar una paleta de colores básica.
2072
- */
2073
1862
  setPalette(palette) {
2074
1863
  if (palette) {
2075
1864
  this.palette = palette;
2076
1865
  }
2077
1866
  }
2078
- /**
2079
- * Permite inyectar un resolver de colores dinámico.
2080
- */
2081
1867
  setColorResolver(resolver) {
2082
1868
  if (resolver) {
2083
1869
  this.colorResolver = resolver;
2084
1870
  }
2085
1871
  }
2086
- // Utils
2087
- getCategoryAxisOptions(data, overrides) {
2088
- // No explicit data needed on category axis when using ECharts dataset
2089
- const categoryAxisOptionsOverrides = {
2090
- ...overrides.categoryAxis[0]
2091
- };
2092
- const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
2093
- return categoryAxisOptions;
1872
+ }
1873
+
1874
+ /**
1875
+ * Director de Builds.
1876
+ */
1877
+ class VSECDirector {
1878
+ builder = undefined;
1879
+ constructor(builder) {
1880
+ this.builder = builder;
2094
1881
  }
2095
- getValueAxisOptions(data, overrides) {
2096
- const valueAxisOptions = getValueAxisOptions();
2097
- return valueAxisOptions;
1882
+ makeBar(data, overrides, opts = {}) {
1883
+ if (this.builder instanceof EChartBuilder == false) {
1884
+ return;
1885
+ }
1886
+ ;
1887
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1888
+ x: 'category',
1889
+ y: 'value',
1890
+ // TODO agregar radius y angle axis
1891
+ } } = opts;
1892
+ this.builder.reset();
1893
+ // El orden importa, primero callbacks y despues componentes.
1894
+ // chart callbaks
1895
+ if (valueFormatter)
1896
+ this.builder.setValueFormatter(valueFormatter);
1897
+ if (palette)
1898
+ this.builder.setPalette(palette);
1899
+ if (colorResolver)
1900
+ this.builder.setColorResolver(colorResolver);
1901
+ const product = this.builder.baseProduct;
1902
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1903
+ // chart components
1904
+ this.builder.addCommons();
1905
+ const seriesOptions = { axisTypes };
1906
+ this.builder.addSeries(data, seriesOverrides, seriesOptions);
1907
+ this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1908
+ this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1909
+ this.builder.addTooltip(data, overrides.tooltip);
1910
+ this.builder.addLegend();
1911
+ }
1912
+ makeBarRadial(data, overrides, opts = {}) {
1913
+ if (this.builder instanceof EChartBuilder == false) {
1914
+ return;
1915
+ }
1916
+ ;
1917
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1918
+ x: 'category',
1919
+ y: 'value',
1920
+ // TODO agregar radius y angle axis
1921
+ } } = opts;
1922
+ this.builder.reset();
1923
+ // El orden importa, primero callbacks y despues componentes.
1924
+ // chart callbaks
1925
+ if (valueFormatter)
1926
+ this.builder.setValueFormatter(valueFormatter);
1927
+ if (palette)
1928
+ this.builder.setPalette(palette);
1929
+ if (colorResolver)
1930
+ this.builder.setColorResolver(colorResolver);
1931
+ const product = this.builder.baseProduct;
1932
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1933
+ // chart components
1934
+ this.builder.addCommons();
1935
+ const seriesOptions = { axisTypes, coordinateSystem: 'polar' };
1936
+ this.builder.addSeries(data, seriesOverrides, seriesOptions);
1937
+ this.builder.addPolar();
1938
+ this.builder.addAngleAxis(data, overrides['axis']);
1939
+ this.builder.addRadiusAxis(data, overrides['axis']);
1940
+ this.builder.addTooltip(data, overrides.tooltip);
1941
+ this.builder.addLegend();
1942
+ }
1943
+ makeLine(data, overrides, opts = {}) {
1944
+ if (this.builder instanceof EChartBuilder == false) {
1945
+ return;
1946
+ }
1947
+ ;
1948
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1949
+ x: 'category',
1950
+ y: 'value',
1951
+ // TODO agregar radius y angle axis
1952
+ } } = opts;
1953
+ this.builder.reset();
1954
+ // El orden importa, primero callbacks y despues componentes.
1955
+ // chart callbaks
1956
+ if (valueFormatter)
1957
+ this.builder.setValueFormatter(valueFormatter);
1958
+ if (palette)
1959
+ this.builder.setPalette(palette);
1960
+ if (colorResolver)
1961
+ this.builder.setColorResolver(colorResolver);
1962
+ const product = this.builder.baseProduct;
1963
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1964
+ // chart components
1965
+ this.builder.addCommons();
1966
+ const seriesOptions = { axisTypes };
1967
+ this.builder.addSeries(data, seriesOverrides, seriesOptions);
1968
+ this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1969
+ this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1970
+ this.builder.addTooltip(data, overrides.tooltip);
1971
+ this.builder.addLegend();
1972
+ }
1973
+ makeScatter(data, overrides, opts = {}) {
1974
+ if (this.builder instanceof EChartBuilder == false) {
1975
+ return;
1976
+ }
1977
+ ;
1978
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
1979
+ x: 'category',
1980
+ y: 'value',
1981
+ } } = opts;
1982
+ this.builder.reset();
1983
+ // El orden importa, primero callbacks y despues componentes.
1984
+ // chart callbaks
1985
+ if (valueFormatter)
1986
+ this.builder.setValueFormatter(valueFormatter);
1987
+ if (palette)
1988
+ this.builder.setPalette(palette);
1989
+ if (colorResolver)
1990
+ this.builder.setColorResolver(colorResolver);
1991
+ const product = this.builder.baseProduct;
1992
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
1993
+ // chart components
1994
+ this.builder.addCommons();
1995
+ const seriesOptions = { axisTypes };
1996
+ this.builder.addSeries(data, seriesOverrides, seriesOptions);
1997
+ this.builder.addXAxis(data, overrides.axis, axisTypes.x);
1998
+ this.builder.addYAxis(data, overrides.axis, axisTypes.y);
1999
+ this.builder.addTooltip(data, overrides.tooltip);
2000
+ this.builder.addLegend();
2001
+ }
2002
+ makeRing(data, overrides, opts = {}) {
2003
+ if (this.builder instanceof RingBuilder == false) {
2004
+ return;
2005
+ }
2006
+ ;
2007
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
2008
+ this.builder.reset();
2009
+ // El orden importa, primero callbacks y despues componentes.
2010
+ // chart callbaks
2011
+ if (valueFormatter)
2012
+ this.builder.setValueFormatter(valueFormatter);
2013
+ if (palette)
2014
+ this.builder.setPalette(palette);
2015
+ if (colorResolver)
2016
+ this.builder.setColorResolver(colorResolver);
2017
+ const product = this.builder.baseProduct;
2018
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
2019
+ // chart components
2020
+ this.builder.addCommons();
2021
+ this.builder.addSeries(data, seriesOverrides);
2022
+ this.builder.addGraphic();
2023
+ this.builder.addTooltip(data, overrides.tooltip);
2024
+ this.builder.addLegend();
2025
+ }
2026
+ makePie(data, overrides, opts = {}) {
2027
+ if (this.builder instanceof PieBuilder == false) {
2028
+ return;
2029
+ }
2030
+ ;
2031
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
2032
+ this.builder.reset();
2033
+ // El orden importa, primero callbacks y despues componentes.
2034
+ // chart callbaks
2035
+ if (valueFormatter)
2036
+ this.builder.setValueFormatter(valueFormatter);
2037
+ if (palette)
2038
+ this.builder.setPalette(palette);
2039
+ if (colorResolver)
2040
+ this.builder.setColorResolver(colorResolver);
2041
+ const product = this.builder.baseProduct;
2042
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
2043
+ // chart components
2044
+ this.builder.addCommons();
2045
+ this.builder.addSeries(data, seriesOverrides);
2046
+ this.builder.addTooltip(data, overrides.tooltip);
2047
+ this.builder.addLegend();
2048
+ }
2049
+ makeFunnel(data, overrides, opts = {}) {
2050
+ if (this.builder instanceof FunnelBuilder == false) {
2051
+ return;
2052
+ }
2053
+ ;
2054
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
2055
+ this.builder.reset();
2056
+ // El orden importa, primero callbacks y despues componentes.
2057
+ // chart callbaks
2058
+ if (valueFormatter)
2059
+ this.builder.setValueFormatter(valueFormatter);
2060
+ if (palette)
2061
+ this.builder.setPalette(palette);
2062
+ if (colorResolver)
2063
+ this.builder.setColorResolver(colorResolver);
2064
+ const product = this.builder.baseProduct;
2065
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
2066
+ // chart components
2067
+ this.builder.addCommons();
2068
+ this.builder.addSeries(data, seriesOverrides);
2069
+ this.builder.addTooltip(data, overrides.tooltip);
2070
+ this.builder.addLegend();
2071
+ }
2072
+ makeSunburst(data, overrides, opts = {}) {
2073
+ if (this.builder instanceof SunburstBuilder == false) {
2074
+ return;
2075
+ }
2076
+ ;
2077
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
2078
+ this.builder.reset();
2079
+ // El orden importa, primero callbacks y despues componentes.
2080
+ // chart callbaks
2081
+ if (valueFormatter)
2082
+ this.builder.setValueFormatter(valueFormatter);
2083
+ if (palette)
2084
+ this.builder.setPalette(palette);
2085
+ if (colorResolver)
2086
+ this.builder.setColorResolver(colorResolver);
2087
+ const product = this.builder.baseProduct;
2088
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
2089
+ // chart components
2090
+ this.builder.addCommons();
2091
+ this.builder.addSeries(data, seriesOverrides);
2092
+ this.builder.addTooltip(data, overrides.tooltip);
2093
+ }
2094
+ makeSankey(data, overrides, opts = {}) {
2095
+ if (this.builder instanceof SankeyBuilder == false) {
2096
+ return;
2097
+ }
2098
+ ;
2099
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
2100
+ this.builder.reset();
2101
+ // El orden importa, primero callbacks y despues componentes.
2102
+ // chart callbaks
2103
+ if (valueFormatter)
2104
+ this.builder.setValueFormatter(valueFormatter);
2105
+ if (palette)
2106
+ this.builder.setPalette(palette);
2107
+ if (colorResolver)
2108
+ this.builder.setColorResolver(colorResolver);
2109
+ const product = this.builder.baseProduct;
2110
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
2111
+ // chart components
2112
+ this.builder.addCommons();
2113
+ this.builder.addSeries(data, seriesOverrides);
2114
+ this.builder.addTooltip(data, overrides.tooltip);
2115
+ }
2116
+ makeBoxplot(data, overrides, opts = {}) {
2117
+ if (this.builder instanceof BoxPlotBuilder == false) {
2118
+ return;
2119
+ }
2120
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
2121
+ x: 'value',
2122
+ y: 'category',
2123
+ }, statisticsKeys = undefined, } = opts;
2124
+ this.builder.reset();
2125
+ // El orden importa, primero callbacks y despues componentes.
2126
+ // chart callbaks
2127
+ if (valueFormatter)
2128
+ this.builder.setValueFormatter(valueFormatter);
2129
+ if (palette)
2130
+ this.builder.setPalette(palette);
2131
+ if (colorResolver)
2132
+ this.builder.setColorResolver(colorResolver);
2133
+ const product = this.builder.baseProduct;
2134
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
2135
+ // chart components
2136
+ this.builder.addCommons();
2137
+ const configOpts = { axisTypes };
2138
+ this.builder.addDataset(data, { statisticsKeys });
2139
+ this.builder.addSeries(data, seriesOverrides, configOpts);
2140
+ this.builder.addXAxis(data, overrides.axis, axisTypes.x);
2141
+ this.builder.addYAxis(data, overrides.axis, axisTypes.y);
2142
+ this.builder.addTooltip(data, overrides.tooltip);
2143
+ this.builder.addDataZoom();
2144
+ }
2145
+ }
2146
+
2147
+ /**
2148
+ * EchartsRingComponent
2149
+ *
2150
+ * Especialista en visualización de tipo Ring. Soporta multi-medidas y KPI central.
2151
+ * @see {@link vs-echarts/docs/charts/ring-patterns.md}
2152
+ */
2153
+ class EchartsRingComponent extends BaseEchartsComponent {
2154
+ baseSeriesOptions = {
2155
+ type: 'pie',
2156
+ center: ['50%', '50%'],
2157
+ avoidLabelOverlap: true,
2158
+ minAngle: 3,
2159
+ selectedMode: 'single',
2160
+ selectedOffset: 4,
2161
+ itemStyle: {
2162
+ borderColor: '#fff',
2163
+ },
2164
+ label: { show: false },
2165
+ emphasis: {
2166
+ scale: true,
2167
+ scaleSize: 2,
2168
+ },
2169
+ select: {
2170
+ itemStyle: {
2171
+ borderColor: EChartsTokens.sBorderColor,
2172
+ shadowColor: EChartsTokens.sShadowColor,
2173
+ borderWidth: 1,
2174
+ shadowBlur: 4,
2175
+ },
2176
+ },
2177
+ animationType: 'scale',
2178
+ animationEasing: 'elasticOut',
2179
+ };
2180
+ baseProduct = {
2181
+ chartKey: 'ring',
2182
+ baseOptions: {
2183
+ series: this.baseSeriesOptions,
2184
+ }
2185
+ };
2186
+ builder = new RingBuilder(this.baseProduct);
2187
+ director = new VSECDirector(this.builder);
2188
+ lastSelectedSeriesIndex = null;
2189
+ lastSelectedDataIndex = null;
2190
+ selectedPercent = null;
2191
+ currentGraphicText = '';
2192
+ constructor() {
2193
+ super();
2194
+ }
2195
+ make() {
2196
+ const makeOpts = {
2197
+ valueFormatter: this.valueFormatter,
2198
+ palette: this.palette,
2199
+ colorResolver: this.colorResolver,
2200
+ };
2201
+ this.director.makeRing(this.data, this.optionsOverrides, makeOpts);
2202
+ }
2203
+ onInputChanges(changes) {
2204
+ // Reset selection only if data changed
2205
+ if (changes['data']) {
2206
+ this.lastSelectedSeriesIndex = null;
2207
+ this.lastSelectedDataIndex = null;
2208
+ this.selectedPercent = null;
2209
+ this.currentGraphicText = '';
2210
+ }
2211
+ super.onInputChanges(changes);
2212
+ }
2213
+ /**
2214
+ * Maneja clics en los sectores del ring.
2215
+ * Soporta múltiples series (anillos) y actualiza el KPI central.
2216
+ */
2217
+ onChartClick(event) {
2218
+ if (this.chartInstance && event && event.dataIndex !== undefined) {
2219
+ const isSameSelection = event.seriesIndex === this.lastSelectedSeriesIndex &&
2220
+ event.dataIndex === this.lastSelectedDataIndex;
2221
+ if (isSameSelection) {
2222
+ // Toggle OFF
2223
+ this.lastSelectedSeriesIndex = null;
2224
+ this.lastSelectedDataIndex = null;
2225
+ this.selectedPercent = null;
2226
+ this.setGraphicText('');
2227
+ }
2228
+ else {
2229
+ // SELECT
2230
+ this.lastSelectedSeriesIndex = event.seriesIndex;
2231
+ this.lastSelectedDataIndex = event.dataIndex;
2232
+ this.selectedPercent = (event.percent !== undefined) ? event.percent + '%' : '';
2233
+ this.setGraphicText(this.selectedPercent);
2234
+ }
2235
+ this.chartClick.emit({
2236
+ type: 'cross-filter',
2237
+ data: {
2238
+ category: event.name,
2239
+ serie: event.seriesName,
2240
+ value: event.value
2241
+ }
2242
+ });
2243
+ }
2244
+ }
2245
+ onChartMouseOver(event) {
2246
+ if (this.selectedPercent === null && event && event.percent !== undefined) {
2247
+ this.setGraphicText(event.percent + '%');
2248
+ }
2249
+ }
2250
+ onChartMouseOut(event) {
2251
+ if (this.selectedPercent === null) {
2252
+ this.setGraphicText('');
2253
+ }
2254
+ }
2255
+ /**
2256
+ * Actualiza el texto del Graphic central y persiste la selección en el modelo de opciones.
2257
+ */
2258
+ setGraphicText(text) {
2259
+ this.currentGraphicText = text;
2260
+ // Persistencia de GRAPHIC (KPI central)
2261
+ this.chartInstance?.setOption({
2262
+ graphic: {
2263
+ style: {
2264
+ text: this.currentGraphicText,
2265
+ opacity: this.currentGraphicText ? 1 : 0,
2266
+ }
2267
+ }
2268
+ });
2269
+ }
2270
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsRingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2271
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsRingComponent, isStandalone: true, selector: "vs-echarts-ring", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" \n echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartMouseOver)=\"onChartMouseOver($event)\" \n (chartMouseOut)=\"onChartMouseOut($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\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"] }] });
2272
+ }
2273
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsRingComponent, decorators: [{
2274
+ type: Component,
2275
+ args: [{ selector: 'vs-echarts-ring', standalone: true, imports: [
2276
+ CommonModule,
2277
+ NgxEchartsDirective,
2278
+ ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" \n echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\"\n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartMouseOver)=\"onChartMouseOver($event)\" \n (chartMouseOut)=\"onChartMouseOut($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\n></div>\n ", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
2279
+ }], ctorParameters: () => [] });
2280
+
2281
+ /**
2282
+ * EchartsPieComponent
2283
+ *
2284
+ * Especialista en visualización de tipo Pie (Torta y Anillos concéntricos).
2285
+ * La primera serie se dibuja como un gráfico de torta tradicional (lleno) y
2286
+ * las subsecuentes como anillos concéntricos alrededor.
2287
+ */
2288
+ class EchartsPieComponent extends BaseEchartsComponent {
2289
+ baseSeriesOptions = {
2290
+ type: 'pie',
2291
+ center: ['50%', '50%'],
2292
+ avoidLabelOverlap: true,
2293
+ minAngle: 3,
2294
+ selectedMode: 'single',
2295
+ selectedOffset: 4,
2296
+ emphasis: {
2297
+ scale: true,
2298
+ scaleSize: 2,
2299
+ },
2300
+ select: {
2301
+ itemStyle: {
2302
+ borderColor: EChartsTokens.sBorderColor,
2303
+ shadowColor: EChartsTokens.sShadowColor,
2304
+ borderWidth: 1,
2305
+ shadowBlur: 4,
2306
+ },
2307
+ },
2308
+ animationType: 'scale',
2309
+ animationEasing: 'elasticOut',
2310
+ };
2311
+ baseProduct = {
2312
+ chartKey: 'pie',
2313
+ baseOptions: {
2314
+ series: this.baseSeriesOptions,
2315
+ }
2316
+ };
2317
+ builder = new PieBuilder(this.baseProduct);
2318
+ director = new VSECDirector(this.builder);
2319
+ constructor() {
2320
+ super();
2321
+ }
2322
+ make() {
2323
+ const makeOpts = {
2324
+ valueFormatter: this.valueFormatter,
2325
+ palette: this.palette,
2326
+ colorResolver: this.colorResolver,
2327
+ };
2328
+ this.director.makePie(this.data, this.optionsOverrides, makeOpts);
2329
+ }
2330
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsPieComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2331
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsPieComponent, isStandalone: true, selector: "vs-echarts-pie", 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 (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\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"] }] });
2332
+ }
2333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsPieComponent, decorators: [{
2334
+ type: Component,
2335
+ args: [{ selector: 'vs-echarts-pie', standalone: true, imports: [
2336
+ CommonModule,
2337
+ NgxEchartsDirective,
2338
+ ], 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 (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
2339
+ }], ctorParameters: () => [] });
2340
+
2341
+ /**
2342
+ * EchartsFunnelComponent
2343
+ *
2344
+ * Component for Funnel visualization. Supports single and multiple measures.
2345
+ */
2346
+ class EchartsFunnelComponent extends BaseEchartsComponent {
2347
+ baseSeriesOptions = {
2348
+ type: 'funnel',
2349
+ left: '10%',
2350
+ width: '80%',
2351
+ minSize: '0.01%',
2352
+ maxSize: '100%',
2353
+ sort: 'descending',
2354
+ gap: 2,
2355
+ label: {
2356
+ show: true,
2357
+ position: 'inside'
2358
+ },
2359
+ labelLine: {
2360
+ show: false
2361
+ },
2362
+ itemStyle: {
2363
+ borderColor: '#fff',
2364
+ borderWidth: 1
2365
+ },
2366
+ emphasis: {
2367
+ label: {
2368
+ fontSize: 16
2369
+ }
2370
+ },
2371
+ selectedMode: 'single',
2372
+ select: {
2373
+ label: {
2374
+ fontSize: 16
2375
+ },
2376
+ itemStyle: {
2377
+ borderWidth: 1,
2378
+ borderColor: EChartsTokens.sBorderColor,
2379
+ shadowColor: EChartsTokens.sShadowColor,
2380
+ shadowBlur: 6,
2381
+ }
2382
+ },
2383
+ };
2384
+ baseProduct = {
2385
+ chartKey: 'funnel',
2386
+ baseOptions: {
2387
+ series: this.baseSeriesOptions,
2388
+ }
2389
+ };
2390
+ builder = new FunnelBuilder(this.baseProduct);
2391
+ director = new VSECDirector(this.builder);
2392
+ constructor() {
2393
+ super();
2394
+ }
2395
+ make() {
2396
+ const makeOpts = {
2397
+ valueFormatter: this.valueFormatter,
2398
+ palette: this.palette,
2399
+ colorResolver: this.colorResolver,
2400
+ };
2401
+ this.director.makeFunnel(this.data, this.optionsOverrides, makeOpts);
2098
2402
  }
2403
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsFunnelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2404
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsFunnelComponent, isStandalone: true, selector: "vs-echarts-funnel", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\" \n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\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"] }] });
2099
2405
  }
2406
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsFunnelComponent, decorators: [{
2407
+ type: Component,
2408
+ args: [{ selector: 'vs-echarts-funnel', standalone: true, imports: [
2409
+ CommonModule,
2410
+ NgxEchartsDirective,
2411
+ ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\" \n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event, { fixPieDataIndexInside: true })\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
2412
+ }], ctorParameters: () => [] });
2100
2413
 
2101
2414
  class EchartsBarComponent extends BaseEchartsComponent {
2102
2415
  /**
@@ -2502,100 +2815,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2502
2815
  ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts \n [options]=\"{}\"\n [initOpts]=\"initOptions\" \n [autoResize]=\"true\" \n (chartInit)=\"onChartInit($event)\" \n (chartClick)=\"onChartClick($event)\" \n (chartSelectChanged)=\"onChartSelectChanged($event)\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
2503
2816
  }], ctorParameters: () => [] });
2504
2817
 
2505
- class SunburstBuilder {
2506
- baseProduct;
2507
- valueFormatter = (value) => value.toLocaleString();
2508
- palette = [];
2509
- // TODO: Hay que implementar un valor por defecto.
2510
- colorResolver;
2511
- result = {};
2512
- constructor(baseProduct) {
2513
- this.baseProduct = baseProduct;
2514
- }
2515
- reset() {
2516
- this.result = {};
2517
- }
2518
- addSeries(data, overrides) {
2519
- if (!data || !data.source || data.source.length === 0) {
2520
- return;
2521
- }
2522
- const sunburstData = mapHierarchicalData(data.source, data.dimensions);
2523
- const depth = getTreeDepth(sunburstData);
2524
- const levels = [];
2525
- for (let i = 0; i <= depth; i++) {
2526
- levels.push({
2527
- label: {
2528
- show: false,
2529
- },
2530
- });
2531
- }
2532
- const dynamiSerieOptions = {
2533
- name: '',
2534
- data: sunburstData,
2535
- levels: levels
2536
- };
2537
- const serie = merge$1({}, dynamiSerieOptions, overrides);
2538
- if (this.colorResolver) {
2539
- if (!serie.itemStyle) {
2540
- serie.itemStyle = {};
2541
- }
2542
- serie.itemStyle.color = this.colorResolver;
2543
- }
2544
- this.result.series = serie;
2545
- }
2546
- addTooltip(data, overrides) {
2547
- merge$1(overrides, {
2548
- formatter: getTooltipFormatter(overrides.trigger || 'item', data, this.valueFormatter),
2549
- });
2550
- const tooltip = getTooltipOptions(overrides);
2551
- this.result.tooltip = tooltip;
2552
- }
2553
- addCommons() {
2554
- const opts = {
2555
- palette: this.palette,
2556
- };
2557
- merge$1(this.result, getCommons(opts));
2558
- }
2559
- addGraphic() { }
2560
- getResult() {
2561
- return this.result;
2562
- }
2563
- ;
2564
- addPolar() { }
2565
- addXAxis(data, overrides, type) { }
2566
- addYAxis(data, overrides, type) { }
2567
- addRadiusAxis(data, overrides) { }
2568
- addAngleAxis(data, overrides) { }
2569
- addLegend() { }
2570
- addDataZoom() { }
2571
- addDataset(data, opts) { }
2572
- // Setters
2573
- /**
2574
- * Permite inyectar un formateador de valores externo.
2575
- */
2576
- setValueFormatter(formatter) {
2577
- if (formatter) {
2578
- this.valueFormatter = formatter;
2579
- }
2580
- }
2581
- /**
2582
- * Permite inyectar una paleta de colores básica.
2583
- */
2584
- setPalette(palette) {
2585
- if (palette) {
2586
- this.palette = palette;
2587
- }
2588
- }
2589
- /**
2590
- * Permite inyectar un resolver de colores dinámico.
2591
- */
2592
- setColorResolver(resolver) {
2593
- if (resolver) {
2594
- this.colorResolver = resolver;
2595
- }
2596
- }
2597
- }
2598
-
2599
2818
  class EChartsSunburstComponent extends BaseEchartsComponent {
2600
2819
  baseSeriesOptions = {
2601
2820
  type: 'sunburst',
@@ -2644,158 +2863,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2644
2863
  ], 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"] }]
2645
2864
  }] });
2646
2865
 
2647
- /**
2648
- * SankeyBuilder
2649
- *
2650
- * Builder concreto para el gráfico Sankey (diagrama de flujos de izquierda a derecha).
2651
- */
2652
- class SankeyBuilder {
2653
- baseProduct;
2654
- valueFormatter = (value) => value.toLocaleString();
2655
- palette = [];
2656
- colorResolver;
2657
- result = {};
2658
- constructor(baseProduct) {
2659
- this.baseProduct = baseProduct;
2660
- }
2661
- reset() {
2662
- this.result = {};
2663
- }
2664
- addSeries(data, overrides) {
2665
- if (!data || !data.source || data.source.length === 0) {
2666
- return;
2667
- }
2668
- // Identificar medidas (todas las dimensiones excepto 'category')
2669
- const measureKeys = data.dimensions
2670
- .filter((d) => d.name !== "category")
2671
- .map((d) => d.name);
2672
- // Función auxiliar para sumarizar valores de medidas en caso de haber más de una
2673
- const getNodeValue = (node) => {
2674
- return measureKeys.reduce((sum, key) => sum + (Number(node[key]) || 0), 0);
2675
- };
2676
- const nodesMap = new Map();
2677
- const linksMap = new Map();
2678
- // Función recursiva para aplanar datos jerárquicos a nodos y enlaces
2679
- const traverse = (nodeList, level, parentId) => {
2680
- for (const node of nodeList) {
2681
- const category = node.category;
2682
- const currentId = `${category}___${level}`;
2683
- const value = getNodeValue(node);
2684
- nodesMap.set(currentId, (nodesMap.get(currentId) || 0) + value);
2685
- if (parentId) {
2686
- const linkKey = `${parentId}--->${currentId}`;
2687
- if (linksMap.has(linkKey)) {
2688
- linksMap.get(linkKey).value += value;
2689
- }
2690
- else {
2691
- linksMap.set(linkKey, {
2692
- source: parentId,
2693
- target: currentId,
2694
- value: value,
2695
- });
2696
- }
2697
- }
2698
- if (node.children && node.children.length > 0) {
2699
- traverse(node.children, level + 1, currentId);
2700
- }
2701
- }
2702
- };
2703
- // Comenzar el recorrido en el nivel 0
2704
- traverse(data.source, 0);
2705
- // al menos un nivel de links para dibujar.
2706
- if (linksMap.size === 0)
2707
- return;
2708
- // Mapear nodos acumulados a la estructura requerida por ECharts (name y opcionalmente color, sin value redundante)
2709
- const nodes = Array.from(nodesMap.keys()).map((currentId) => {
2710
- const category = currentId.split("___")[0];
2711
- const nodeItem = {
2712
- name: currentId,
2713
- };
2714
- if (this.colorResolver) {
2715
- const color = this.colorResolver({ name: category, data: nodeItem });
2716
- if (color) {
2717
- nodeItem.itemStyle = { color };
2718
- }
2719
- }
2720
- return nodeItem;
2721
- });
2722
- const dynamicSerieOptions = {
2723
- type: "sankey",
2724
- orient: "horizontal", // De izquierda a derecha
2725
- draggable: true,
2726
- emphasis: {
2727
- focus: "adjacency",
2728
- },
2729
- lineStyle: {
2730
- color: "source",
2731
- opacity: 0.25,
2732
- curveness: 0.5,
2733
- },
2734
- label: {
2735
- show: true,
2736
- position: "right",
2737
- fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif",
2738
- fontSize: 10,
2739
- formatter: (params) => {
2740
- // Remover el sufijo de nivel de la etiqueta visual
2741
- return params.name.split("___")[0];
2742
- },
2743
- },
2744
- roam: true,
2745
- data: nodes,
2746
- links: Array.from(linksMap.values()),
2747
- };
2748
- const serie = merge$1({}, dynamicSerieOptions, overrides);
2749
- if (this.colorResolver && !serie.itemStyle) {
2750
- serie.itemStyle = {};
2751
- }
2752
- if (this.colorResolver && serie.itemStyle) {
2753
- serie.itemStyle.color = this.colorResolver;
2754
- }
2755
- this.result.series = serie;
2756
- }
2757
- addTooltip(data, overrides) {
2758
- merge$1(overrides, {
2759
- formatter: getTooltipFormatter(overrides.trigger || 'item', data, this.valueFormatter),
2760
- });
2761
- const tooltip = getTooltipOptions(overrides);
2762
- this.result.tooltip = tooltip;
2763
- }
2764
- addPolar() { }
2765
- addXAxis(data, overrides, type) { }
2766
- addYAxis(data, overrides, type) { }
2767
- addRadiusAxis(data, overrides) { }
2768
- addAngleAxis(data, overrides) { }
2769
- addLegend() { }
2770
- addDataZoom() { }
2771
- addDataset(data, opts) { }
2772
- addCommons() {
2773
- const opts = {
2774
- palette: this.palette,
2775
- };
2776
- merge$1(this.result, getCommons(opts));
2777
- }
2778
- addGraphic() { }
2779
- getResult() {
2780
- return this.result;
2781
- }
2782
- setValueFormatter(formatter) {
2783
- if (formatter) {
2784
- this.valueFormatter = formatter;
2785
- }
2786
- }
2787
- setPalette(palette) {
2788
- if (palette) {
2789
- this.palette = palette;
2790
- }
2791
- }
2792
- setColorResolver(resolver) {
2793
- if (resolver) {
2794
- this.colorResolver = resolver;
2795
- }
2796
- }
2797
- }
2798
-
2799
2866
  class EchartsSankeyComponent extends BaseEchartsComponent {
2800
2867
  baseSeriesOptions = {
2801
2868
  type: 'sankey',