@visionaris-bruno/vs-echarts 5.9.1 → 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
@@ -360,80 +82,47 @@ function defaultOptionsOverrides() {
360
82
  valueAxis: [],
361
83
  },
362
84
  line: {
363
- series: {},
85
+ series: {
86
+ smooth: true,
87
+ },
364
88
  },
365
89
  area: {
366
90
  series: {
367
91
  smooth: true,
368
- areaStyle: {},
369
92
  },
370
93
  },
371
94
  areaStack: {
372
95
  series: {
373
96
  smooth: true,
374
- areaStyle: {},
375
- stack: 'total',
376
97
  },
377
98
  },
378
99
  bar: {
379
- // tooltip: {},
380
100
  series: {
381
101
  showBackground: true,
382
102
  },
383
103
  },
384
104
  barStacked: {
385
- // tooltip: {
386
- // trigger: 'axis',
387
- // },
388
105
  series: {
389
106
  showBackground: false,
390
- stack: 'total',
391
- itemStyle: {
392
- borderRadius: [0, 0, 0, 0],
393
- },
394
- emphasis: {
395
- focus: 'series',
396
- }
397
107
  }
398
108
  },
399
109
  barStackedRadial: {
400
110
  series: {
401
111
  showBackground: false,
402
- stack: 'total',
403
- itemStyle: {
404
- borderRadius: [0, 0, 0, 0],
405
- },
406
- emphasis: {
407
- focus: 'series',
408
- },
409
- coordinateSystem: 'polar',
410
112
  }
411
113
  },
412
114
  hBar: {
413
- orientation: 'h',
414
- // tooltip: {},
415
115
  series: {
416
116
  showBackground: true,
417
- itemStyle: {
418
- borderRadius: [0, 4, 4, 0],
419
- }
420
117
  }
421
118
  },
422
119
  hBarStacked: {
423
- orientation: 'h',
424
- // tooltip: {
425
- // trigger: 'axis',
426
- // },
427
120
  series: {
428
- stack: 'total',
429
121
  showBackground: false,
430
- itemStyle: {
431
- borderRadius: [0, 0, 0, 0],
432
- },
433
- emphasis: {
434
- focus: 'series',
435
- }
436
122
  }
123
+ },
124
+ ring: {
125
+ series: {}
437
126
  }
438
127
  };
439
128
  }
@@ -458,21 +147,21 @@ class BaseEchartsComponent {
458
147
  /** Formateador de valores para etiquetas y tooltips */
459
148
  valueFormatter;
460
149
  chartClick = new EventEmitter();
461
- /** Opciones configuradas para ngx-echarts */
462
- chartOptions = {};
463
150
  /** Subject para debouncing de actualizaciones. ReplaySubject asegura no perder el primer renderizado. */
464
151
  updateSubject = new ReplaySubject(1);
465
152
  updateSubscription;
466
- constructor() {
467
- this.updateSubscription = this.updateSubject.pipe(debounceTime(150)).subscribe(options => {
468
- this.updateOptions(options);
469
- });
470
- }
471
153
  chartInstance;
472
154
  currentLegendSelected = null;
473
155
  /** Estado de selección para filtros cruzados */
474
156
  selectedCategoryIndex = null;
475
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
+ }
476
165
  ngOnChanges(changes) {
477
166
  this.onInputChanges(changes);
478
167
  }
@@ -581,124 +270,371 @@ class BaseEchartsComponent {
581
270
  triggerUpdate(options) {
582
271
  this.updateSubject.next(options);
583
272
  }
584
- /**
585
- * Método público para forzar el redimensionado desde el padre
586
- */
587
- resize() {
588
- 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;
589
445
  }
590
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
591
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.19", type: BaseEchartsComponent, isStandalone: true, inputs: { data: "data", optionsOverrides: ["optionsOverrides", "optionsOverrides", (values) => {
592
- return merge(defaultOptionsOverrides(), values || {});
593
- }], 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;
594
608
  }
595
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, decorators: [{
596
- type: Directive,
597
- args: [{
598
- standalone: true
599
- }]
600
- }], ctorParameters: () => [], propDecorators: { chartContainer: [{
601
- type: ViewChild,
602
- args: ['chartContainer', { static: true }]
603
- }], data: [{
604
- type: Input
605
- }], optionsOverrides: [{
606
- type: Input,
607
- args: [{
608
- "transform": (values) => {
609
- return merge(defaultOptionsOverrides(), values || {});
610
- }
611
- }]
612
- }], palette: [{
613
- type: Input
614
- }], colorResolver: [{
615
- type: Input
616
- }], valueFormatter: [{
617
- type: Input
618
- }], chartClick: [{
619
- type: Output
620
- }] } });
621
609
 
622
610
  /**
623
- * BaseEchartBuilder
611
+ * RingBuilder
624
612
  *
625
- * Clase base para la construcción de opciones de ECharts.
626
- * Implementa lógica compartida de paletas y opciones comunes.
613
+ * Builder concreto para el grafico de Ring.
627
614
  *
628
- * @see {@link vs-echarts/docs/internal-architecture.md}
629
615
  */
630
- class BaseEchartBuilder {
616
+ class RingBuilder {
617
+ product;
631
618
  valueFormatter = (value) => value.toLocaleString();
632
619
  palette = [];
633
- // TODO: Hay que implementar un valor por defecto.
634
620
  colorResolver;
635
- constructor() { }
636
- /**
637
- * Permite inyectar un formateador de valores externo.
638
- */
639
- setValueFormatter(formatter) {
640
- if (formatter) {
641
- this.valueFormatter = formatter;
642
- }
643
- }
644
- /**
645
- * Permite inyectar una paleta de colores básica.
646
- */
647
- setPalette(palette) {
648
- if (palette) {
649
- this.palette = palette;
650
- }
621
+ result = {};
622
+ constructor(product) {
623
+ this.product = product;
651
624
  }
652
- /**
653
- * Permite inyectar un resolver de colores dinámico.
654
- */
655
- setColorResolver(resolver) {
656
- if (resolver) {
657
- this.colorResolver = resolver;
658
- }
625
+ reset() {
626
+ this.result = {};
659
627
  }
660
- /**
661
- * Retorna configuraciones comunes para todos los gráficos.
662
- *
663
- * TODO: particionar en configuraciones concretas con sus
664
- * respectivos overrides.
665
- */
666
- getCommonOptions(overrides) {
667
- const common = {
668
- backgroundColor: 'transparent',
669
- textStyle: {
670
- fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif"
671
- },
672
- grid: {
673
- left: '3%',
674
- right: '4%',
675
- bottom: '15%',
676
- top: '20px',
677
- containLabel: true
678
- }
628
+ addCommons() {
629
+ const opts = {
630
+ palette: this.palette,
679
631
  };
680
- // Aplicar paleta global: Prioridad Palette Inyectada > Default Visionaris
681
- common.color = (this.palette && this.palette.length > 0) ? this.palette : getDefaultPalette();
682
- return common;
683
- }
684
- /**
685
- * Formatea un valor utilizando el callback inyectado.
686
- */
687
- formatCellValue(value, key) {
688
- return this.valueFormatter(value, key);
632
+ const common = getCommons(opts);
633
+ merge(this.result, common);
689
634
  }
690
- }
691
-
692
- /**
693
- * RingBuilder
694
- *
695
- * Especializado en construir opciones para gráficos de tipo Ring (Donas concéntricas).
696
- * @see {@link vs-echarts/docs/charts/ring-patterns.md}
697
- */
698
- class RingBuilder extends BaseEchartBuilder {
699
- build(data, overrides) {
635
+ addSeries(data, overrides) {
700
636
  if (!data || !data.series.length)
701
- return {};
637
+ return;
702
638
  const totalRings = data.series.length; // Cada serie es un anillo
703
639
  // Configuración dinámica de radios y márgenes
704
640
  const margin = totalRings > 1 ? Math.max(0.5, 2.5 - (totalRings * 0.1)) : 0;
@@ -716,81 +652,194 @@ class RingBuilder extends BaseEchartBuilder {
716
652
  value: s.data[catIndex],
717
653
  originalMeassureKey: s.originalKey || (data.categoryKeys ? data.categoryKeys[catIndex] : '')
718
654
  }));
719
- const seriesOption = {
655
+ const dynamicRingSeriesOptions = {
720
656
  name: s.name,
721
- type: 'pie',
722
657
  radius: [`${inner}%`, `${outer}%`],
723
- center: ['50%', '50%'],
724
- avoidLabelOverlap: true,
725
- minAngle: 3,
726
- selectedMode: 'single',
727
- selectedOffset: 4,
728
658
  itemStyle: {
729
659
  borderRadius: borderRadius,
730
- borderColor: '#fff',
731
- borderWidth: borderWidth
660
+ borderWidth: borderWidth,
732
661
  },
733
- label: { show: false },
734
662
  emphasis: {
735
- scale: true,
736
- scaleSize: 2,
737
663
  itemStyle: {
738
- borderColor: '#fff',
739
- borderWidth: borderWidth
740
- }
664
+ borderWidth: borderWidth,
665
+ },
741
666
  },
742
667
  select: {
743
668
  itemStyle: {
744
- borderColor: '#fff',
745
- borderWidth: borderWidth
746
- }
669
+ borderWidth: borderWidth,
670
+ },
747
671
  },
748
- animationType: 'scale',
749
- animationEasing: 'elasticOut',
750
672
  data: pieData,
751
- id: `ring_${ringIndex}`
673
+ id: `ring_${ringIndex}`,
752
674
  };
675
+ const seriesOption = merge(dynamicRingSeriesOptions, overrides);
753
676
  // Inyectar el resolver de color si existe
754
- if (this.colorResolver) {
677
+ if (this.colorResolver && seriesOption.itemStyle) {
755
678
  seriesOption.itemStyle.color = this.colorResolver;
756
679
  }
757
680
  return seriesOption;
758
681
  });
759
- const common = this.getCommonOptions(overrides);
760
- return {
761
- ...common,
762
- tooltip: {
763
- ...getTooltipOptions({ trigger: 'item' }),
764
- formatter: (params) => {
765
- const key = params.data.originalMeassureKey || '';
766
- const valFormatted = this.formatCellValue(params.value, key);
767
- const seriesHeader = totalRings > 1 ? `<b>${params.seriesName}</b><br/>` : '';
768
- return `${seriesHeader}${params.name}<br/>${params.marker} <b>${valFormatted}</b> (${params.percent}%)`;
769
- }
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}%)`;
770
715
  },
771
- legend: getLegendOptions(),
772
- graphic: [{
773
- id: 'center-kpi',
774
- type: 'text',
775
- left: 'center',
776
- top: 'middle',
777
- z: 100,
778
- transition: ['style'],
779
- style: {
780
- text: '',
781
- fontSize: 22,
782
- fontWeight: 'bold',
783
- fill: '#333',
784
- stroke: '#fff',
785
- lineWidth: 1,
786
- paintOrder: 'stroke',
787
- textAlign: 'center',
788
- textVerticalAlign: 'middle',
789
- opacity: 0
790
- }
791
- }],
792
- series: series,
793
- };
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();
794
843
  }
795
844
  }
796
845
 
@@ -801,14 +850,49 @@ class RingBuilder extends BaseEchartBuilder {
801
850
  * @see {@link vs-echarts/docs/charts/ring-patterns.md}
802
851
  */
803
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);
804
887
  lastSelectedSeriesIndex = null;
805
888
  lastSelectedDataIndex = null;
806
889
  selectedPercent = null;
807
890
  currentGraphicText = '';
808
- builder;
809
891
  constructor() {
810
892
  super();
811
- this.builder = new RingBuilder();
893
+ }
894
+ make(makeOpts) {
895
+ this.director.makeRing(this.data, this.optionsOverrides, makeOpts);
812
896
  }
813
897
  onInputChanges(changes) {
814
898
  // Reset selection only if data changed
@@ -895,15 +979,14 @@ class EchartsRingComponent extends BaseEchartsComponent {
895
979
  if (!this.data)
896
980
  return;
897
981
  // 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
898
- // Pero aquí necesitamos llamar a super o duplicar la lógica de inyección de inputs
899
- if (this.valueFormatter)
900
- this.builder.setValueFormatter(this.valueFormatter);
901
- if (this.palette)
902
- this.builder.setPalette(this.palette);
903
- if (this.colorResolver)
904
- 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);
905
988
  // 2. Obtenemos las bases del chart usando el builder
906
- let options = this.builder.build(this.data, this.optionsOverrides);
989
+ let options = this.builder.getResult();
907
990
  // 3. Persistencia de GRAPHIC (KPI central)
908
991
  if (options.graphic && Array.isArray(options.graphic)) {
909
992
  const graphic = options.graphic[0];
@@ -946,359 +1029,276 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
946
1029
  }], ctorParameters: () => [] });
947
1030
 
948
1031
  /**
949
- * VerticalBandsBuilder
1032
+ * Builder principal.
1033
+ *
1034
+ * Es muy completo, tiene soporte para ejes y sistema cartesiano polar.
950
1035
  *
951
- * Especializado en construir opciones para gráficos de barras verticales.
952
- * @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.
953
1037
  */
954
- class VerticalBandsBuilder extends BaseEchartBuilder {
955
- constructor() {
956
- 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));
957
1056
  }
958
- build(data, overrides) {
1057
+ /**
1058
+ *
1059
+ * @param data
1060
+ * @param overrides
1061
+ * @returns
1062
+ */
1063
+ addSeries(data, overrides) {
959
1064
  if (!data || !data.series.length)
960
- return {};
1065
+ return;
961
1066
  const series = data.series.map((s) => {
962
- const seriesOption = {
1067
+ const dynamicOverrides = {
963
1068
  name: s.name,
964
- type: 'bar',
965
- barMaxWidth: 50,
966
- barGap: '15%',
967
- barCategoryGap: '35%',
968
- animation: true,
969
- animationDuration: 1000,
970
- animationEasing: 'cubicOut',
971
- itemStyle: {
972
- borderRadius: [4, 4, 0, 0]
973
- },
974
1069
  data: s.data,
975
- emphasis: {
976
- focus: 'none'
977
- },
978
- blur: {
979
- itemStyle: {
980
- opacity: 0.2
981
- }
982
- },
983
- select: {
984
- itemStyle: {
985
- opacity: 1,
986
- shadowBlur: 10,
987
- shadowColor: 'rgba(0,0,0,0.3)'
988
- }
989
- },
990
1070
  label: {
991
- show: false,
992
- position: 'top',
993
1071
  formatter: (params) => {
994
1072
  const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
995
1073
  return this.formatCellValue(params.value, key);
996
1074
  }
997
1075
  }
998
1076
  };
1077
+ const seriesOption = merge$1(dynamicOverrides, overrides);
999
1078
  // Inyectar el resolver de color si existe
1000
- if (this.colorResolver) {
1079
+ if (this.colorResolver && seriesOption.itemStyle) {
1001
1080
  seriesOption.itemStyle.color = this.colorResolver;
1002
1081
  }
1003
1082
  return seriesOption;
1004
1083
  });
1005
- const common = this.getCommonOptions(overrides);
1006
- const categoryAxisOptions = {
1007
- ...overrides.axis.categoryAxis[0],
1008
- data: data.categories,
1009
- };
1010
- const { trigger = 'axis' } = overrides.tooltip || {};
1011
- const tooltipOptionsOverrides = {
1012
- trigger,
1013
- };
1014
- return {
1015
- ...common,
1016
- tooltip: {
1017
- ...getTooltipOptions(tooltipOptionsOverrides),
1018
- 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,
1019
1137
  },
1020
- legend: getLegendOptions(),
1021
- xAxis: [getCategoryAxisOptions(categoryAxisOptions)],
1022
- yAxis: [getValueAxisOptions()],
1023
- 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
+ }
1024
1150
  };
1151
+ const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
1152
+ radiusAxis.push(radialAxisOptions);
1153
+ this.result.radiusAxis = radiusAxis;
1025
1154
  }
1026
- }
1027
-
1028
- /**
1029
- * EchartsVerticalBandsComponent
1030
- *
1031
- * Especialista en visualización de bandas/barras verticales.
1032
- * Implementa patrones de interacción ZRender y resaltado de grupos.
1033
- * @see {@link vs-echarts/docs/charts/vertical-bands-patterns.md}
1034
- */
1035
- class EchartsVerticalBandsComponent extends BaseEchartsComponent {
1036
- builder;
1037
- constructor() {
1038
- super();
1039
- 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;
1040
1160
  }
1041
- onChartInit(instance) {
1042
- super.onChartInit(instance);
1043
- this.setupAdditionalInteractions();
1161
+ addLegend() {
1162
+ this.result.legend = getLegendOptions();
1044
1163
  }
1045
- onInputChanges(changes) {
1046
- if (changes['data']) {
1047
- this.selectedCategoryIndex = null;
1048
- this.selectedSeriesIndex = null;
1049
- 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;
1050
1183
  }
1051
- super.onInputChanges(changes);
1052
1184
  }
1053
- setupAdditionalInteractions() {
1054
- if (!this.chartInstance)
1055
- return;
1056
- // 1. ZRender click for background "sectors" (Specific to bands)
1057
- const zr = this.chartInstance.getZr();
1058
- zr.on('click', (params) => {
1059
- if (!params.target) {
1060
- const pointInPixel = [params.offsetX, params.offsetY];
1061
- if (this.chartInstance.containPixel('grid', pointInPixel)) {
1062
- const xIndexResult = this.chartInstance.convertFromPixel({ xAxisIndex: 0 }, pointInPixel);
1063
- const xIndex = Array.isArray(xIndexResult) ? xIndexResult[0] : xIndexResult;
1064
- if (typeof xIndex === 'number' && xIndex >= 0) {
1065
- this.handleSelection(xIndex, -1); // Use -1 or null to indicate sector selection without specific series
1066
- }
1067
- }
1068
- }
1069
- });
1070
- // 2. Mouseover for Group Highlighting
1071
- this.chartInstance.on('mouseover', (params) => {
1072
- if (params.dataIndex !== undefined) {
1073
- this.highlightSector(params.dataIndex);
1074
- }
1075
- });
1076
- this.chartInstance.on('mouseout', () => {
1077
- this.clearHighlight();
1078
- });
1185
+ /**
1186
+ * Permite inyectar una paleta de colores básica.
1187
+ */
1188
+ setPalette(palette) {
1189
+ if (palette) {
1190
+ this.palette = palette;
1191
+ }
1079
1192
  }
1080
- highlightSector(index) {
1081
- if (!this.chartInstance || this.selectedCategoryIndex !== null)
1082
- return;
1083
- const seriesCount = Array.isArray(this.chartOptions.series) ? this.chartOptions.series.length : 0;
1084
- this.chartInstance.dispatchAction({
1085
- type: 'highlight',
1086
- seriesIndex: Array.from({ length: seriesCount }, (_, i) => i),
1087
- dataIndex: index
1088
- });
1193
+ /**
1194
+ * Permite inyectar un resolver de colores dinámico.
1195
+ */
1196
+ setColorResolver(resolver) {
1197
+ if (resolver) {
1198
+ this.colorResolver = resolver;
1199
+ }
1089
1200
  }
1090
- clearHighlight() {
1091
- if (!this.chartInstance)
1092
- return;
1093
- const seriesCount = Array.isArray(this.chartOptions.series) ? this.chartOptions.series.length : 0;
1094
- this.chartInstance.dispatchAction({
1095
- type: 'downplay',
1096
- seriesIndex: Array.from({ length: seriesCount }, (_, i) => i)
1097
- });
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;
1098
1213
  }
1214
+ }
1215
+
1216
+ class EchartsBarComponent extends BaseEchartsComponent {
1099
1217
  /**
1100
- * Maneja clics en la leyenda para persistir filtros.
1218
+ * Opciones escenciales inmutables estaticas comunes a todos los charts de barras.
1101
1219
  */
1102
- onLegendSelectChanged(event) {
1103
- if (event && event.selected) {
1104
- this.currentLegendSelected = event.selected;
1105
- 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,
1106
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);
1107
1259
  }
1108
1260
  updateChartOptions() {
1109
1261
  if (!this.chartInstance)
1110
1262
  return;
1111
1263
  if (!this.data)
1112
1264
  return;
1113
- // 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
1114
- if (this.valueFormatter)
1115
- this.builder.setValueFormatter(this.valueFormatter);
1116
- if (this.palette)
1117
- this.builder.setPalette(this.palette);
1118
- if (this.colorResolver)
1119
- this.builder.setColorResolver(this.colorResolver);
1120
- // 2. Obtenemos las bases del chart usando el builder
1121
- let baseOptions = this.builder.build(this.data, this.optionsOverrides);
1122
- // 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();
1123
1272
  if (this.currentLegendSelected && baseOptions.legend) {
1124
1273
  baseOptions.legend.selected = { ...this.currentLegendSelected };
1125
1274
  }
1126
- // 4. Apply persistent selection style if a sector is selected
1127
1275
  if (this.selectedCategoryIndex !== null && baseOptions.series) {
1128
- const seriesArray = baseOptions.series;
1129
- baseOptions.series = seriesArray.map((s, sIdx) => {
1130
- if (s.type === 'bar' && Array.isArray(s.data)) {
1131
- return {
1132
- ...s,
1133
- emphasis: {
1134
- disabled: true
1135
- },
1136
- data: s.data.map((val, idx) => {
1137
- const isSelected = idx === this.selectedCategoryIndex;
1138
- const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
1139
- const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
1140
- return {
1141
- value: itemVal,
1142
- itemStyle: {
1143
- opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
1144
- borderWidth: 0
1145
- }
1146
- };
1147
- })
1148
- };
1149
- }
1150
- return s;
1151
- });
1152
- }
1153
- this.triggerUpdate(baseOptions);
1154
- }
1155
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1156
- 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"] }] });
1157
- }
1158
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, decorators: [{
1159
- type: Component,
1160
- args: [{ selector: 'vs-echarts-vertical-bands', standalone: true, imports: [
1161
- CommonModule,
1162
- NgxEchartsDirective,
1163
- ], 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"] }]
1164
- }], ctorParameters: () => [] });
1165
-
1166
- /**
1167
- * BarBuilder
1168
- *
1169
- * Especializado en construir opciones para gráficos de barras generales.
1170
- */
1171
- class BarBuilder extends BaseEchartBuilder {
1172
- constructor() {
1173
- super();
1174
- }
1175
- build(data, overrides) {
1176
- if (!data || !data.series.length)
1177
- return {};
1178
- const { itemStyle, emphasis = { focus: 'none' }, stack = undefined, showBackground = false, coordinateSystem = 'cartesian2d', } = overrides.bar.series;
1179
- const itStBorderRadius = itemStyle?.borderRadius ?? [4, 4, 0, 0];
1180
- const emphasisFocus = emphasis.focus ?? 'none';
1181
- const series = data.series.map((s) => {
1182
- const seriesOption = {
1183
- name: s.name,
1184
- type: 'bar',
1185
- barMaxWidth: 50,
1186
- barGap: '15%',
1187
- barCategoryGap: '35%',
1188
- animation: true,
1189
- animationDuration: 1000,
1190
- animationEasing: 'cubicOut',
1191
- coordinateSystem,
1192
- itemStyle: {
1193
- borderRadius: itStBorderRadius,
1194
- },
1195
- data: s.data,
1196
- stack,
1197
- emphasis: {
1198
- focus: emphasisFocus
1199
- },
1200
- showBackground,
1201
- backgroundStyle: {
1202
- color: 'rgba(180, 180, 180, 0.2)' // gris claro
1203
- },
1204
- label: {
1205
- show: false,
1206
- position: 'top',
1207
- formatter: (params) => {
1208
- const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
1209
- return this.formatCellValue(params.value, key);
1210
- }
1211
- }
1212
- };
1213
- // Inyectar el resolver de color si existe
1214
- if (this.colorResolver && seriesOption.itemStyle) {
1215
- seriesOption.itemStyle.color = this.colorResolver;
1216
- }
1217
- return seriesOption;
1218
- });
1219
- const common = this.getCommonOptions(overrides);
1220
- const xAxis = [];
1221
- const yAxis = [];
1222
- const radiusAxis = [];
1223
- const polar = [];
1224
- const angleAxis = [];
1225
- const categoryAxisOptionsOverrides = {
1226
- ...overrides.axis.categoryAxis[0],
1227
- data: data.categories,
1228
- };
1229
- const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
1230
- const valueAxisOptions = getValueAxisOptions();
1231
- if (coordinateSystem == "polar") {
1232
- // polar coord system.
1233
- /** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
1234
- const radiusAxisOverrides = {
1235
- axisTick: {
1236
- show: false,
1237
- },
1238
- axisLabel: {
1239
- margin: 2,
1240
- fontSize: 8,
1241
- align: 'right',
1242
- rotate: 20,
1243
- verticalAlign: 'top',
1244
- },
1245
- axisLine: {
1246
- lineStyle: {
1247
- type: 'dashed',
1248
- },
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
+ };
1249
1297
  }
1250
- };
1251
- angleAxis.push(categoryAxisOptions);
1252
- const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
1253
- radiusAxis.push(radialAxisOptions);
1254
- polar.push({
1255
- radius: '65%',
1256
- center: ["50%", "44%"],
1298
+ return s;
1257
1299
  });
1258
1300
  }
1259
- else {
1260
- // cartesian 2d coord system.
1261
- if (overrides.bar.orientation === 'h') {
1262
- xAxis.push(valueAxisOptions);
1263
- yAxis.push(categoryAxisOptions);
1264
- }
1265
- else {
1266
- xAxis.push(categoryAxisOptions);
1267
- yAxis.push(valueAxisOptions);
1268
- }
1269
- }
1270
- const { trigger = 'item' } = overrides.tooltip;
1271
- const tooltipOptionsOverrides = {
1272
- trigger,
1273
- };
1274
- return {
1275
- ...common,
1276
- tooltip: {
1277
- ...getTooltipOptions(tooltipOptionsOverrides),
1278
- formatter: getTooltipFormatter(trigger, data, this.formatCellValue.bind(this))
1279
- },
1280
- legend: getLegendOptions(),
1281
- xAxis,
1282
- yAxis,
1283
- radiusAxis,
1284
- angleAxis,
1285
- polar,
1286
- series: series
1287
- };
1288
- }
1289
- }
1290
-
1291
- /**
1292
- * EchartsBarComponent
1293
- *
1294
- * Componente especialista para visualización de gráficos de barras.
1295
- * Implementa patrones de interacción ZRender y resaltado de grupos.
1296
- */
1297
- class EchartsBarComponent extends BaseEchartsComponent {
1298
- builder;
1299
- constructor() {
1300
- super();
1301
- this.builder = new BarBuilder();
1301
+ this.triggerUpdate(baseOptions);
1302
1302
  }
1303
1303
  onChartInit(instance) {
1304
1304
  super.onChartInit(instance);
@@ -1355,49 +1355,6 @@ class EchartsBarComponent extends BaseEchartsComponent {
1355
1355
  this.updateChartOptions();
1356
1356
  }
1357
1357
  }
1358
- updateChartOptions() {
1359
- if (!this.chartInstance)
1360
- return;
1361
- if (!this.data)
1362
- return;
1363
- if (this.valueFormatter)
1364
- this.builder.setValueFormatter(this.valueFormatter);
1365
- if (this.palette)
1366
- this.builder.setPalette(this.palette);
1367
- if (this.colorResolver)
1368
- this.builder.setColorResolver(this.colorResolver);
1369
- let baseOptions = this.builder.build(this.data, this.optionsOverrides);
1370
- if (this.currentLegendSelected && baseOptions.legend) {
1371
- baseOptions.legend.selected = { ...this.currentLegendSelected };
1372
- }
1373
- if (this.selectedCategoryIndex !== null && baseOptions.series) {
1374
- const seriesArray = baseOptions.series;
1375
- baseOptions.series = seriesArray.map((s, sIdx) => {
1376
- if (s.type === 'bar' && Array.isArray(s.data)) {
1377
- return {
1378
- ...s,
1379
- emphasis: {
1380
- disabled: true
1381
- },
1382
- data: s.data.map((val, idx) => {
1383
- const isSelected = idx === this.selectedCategoryIndex;
1384
- const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
1385
- const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
1386
- return {
1387
- value: itemVal,
1388
- itemStyle: {
1389
- opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
1390
- borderWidth: 0
1391
- }
1392
- };
1393
- })
1394
- };
1395
- }
1396
- return s;
1397
- });
1398
- }
1399
- this.triggerUpdate(baseOptions);
1400
- }
1401
1358
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1402
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"] }] });
1403
1360
  }
@@ -1409,86 +1366,258 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
1409
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"] }]
1410
1367
  }], ctorParameters: () => [] });
1411
1368
 
1412
- class LineBuilder extends BaseEchartBuilder {
1413
- constructor() {
1414
- super();
1415
- }
1416
- build(data, overrides) {
1417
- if (!data || !data.series.length)
1418
- return {};
1419
- const { areaStyle = undefined, stack = undefined, smooth = true, } = overrides.line.series;
1420
- const series = data.series.map((s) => {
1421
- const seriesOption = {
1422
- name: s.name,
1423
- type: 'line',
1424
- animation: true,
1425
- animationDuration: 1000,
1426
- animationEasing: 'cubicOut',
1427
- data: s.data,
1428
- smooth,
1429
- smoothMonotone: 'x',
1430
- symbolSize: 6,
1431
- itemStyle: {
1432
- shadowColor: 'rgba(0, 0, 0, 0.2)',
1433
- shadowBlur: 5,
1434
- shadowOffsetY: 2,
1435
- },
1436
- lineStyle: {
1437
- width: 2,
1438
- shadowColor: 'rgba(0, 0, 0, 0.2)',
1439
- shadowBlur: 8,
1440
- shadowOffsetY: 6,
1441
- cap: 'round',
1442
- join: 'round',
1443
- },
1444
- emphasis: {
1445
- focus: 'none',
1446
- itemStyle: {
1447
- borderWidth: 2,
1448
- shadowBlur: 10,
1449
- },
1450
- lineStyle: {
1451
- width: 4,
1452
- shadowBlur: 12,
1453
- }
1454
- },
1455
- areaStyle,
1456
- stack,
1457
- };
1458
- // Inyectar el resolver de color si existe
1459
- if (this.colorResolver && seriesOption.itemStyle != undefined) {
1460
- seriesOption.itemStyle.color = this.colorResolver;
1461
- }
1462
- return seriesOption;
1463
- });
1464
- const common = this.getCommonOptions(overrides);
1465
- const categoryAxisOptions = {
1466
- ...overrides.axis.categoryAxis[0],
1467
- 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',
1468
1388
  };
1469
- const { trigger = 'item' } = overrides.tooltip;
1470
- const tooltipOptionsOverrides = {
1471
- 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',
1472
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;
1473
1520
  return {
1474
- ...common,
1475
- tooltip: {
1476
- ...getTooltipOptions(tooltipOptionsOverrides),
1477
- 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
1478
1532
  },
1479
- legend: getLegendOptions(),
1480
- xAxis: [getCategoryAxisOptions(categoryAxisOptions)],
1481
- yAxis: [getValueAxisOptions()],
1482
- 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
+ })
1483
1573
  };
1484
- }
1574
+ });
1485
1575
  }
1486
1576
 
1487
1577
  class EchartsLineComponent extends BaseEchartsComponent {
1488
- 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);
1489
1619
  constructor() {
1490
1620
  super();
1491
- this.builder = new LineBuilder();
1492
1621
  }
1493
1622
  onInputChanges(changes) {
1494
1623
  if (changes['data']) {
@@ -1498,41 +1627,96 @@ class EchartsLineComponent extends BaseEchartsComponent {
1498
1627
  }
1499
1628
  super.onInputChanges(changes);
1500
1629
  }
1630
+ make(makeOpts) {
1631
+ this.director.makeLine(this.data, this.optionsOverrides, makeOpts);
1632
+ }
1501
1633
  updateChartOptions() {
1502
1634
  if (!this.chartInstance)
1503
1635
  return;
1504
1636
  if (!this.data)
1505
1637
  return;
1506
- // 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
1507
- if (this.valueFormatter)
1508
- this.builder.setValueFormatter(this.valueFormatter);
1509
- if (this.palette)
1510
- this.builder.setPalette(this.palette);
1511
- if (this.colorResolver)
1512
- this.builder.setColorResolver(this.colorResolver);
1513
- // 2. Obtenemos las bases del chart usando el builder
1514
- let baseOptions = this.builder.build(this.data, this.optionsOverrides);
1515
- // 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
1516
1647
  if (this.currentLegendSelected && baseOptions.legend) {
1517
1648
  baseOptions.legend.selected = { ...this.currentLegendSelected };
1518
1649
  }
1519
- // 4. Apply persistent selection style if a point is selected
1650
+ //3. Apply persistent selection style if a point is selected
1520
1651
  if (this.selectedCategoryIndex !== null && baseOptions.series) {
1521
1652
  baseOptions.series = applyLineSelectionStyle(baseOptions.series, this.selectedCategoryIndex, this.selectedSeriesIndex);
1522
1653
  }
1523
1654
  this.triggerUpdate(baseOptions);
1524
1655
  }
1525
1656
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1526
- 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"] }] });
1527
1660
  }
1528
1661
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, decorators: [{
1529
1662
  type: Component,
1530
1663
  args: [{ selector: 'vs-echarts-line', standalone: true, imports: [
1531
1664
  CommonModule,
1532
1665
  NgxEchartsDirective,
1533
- ], 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"] }]
1534
1669
  }], ctorParameters: () => [] });
1535
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
+
1536
1720
  // Interfaces de Inputs de Base EChart Component //
1537
1721
 
1538
1722
  ;
@@ -1547,5 +1731,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
1547
1731
  * Generated bundle index. Do not edit.
1548
1732
  */
1549
1733
 
1550
- export { BaseEchartsComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent, EchartsVerticalBandsComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
1734
+ export { BaseEchartsComponent, EChartsAreaComponent, EChartsAreaStackComponent, EChartsBarStackedComponent, EChartsBarStackedRadialComponent, EChartsHBarComponent, EChartsHBarStackedComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
1551
1735
  //# sourceMappingURL=visionaris-bruno-vs-echarts.mjs.map