@visionaris-bruno/vs-echarts 5.9.2 → 6.0.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.
@@ -3,33 +3,14 @@ import * as echarts from 'echarts/core';
3
3
  import { BarChart, PieChart, LineChart } from 'echarts/charts';
4
4
  import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GraphicComponent, ToolboxComponent, PolarComponent } from 'echarts/components';
5
5
  import { CanvasRenderer } from 'echarts/renderers';
6
- import merge from 'lodash/merge';
7
6
  import * as i0 from '@angular/core';
8
7
  import { EventEmitter, Output, Input, ViewChild, Directive, Component } from '@angular/core';
9
8
  import { ReplaySubject } from 'rxjs';
10
9
  import { debounceTime } from 'rxjs/operators';
10
+ import merge from 'lodash/merge';
11
11
  import { CommonModule } from '@angular/common';
12
+ import { merge as merge$1 } from 'lodash';
12
13
 
13
- /**
14
- * ECharts Options Standard Library
15
- *
16
- * Biblioteca de fragmentos de configuración y tokens de diseño para asegurar
17
- * una estética cohesiva en todos los gráficos de Visionaris.
18
- *
19
- * @see {@link VisionarisFrontEnd/docs/technical/echarts-architecture.md}
20
- */
21
- // Pre-cached native formatter for performance in axis ticks
22
- const compactFormatter = new Intl.NumberFormat('es-AR', {
23
- notation: 'compact',
24
- compactDisplay: 'short',
25
- maximumFractionDigits: 1
26
- });
27
- /**
28
- * Formats a value using native browser SI suffixes (k, M, B).
29
- */
30
- function formatAxisValue(value) {
31
- return compactFormatter.format(value);
32
- }
33
14
  /**
34
15
  * Global Design Tokens for ECharts
35
16
  */
@@ -48,265 +29,6 @@ const EChartsTokens = {
48
29
  function getDefaultPalette() {
49
30
  return [...EChartsTokens.defaultPalette];
50
31
  }
51
- /**
52
- * Common legend configuration with scroll to prevent "cannibalization".
53
- * Atomic Pattern: Provides the scrollable container with Visionaris styling.
54
- */
55
- function getLegendOptions(overrides) {
56
- const defaults = {
57
- show: true,
58
- type: 'scroll',
59
- orient: 'horizontal',
60
- bottom: 0,
61
- left: 'center',
62
- height: 60,
63
- textStyle: {
64
- color: '#333',
65
- fontSize: EChartsTokens.fontSize,
66
- fontFamily: EChartsTokens.fontFamily
67
- },
68
- pageButtonPosition: 'end',
69
- pageIconColor: EChartsTokens.primaryColor,
70
- pageIconInactiveColor: '#ccc',
71
- pageIconSize: 12,
72
- pageTextStyle: {
73
- color: '#666'
74
- }
75
- };
76
- return merge({}, defaults, overrides);
77
- }
78
- function getCategoryAxisOptions(overrides) {
79
- const categories = overrides?.data ?? [];
80
- const autoRotate = categories.length > 10 ? 45 : 0;
81
- const defaults = {
82
- type: 'category',
83
- triggerEvent: true,
84
- data: categories,
85
- axisLabel: {
86
- rotate: autoRotate,
87
- interval: 0,
88
- fontFamily: EChartsTokens.fontFamily,
89
- color: EChartsTokens.axisColor,
90
- fontSize: EChartsTokens.fontSize,
91
- margin: 8,
92
- fontWeight: 'normal',
93
- overflow: 'break',
94
- width: 1000,
95
- },
96
- axisLine: {
97
- lineStyle: {
98
- color: EChartsTokens.lineColor
99
- }
100
- }
101
- };
102
- return merge({}, defaults, overrides);
103
- }
104
- function getValueAxisOptions(overrides) {
105
- const defaults = {
106
- type: 'value',
107
- splitLine: {
108
- show: true,
109
- lineStyle: {
110
- type: 'dashed',
111
- color: '#f0f0f0'
112
- }
113
- },
114
- axisLabel: {
115
- formatter: (value) => formatAxisValue(value),
116
- color: EChartsTokens.axisColor,
117
- fontSize: EChartsTokens.fontSize
118
- }
119
- };
120
- return merge({}, defaults, overrides);
121
- }
122
- /**
123
- * Callback function to dynamically position the tooltip inside the chart container boundaries.
124
- */
125
- function getTooltipPositionCallback(point, params, dom, rect, size) {
126
- const [x, y] = point;
127
- const tooltipWidth = size?.contentSize?.[0] || dom?.offsetWidth || 150;
128
- const tooltipHeight = size?.contentSize?.[1] || dom?.offsetHeight || 100;
129
- const containerWidth = size?.viewSize?.[0] || 400;
130
- const containerHeight = size?.viewSize?.[1] || 300;
131
- const offset = 15; // Safe distance from cursor
132
- let posX = x - tooltipWidth / 2;
133
- let posY = y - tooltipHeight - offset; // default: above the cursor
134
- // Left and right boundary checks
135
- if (posX < 0) {
136
- // Overflows left boundary: place to the right of the cursor
137
- posX = x + offset;
138
- }
139
- else if (posX + tooltipWidth > containerWidth) {
140
- // Overflows right boundary: place to the left of the cursor
141
- posX = x - tooltipWidth - offset;
142
- }
143
- // Final safety clamp to container boundaries
144
- if (posX + tooltipWidth > containerWidth) {
145
- posX = Math.max(0, containerWidth - tooltipWidth);
146
- }
147
- if (posX < 0) {
148
- posX = 0;
149
- }
150
- // Top and bottom boundary checks
151
- if (posY < 0) {
152
- // Overflows top boundary: place below the cursor
153
- posY = y + offset;
154
- }
155
- else if (posY + tooltipHeight > containerHeight) {
156
- // Overflows bottom boundary: place above the cursor
157
- posY = y - tooltipHeight - offset;
158
- }
159
- // Final safety clamp to container boundaries
160
- if (posY + tooltipHeight > containerHeight) {
161
- posY = Math.max(0, containerHeight - tooltipHeight);
162
- }
163
- if (posY < 0) {
164
- posY = 0;
165
- }
166
- return [posX, posY];
167
- }
168
- /**
169
- * Common Tooltip configuration.
170
- * Atomic Pattern: Enforces consistent glassmorphism and pointer styles.
171
- */
172
- function getTooltipOptions(overrides) {
173
- const trigger = overrides?.trigger || 'axis';
174
- const isAxis = trigger === 'axis';
175
- const defaults = {
176
- show: true,
177
- trigger: trigger,
178
- position: getTooltipPositionCallback,
179
- backgroundColor: EChartsTokens.tooltipBg,
180
- borderColor: '#eee',
181
- borderWidth: 1,
182
- textStyle: {
183
- color: '#333',
184
- fontSize: 12
185
- },
186
- extraCssText: 'box-shadow: 0 0 10px rgba(0,0,0,0.1); border-radius: 8px;',
187
- ...(isAxis ? {
188
- axisPointer: {
189
- type: 'shadow'
190
- }
191
- } : {})
192
- };
193
- return merge({}, defaults, overrides);
194
- }
195
- /**
196
- * Applies a visual selection effect to line-based series.
197
- * Highlights the selected series and point, and dims everything else.
198
- *
199
- * @param series The series array to modify
200
- * @param selectedCategoryIndex Index of the selected category
201
- * @param selectedSeriesIndex Index of the selected series
202
- * @returns Modified series array
203
- */
204
- function applyLineSelectionStyle(series, selectedCategoryIndex, selectedSeriesIndex) {
205
- if (selectedCategoryIndex === null || !series)
206
- return series;
207
- return series.map((s, sIdx) => {
208
- const isSelectedSeries = sIdx === selectedSeriesIndex;
209
- // Serie seleccionada: Línea con opacidad 1 para que destaque la tendencia.
210
- // Serie NO seleccionada: Opacidad 0.20 para atenuar fuertemente.
211
- const seriesOpacity = isSelectedSeries ? 1 : 0.20;
212
- return {
213
- ...s,
214
- emphasis: {
215
- disabled: true // Deshabilitar el énfasis (hover) cuando hay una selección activa
216
- },
217
- itemStyle: {
218
- ...s.itemStyle,
219
- opacity: seriesOpacity
220
- },
221
- lineStyle: {
222
- ...s.lineStyle,
223
- opacity: seriesOpacity
224
- },
225
- ...(s.areaStyle ? {
226
- areaStyle: {
227
- ...s.areaStyle,
228
- opacity: isSelectedSeries ? 0.6 : 0.1
229
- }
230
- } : {}),
231
- // Personalizamos los puntos individualmente
232
- data: (s.data || []).map((val, idx) => {
233
- const isSelectedPoint = isSelectedSeries && idx === selectedCategoryIndex;
234
- const isOtherPointInSelectedSeries = isSelectedSeries && idx !== selectedCategoryIndex;
235
- const originalPoint = (val && typeof val === 'object') ? val : { value: val };
236
- if (isSelectedPoint) {
237
- return {
238
- ...originalPoint,
239
- z: 10, // Asegurar que el punto seleccionado esté por encima de los demás
240
- itemStyle: {
241
- ...originalPoint.itemStyle,
242
- opacity: 1,
243
- borderWidth: 2,
244
- borderColor: '#fff',
245
- shadowBlur: 10,
246
- shadowColor: 'rgba(0,0,0,0.5)'
247
- },
248
- symbolSize: 12
249
- };
250
- }
251
- else if (isOtherPointInSelectedSeries) {
252
- // Puntos de la serie seleccionada que NO son el clicado: un poco más pequeños y traslúcidos
253
- return {
254
- ...originalPoint,
255
- itemStyle: {
256
- ...originalPoint.itemStyle,
257
- opacity: 0.5
258
- },
259
- symbolSize: 6
260
- };
261
- }
262
- // Puntos de otras series o por defecto
263
- return val;
264
- })
265
- };
266
- });
267
- }
268
- /**
269
- * Formatter generator for 'item' trigger strategy in tooltips.
270
- */
271
- function getItemTooltipFormatter(data, formatCellValue) {
272
- return (params) => {
273
- const seriesObj = data.series[params.seriesIndex];
274
- const key = seriesObj?.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
275
- const valFormatted = formatCellValue(params.value, key);
276
- return `<div style="text-align: center;"><b>${params.name}</b><br/>${params.marker} ${params.seriesName}<br/><b>${valFormatted}</b></div>`;
277
- };
278
- }
279
- /**
280
- * Formatter generator for 'axis' trigger strategy in tooltips.
281
- */
282
- function getAxisTooltipFormatter(data, formatCellValue) {
283
- return (params) => {
284
- if (!params)
285
- return '';
286
- const items = Array.isArray(params) ? params : [params];
287
- if (items.length === 0)
288
- return '';
289
- const firstItem = items[0];
290
- let html = `<b>${firstItem.name}</b><br/>`;
291
- for (const item of items) {
292
- const seriesObj = data.series[item.seriesIndex];
293
- if (!seriesObj)
294
- continue;
295
- const key = seriesObj.originalKey || (data.categoryKeys ? data.categoryKeys[item.dataIndex] : String(item.dataIndex));
296
- const valFormatted = formatCellValue(item.value, key);
297
- html += `${item.marker} ${item.seriesName}: <b>${valFormatted}</b><br/>`;
298
- }
299
- return html;
300
- };
301
- }
302
- /**
303
- * Unified tooltip formatter generator that selects the appropriate strategy based on the trigger.
304
- */
305
- function getTooltipFormatter(trigger, data, formatCellValue) {
306
- return trigger === 'axis'
307
- ? getAxisTooltipFormatter(data, formatCellValue)
308
- : getItemTooltipFormatter(data, formatCellValue);
309
- }
310
32
 
311
33
  /**
312
34
  * Inicialización centralizada de ECharts para evitar duplicación y efectos secundarios
@@ -367,75 +89,40 @@ function defaultOptionsOverrides() {
367
89
  area: {
368
90
  series: {
369
91
  smooth: true,
370
- areaStyle: {},
371
92
  },
372
93
  },
373
94
  areaStack: {
374
95
  series: {
375
96
  smooth: true,
376
- areaStyle: {},
377
- stack: 'total',
378
97
  },
379
98
  },
380
99
  bar: {
381
- // tooltip: {},
382
100
  series: {
383
101
  showBackground: true,
384
102
  },
385
103
  },
386
104
  barStacked: {
387
- // tooltip: {
388
- // trigger: 'axis',
389
- // },
390
105
  series: {
391
106
  showBackground: false,
392
- stack: 'total',
393
- itemStyle: {
394
- borderRadius: [0, 0, 0, 0],
395
- },
396
- emphasis: {
397
- focus: 'series',
398
- }
399
107
  }
400
108
  },
401
109
  barStackedRadial: {
402
110
  series: {
403
111
  showBackground: false,
404
- stack: 'total',
405
- itemStyle: {
406
- borderRadius: [0, 0, 0, 0],
407
- },
408
- emphasis: {
409
- focus: 'series',
410
- },
411
- coordinateSystem: 'polar',
412
112
  }
413
113
  },
414
114
  hBar: {
415
- orientation: 'h',
416
- // tooltip: {},
417
115
  series: {
418
116
  showBackground: true,
419
- itemStyle: {
420
- borderRadius: [0, 4, 4, 0],
421
- }
422
117
  }
423
118
  },
424
119
  hBarStacked: {
425
- orientation: 'h',
426
- // tooltip: {
427
- // trigger: 'axis',
428
- // },
429
120
  series: {
430
- stack: 'total',
431
121
  showBackground: false,
432
- itemStyle: {
433
- borderRadius: [0, 0, 0, 0],
434
- },
435
- emphasis: {
436
- focus: 'series',
437
- }
438
122
  }
123
+ },
124
+ ring: {
125
+ series: {}
439
126
  }
440
127
  };
441
128
  }
@@ -460,21 +147,21 @@ class BaseEchartsComponent {
460
147
  /** Formateador de valores para etiquetas y tooltips */
461
148
  valueFormatter;
462
149
  chartClick = new EventEmitter();
463
- /** Opciones configuradas para ngx-echarts */
464
- chartOptions = {};
465
150
  /** Subject para debouncing de actualizaciones. ReplaySubject asegura no perder el primer renderizado. */
466
151
  updateSubject = new ReplaySubject(1);
467
152
  updateSubscription;
468
- constructor() {
469
- this.updateSubscription = this.updateSubject.pipe(debounceTime(150)).subscribe(options => {
470
- this.updateOptions(options);
471
- });
472
- }
473
153
  chartInstance;
474
154
  currentLegendSelected = null;
475
155
  /** Estado de selección para filtros cruzados */
476
156
  selectedCategoryIndex = null;
477
157
  selectedSeriesIndex = null;
158
+ /** Opciones configuradas para ngx-echarts */
159
+ chartOptions = {};
160
+ constructor() {
161
+ this.updateSubscription = this.updateSubject.pipe(debounceTime(150)).subscribe(options => {
162
+ this.updateOptions(options);
163
+ });
164
+ }
478
165
  ngOnChanges(changes) {
479
166
  this.onInputChanges(changes);
480
167
  }
@@ -583,124 +270,371 @@ class BaseEchartsComponent {
583
270
  triggerUpdate(options) {
584
271
  this.updateSubject.next(options);
585
272
  }
586
- /**
587
- * Método público para forzar el redimensionado desde el padre
588
- */
589
- resize() {
590
- this.chartInstance?.resize();
273
+ /**
274
+ * Método público para forzar el redimensionado desde el padre
275
+ */
276
+ resize() {
277
+ this.chartInstance?.resize();
278
+ }
279
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
280
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.19", type: BaseEchartsComponent, isStandalone: true, inputs: { data: "data", optionsOverrides: ["optionsOverrides", "optionsOverrides", (values) => {
281
+ return merge(defaultOptionsOverrides(), values || {});
282
+ }], palette: "palette", colorResolver: "colorResolver", valueFormatter: "valueFormatter" }, outputs: { chartClick: "chartClick" }, viewQueries: [{ propertyName: "chartContainer", first: true, predicate: ["chartContainer"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0 });
283
+ }
284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, decorators: [{
285
+ type: Directive,
286
+ args: [{
287
+ standalone: true
288
+ }]
289
+ }], ctorParameters: () => [], propDecorators: { chartContainer: [{
290
+ type: ViewChild,
291
+ args: ['chartContainer', { static: true }]
292
+ }], data: [{
293
+ type: Input
294
+ }], optionsOverrides: [{
295
+ type: Input,
296
+ args: [{
297
+ "transform": (values) => {
298
+ return merge(defaultOptionsOverrides(), values || {});
299
+ }
300
+ }]
301
+ }], palette: [{
302
+ type: Input
303
+ }], colorResolver: [{
304
+ type: Input
305
+ }], valueFormatter: [{
306
+ type: Input
307
+ }], chartClick: [{
308
+ type: Output
309
+ }] } });
310
+
311
+ /**
312
+ * ECharts Builder utils
313
+ *
314
+ * Biblioteca de fragmentos de configuración y tokens de diseño para asegurar
315
+ * una estética cohesiva en todos los gráficos de Visionaris.
316
+ *
317
+ * @see {@link VisionarisFrontEnd/docs/technical/echarts-architecture.md}
318
+ */
319
+ // Pre-cached native formatter for performance in axis ticks
320
+ const compactFormatter = new Intl.NumberFormat('es-AR', {
321
+ notation: 'compact',
322
+ compactDisplay: 'short',
323
+ maximumFractionDigits: 1
324
+ });
325
+ /**
326
+ * Formats a value using native browser SI suffixes (k, M, B).
327
+ */
328
+ function formatAxisValue(value) {
329
+ return compactFormatter.format(value);
330
+ }
331
+ /**
332
+ * Common legend configuration with scroll to prevent "cannibalization".
333
+ * Atomic Pattern: Provides the scrollable container with Visionaris styling.
334
+ */
335
+ function getLegendOptions(overrides) {
336
+ const defaults = {
337
+ show: true,
338
+ type: 'scroll',
339
+ orient: 'horizontal',
340
+ bottom: 0,
341
+ left: 'center',
342
+ height: 60,
343
+ textStyle: {
344
+ color: '#333',
345
+ fontSize: EChartsTokens.fontSize,
346
+ fontFamily: EChartsTokens.fontFamily
347
+ },
348
+ pageButtonPosition: 'end',
349
+ pageIconColor: EChartsTokens.primaryColor,
350
+ pageIconInactiveColor: '#ccc',
351
+ pageIconSize: 12,
352
+ pageTextStyle: {
353
+ color: '#666'
354
+ }
355
+ };
356
+ return merge({}, defaults, overrides);
357
+ }
358
+ function getCategoryAxisOptions(overrides) {
359
+ const categories = overrides?.data ?? [];
360
+ const autoRotate = categories.length > 10 ? 45 : 0;
361
+ const defaults = {
362
+ type: 'category',
363
+ triggerEvent: true,
364
+ data: categories,
365
+ axisLabel: {
366
+ rotate: autoRotate,
367
+ interval: 0,
368
+ fontFamily: EChartsTokens.fontFamily,
369
+ color: EChartsTokens.axisColor,
370
+ fontSize: EChartsTokens.fontSize,
371
+ margin: 8,
372
+ fontWeight: 'normal',
373
+ overflow: 'break',
374
+ width: 1000,
375
+ },
376
+ axisLine: {
377
+ lineStyle: {
378
+ color: EChartsTokens.lineColor
379
+ }
380
+ }
381
+ };
382
+ return merge({}, defaults, overrides);
383
+ }
384
+ function getValueAxisOptions(overrides) {
385
+ const defaults = {
386
+ type: 'value',
387
+ splitLine: {
388
+ show: true,
389
+ lineStyle: {
390
+ type: 'dashed',
391
+ color: '#f0f0f0'
392
+ }
393
+ },
394
+ axisLabel: {
395
+ formatter: (value) => formatAxisValue(value),
396
+ color: EChartsTokens.axisColor,
397
+ fontSize: EChartsTokens.fontSize
398
+ }
399
+ };
400
+ return merge({}, defaults, overrides);
401
+ }
402
+ /**
403
+ * Callback function to dynamically position the tooltip inside the chart container boundaries.
404
+ */
405
+ function getTooltipPositionCallback(point, params, dom, rect, size) {
406
+ const [x, y] = point;
407
+ const tooltipWidth = size?.contentSize?.[0] || dom?.offsetWidth || 150;
408
+ const tooltipHeight = size?.contentSize?.[1] || dom?.offsetHeight || 100;
409
+ const containerWidth = size?.viewSize?.[0] || 400;
410
+ const containerHeight = size?.viewSize?.[1] || 300;
411
+ const offset = 15; // Safe distance from cursor
412
+ let posX = x - tooltipWidth / 2;
413
+ let posY = y - tooltipHeight - offset; // default: above the cursor
414
+ // Left and right boundary checks
415
+ if (posX < 0) {
416
+ // Overflows left boundary: place to the right of the cursor
417
+ posX = x + offset;
418
+ }
419
+ else if (posX + tooltipWidth > containerWidth) {
420
+ // Overflows right boundary: place to the left of the cursor
421
+ posX = x - tooltipWidth - offset;
422
+ }
423
+ // Final safety clamp to container boundaries
424
+ if (posX + tooltipWidth > containerWidth) {
425
+ posX = Math.max(0, containerWidth - tooltipWidth);
426
+ }
427
+ if (posX < 0) {
428
+ posX = 0;
429
+ }
430
+ // Top and bottom boundary checks
431
+ if (posY < 0) {
432
+ // Overflows top boundary: place below the cursor
433
+ posY = y + offset;
434
+ }
435
+ else if (posY + tooltipHeight > containerHeight) {
436
+ // Overflows bottom boundary: place above the cursor
437
+ posY = y - tooltipHeight - offset;
438
+ }
439
+ // Final safety clamp to container boundaries
440
+ if (posY + tooltipHeight > containerHeight) {
441
+ posY = Math.max(0, containerHeight - tooltipHeight);
442
+ }
443
+ if (posY < 0) {
444
+ posY = 0;
591
445
  }
592
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
593
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.19", type: BaseEchartsComponent, isStandalone: true, inputs: { data: "data", optionsOverrides: ["optionsOverrides", "optionsOverrides", (values) => {
594
- return merge(defaultOptionsOverrides(), values || {});
595
- }], palette: "palette", colorResolver: "colorResolver", valueFormatter: "valueFormatter" }, outputs: { chartClick: "chartClick" }, viewQueries: [{ propertyName: "chartContainer", first: true, predicate: ["chartContainer"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0 });
446
+ return [posX, posY];
447
+ }
448
+ /**
449
+ * Common Tooltip configuration.
450
+ * Atomic Pattern: Enforces consistent glassmorphism and pointer styles.
451
+ */
452
+ function getTooltipOptions(overrides) {
453
+ const trigger = overrides?.trigger || 'axis';
454
+ const isAxis = trigger === 'axis';
455
+ const defaults = {
456
+ show: true,
457
+ trigger: trigger,
458
+ position: getTooltipPositionCallback,
459
+ backgroundColor: EChartsTokens.tooltipBg,
460
+ borderColor: '#eee',
461
+ borderWidth: 1,
462
+ textStyle: {
463
+ color: '#333',
464
+ fontSize: 12
465
+ },
466
+ extraCssText: 'box-shadow: 0 0 10px rgba(0,0,0,0.1); border-radius: 8px;',
467
+ ...(isAxis ? {
468
+ axisPointer: {
469
+ type: 'shadow'
470
+ }
471
+ } : {})
472
+ };
473
+ return merge({}, defaults, overrides);
474
+ }
475
+ /**
476
+ * Applies a visual selection effect to line-based series.
477
+ * Highlights the selected series and point, and dims everything else.
478
+ *
479
+ * @param series The series array to modify
480
+ * @param selectedCategoryIndex Index of the selected category
481
+ * @param selectedSeriesIndex Index of the selected series
482
+ * @returns Modified series array
483
+ */
484
+ function applyLineSelectionStyle$1(series, selectedCategoryIndex, selectedSeriesIndex) {
485
+ if (selectedCategoryIndex === null || !series)
486
+ return series;
487
+ return series.map((s, sIdx) => {
488
+ const isSelectedSeries = sIdx === selectedSeriesIndex;
489
+ // Serie seleccionada: Línea con opacidad 1 para que destaque la tendencia.
490
+ // Serie NO seleccionada: Opacidad 0.20 para atenuar fuertemente.
491
+ const seriesOpacity = isSelectedSeries ? 1 : 0.20;
492
+ return {
493
+ ...s,
494
+ emphasis: {
495
+ disabled: true // Deshabilitar el énfasis (hover) cuando hay una selección activa
496
+ },
497
+ itemStyle: {
498
+ ...s.itemStyle,
499
+ opacity: seriesOpacity
500
+ },
501
+ lineStyle: {
502
+ ...s.lineStyle,
503
+ opacity: seriesOpacity
504
+ },
505
+ ...(s.areaStyle ? {
506
+ areaStyle: {
507
+ ...s.areaStyle,
508
+ opacity: isSelectedSeries ? 0.6 : 0.1
509
+ }
510
+ } : {}),
511
+ // Personalizamos los puntos individualmente
512
+ data: (s.data || []).map((val, idx) => {
513
+ const isSelectedPoint = isSelectedSeries && idx === selectedCategoryIndex;
514
+ const isOtherPointInSelectedSeries = isSelectedSeries && idx !== selectedCategoryIndex;
515
+ const originalPoint = (val && typeof val === 'object') ? val : { value: val };
516
+ if (isSelectedPoint) {
517
+ return {
518
+ ...originalPoint,
519
+ z: 10, // Asegurar que el punto seleccionado esté por encima de los demás
520
+ itemStyle: {
521
+ ...originalPoint.itemStyle,
522
+ opacity: 1,
523
+ borderWidth: 2,
524
+ borderColor: '#fff',
525
+ shadowBlur: 10,
526
+ shadowColor: 'rgba(0,0,0,0.5)'
527
+ },
528
+ symbolSize: 12
529
+ };
530
+ }
531
+ else if (isOtherPointInSelectedSeries) {
532
+ // Puntos de la serie seleccionada que NO son el clicado: un poco más pequeños y traslúcidos
533
+ return {
534
+ ...originalPoint,
535
+ itemStyle: {
536
+ ...originalPoint.itemStyle,
537
+ opacity: 0.5
538
+ },
539
+ symbolSize: 6
540
+ };
541
+ }
542
+ // Puntos de otras series o por defecto
543
+ return val;
544
+ })
545
+ };
546
+ });
547
+ }
548
+ /**
549
+ * Formatter generator for 'item' trigger strategy in tooltips.
550
+ */
551
+ function getItemTooltipFormatter(data, formatCellValue) {
552
+ return (params) => {
553
+ const seriesObj = data.series[params.seriesIndex];
554
+ const key = seriesObj?.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
555
+ const valFormatted = formatCellValue(params.value, key);
556
+ return `<div style="text-align: center;"><b>${params.name}</b><br/>${params.marker} ${params.seriesName}<br/><b>${valFormatted}</b></div>`;
557
+ };
558
+ }
559
+ /**
560
+ * Formatter generator for 'axis' trigger strategy in tooltips.
561
+ */
562
+ function getAxisTooltipFormatter(data, formatCellValue) {
563
+ return (params) => {
564
+ if (!params)
565
+ return '';
566
+ const items = Array.isArray(params) ? params : [params];
567
+ if (items.length === 0)
568
+ return '';
569
+ const firstItem = items[0];
570
+ let html = `<b>${firstItem.name}</b><br/>`;
571
+ for (const item of items) {
572
+ const seriesObj = data.series[item.seriesIndex];
573
+ if (!seriesObj)
574
+ continue;
575
+ const key = seriesObj.originalKey || (data.categoryKeys ? data.categoryKeys[item.dataIndex] : String(item.dataIndex));
576
+ const valFormatted = formatCellValue(item.value, key);
577
+ html += `${item.marker} ${item.seriesName}: <b>${valFormatted}</b><br/>`;
578
+ }
579
+ return html;
580
+ };
581
+ }
582
+ /**
583
+ * Unified tooltip formatter generator that selects the appropriate strategy based on the trigger.
584
+ */
585
+ function getTooltipFormatter(trigger, data, formatCellValue) {
586
+ return trigger === 'axis'
587
+ ? getAxisTooltipFormatter(data, formatCellValue)
588
+ : getItemTooltipFormatter(data, formatCellValue);
589
+ }
590
+ function getCommons(opts) {
591
+ const palette = opts?.palette ?? getDefaultPalette();
592
+ const common = {
593
+ backgroundColor: 'transparent',
594
+ textStyle: {
595
+ fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif",
596
+ },
597
+ grid: {
598
+ left: '3%',
599
+ right: '4%',
600
+ bottom: '15%',
601
+ top: '20px',
602
+ containLabel: true,
603
+ },
604
+ };
605
+ // Aplicar paleta global: Prioridad Palette Inyectada > Default Visionaris
606
+ common.color = (palette && palette.length > 0) ? palette : getDefaultPalette();
607
+ return common;
596
608
  }
597
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, decorators: [{
598
- type: Directive,
599
- args: [{
600
- standalone: true
601
- }]
602
- }], ctorParameters: () => [], propDecorators: { chartContainer: [{
603
- type: ViewChild,
604
- args: ['chartContainer', { static: true }]
605
- }], data: [{
606
- type: Input
607
- }], optionsOverrides: [{
608
- type: Input,
609
- args: [{
610
- "transform": (values) => {
611
- return merge(defaultOptionsOverrides(), values || {});
612
- }
613
- }]
614
- }], palette: [{
615
- type: Input
616
- }], colorResolver: [{
617
- type: Input
618
- }], valueFormatter: [{
619
- type: Input
620
- }], chartClick: [{
621
- type: Output
622
- }] } });
623
609
 
624
610
  /**
625
- * BaseEchartBuilder
611
+ * RingBuilder
626
612
  *
627
- * Clase base para la construcción de opciones de ECharts.
628
- * Implementa lógica compartida de paletas y opciones comunes.
613
+ * Builder concreto para el grafico de Ring.
629
614
  *
630
- * @see {@link vs-echarts/docs/internal-architecture.md}
631
615
  */
632
- class BaseEchartBuilder {
616
+ class RingBuilder {
617
+ product;
633
618
  valueFormatter = (value) => value.toLocaleString();
634
619
  palette = [];
635
- // TODO: Hay que implementar un valor por defecto.
636
620
  colorResolver;
637
- constructor() { }
638
- /**
639
- * Permite inyectar un formateador de valores externo.
640
- */
641
- setValueFormatter(formatter) {
642
- if (formatter) {
643
- this.valueFormatter = formatter;
644
- }
645
- }
646
- /**
647
- * Permite inyectar una paleta de colores básica.
648
- */
649
- setPalette(palette) {
650
- if (palette) {
651
- this.palette = palette;
652
- }
621
+ result = {};
622
+ constructor(product) {
623
+ this.product = product;
653
624
  }
654
- /**
655
- * Permite inyectar un resolver de colores dinámico.
656
- */
657
- setColorResolver(resolver) {
658
- if (resolver) {
659
- this.colorResolver = resolver;
660
- }
625
+ reset() {
626
+ this.result = {};
661
627
  }
662
- /**
663
- * Retorna configuraciones comunes para todos los gráficos.
664
- *
665
- * TODO: particionar en configuraciones concretas con sus
666
- * respectivos overrides.
667
- */
668
- getCommonOptions(overrides) {
669
- const common = {
670
- backgroundColor: 'transparent',
671
- textStyle: {
672
- fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif"
673
- },
674
- grid: {
675
- left: '3%',
676
- right: '4%',
677
- bottom: '15%',
678
- top: '20px',
679
- containLabel: true
680
- }
628
+ addCommons() {
629
+ const opts = {
630
+ palette: this.palette,
681
631
  };
682
- // Aplicar paleta global: Prioridad Palette Inyectada > Default Visionaris
683
- common.color = (this.palette && this.palette.length > 0) ? this.palette : getDefaultPalette();
684
- return common;
685
- }
686
- /**
687
- * Formatea un valor utilizando el callback inyectado.
688
- */
689
- formatCellValue(value, key) {
690
- return this.valueFormatter(value, key);
632
+ const common = getCommons(opts);
633
+ merge(this.result, common);
691
634
  }
692
- }
693
-
694
- /**
695
- * RingBuilder
696
- *
697
- * Especializado en construir opciones para gráficos de tipo Ring (Donas concéntricas).
698
- * @see {@link vs-echarts/docs/charts/ring-patterns.md}
699
- */
700
- class RingBuilder extends BaseEchartBuilder {
701
- build(data, overrides) {
635
+ addSeries(data, overrides) {
702
636
  if (!data || !data.series.length)
703
- return {};
637
+ return;
704
638
  const totalRings = data.series.length; // Cada serie es un anillo
705
639
  // Configuración dinámica de radios y márgenes
706
640
  const margin = totalRings > 1 ? Math.max(0.5, 2.5 - (totalRings * 0.1)) : 0;
@@ -718,81 +652,194 @@ class RingBuilder extends BaseEchartBuilder {
718
652
  value: s.data[catIndex],
719
653
  originalMeassureKey: s.originalKey || (data.categoryKeys ? data.categoryKeys[catIndex] : '')
720
654
  }));
721
- const seriesOption = {
655
+ const dynamicRingSeriesOptions = {
722
656
  name: s.name,
723
- type: 'pie',
724
657
  radius: [`${inner}%`, `${outer}%`],
725
- center: ['50%', '50%'],
726
- avoidLabelOverlap: true,
727
- minAngle: 3,
728
- selectedMode: 'single',
729
- selectedOffset: 4,
730
658
  itemStyle: {
731
659
  borderRadius: borderRadius,
732
- borderColor: '#fff',
733
- borderWidth: borderWidth
660
+ borderWidth: borderWidth,
734
661
  },
735
- label: { show: false },
736
662
  emphasis: {
737
- scale: true,
738
- scaleSize: 2,
739
663
  itemStyle: {
740
- borderColor: '#fff',
741
- borderWidth: borderWidth
742
- }
664
+ borderWidth: borderWidth,
665
+ },
743
666
  },
744
667
  select: {
745
668
  itemStyle: {
746
- borderColor: '#fff',
747
- borderWidth: borderWidth
748
- }
669
+ borderWidth: borderWidth,
670
+ },
749
671
  },
750
- animationType: 'scale',
751
- animationEasing: 'elasticOut',
752
672
  data: pieData,
753
- id: `ring_${ringIndex}`
673
+ id: `ring_${ringIndex}`,
754
674
  };
675
+ const seriesOption = merge(dynamicRingSeriesOptions, overrides);
755
676
  // Inyectar el resolver de color si existe
756
- if (this.colorResolver) {
677
+ if (this.colorResolver && seriesOption.itemStyle) {
757
678
  seriesOption.itemStyle.color = this.colorResolver;
758
679
  }
759
680
  return seriesOption;
760
681
  });
761
- const common = this.getCommonOptions(overrides);
762
- return {
763
- ...common,
764
- tooltip: {
765
- ...getTooltipOptions({ trigger: 'item' }),
766
- formatter: (params) => {
767
- const key = params.data.originalMeassureKey || '';
768
- const valFormatted = this.formatCellValue(params.value, key);
769
- const seriesHeader = totalRings > 1 ? `<b>${params.seriesName}</b><br/>` : '';
770
- return `${seriesHeader}${params.name}<br/>${params.marker} <b>${valFormatted}</b> (${params.percent}%)`;
771
- }
682
+ this.result.series = series;
683
+ }
684
+ addGraphic() {
685
+ // Add graphic element for the center KPI
686
+ this.result.graphic = [{
687
+ id: 'center-kpi',
688
+ type: 'text',
689
+ left: 'center',
690
+ top: 'middle',
691
+ z: 100,
692
+ transition: ['style'],
693
+ style: {
694
+ text: '',
695
+ fontSize: 22,
696
+ fontWeight: 'bold',
697
+ fill: '#333',
698
+ stroke: '#fff',
699
+ lineWidth: 1,
700
+ paintOrder: 'stroke',
701
+ textAlign: 'center',
702
+ textVerticalAlign: 'middle',
703
+ opacity: 0,
704
+ },
705
+ }];
706
+ }
707
+ addTooltip(data, overrides) {
708
+ const totalRings = data.series.length;
709
+ merge(overrides, {
710
+ formatter: (params) => {
711
+ const key = params.data.originalMeassureKey || '';
712
+ const valFormatted = this.formatCellValue(params.value, key);
713
+ const seriesHeader = totalRings > 1 ? `<b>${params.seriesName}</b><br/>` : '';
714
+ return `${seriesHeader}${params.name}<br/>${params.marker} <b>${valFormatted}</b> (${params.percent}%)`;
772
715
  },
773
- legend: getLegendOptions(),
774
- graphic: [{
775
- id: 'center-kpi',
776
- type: 'text',
777
- left: 'center',
778
- top: 'middle',
779
- z: 100,
780
- transition: ['style'],
781
- style: {
782
- text: '',
783
- fontSize: 22,
784
- fontWeight: 'bold',
785
- fill: '#333',
786
- stroke: '#fff',
787
- lineWidth: 1,
788
- paintOrder: 'stroke',
789
- textAlign: 'center',
790
- textVerticalAlign: 'middle',
791
- opacity: 0
792
- }
793
- }],
794
- series: series,
795
- };
716
+ });
717
+ const tooltip = getTooltipOptions(overrides);
718
+ this.result.tooltip = tooltip;
719
+ }
720
+ addLegend() {
721
+ this.result.legend = getLegendOptions();
722
+ }
723
+ // No-ops for ring charts
724
+ addPolar() { }
725
+ addXAxis(data, overrides, type) { }
726
+ addYAxis(data, overrides, type) { }
727
+ addRadiusAxis(data, overrides) { }
728
+ addAngleAxis(data, overrides) { }
729
+ // Callback setters
730
+ setValueFormatter(formatter) {
731
+ if (formatter) {
732
+ this.valueFormatter = formatter;
733
+ }
734
+ }
735
+ setPalette(palette) {
736
+ if (palette) {
737
+ this.palette = palette;
738
+ }
739
+ }
740
+ setColorResolver(resolver) {
741
+ if (resolver) {
742
+ this.colorResolver = resolver;
743
+ }
744
+ }
745
+ getResult() {
746
+ return this.result;
747
+ }
748
+ formatCellValue(value, key) {
749
+ return this.valueFormatter(value, key);
750
+ }
751
+ }
752
+
753
+ /**
754
+ * Director de Builds.
755
+ */
756
+ class VSECDirector {
757
+ builder = undefined;
758
+ constructor(builder) {
759
+ this.builder = builder;
760
+ }
761
+ makeBar(data, overrides, opts = {}) {
762
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
763
+ x: 'category',
764
+ y: 'value',
765
+ // TODO agregar radius y angle axis
766
+ } } = opts;
767
+ this.builder.reset();
768
+ // El orden importa, primero callbaks y despues componentes.
769
+ //chart callbacks
770
+ this.builder.setValueFormatter(valueFormatter);
771
+ this.builder.setPalette(palette);
772
+ this.builder.setValueFormatter(valueFormatter);
773
+ const product = this.builder.product;
774
+ const seriesOverrides = merge$1(product.baseOptions.series, overrides[product.chartKey].series);
775
+ // chart components
776
+ this.builder.addCommons();
777
+ this.builder.addSeries(data, seriesOverrides);
778
+ this.builder.addXAxis(data, overrides.axis, axisTypes.x);
779
+ this.builder.addYAxis(data, overrides.axis, axisTypes.y);
780
+ this.builder.addTooltip(data, overrides.tooltip);
781
+ this.builder.addLegend();
782
+ }
783
+ makeBarRadial(data, overrides, opts = {}) {
784
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
785
+ x: 'category',
786
+ y: 'value',
787
+ // TODO agregar radius y angle axis
788
+ } } = opts;
789
+ this.builder.reset();
790
+ // El orden importa, primero callbaks y despues componentes.
791
+ //chart callbacks
792
+ this.builder.setValueFormatter(valueFormatter);
793
+ this.builder.setPalette(palette);
794
+ this.builder.setValueFormatter(valueFormatter);
795
+ const product = this.builder.product;
796
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
797
+ // chart components
798
+ this.builder.addCommons();
799
+ this.builder.addSeries(data, seriesOverrides);
800
+ this.builder.addPolar();
801
+ this.builder.addAngleAxis(data, overrides['axis']);
802
+ this.builder.addRadiusAxis(data, overrides['axis']);
803
+ this.builder.addTooltip(data, overrides.tooltip);
804
+ this.builder.addLegend();
805
+ }
806
+ makeLine(data, overrides, opts = {}) {
807
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
808
+ x: 'category',
809
+ y: 'value',
810
+ // TODO agregar radius y angle axis
811
+ } } = opts;
812
+ this.builder.reset();
813
+ // El orden importa, primero callbaks y despues componentes.
814
+ //chart callbacks
815
+ this.builder.setValueFormatter(valueFormatter);
816
+ this.builder.setPalette(palette);
817
+ this.builder.setValueFormatter(valueFormatter);
818
+ const product = this.builder.product;
819
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
820
+ // chart components
821
+ this.builder.addCommons();
822
+ this.builder.addSeries(data, seriesOverrides);
823
+ this.builder.addXAxis(data, overrides.axis, axisTypes.x);
824
+ this.builder.addYAxis(data, overrides.axis, axisTypes.y);
825
+ this.builder.addTooltip(data, overrides.tooltip);
826
+ this.builder.addLegend();
827
+ }
828
+ makeRing(data, overrides, opts = {}) {
829
+ const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
830
+ this.builder.reset();
831
+ // El orden importa, primero callbacks y despues componentes.
832
+ this.builder.setValueFormatter(valueFormatter);
833
+ this.builder.setPalette(palette);
834
+ this.builder.setColorResolver(colorResolver);
835
+ const product = this.builder.product;
836
+ const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
837
+ // chart components
838
+ this.builder.addCommons();
839
+ this.builder.addSeries(data, seriesOverrides);
840
+ this.builder.addGraphic();
841
+ this.builder.addTooltip(data, overrides.tooltip);
842
+ this.builder.addLegend();
796
843
  }
797
844
  }
798
845
 
@@ -803,14 +850,49 @@ class RingBuilder extends BaseEchartBuilder {
803
850
  * @see {@link vs-echarts/docs/charts/ring-patterns.md}
804
851
  */
805
852
  class EchartsRingComponent extends BaseEchartsComponent {
853
+ baseSeriesOptions = {
854
+ type: 'pie',
855
+ center: ['50%', '50%'],
856
+ avoidLabelOverlap: true,
857
+ minAngle: 3,
858
+ selectedMode: 'single',
859
+ selectedOffset: 4,
860
+ itemStyle: {
861
+ borderColor: '#fff',
862
+ },
863
+ label: { show: false },
864
+ emphasis: {
865
+ scale: true,
866
+ scaleSize: 2,
867
+ itemStyle: {
868
+ borderColor: '#fff',
869
+ },
870
+ },
871
+ select: {
872
+ itemStyle: {
873
+ borderColor: '#fff',
874
+ },
875
+ },
876
+ animationType: 'scale',
877
+ animationEasing: 'elasticOut',
878
+ };
879
+ product = {
880
+ chartKey: 'ring',
881
+ baseOptions: {
882
+ series: this.baseSeriesOptions,
883
+ }
884
+ };
885
+ builder = new RingBuilder(this.product);
886
+ director = new VSECDirector(this.builder);
806
887
  lastSelectedSeriesIndex = null;
807
888
  lastSelectedDataIndex = null;
808
889
  selectedPercent = null;
809
890
  currentGraphicText = '';
810
- builder;
811
891
  constructor() {
812
892
  super();
813
- this.builder = new RingBuilder();
893
+ }
894
+ make(makeOpts) {
895
+ this.director.makeRing(this.data, this.optionsOverrides, makeOpts);
814
896
  }
815
897
  onInputChanges(changes) {
816
898
  // Reset selection only if data changed
@@ -897,15 +979,14 @@ class EchartsRingComponent extends BaseEchartsComponent {
897
979
  if (!this.data)
898
980
  return;
899
981
  // 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
900
- // Pero aquí necesitamos llamar a super o duplicar la lógica de inyección de inputs
901
- if (this.valueFormatter)
902
- this.builder.setValueFormatter(this.valueFormatter);
903
- if (this.palette)
904
- this.builder.setPalette(this.palette);
905
- if (this.colorResolver)
906
- this.builder.setColorResolver(this.colorResolver);
982
+ const makeOpts = {
983
+ valueFormatter: this.valueFormatter,
984
+ palette: this.palette,
985
+ colorResolver: this.colorResolver,
986
+ };
987
+ this.make(makeOpts);
907
988
  // 2. Obtenemos las bases del chart usando el builder
908
- let options = this.builder.build(this.data, this.optionsOverrides);
989
+ let options = this.builder.getResult();
909
990
  // 3. Persistencia de GRAPHIC (KPI central)
910
991
  if (options.graphic && Array.isArray(options.graphic)) {
911
992
  const graphic = options.graphic[0];
@@ -948,359 +1029,276 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
948
1029
  }], ctorParameters: () => [] });
949
1030
 
950
1031
  /**
951
- * VerticalBandsBuilder
1032
+ * Builder principal.
1033
+ *
1034
+ * Es muy completo, tiene soporte para ejes y sistema cartesiano polar.
952
1035
  *
953
- * Especializado en construir opciones para gráficos de barras verticales.
954
- * @see {@link vs-echarts/docs/charts/vertical-bands-patterns.md}
1036
+ * Puede verse utilizado en graficos como Lineas y Bars. Siempre que se pueda priorizar utilizar este.
955
1037
  */
956
- class VerticalBandsBuilder extends BaseEchartBuilder {
957
- constructor() {
958
- super();
1038
+ class EChartBuilder {
1039
+ product = undefined;
1040
+ valueFormatter = (value) => value.toLocaleString();
1041
+ palette = [];
1042
+ // TODO: Hay que implementar un valor por defecto.
1043
+ colorResolver;
1044
+ result = {};
1045
+ constructor(product) {
1046
+ this.product = product;
1047
+ }
1048
+ reset() {
1049
+ this.result = {};
1050
+ }
1051
+ addCommons() {
1052
+ const opts = {
1053
+ palette: this.palette,
1054
+ };
1055
+ merge$1(this.result, getCommons(opts));
959
1056
  }
960
- build(data, overrides) {
1057
+ /**
1058
+ *
1059
+ * @param data
1060
+ * @param overrides
1061
+ * @returns
1062
+ */
1063
+ addSeries(data, overrides) {
961
1064
  if (!data || !data.series.length)
962
- return {};
1065
+ return;
963
1066
  const series = data.series.map((s) => {
964
- const seriesOption = {
1067
+ const dynamicOverrides = {
965
1068
  name: s.name,
966
- type: 'bar',
967
- barMaxWidth: 50,
968
- barGap: '15%',
969
- barCategoryGap: '35%',
970
- animation: true,
971
- animationDuration: 1000,
972
- animationEasing: 'cubicOut',
973
- itemStyle: {
974
- borderRadius: [4, 4, 0, 0]
975
- },
976
1069
  data: s.data,
977
- emphasis: {
978
- focus: 'none'
979
- },
980
- blur: {
981
- itemStyle: {
982
- opacity: 0.2
983
- }
984
- },
985
- select: {
986
- itemStyle: {
987
- opacity: 1,
988
- shadowBlur: 10,
989
- shadowColor: 'rgba(0,0,0,0.3)'
990
- }
991
- },
992
1070
  label: {
993
- show: false,
994
- position: 'top',
995
1071
  formatter: (params) => {
996
1072
  const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
997
1073
  return this.formatCellValue(params.value, key);
998
1074
  }
999
1075
  }
1000
1076
  };
1077
+ const seriesOption = merge$1(dynamicOverrides, overrides);
1001
1078
  // Inyectar el resolver de color si existe
1002
- if (this.colorResolver) {
1079
+ if (this.colorResolver && seriesOption.itemStyle) {
1003
1080
  seriesOption.itemStyle.color = this.colorResolver;
1004
1081
  }
1005
1082
  return seriesOption;
1006
1083
  });
1007
- const common = this.getCommonOptions(overrides);
1008
- const categoryAxisOptions = {
1009
- ...overrides.axis.categoryAxis[0],
1010
- data: data.categories,
1011
- };
1012
- const { trigger = 'axis' } = overrides.tooltip || {};
1013
- const tooltipOptionsOverrides = {
1014
- trigger,
1015
- };
1016
- return {
1017
- ...common,
1018
- tooltip: {
1019
- ...getTooltipOptions(tooltipOptionsOverrides),
1020
- formatter: getTooltipFormatter(trigger, data, this.formatCellValue.bind(this)),
1084
+ this.result.series = series;
1085
+ }
1086
+ /**
1087
+ * TODO: Mejorar funcion, no me convence como se implemento el tooltip formatter.
1088
+ * @param data
1089
+ * @param overrides
1090
+ */
1091
+ addTooltip(data, overrides) {
1092
+ // inyecto formateador a overrides de tooltip
1093
+ merge$1(overrides, {
1094
+ formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
1095
+ });
1096
+ const tooltip = getTooltipOptions(overrides);
1097
+ this.result.tooltip = tooltip;
1098
+ }
1099
+ addPolar() {
1100
+ const polar = [];
1101
+ polar.push({
1102
+ radius: '65%',
1103
+ center: ["50%", "44%"],
1104
+ });
1105
+ this.result.polar = polar;
1106
+ }
1107
+ addXAxis(data, overrides, type = 'category') {
1108
+ const xAxis = [];
1109
+ const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1110
+ const valueAxisOptions = this.getValueAxisOptions(data, overrides);
1111
+ if (type == 'category') {
1112
+ xAxis.push(categoryAxisOptions);
1113
+ }
1114
+ else if (type == 'value') {
1115
+ xAxis.push(valueAxisOptions);
1116
+ }
1117
+ this.result.xAxis = xAxis;
1118
+ }
1119
+ addYAxis(data, overrides, type = 'value') {
1120
+ const yAxis = [];
1121
+ const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1122
+ const valueAxisOptions = this.getValueAxisOptions(data, overrides);
1123
+ if (type == 'category') {
1124
+ yAxis.push(categoryAxisOptions);
1125
+ }
1126
+ else if (type == 'value') {
1127
+ yAxis.push(valueAxisOptions);
1128
+ }
1129
+ this.result.yAxis = yAxis;
1130
+ }
1131
+ addRadiusAxis(data, overrides) {
1132
+ const radiusAxis = [];
1133
+ /** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
1134
+ const radiusAxisOverrides = {
1135
+ axisTick: {
1136
+ show: false,
1021
1137
  },
1022
- legend: getLegendOptions(),
1023
- xAxis: [getCategoryAxisOptions(categoryAxisOptions)],
1024
- yAxis: [getValueAxisOptions()],
1025
- series: series
1138
+ axisLabel: {
1139
+ margin: 2,
1140
+ fontSize: 8,
1141
+ align: 'right',
1142
+ rotate: 20,
1143
+ verticalAlign: 'top',
1144
+ },
1145
+ axisLine: {
1146
+ lineStyle: {
1147
+ type: 'dashed',
1148
+ },
1149
+ }
1026
1150
  };
1151
+ const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
1152
+ radiusAxis.push(radialAxisOptions);
1153
+ this.result.radiusAxis = radiusAxis;
1027
1154
  }
1028
- }
1029
-
1030
- /**
1031
- * EchartsVerticalBandsComponent
1032
- *
1033
- * Especialista en visualización de bandas/barras verticales.
1034
- * Implementa patrones de interacción ZRender y resaltado de grupos.
1035
- * @see {@link vs-echarts/docs/charts/vertical-bands-patterns.md}
1036
- */
1037
- class EchartsVerticalBandsComponent extends BaseEchartsComponent {
1038
- builder;
1039
- constructor() {
1040
- super();
1041
- this.builder = new VerticalBandsBuilder();
1155
+ addAngleAxis(data, overrides) {
1156
+ const angleAxis = [];
1157
+ const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
1158
+ angleAxis.push(categoryAxisOptions);
1159
+ this.result.angleAxis = angleAxis;
1042
1160
  }
1043
- onChartInit(instance) {
1044
- super.onChartInit(instance);
1045
- this.setupAdditionalInteractions();
1161
+ addLegend() {
1162
+ this.result.legend = getLegendOptions();
1046
1163
  }
1047
- onInputChanges(changes) {
1048
- if (changes['data']) {
1049
- this.selectedCategoryIndex = null;
1050
- this.selectedSeriesIndex = null;
1051
- this.currentLegendSelected = null;
1164
+ // No-ops for ring charts
1165
+ addGraphic() { }
1166
+ getResult() {
1167
+ return this.result;
1168
+ }
1169
+ ;
1170
+ /**
1171
+ * Formatea un valor utilizando el callback inyectado.
1172
+ */
1173
+ formatCellValue(value, key) {
1174
+ return this.valueFormatter(value, key);
1175
+ }
1176
+ // Setters
1177
+ /**
1178
+ * Permite inyectar un formateador de valores externo.
1179
+ */
1180
+ setValueFormatter(formatter) {
1181
+ if (formatter) {
1182
+ this.valueFormatter = formatter;
1052
1183
  }
1053
- super.onInputChanges(changes);
1054
1184
  }
1055
- setupAdditionalInteractions() {
1056
- if (!this.chartInstance)
1057
- return;
1058
- // 1. ZRender click for background "sectors" (Specific to bands)
1059
- const zr = this.chartInstance.getZr();
1060
- zr.on('click', (params) => {
1061
- if (!params.target) {
1062
- const pointInPixel = [params.offsetX, params.offsetY];
1063
- if (this.chartInstance.containPixel('grid', pointInPixel)) {
1064
- const xIndexResult = this.chartInstance.convertFromPixel({ xAxisIndex: 0 }, pointInPixel);
1065
- const xIndex = Array.isArray(xIndexResult) ? xIndexResult[0] : xIndexResult;
1066
- if (typeof xIndex === 'number' && xIndex >= 0) {
1067
- this.handleSelection(xIndex, -1); // Use -1 or null to indicate sector selection without specific series
1068
- }
1069
- }
1070
- }
1071
- });
1072
- // 2. Mouseover for Group Highlighting
1073
- this.chartInstance.on('mouseover', (params) => {
1074
- if (params.dataIndex !== undefined) {
1075
- this.highlightSector(params.dataIndex);
1076
- }
1077
- });
1078
- this.chartInstance.on('mouseout', () => {
1079
- this.clearHighlight();
1080
- });
1185
+ /**
1186
+ * Permite inyectar una paleta de colores básica.
1187
+ */
1188
+ setPalette(palette) {
1189
+ if (palette) {
1190
+ this.palette = palette;
1191
+ }
1081
1192
  }
1082
- highlightSector(index) {
1083
- if (!this.chartInstance || this.selectedCategoryIndex !== null)
1084
- return;
1085
- const seriesCount = Array.isArray(this.chartOptions.series) ? this.chartOptions.series.length : 0;
1086
- this.chartInstance.dispatchAction({
1087
- type: 'highlight',
1088
- seriesIndex: Array.from({ length: seriesCount }, (_, i) => i),
1089
- dataIndex: index
1090
- });
1193
+ /**
1194
+ * Permite inyectar un resolver de colores dinámico.
1195
+ */
1196
+ setColorResolver(resolver) {
1197
+ if (resolver) {
1198
+ this.colorResolver = resolver;
1199
+ }
1091
1200
  }
1092
- clearHighlight() {
1093
- if (!this.chartInstance)
1094
- return;
1095
- const seriesCount = Array.isArray(this.chartOptions.series) ? this.chartOptions.series.length : 0;
1096
- this.chartInstance.dispatchAction({
1097
- type: 'downplay',
1098
- seriesIndex: Array.from({ length: seriesCount }, (_, i) => i)
1099
- });
1201
+ // Utils
1202
+ getCategoryAxisOptions(data, overrides) {
1203
+ const categoryAxisOptionsOverrides = {
1204
+ ...overrides.categoryAxis[0],
1205
+ data: data.categories,
1206
+ };
1207
+ const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
1208
+ return categoryAxisOptions;
1209
+ }
1210
+ getValueAxisOptions(data, overrides) {
1211
+ const valueAxisOptions = getValueAxisOptions();
1212
+ return valueAxisOptions;
1100
1213
  }
1214
+ }
1215
+
1216
+ class EchartsBarComponent extends BaseEchartsComponent {
1101
1217
  /**
1102
- * Maneja clics en la leyenda para persistir filtros.
1218
+ * Opciones escenciales inmutables estaticas comunes a todos los charts de barras.
1103
1219
  */
1104
- onLegendSelectChanged(event) {
1105
- if (event && event.selected) {
1106
- this.currentLegendSelected = event.selected;
1107
- this.updateChartOptions();
1220
+ baseSeriesOptions = {
1221
+ type: 'bar',
1222
+ barMaxWidth: 50,
1223
+ barGap: '15%',
1224
+ barCategoryGap: '35%',
1225
+ animation: true,
1226
+ animationDuration: 1000,
1227
+ animationEasing: 'cubicOut',
1228
+ itemStyle: {
1229
+ borderRadius: [4, 4, 0, 0],
1230
+ },
1231
+ stack: undefined,
1232
+ emphasis: {
1233
+ focus: 'none'
1234
+ },
1235
+ showBackground: true,
1236
+ backgroundStyle: {
1237
+ color: 'rgba(180, 180, 180, 0.2)' // gris claro
1238
+ },
1239
+ label: {
1240
+ show: false,
1241
+ position: 'top',
1242
+ }
1243
+ };
1244
+ // va a tener que estar en el base como "abstract".
1245
+ product = {
1246
+ chartKey: 'bar',
1247
+ baseOptions: {
1248
+ series: this.baseSeriesOptions,
1108
1249
  }
1250
+ };
1251
+ builder = new EChartBuilder(this.product);
1252
+ director = new VSECDirector(this.builder);
1253
+ constructor() {
1254
+ super();
1255
+ }
1256
+ // va a tener que estar en el base como "abstract".
1257
+ make(makeOpts) {
1258
+ this.director.makeBar(this.data, this.optionsOverrides, makeOpts);
1109
1259
  }
1110
1260
  updateChartOptions() {
1111
1261
  if (!this.chartInstance)
1112
1262
  return;
1113
1263
  if (!this.data)
1114
1264
  return;
1115
- // 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
1116
- if (this.valueFormatter)
1117
- this.builder.setValueFormatter(this.valueFormatter);
1118
- if (this.palette)
1119
- this.builder.setPalette(this.palette);
1120
- if (this.colorResolver)
1121
- this.builder.setColorResolver(this.colorResolver);
1122
- // 2. Obtenemos las bases del chart usando el builder
1123
- let baseOptions = this.builder.build(this.data, this.optionsOverrides);
1124
- // 3. Re-apply legend selection state if exists
1265
+ const makeBarOpts = {
1266
+ valueFormatter: this.valueFormatter,
1267
+ palette: this.palette,
1268
+ colorResolver: this.colorResolver,
1269
+ };
1270
+ this.make(makeBarOpts);
1271
+ const baseOptions = this.builder.getResult();
1125
1272
  if (this.currentLegendSelected && baseOptions.legend) {
1126
1273
  baseOptions.legend.selected = { ...this.currentLegendSelected };
1127
1274
  }
1128
- // 4. Apply persistent selection style if a sector is selected
1129
1275
  if (this.selectedCategoryIndex !== null && baseOptions.series) {
1130
- const seriesArray = baseOptions.series;
1131
- baseOptions.series = seriesArray.map((s, sIdx) => {
1132
- if (s.type === 'bar' && Array.isArray(s.data)) {
1133
- return {
1134
- ...s,
1135
- emphasis: {
1136
- disabled: true
1137
- },
1138
- data: s.data.map((val, idx) => {
1139
- const isSelected = idx === this.selectedCategoryIndex;
1140
- const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
1141
- const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
1142
- return {
1143
- value: itemVal,
1144
- itemStyle: {
1145
- opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
1146
- borderWidth: 0
1147
- }
1148
- };
1149
- })
1150
- };
1151
- }
1152
- return s;
1153
- });
1154
- }
1155
- this.triggerUpdate(baseOptions);
1156
- }
1157
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1158
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsVerticalBandsComponent, isStandalone: true, selector: "vs-echarts-vertical-bands", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($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"] }] });
1159
- }
1160
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, decorators: [{
1161
- type: Component,
1162
- args: [{ selector: 'vs-echarts-vertical-bands', standalone: true, imports: [
1163
- CommonModule,
1164
- NgxEchartsDirective,
1165
- ], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1166
- }], ctorParameters: () => [] });
1167
-
1168
- /**
1169
- * BarBuilder
1170
- *
1171
- * Especializado en construir opciones para gráficos de barras generales.
1172
- */
1173
- class BarBuilder extends BaseEchartBuilder {
1174
- constructor() {
1175
- super();
1176
- }
1177
- build(data, overrides) {
1178
- if (!data || !data.series.length)
1179
- return {};
1180
- const { itemStyle, emphasis = { focus: 'none' }, stack = undefined, showBackground = false, coordinateSystem = 'cartesian2d', } = overrides.bar.series;
1181
- const itStBorderRadius = itemStyle?.borderRadius ?? [4, 4, 0, 0];
1182
- const emphasisFocus = emphasis.focus ?? 'none';
1183
- const series = data.series.map((s) => {
1184
- const seriesOption = {
1185
- name: s.name,
1186
- type: 'bar',
1187
- barMaxWidth: 50,
1188
- barGap: '15%',
1189
- barCategoryGap: '35%',
1190
- animation: true,
1191
- animationDuration: 1000,
1192
- animationEasing: 'cubicOut',
1193
- coordinateSystem,
1194
- itemStyle: {
1195
- borderRadius: itStBorderRadius,
1196
- },
1197
- data: s.data,
1198
- stack,
1199
- emphasis: {
1200
- focus: emphasisFocus
1201
- },
1202
- showBackground,
1203
- backgroundStyle: {
1204
- color: 'rgba(180, 180, 180, 0.2)' // gris claro
1205
- },
1206
- label: {
1207
- show: false,
1208
- position: 'top',
1209
- formatter: (params) => {
1210
- const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
1211
- return this.formatCellValue(params.value, key);
1212
- }
1213
- }
1214
- };
1215
- // Inyectar el resolver de color si existe
1216
- if (this.colorResolver && seriesOption.itemStyle) {
1217
- seriesOption.itemStyle.color = this.colorResolver;
1218
- }
1219
- return seriesOption;
1220
- });
1221
- const common = this.getCommonOptions(overrides);
1222
- const xAxis = [];
1223
- const yAxis = [];
1224
- const radiusAxis = [];
1225
- const polar = [];
1226
- const angleAxis = [];
1227
- const categoryAxisOptionsOverrides = {
1228
- ...overrides.axis.categoryAxis[0],
1229
- data: data.categories,
1230
- };
1231
- const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
1232
- const valueAxisOptions = getValueAxisOptions();
1233
- if (coordinateSystem == "polar") {
1234
- // polar coord system.
1235
- /** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
1236
- const radiusAxisOverrides = {
1237
- axisTick: {
1238
- show: false,
1239
- },
1240
- axisLabel: {
1241
- margin: 2,
1242
- fontSize: 8,
1243
- align: 'right',
1244
- rotate: 20,
1245
- verticalAlign: 'top',
1246
- },
1247
- axisLine: {
1248
- lineStyle: {
1249
- type: 'dashed',
1250
- },
1276
+ const seriesArray = baseOptions.series;
1277
+ baseOptions.series = seriesArray.map((s, sIdx) => {
1278
+ if (s.type === 'bar' && Array.isArray(s.data)) {
1279
+ return {
1280
+ ...s,
1281
+ emphasis: {
1282
+ disabled: true
1283
+ },
1284
+ data: s.data.map((val, idx) => {
1285
+ const isSelected = idx === this.selectedCategoryIndex;
1286
+ const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
1287
+ const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
1288
+ return {
1289
+ value: itemVal,
1290
+ itemStyle: {
1291
+ opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
1292
+ borderWidth: 0
1293
+ }
1294
+ };
1295
+ })
1296
+ };
1251
1297
  }
1252
- };
1253
- angleAxis.push(categoryAxisOptions);
1254
- const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
1255
- radiusAxis.push(radialAxisOptions);
1256
- polar.push({
1257
- radius: '65%',
1258
- center: ["50%", "44%"],
1298
+ return s;
1259
1299
  });
1260
1300
  }
1261
- else {
1262
- // cartesian 2d coord system.
1263
- if (overrides.bar.orientation === 'h') {
1264
- xAxis.push(valueAxisOptions);
1265
- yAxis.push(categoryAxisOptions);
1266
- }
1267
- else {
1268
- xAxis.push(categoryAxisOptions);
1269
- yAxis.push(valueAxisOptions);
1270
- }
1271
- }
1272
- const { trigger = 'item' } = overrides.tooltip;
1273
- const tooltipOptionsOverrides = {
1274
- trigger,
1275
- };
1276
- return {
1277
- ...common,
1278
- tooltip: {
1279
- ...getTooltipOptions(tooltipOptionsOverrides),
1280
- formatter: getTooltipFormatter(trigger, data, this.formatCellValue.bind(this))
1281
- },
1282
- legend: getLegendOptions(),
1283
- xAxis,
1284
- yAxis,
1285
- radiusAxis,
1286
- angleAxis,
1287
- polar,
1288
- series: series
1289
- };
1290
- }
1291
- }
1292
-
1293
- /**
1294
- * EchartsBarComponent
1295
- *
1296
- * Componente especialista para visualización de gráficos de barras.
1297
- * Implementa patrones de interacción ZRender y resaltado de grupos.
1298
- */
1299
- class EchartsBarComponent extends BaseEchartsComponent {
1300
- builder;
1301
- constructor() {
1302
- super();
1303
- this.builder = new BarBuilder();
1301
+ this.triggerUpdate(baseOptions);
1304
1302
  }
1305
1303
  onChartInit(instance) {
1306
1304
  super.onChartInit(instance);
@@ -1357,49 +1355,6 @@ class EchartsBarComponent extends BaseEchartsComponent {
1357
1355
  this.updateChartOptions();
1358
1356
  }
1359
1357
  }
1360
- updateChartOptions() {
1361
- if (!this.chartInstance)
1362
- return;
1363
- if (!this.data)
1364
- return;
1365
- if (this.valueFormatter)
1366
- this.builder.setValueFormatter(this.valueFormatter);
1367
- if (this.palette)
1368
- this.builder.setPalette(this.palette);
1369
- if (this.colorResolver)
1370
- this.builder.setColorResolver(this.colorResolver);
1371
- let baseOptions = this.builder.build(this.data, this.optionsOverrides);
1372
- if (this.currentLegendSelected && baseOptions.legend) {
1373
- baseOptions.legend.selected = { ...this.currentLegendSelected };
1374
- }
1375
- if (this.selectedCategoryIndex !== null && baseOptions.series) {
1376
- const seriesArray = baseOptions.series;
1377
- baseOptions.series = seriesArray.map((s, sIdx) => {
1378
- if (s.type === 'bar' && Array.isArray(s.data)) {
1379
- return {
1380
- ...s,
1381
- emphasis: {
1382
- disabled: true
1383
- },
1384
- data: s.data.map((val, idx) => {
1385
- const isSelected = idx === this.selectedCategoryIndex;
1386
- const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
1387
- const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
1388
- return {
1389
- value: itemVal,
1390
- itemStyle: {
1391
- opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
1392
- borderWidth: 0
1393
- }
1394
- };
1395
- })
1396
- };
1397
- }
1398
- return s;
1399
- });
1400
- }
1401
- this.triggerUpdate(baseOptions);
1402
- }
1403
1358
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1404
1359
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsBarComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></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"] }] });
1405
1360
  }
@@ -1411,86 +1366,258 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
1411
1366
  ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1412
1367
  }], ctorParameters: () => [] });
1413
1368
 
1414
- class LineBuilder extends BaseEchartBuilder {
1415
- constructor() {
1416
- super();
1417
- }
1418
- build(data, overrides) {
1419
- if (!data || !data.series.length)
1420
- return {};
1421
- const { areaStyle = undefined, stack = undefined, smooth = true, } = overrides.line.series;
1422
- const series = data.series.map((s) => {
1423
- const seriesOption = {
1424
- name: s.name,
1425
- type: 'line',
1426
- animation: true,
1427
- animationDuration: 1000,
1428
- animationEasing: 'cubicOut',
1429
- data: s.data,
1430
- smooth,
1431
- smoothMonotone: 'x',
1432
- symbolSize: 6,
1433
- itemStyle: {
1434
- shadowColor: 'rgba(0, 0, 0, 0.2)',
1435
- shadowBlur: 5,
1436
- shadowOffsetY: 2,
1437
- },
1438
- lineStyle: {
1439
- width: 2,
1440
- shadowColor: 'rgba(0, 0, 0, 0.2)',
1441
- shadowBlur: 8,
1442
- shadowOffsetY: 6,
1443
- cap: 'round',
1444
- join: 'round',
1445
- },
1446
- emphasis: {
1447
- focus: 'none',
1448
- itemStyle: {
1449
- borderWidth: 2,
1450
- shadowBlur: 10,
1451
- },
1452
- lineStyle: {
1453
- width: 4,
1454
- shadowBlur: 12,
1455
- }
1456
- },
1457
- areaStyle,
1458
- stack,
1459
- };
1460
- // Inyectar el resolver de color si existe
1461
- if (this.colorResolver && seriesOption.itemStyle != undefined) {
1462
- seriesOption.itemStyle.color = this.colorResolver;
1463
- }
1464
- return seriesOption;
1465
- });
1466
- const common = this.getCommonOptions(overrides);
1467
- const categoryAxisOptions = {
1468
- ...overrides.axis.categoryAxis[0],
1469
- data: data.categories,
1369
+ class EChartsHBarComponent extends EchartsBarComponent {
1370
+ variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
1371
+ showBackground: false,
1372
+ itemStyle: {
1373
+ borderRadius: [0, 4, 4, 0],
1374
+ }
1375
+ });
1376
+ variantProduct = {
1377
+ chartKey: 'hBar',
1378
+ baseOptions: {
1379
+ series: this.variantSeriesOptionsBase,
1380
+ }
1381
+ };
1382
+ builder = new EChartBuilder(this.variantProduct);
1383
+ director = new VSECDirector(this.builder);
1384
+ make(makeOpts) {
1385
+ makeOpts.axisTypes = {
1386
+ x: 'value',
1387
+ y: 'category',
1470
1388
  };
1471
- const { trigger = 'item' } = overrides.tooltip;
1472
- const tooltipOptionsOverrides = {
1473
- trigger,
1389
+ this.director.makeBar(this.data, this.optionsOverrides, makeOpts);
1390
+ }
1391
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1392
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsHBarComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></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"] }] });
1393
+ }
1394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarComponent, decorators: [{
1395
+ type: Component,
1396
+ args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
1397
+ CommonModule,
1398
+ NgxEchartsDirective,
1399
+ ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1400
+ }] });
1401
+
1402
+ class EChartsBarStackedComponent extends EchartsBarComponent {
1403
+ variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
1404
+ showBackground: false,
1405
+ stack: 'total',
1406
+ itemStyle: {
1407
+ borderRadius: [0, 0, 0, 0],
1408
+ },
1409
+ emphasis: {
1410
+ focus: 'series',
1411
+ }
1412
+ });
1413
+ variantProduct = {
1414
+ chartKey: 'barStacked',
1415
+ baseOptions: {
1416
+ series: this.variantSeriesOptionsBase,
1417
+ }
1418
+ };
1419
+ builder = new EChartBuilder(this.variantProduct);
1420
+ director = new VSECDirector(this.builder);
1421
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1422
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsBarStackedComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></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"] }] });
1423
+ }
1424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedComponent, decorators: [{
1425
+ type: Component,
1426
+ args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
1427
+ CommonModule,
1428
+ NgxEchartsDirective,
1429
+ ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1430
+ }] });
1431
+
1432
+ class EChartsHBarStackedComponent extends EchartsBarComponent {
1433
+ variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
1434
+ showBackground: false,
1435
+ stack: 'total',
1436
+ itemStyle: {
1437
+ borderRadius: [0, 0, 0, 0],
1438
+ },
1439
+ emphasis: {
1440
+ focus: 'series',
1441
+ }
1442
+ });
1443
+ variantProduct = {
1444
+ chartKey: 'hBarStacked',
1445
+ baseOptions: {
1446
+ series: this.variantSeriesOptionsBase,
1447
+ }
1448
+ };
1449
+ builder = new EChartBuilder(this.variantProduct);
1450
+ director = new VSECDirector(this.builder);
1451
+ make(makeOpts) {
1452
+ makeOpts.axisTypes = {
1453
+ x: 'value',
1454
+ y: 'category',
1474
1455
  };
1456
+ this.director.makeBar(this.data, this.optionsOverrides, makeOpts);
1457
+ }
1458
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1459
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsHBarStackedComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></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"] }] });
1460
+ }
1461
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarStackedComponent, decorators: [{
1462
+ type: Component,
1463
+ args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
1464
+ CommonModule,
1465
+ NgxEchartsDirective,
1466
+ ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1467
+ }] });
1468
+
1469
+ class EChartsBarStackedRadialComponent extends EchartsBarComponent {
1470
+ variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
1471
+ showBackground: false,
1472
+ stack: 'total',
1473
+ itemStyle: {
1474
+ borderRadius: [0, 0, 0, 0],
1475
+ },
1476
+ emphasis: {
1477
+ focus: 'series',
1478
+ },
1479
+ coordinateSystem: 'polar',
1480
+ });
1481
+ variantProduct = {
1482
+ chartKey: 'barStackedRadial',
1483
+ baseOptions: {
1484
+ series: this.variantSeriesOptionsBase,
1485
+ }
1486
+ };
1487
+ builder = new EChartBuilder(this.variantProduct);
1488
+ director = new VSECDirector(this.builder);
1489
+ make(makeOpts) {
1490
+ this.director.makeBarRadial(this.data, this.optionsOverrides, makeOpts);
1491
+ }
1492
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedRadialComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1493
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsBarStackedRadialComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></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"] }] });
1494
+ }
1495
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedRadialComponent, decorators: [{
1496
+ type: Component,
1497
+ args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
1498
+ CommonModule,
1499
+ NgxEchartsDirective,
1500
+ ], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1501
+ }] });
1502
+
1503
+ /**
1504
+ * Applies a visual selection effect to line-based series.
1505
+ * Highlights the selected series and point, and dims everything else.
1506
+ *
1507
+ * @param series The series array to modify
1508
+ * @param selectedCategoryIndex Index of the selected category
1509
+ * @param selectedSeriesIndex Index of the selected series
1510
+ * @returns Modified series array
1511
+ */
1512
+ function applyLineSelectionStyle(series, selectedCategoryIndex, selectedSeriesIndex) {
1513
+ if (selectedCategoryIndex === null || !series)
1514
+ return series;
1515
+ return series.map((s, sIdx) => {
1516
+ const isSelectedSeries = sIdx === selectedSeriesIndex;
1517
+ // Serie seleccionada: Línea con opacidad 1 para que destaque la tendencia.
1518
+ // Serie NO seleccionada: Opacidad 0.20 para atenuar fuertemente.
1519
+ const seriesOpacity = isSelectedSeries ? 1 : 0.20;
1475
1520
  return {
1476
- ...common,
1477
- tooltip: {
1478
- ...getTooltipOptions(tooltipOptionsOverrides),
1479
- formatter: getTooltipFormatter(trigger, data, this.formatCellValue.bind(this)),
1521
+ ...s,
1522
+ emphasis: {
1523
+ disabled: true // Deshabilitar el énfasis (hover) cuando hay una selección activa
1524
+ },
1525
+ itemStyle: {
1526
+ ...s.itemStyle,
1527
+ opacity: seriesOpacity
1528
+ },
1529
+ lineStyle: {
1530
+ ...s.lineStyle,
1531
+ opacity: seriesOpacity
1480
1532
  },
1481
- legend: getLegendOptions(),
1482
- xAxis: [getCategoryAxisOptions(categoryAxisOptions)],
1483
- yAxis: [getValueAxisOptions()],
1484
- series: series
1533
+ ...(s.areaStyle ? {
1534
+ areaStyle: {
1535
+ ...s.areaStyle,
1536
+ opacity: isSelectedSeries ? 0.6 : 0.1
1537
+ }
1538
+ } : {}),
1539
+ // Personalizamos los puntos individualmente
1540
+ data: (s.data || []).map((val, idx) => {
1541
+ const isSelectedPoint = isSelectedSeries && idx === selectedCategoryIndex;
1542
+ const isOtherPointInSelectedSeries = isSelectedSeries && idx !== selectedCategoryIndex;
1543
+ const originalPoint = (val && typeof val === 'object') ? val : { value: val };
1544
+ if (isSelectedPoint) {
1545
+ return {
1546
+ ...originalPoint,
1547
+ z: 10, // Asegurar que el punto seleccionado esté por encima de los demás
1548
+ itemStyle: {
1549
+ ...originalPoint.itemStyle,
1550
+ opacity: 1,
1551
+ borderWidth: 2,
1552
+ borderColor: '#fff',
1553
+ shadowBlur: 10,
1554
+ shadowColor: 'rgba(0,0,0,0.5)'
1555
+ },
1556
+ symbolSize: 12
1557
+ };
1558
+ }
1559
+ else if (isOtherPointInSelectedSeries) {
1560
+ // Puntos de la serie seleccionada que NO son el clicado: un poco más pequeños y traslúcidos
1561
+ return {
1562
+ ...originalPoint,
1563
+ itemStyle: {
1564
+ ...originalPoint.itemStyle,
1565
+ opacity: 0.5
1566
+ },
1567
+ symbolSize: 6
1568
+ };
1569
+ }
1570
+ // Puntos de otras series o por defecto
1571
+ return val;
1572
+ })
1485
1573
  };
1486
- }
1574
+ });
1487
1575
  }
1488
1576
 
1489
1577
  class EchartsLineComponent extends BaseEchartsComponent {
1490
- builder;
1578
+ baseSeriesOptions = {
1579
+ type: 'line',
1580
+ animation: true,
1581
+ animationDuration: 1000,
1582
+ animationEasing: 'cubicOut',
1583
+ smooth: true,
1584
+ smoothMonotone: 'x',
1585
+ symbolSize: 6,
1586
+ itemStyle: {
1587
+ shadowColor: 'rgba(0, 0, 0, 0.2)',
1588
+ shadowBlur: 5,
1589
+ shadowOffsetY: 2,
1590
+ },
1591
+ lineStyle: {
1592
+ width: 2,
1593
+ shadowColor: 'rgba(0, 0, 0, 0.2)',
1594
+ shadowBlur: 8,
1595
+ shadowOffsetY: 6,
1596
+ cap: 'round',
1597
+ join: 'round',
1598
+ },
1599
+ emphasis: {
1600
+ focus: 'none',
1601
+ itemStyle: {
1602
+ borderWidth: 2,
1603
+ shadowBlur: 10,
1604
+ },
1605
+ lineStyle: {
1606
+ width: 4,
1607
+ shadowBlur: 12,
1608
+ }
1609
+ },
1610
+ };
1611
+ product = {
1612
+ chartKey: 'line',
1613
+ baseOptions: {
1614
+ series: this.baseSeriesOptions,
1615
+ }
1616
+ };
1617
+ builder = new EChartBuilder(this.product);
1618
+ director = new VSECDirector(this.builder);
1491
1619
  constructor() {
1492
1620
  super();
1493
- this.builder = new LineBuilder();
1494
1621
  }
1495
1622
  onInputChanges(changes) {
1496
1623
  if (changes['data']) {
@@ -1500,41 +1627,96 @@ class EchartsLineComponent extends BaseEchartsComponent {
1500
1627
  }
1501
1628
  super.onInputChanges(changes);
1502
1629
  }
1630
+ make(makeOpts) {
1631
+ this.director.makeLine(this.data, this.optionsOverrides, makeOpts);
1632
+ }
1503
1633
  updateChartOptions() {
1504
1634
  if (!this.chartInstance)
1505
1635
  return;
1506
1636
  if (!this.data)
1507
1637
  return;
1508
- // 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
1509
- if (this.valueFormatter)
1510
- this.builder.setValueFormatter(this.valueFormatter);
1511
- if (this.palette)
1512
- this.builder.setPalette(this.palette);
1513
- if (this.colorResolver)
1514
- this.builder.setColorResolver(this.colorResolver);
1515
- // 2. Obtenemos las bases del chart usando el builder
1516
- let baseOptions = this.builder.build(this.data, this.optionsOverrides);
1517
- // 3. Re-apply legend selection state if exists
1638
+ // 1.
1639
+ const makeBarOpts = {
1640
+ valueFormatter: this.valueFormatter,
1641
+ palette: this.palette,
1642
+ colorResolver: this.colorResolver,
1643
+ };
1644
+ this.make(makeBarOpts);
1645
+ const baseOptions = this.builder.getResult();
1646
+ // 2. Re-apply legend selection state if exists
1518
1647
  if (this.currentLegendSelected && baseOptions.legend) {
1519
1648
  baseOptions.legend.selected = { ...this.currentLegendSelected };
1520
1649
  }
1521
- // 4. Apply persistent selection style if a point is selected
1650
+ //3. Apply persistent selection style if a point is selected
1522
1651
  if (this.selectedCategoryIndex !== null && baseOptions.series) {
1523
1652
  baseOptions.series = applyLineSelectionStyle(baseOptions.series, this.selectedCategoryIndex, this.selectedSeriesIndex);
1524
1653
  }
1525
1654
  this.triggerUpdate(baseOptions);
1526
1655
  }
1527
1656
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1528
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsLineComponent, isStandalone: true, selector: "vs-echarts-line", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", 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"] }] });
1657
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsLineComponent, isStandalone: true, selector: "vs-echarts-line", providers: [
1658
+ provideVSEcharts(),
1659
+ ], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", 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"] }] });
1529
1660
  }
1530
1661
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, decorators: [{
1531
1662
  type: Component,
1532
1663
  args: [{ selector: 'vs-echarts-line', standalone: true, imports: [
1533
1664
  CommonModule,
1534
1665
  NgxEchartsDirective,
1535
- ], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1666
+ ], providers: [
1667
+ provideVSEcharts(),
1668
+ ], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1536
1669
  }], ctorParameters: () => [] });
1537
1670
 
1671
+ class EChartsAreaComponent extends EchartsLineComponent {
1672
+ variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
1673
+ smooth: true,
1674
+ areaStyle: {},
1675
+ });
1676
+ variantProduct = {
1677
+ chartKey: 'area',
1678
+ baseOptions: {
1679
+ series: this.variantSeriesOptionsBase,
1680
+ }
1681
+ };
1682
+ builder = new EChartBuilder(this.variantProduct);
1683
+ director = new VSECDirector(this.builder);
1684
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1685
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsAreaComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", 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"] }] });
1686
+ }
1687
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaComponent, decorators: [{
1688
+ type: Component,
1689
+ args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
1690
+ CommonModule,
1691
+ NgxEchartsDirective,
1692
+ ], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1693
+ }] });
1694
+
1695
+ class EChartsAreaStackComponent extends EchartsLineComponent {
1696
+ variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
1697
+ smooth: true,
1698
+ areaStyle: {},
1699
+ stack: 'total',
1700
+ });
1701
+ variantProduct = {
1702
+ chartKey: 'areaStack',
1703
+ baseOptions: {
1704
+ series: this.variantSeriesOptionsBase,
1705
+ }
1706
+ };
1707
+ builder = new EChartBuilder(this.variantProduct);
1708
+ director = new VSECDirector(this.builder);
1709
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaStackComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1710
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsAreaStackComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", 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"] }] });
1711
+ }
1712
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaStackComponent, decorators: [{
1713
+ type: Component,
1714
+ args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
1715
+ CommonModule,
1716
+ NgxEchartsDirective,
1717
+ ], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
1718
+ }] });
1719
+
1538
1720
  // Interfaces de Inputs de Base EChart Component //
1539
1721
 
1540
1722
  ;
@@ -1549,5 +1731,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
1549
1731
  * Generated bundle index. Do not edit.
1550
1732
  */
1551
1733
 
1552
- export { BaseEchartsComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent, EchartsVerticalBandsComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
1734
+ export { BaseEchartsComponent, EChartsAreaComponent, EChartsAreaStackComponent, EChartsBarStackedComponent, EChartsBarStackedRadialComponent, EChartsHBarComponent, EChartsHBarStackedComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
1553
1735
  //# sourceMappingURL=visionaris-bruno-vs-echarts.mjs.map